diff --git a/examples/full_multisolve.py b/examples/full_multisolve.py index 3f646c44e5..c6809f2124 100644 --- a/examples/full_multisolve.py +++ b/examples/full_multisolve.py @@ -23,9 +23,10 @@ to the proper certificate (https://stackoverflow.com/a/31060428). """ +from collections.abc import Callable from dataclasses import dataclass from math import sqrt -from typing import Callable, Optional +from typing import Optional import gymnasium as gym import numpy as np diff --git a/examples/gym_jsbsim_greedy.py b/examples/gym_jsbsim_greedy.py index 72ab8e33c2..7f47d34fd7 100644 --- a/examples/gym_jsbsim_greedy.py +++ b/examples/gym_jsbsim_greedy.py @@ -2,7 +2,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from typing import Any, Callable +from collections.abc import Callable +from typing import Any import folium import gym_jsbsim diff --git a/examples/gym_jsbsim_iw.py b/examples/gym_jsbsim_iw.py index 1e42be860d..a72e77dfaa 100644 --- a/examples/gym_jsbsim_iw.py +++ b/examples/gym_jsbsim_iw.py @@ -2,7 +2,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from typing import Any, Callable, Optional +from collections.abc import Callable +from typing import Any, Optional import folium import gym_jsbsim diff --git a/examples/gym_jsbsim_riw.py b/examples/gym_jsbsim_riw.py index ec14f028f3..5c03c7a27c 100644 --- a/examples/gym_jsbsim_riw.py +++ b/examples/gym_jsbsim_riw.py @@ -5,7 +5,8 @@ import bisect import json import math -from typing import Any, Callable +from collections.abc import Callable +from typing import Any import folium import gym_jsbsim diff --git a/examples/gym_line_control.py b/examples/gym_line_control.py index 55438df9bc..aca1a96167 100644 --- a/examples/gym_line_control.py +++ b/examples/gym_line_control.py @@ -2,8 +2,9 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +from collections.abc import Callable from math import exp, fabs, sqrt -from typing import Any, Callable, Optional +from typing import Optional import gymnasium as gym import numpy as np diff --git a/examples/nocycle_grid_goal_mdp.py b/examples/nocycle_grid_goal_mdp.py index 61cfad0230..2dd82ba6dc 100644 --- a/examples/nocycle_grid_goal_mdp.py +++ b/examples/nocycle_grid_goal_mdp.py @@ -4,9 +4,10 @@ import getopt import sys +from collections.abc import Iterable from enum import IntEnum from math import sqrt -from typing import Iterable, NamedTuple, Optional +from typing import NamedTuple, Optional from skdecide import ( DiscreteDistribution, diff --git a/examples/optuna_gym.py b/examples/optuna_gym.py index 21a10417b1..326b7ba6b1 100644 --- a/examples/optuna_gym.py +++ b/examples/optuna_gym.py @@ -17,7 +17,7 @@ from __future__ import annotations import logging -from typing import Any, Dict, List, Tuple, Type, Union +from typing import Any, Union import gymnasium as gym from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( @@ -95,18 +95,18 @@ def heuristic(domain, state): def bee1_features( domain: Union[GymDomainForWidthSolvers, GymDomain], state: "State" -) -> Tuple[int, Any]: +) -> tuple[int, Any]: return domain.bee1_features(state) def bee2_features( domain: Union[GymDomainForWidthSolvers, GymDomain], state: "State" -) -> Tuple[int, Any]: +) -> tuple[int, Any]: return domain.bee2_features(state) # Fixed kwargs per solver: either hyperparameters we do not want to search, or other parameters like time limits -kwargs_fixed_by_solver: Dict[Type[Solver], Dict[str, Any]] = { +kwargs_fixed_by_solver: dict[type[Solver], dict[str, Any]] = { Astar: dict( parallel=False, verbose=False, @@ -123,7 +123,7 @@ def bee2_features( # Add new hyperparameters to some solvers -additional_hyperparameters_by_solver: Dict[Type[Solver], List[Hyperparameter]] = { +additional_hyperparameters_by_solver: dict[type[Solver], list[Hyperparameter]] = { StableBaseline: [ # defined only if $algo_class \in [PPO]$ FloatHyperparameter( @@ -148,8 +148,8 @@ def bee2_features( # Restrict some hyperparameters choices, for some solvers (making use of `kwargs_by_name` of `suggest_with_optuna`) -suggest_optuna_kwargs_by_name_by_solver: Dict[ - Type[Solver], Dict[str, Dict[str, Any]] +suggest_optuna_kwargs_by_name_by_solver: dict[ + type[Solver], dict[str, dict[str, Any]] ] = { StableBaseline: { # restrict the choices of algo classes diff --git a/examples/optuna_gym_utils.py b/examples/optuna_gym_utils.py index 53fae54169..3e07b019d8 100644 --- a/examples/optuna_gym_utils.py +++ b/examples/optuna_gym_utils.py @@ -2,7 +2,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from typing import Callable, Optional +from collections.abc import Callable +from typing import Optional import gymnasium as gym diff --git a/examples/optuna_maze.py b/examples/optuna_maze.py index 7bf16a7795..20575128ac 100644 --- a/examples/optuna_maze.py +++ b/examples/optuna_maze.py @@ -18,7 +18,7 @@ import logging import math -from typing import Any, Dict, List, Type +from typing import Any from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -85,7 +85,7 @@ def state_features(domain: Maze, state: State): # Fixed kwargs per solver: either hyperparameters we do not want to search, or other parameters like time limits -kwargs_fixed_by_solver: Dict[Type[Solver], Dict[str, Any]] = { +kwargs_fixed_by_solver: dict[type[Solver], dict[str, Any]] = { Astar: dict( parallel=False, verbose=False, @@ -120,7 +120,7 @@ def state_features(domain: Maze, state: State): # Add new hyperparameters to some solvers -additional_hyperparameters_by_solver: Dict[Type[Solver], List[Hyperparameter]] = { +additional_hyperparameters_by_solver: dict[type[Solver], list[Hyperparameter]] = { # ex 1: ent_coef for StableBaselines for PPO algo only StableBaseline: [ # defined only if $algo_class \in [PPO]$ @@ -156,8 +156,8 @@ def state_features(domain: Maze, state: State): # Restrict some hyperparameters choices, for some solvers (making use of `kwargs_by_name` of `suggest_with_optuna`) -suggest_optuna_kwargs_by_name_by_solver: Dict[ - Type[Solver], Dict[str, Dict[str, Any]] +suggest_optuna_kwargs_by_name_by_solver: dict[ + type[Solver], dict[str, dict[str, Any]] ] = { StableBaseline: { # restrict the choices of algo classes diff --git a/examples/optuna_maze_explored_nodes.py b/examples/optuna_maze_explored_nodes.py index 7b7caabb18..4aeea0b615 100644 --- a/examples/optuna_maze_explored_nodes.py +++ b/examples/optuna_maze_explored_nodes.py @@ -15,7 +15,7 @@ import logging import math -from typing import Any, Dict, List, Tuple, Type +from typing import Any from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -81,7 +81,7 @@ def state_features(domain: Maze, state: State): # Fixed kwargs per solver: either hyperparameters we do not want to search, or other parameters like time limits -kwargs_fixed_by_solver: Dict[Type[Solver], Dict[str, Any]] = { +kwargs_fixed_by_solver: dict[type[Solver], dict[str, Any]] = { Astar: dict( parallel=False, verbose=False, @@ -111,7 +111,7 @@ def state_features(domain: Maze, state: State): } # Add new hyperparameters to some solvers -additional_hyperparameters_by_solver: Dict[Type[Solver], List[Hyperparameter]] = { +additional_hyperparameters_by_solver: dict[type[Solver], list[Hyperparameter]] = { # ex: heuristic for A* and co Astar: [ CategoricalHyperparameter( @@ -135,8 +135,8 @@ def state_features(domain: Maze, state: State): # Restrict some hyperparameters choices, for some solvers (making use of `kwargs_by_name` of `suggest_with_optuna`) -suggest_optuna_kwargs_by_name_by_solver: Dict[ - Type[Solver], Dict[str, Dict[str, Any]] +suggest_optuna_kwargs_by_name_by_solver: dict[ + type[Solver], dict[str, dict[str, Any]] ] = { StableBaseline: { # restrict the choices of algo classes @@ -152,11 +152,11 @@ def state_features(domain: Maze, state: State): def objective( solver: Solver, - episodes: List[ - Tuple[ - List[D.T_agent[D.T_observation]], - List[D.T_agent[D.T_concurrency[D.T_event]]], - List[D.T_agent[Value[D.T_value]]], + episodes: list[ + tuple[ + list[D.T_agent[D.T_observation]], + list[D.T_agent[D.T_concurrency[D.T_event]]], + list[D.T_agent[Value[D.T_value]]], ] ], ) -> float: diff --git a/examples/scheduling/toy_rcpsp_examples.py b/examples/scheduling/toy_rcpsp_examples.py index a65e6689c9..6ae30a622c 100644 --- a/examples/scheduling/toy_rcpsp_examples.py +++ b/examples/scheduling/toy_rcpsp_examples.py @@ -1,6 +1,6 @@ import random from enum import Enum -from typing import Any, Dict, List, Optional, Set, Union +from typing import Any, Optional, Union from skdecide import DiscreteDistribution, Distribution, rollout from skdecide.builders.domain.scheduling.modes import ( @@ -18,7 +18,7 @@ class MyExampleRCPSPDomain(SingleModeRCPSP): - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -27,13 +27,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return {1, 2, 3, 4, 5} - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -42,7 +42,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 5: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_task_duration( @@ -57,10 +57,10 @@ def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: class MyExampleMRCPSPDomain_WithCost(MultiModeRCPSPWithCost): - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return {"r1": True, "r2": True} - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return { 1: {1: ConstantModeConsumption({"r1": 0, "r2": 0})}, 2: { @@ -78,7 +78,7 @@ def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: 5: {1: ConstantModeConsumption({"r1": 0, "r2": 0})}, } - def _get_mode_costs(self) -> Dict[int, Dict[int, float]]: + def _get_mode_costs(self) -> dict[int, dict[int, float]]: return { 1: {1: 0.0}, 2: {1: 1.0, 2: 2.0}, @@ -87,10 +87,10 @@ def _get_mode_costs(self) -> Dict[int, Dict[int, float]]: 5: {1: 0.0}, } - def _get_resource_cost_per_time_unit(self) -> Dict[str, float]: + def _get_resource_cost_per_time_unit(self) -> dict[str, float]: return {"r1": 1, "r2": 2} - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.COST] def __init__(self): @@ -99,13 +99,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5]) - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_task_duration( @@ -125,7 +125,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: all_distributions = {} all_distributions[1] = DiscreteDistribution([(0, 1.0)]) @@ -135,7 +135,7 @@ def _get_task_duration_distribution( all_distributions[5] = DiscreteDistribution([(0, 1.0)]) return all_distributions[task] - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -144,13 +144,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 20 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5]) - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -159,7 +159,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 5: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -173,7 +173,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: all_distributions = {} t = None @@ -192,7 +192,7 @@ def _get_task_duration_distribution( all_distributions[5] = DiscreteDistribution([(0, 1.0)]) return all_distributions[task] - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -201,13 +201,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 20 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5]) - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -216,7 +216,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 5: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -236,7 +236,7 @@ class MyExampleCondSRCPSPDomain( def _get_all_condition_items(self) -> Enum: return ConditionElementsExample - def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution]]: + def _get_task_on_completion_added_conditions(self) -> dict[int, list[Distribution]]: completion_conditions_dict = {} completion_conditions_dict[2] = [ @@ -267,7 +267,7 @@ def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distributio return completion_conditions_dict - def _get_task_existence_conditions(self) -> Dict[int, List[int]]: + def _get_task_existence_conditions(self) -> dict[int, list[int]]: existence_conditions_dict = { 5: [self.get_all_condition_items().PROBLEM_OPERATION_2], 6: [self.get_all_condition_items().PROBLEM_OPERATION_3], @@ -279,7 +279,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: all_distributions = {} all_distributions[1] = DiscreteDistribution([(0, 1.0)]) @@ -292,7 +292,7 @@ def _get_task_duration_distribution( return all_distributions[task] - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -301,13 +301,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [7], 4: [7], 5: [7], 6: [7], 7: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return {1, 2, 3, 4, 5, 6, 7} - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -318,7 +318,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 7: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -332,7 +332,7 @@ class MyExampleSimulatedCondSRCPSPDomain( def _get_all_condition_items(self) -> Enum: return ConditionElementsExample - def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution]]: + def _get_task_on_completion_added_conditions(self) -> dict[int, list[Distribution]]: completion_conditions_dict = {} completion_conditions_dict[2] = [ @@ -363,14 +363,14 @@ def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distributio return completion_conditions_dict - def _get_task_existence_conditions(self) -> Dict[int, List[int]]: + def _get_task_existence_conditions(self) -> dict[int, list[int]]: existence_conditions_dict = { 5: [self.get_all_condition_items().PROBLEM_OPERATION_2], 6: [self.get_all_condition_items().PROBLEM_OPERATION_3], } return existence_conditions_dict - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -379,13 +379,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [7], 4: [7], 5: [7], 6: [7], 7: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5, 6, 7]) - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -396,7 +396,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 7: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: diff --git a/notebooks/12_gym_tuto.ipynb b/notebooks/12_gym_tuto.ipynb index 01cc40bd9c..785bd3db39 100644 --- a/notebooks/12_gym_tuto.ipynb +++ b/notebooks/12_gym_tuto.ipynb @@ -114,8 +114,9 @@ "metadata": {}, "outputs": [], "source": [ + "from collections.abc import Callable\n", "from time import sleep\n", - "from typing import Callable, Optional\n", + "from typing import Optional\n", "\n", "import gymnasium as gym\n", "import matplotlib.pyplot as plt\n", diff --git a/notebooks/13_scheduling_tuto.ipynb b/notebooks/13_scheduling_tuto.ipynb index bf1ebc4414..d132864406 100644 --- a/notebooks/13_scheduling_tuto.ipynb +++ b/notebooks/13_scheduling_tuto.ipynb @@ -172,7 +172,7 @@ "metadata": {}, "outputs": [], "source": [ - "from typing import Any, Dict, List, Optional, Set, Union\n", + "from typing import Any, Optional, Union\n", "\n", "from skdecide import rollout\n", "from skdecide.builders.domain.scheduling.modes import (\n", @@ -189,13 +189,13 @@ " def __init__(self):\n", " self.initialize_domain()\n", "\n", - " def _get_objectives(self) -> List[SchedulingObjectiveEnum]:\n", + " def _get_objectives(self) -> list[SchedulingObjectiveEnum]:\n", " return [SchedulingObjectiveEnum.MAKESPAN]\n", "\n", " def _get_max_horizon(self) -> int:\n", " return 10\n", "\n", - " def _get_successors(self) -> Dict[int, List[int]]:\n", + " def _get_successors(self) -> dict[int, list[int]]:\n", " return {\n", " 1: [2, 4],\n", " 2: [3],\n", @@ -204,10 +204,10 @@ " 5: [],\n", " }\n", "\n", - " def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]:\n", + " def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]:\n", " return set([*range(1, 6)])\n", "\n", - " def _get_tasks_mode(self) -> Dict[int, ModeConsumption]:\n", + " def _get_tasks_mode(self) -> dict[int, ModeConsumption]:\n", " return {\n", " 1: ConstantModeConsumption({\"r1\": 0}),\n", " 2: ConstantModeConsumption({\"r1\": 4}),\n", @@ -216,7 +216,7 @@ " 5: ConstantModeConsumption({\"r1\": 0}),\n", " }\n", "\n", - " def _get_resource_types_names(self) -> List[str]:\n", + " def _get_resource_types_names(self) -> list[str]:\n", " return [\"r1\"]\n", "\n", " def _get_task_duration(\n", @@ -486,13 +486,13 @@ " def __init__(self):\n", " self.initialize_domain()\n", "\n", - " def _get_objectives(self) -> List[SchedulingObjectiveEnum]:\n", + " def _get_objectives(self) -> list[SchedulingObjectiveEnum]:\n", " return [SchedulingObjectiveEnum.MAKESPAN]\n", "\n", " def _get_max_horizon(self) -> int:\n", " return 158\n", "\n", - " def _get_successors(self) -> Dict[int, List[int]]:\n", + " def _get_successors(self) -> dict[int, list[int]]:\n", " return {\n", " 1: [2, 3, 4],\n", " 2: [6, 11, 15],\n", @@ -528,10 +528,10 @@ " 32: [],\n", " }\n", "\n", - " def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]:\n", + " def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]:\n", " return set([*range(1, 33)])\n", "\n", - " def _get_tasks_mode(self) -> Dict[int, ModeConsumption]:\n", + " def _get_tasks_mode(self) -> dict[int, ModeConsumption]:\n", " return {\n", " 1: ConstantModeConsumption({\"r1\": 0, \"r2\": 0, \"r3\": 0, \"r4\": 0}),\n", " 2: ConstantModeConsumption({\"r1\": 4, \"r2\": 0, \"r3\": 0, \"r4\": 0}),\n", @@ -567,7 +567,7 @@ " 32: ConstantModeConsumption({\"r1\": 0, \"r2\": 0, \"r3\": 0, \"r4\": 0}),\n", " }\n", "\n", - " def _get_resource_types_names(self) -> List[str]:\n", + " def _get_resource_types_names(self) -> list[str]:\n", " return [\"r1\", \"r2\", \"r3\", \"r4\"]\n", "\n", " def _get_task_duration(\n", diff --git a/notebooks/flightplanning_utils.py b/notebooks/flightplanning_utils.py index e6fd467219..6d4ef41d73 100644 --- a/notebooks/flightplanning_utils.py +++ b/notebooks/flightplanning_utils.py @@ -6,7 +6,7 @@ from datetime import datetime, timedelta from math import asin, atan2, cos, degrees, radians, sin, sqrt from tempfile import NamedTemporaryFile -from typing import Callable, Collection, Iterable, Tuple, Union +from typing import Callable, Collection, Iterable, Union, tuple import cdsapi import cfgrib @@ -283,13 +283,13 @@ def plot_wind( def flying( - from_: pd.DataFrame, to_: Tuple[float, float], ds: xr.Dataset, fflow: Callable + from_: pd.DataFrame, to_: tuple[float, float], ds: xr.Dataset, fflow: Callable ) -> pd.DataFrame: """Compute the trajectory of a flying object from a given point to a given point # Parameters from_ (pd.DataFrame): the trajectory of the object so far - to_ (Tuple[float, float]): the destination of the object + to_ (tuple[float, float]): the destination of the object ds (xr.Dataset): dataset containing the wind field fflow (Callable): fuel flow function diff --git a/notebooks/maze_utils.py b/notebooks/maze_utils.py index 60495e5178..2ba1fb0a6a 100644 --- a/notebooks/maze_utils.py +++ b/notebooks/maze_utils.py @@ -2,7 +2,7 @@ import random from collections import deque -from typing import Any, Optional, Tuple +from typing import Any, Optional, tuple import matplotlib.pyplot as plt import numpy as np @@ -89,8 +89,8 @@ def generate_random_maze(width: int, height: int) -> "Maze": def get_image_data( self, - current_position: Optional[Tuple[int, int]] = None, - goal: Optional[Tuple[int, int]] = None, + current_position: Optional[tuple[int, int]] = None, + goal: Optional[tuple[int, int]] = None, ) -> np.array: """Return a numpy array to be displayed with `matplotlib.pyplot.imshow()`. @@ -110,11 +110,11 @@ def get_image_data( def render( self, - current_position: Optional[Tuple[int, int]] = None, - goal: Optional[Tuple[int, int]] = None, + current_position: Optional[tuple[int, int]] = None, + goal: Optional[tuple[int, int]] = None, ax: Optional[Any] = None, image: Optional[Any] = None, - ) -> Tuple[Any, Any]: + ) -> tuple[Any, Any]: """Render the maze in a matplotlib figure. Args: diff --git a/skdecide/builders/domain/agent.py b/skdecide/builders/domain/agent.py index 89fc516a64..edfbd257ad 100644 --- a/skdecide/builders/domain/agent.py +++ b/skdecide/builders/domain/agent.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Set, Union +from typing import Union from skdecide.core import SINGLE_AGENT_ID, StrDict @@ -19,7 +19,7 @@ class MultiAgent: T_agent = StrDict - def get_agents(self) -> Set[str]: + def get_agents(self) -> set[str]: """Return the set of available agents ids.""" return set(self.get_observation_space()) @@ -29,7 +29,7 @@ class SingleAgent(MultiAgent): T_agent = Union - def get_agents(self) -> Set[str]: + def get_agents(self) -> set[str]: """Return a singleton for single agent domains. We must be here consistent with `skdecide.core.autocast()` which transforms a single agent domain diff --git a/skdecide/builders/domain/concurrency.py b/skdecide/builders/domain/concurrency.py index fbb010c96e..3f5e7c1c50 100644 --- a/skdecide/builders/domain/concurrency.py +++ b/skdecide/builders/domain/concurrency.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import List, Union +from typing import Union __all__ = ["Parallel", "Sequential"] @@ -12,7 +12,7 @@ class Parallel: """A domain must inherit this class if multiple events/actions can happen in parallel.""" - T_concurrency = List # note: Set cannot handle non-hashable events (and Iterable would not provide enough guidance) + T_concurrency = list # note: set cannot handle non-hashable events (and Iterable would not provide enough guidance) class Sequential(Parallel): diff --git a/skdecide/builders/domain/constraints.py b/skdecide/builders/domain/constraints.py index 2a944ef47e..e75c851993 100644 --- a/skdecide/builders/domain/constraints.py +++ b/skdecide/builders/domain/constraints.py @@ -5,7 +5,6 @@ from __future__ import annotations import functools -from typing import List from skdecide.core import Constraint, D, autocastable @@ -18,7 +17,7 @@ class Constrained: @autocastable def get_constraints( self, - ) -> List[ + ) -> list[ Constraint[ D.T_memory[D.T_state], D.T_agent[D.T_concurrency[D.T_event]], D.T_state ] @@ -37,7 +36,7 @@ def get_constraints( @functools.lru_cache() def _get_constraints( self, - ) -> List[ + ) -> list[ Constraint[ D.T_memory[D.T_state], D.T_agent[D.T_concurrency[D.T_event]], D.T_state ] @@ -55,7 +54,7 @@ def _get_constraints( def _get_constraints_( self, - ) -> List[ + ) -> list[ Constraint[ D.T_memory[D.T_state], D.T_agent[D.T_concurrency[D.T_event]], D.T_state ] diff --git a/skdecide/builders/domain/scheduling/conditional_tasks.py b/skdecide/builders/domain/scheduling/conditional_tasks.py index afe55c02b0..d7edd42547 100644 --- a/skdecide/builders/domain/scheduling/conditional_tasks.py +++ b/skdecide/builders/domain/scheduling/conditional_tasks.py @@ -4,9 +4,7 @@ from __future__ import annotations -import random from enum import Enum -from typing import Dict, List, Set, Tuple from skdecide.core import Distribution @@ -22,7 +20,7 @@ class WithConditionalTasks: # def __init__(self): # self._current_conditions = set() - # def _get_current_conditions(self) -> Set[int]: + # def _get_current_conditions(self) -> set[int]: # return self._current_conditions # def _reset_current_conditions(self): @@ -47,7 +45,7 @@ def get_all_condition_items(self) -> Enum: def _get_all_condition_items(self) -> Enum: raise NotImplementedError - def get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution]]: + def get_task_on_completion_added_conditions(self) -> dict[int, list[Distribution]]: """Return a dict of list. The key of the dict is the task id and each list is composed of a list of tuples. Each tuple contains the probability (first item in tuple) that the conditionElement (second item in tuple) is True. The probabilities in the inner list should sum up to 1. The dictionary should only contains the keys @@ -65,10 +63,10 @@ def get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution """ return self._get_task_on_completion_added_conditions() - def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution]]: + def _get_task_on_completion_added_conditions(self) -> dict[int, list[Distribution]]: raise NotImplementedError - def _sample_completion_conditions(self, task: int) -> List[int]: + def _sample_completion_conditions(self, task: int) -> list[int]: """Samples the condition distributions associated with the given task and return a list of sampled conditions.""" conditions_to_add = [] @@ -77,12 +75,12 @@ def _sample_completion_conditions(self, task: int) -> List[int]: conditions_to_add.append(test.sample()) return conditions_to_add - def sample_completion_conditions(self, task: int) -> List[int]: + def sample_completion_conditions(self, task: int) -> list[int]: """Samples the condition distributions associated with the given task and return a list of sampled conditions.""" return self._sample_completion_conditions(task=task) - def _get_task_existence_conditions(self) -> Dict[int, List[int]]: + def _get_task_existence_conditions(self) -> dict[int, list[int]]: """Return a dictionary where the key is a task id and the value a list of conditions to be respected (True) for the task to be part of the schedule. If a task has no entry in the dictionary, there is no conditions for that task. @@ -98,7 +96,7 @@ def _get_task_existence_conditions(self) -> Dict[int, List[int]]: """ raise NotImplementedError - def get_task_existence_conditions(self) -> Dict[int, List[int]]: + def get_task_existence_conditions(self) -> dict[int, list[int]]: """Return a dictionary where the key is a task id and the value a list of conditions to be respected (True) for the task to be part of the schedule. If a task has no entry in the dictionary, there is no conditions for that task. @@ -126,7 +124,7 @@ def add_to_current_conditions(self, task: int, state): given state. This function should be called when a task complete.""" return self._add_to_current_conditions(task=task, state=state) - def _get_available_tasks(self, state) -> Set[int]: + def _get_available_tasks(self, state) -> set[int]: """Returns the set of all task ids that can be considered under the conditions defined in the given state. Note that the set will contains all ids for all tasks in the domain that meet the conditions, that is tasks that are remaining, or that have been completed, paused or started / resumed.""" @@ -145,13 +143,13 @@ def _get_available_tasks(self, state) -> Set[int]: available_ids.add(id) return available_ids - def get_available_tasks(self, state) -> Set[int]: + def get_available_tasks(self, state) -> set[int]: """Returns the set of all task ids that can be considered under the conditions defined in the given state. Note that the set will contains all ids for all tasks in the domain that meet the conditions, that is tasks that are remaining, or that have been completed, paused or started / resumed.""" return self._get_available_tasks(state=state) - def _get_all_unconditional_tasks(self) -> Set[int]: + def _get_all_unconditional_tasks(self) -> set[int]: """Returns the set of all task ids for which there are no conditions. These tasks are to be considered at the start of a project (i.e. in the initial state).""" all_ids = self.get_tasks_ids() @@ -163,7 +161,7 @@ def _get_all_unconditional_tasks(self) -> Set[int]: available_ids.add(id) return available_ids - def get_all_unconditional_tasks(self) -> Set[int]: + def get_all_unconditional_tasks(self) -> set[int]: """Returns the set of all task ids for which there are no conditions. These tasks are to be considered at the start of a project (i.e. in the initial state).""" return self._get_all_unconditional_tasks() @@ -177,8 +175,8 @@ def _get_all_condition_items(self) -> Enum: def _get_task_on_completion_added_conditions( self, - ) -> Dict[int, List[List[Tuple[float, int]]]]: + ) -> dict[int, list[list[tuple[float, int]]]]: return {} - def _get_task_existence_conditions(self) -> Dict[int, List[int]]: + def _get_task_existence_conditions(self) -> dict[int, list[int]]: return {} diff --git a/skdecide/builders/domain/scheduling/graph_toolbox.py b/skdecide/builders/domain/scheduling/graph_toolbox.py index cf466136cb..3fc9eadeed 100644 --- a/skdecide/builders/domain/scheduling/graph_toolbox.py +++ b/skdecide/builders/domain/scheduling/graph_toolbox.py @@ -4,7 +4,8 @@ from __future__ import annotations -from typing import Any, Dict, Hashable, List, Tuple +from collections.abc import Hashable +from typing import Any import networkx as nx @@ -12,8 +13,8 @@ class Graph: def __init__( self, - nodes: List[Tuple[Hashable, Dict[str, Any]]], - edges: List[Tuple[Hashable, Hashable, Dict[str, Any]]], + nodes: list[tuple[Hashable, dict[str, Any]]], + edges: list[tuple[Hashable, Hashable, dict[str, Any]]], undirected=True, ): self.nodes = nodes diff --git a/skdecide/builders/domain/scheduling/modes.py b/skdecide/builders/domain/scheduling/modes.py index 9d72194e08..770c84139f 100644 --- a/skdecide/builders/domain/scheduling/modes.py +++ b/skdecide/builders/domain/scheduling/modes.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Any, Dict, List, Set, Union +from typing import Any, Union __all__ = ["MultiMode", "SingleMode"] @@ -36,7 +36,7 @@ def get_ressource_names(self): class VaryingModeConsumption(ModeConsumption): """Defines the most generic type of mode.""" - def __init__(self, mode_dict: Dict[str, List[int]]): + def __init__(self, mode_dict: dict[str, list[int]]): self.mode_details = mode_dict def _get_resource_need_at_time(self, resource_name: str, time: int): @@ -60,7 +60,7 @@ class ConstantModeConsumption(VaryingModeConsumption): """Defines a mode where the resource consumption is constant throughout the duration of the task.""" - def __init__(self, mode_dict: Dict[str, int]): + def __init__(self, mode_dict: dict[str, int]): self.mode_details = {} for key in mode_dict.keys(): # TODO i challenge this to be usefull? @@ -83,14 +83,14 @@ def _get_resource_need_at_time(self, resource_name: str, time: int): class MultiMode: """A domain must inherit this class if tasks can be done in 1 or more modes.""" - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: """Return a set or dict of int = id of tasks""" raise NotImplementedError - def get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self._get_tasks_ids() - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: """Return a nested dictionary where the first key is a task id and the second key is a mode id. The value is a Mode object defining the resource consumption. If the domain is an instance of VariableResourceConsumption, VaryingModeConsumption objects should be used. @@ -115,7 +115,7 @@ def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: """ raise NotImplementedError - def get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self._get_tasks_modes() def _get_ressource_names_for_task_mode(self, task: int, mode: int): @@ -146,7 +146,7 @@ def get_task_consumption(self, task: int, mode: int, resource_name: str, time: i class SingleMode(MultiMode): """A domain must inherit this class if ALL tasks only have 1 possible execution mode.""" - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: """Return a nested dictionary where the first key is a task id and the second key is a mode id. The value is a Mode object defining the resource consumption.""" modes = {} @@ -156,7 +156,7 @@ def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: modes[key][1] = tmp_dict[key] return modes - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: """Return a dictionary where the key is a task id and the value is a ModeConsumption object defining the resource consumption. If the domain is an instance of VariableResourceConsumption, VaryingModeConsumption objects should be used. @@ -182,5 +182,5 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: raise NotImplementedError - def get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def get_tasks_mode(self) -> dict[int, ModeConsumption]: return self._get_tasks_mode() diff --git a/skdecide/builders/domain/scheduling/preallocations.py b/skdecide/builders/domain/scheduling/preallocations.py index fc4437bc6e..d839853ce9 100644 --- a/skdecide/builders/domain/scheduling/preallocations.py +++ b/skdecide/builders/domain/scheduling/preallocations.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Dict, List - __all__ = ["WithPreallocations", "WithoutPreallocations"] @@ -14,7 +12,7 @@ class WithPreallocations: def _get_preallocations( self, - ) -> Dict[int, List[str]]: # TODO: To be handled by domain (applicable actions) + ) -> dict[int, list[str]]: # TODO: To be handled by domain (applicable actions) """ Return a dictionary where the key is the id of a task (int) and the value indicates the pre-allocated resources for this task (as a list of str)""" @@ -22,7 +20,7 @@ def _get_preallocations( def get_preallocations( self, - ) -> Dict[int, List[str]]: # TODO: To be handled by domain (applicable actions) + ) -> dict[int, list[str]]: # TODO: To be handled by domain (applicable actions) """ Return a dictionary where the key is the id of a task (int) and the value indicates the pre-allocated resources for this task (as a list of str)""" @@ -32,5 +30,5 @@ def get_preallocations( class WithoutPreallocations(WithPreallocations): """A domain must inherit this class if there are no pre-allocations to consider.""" - def _get_preallocations(self) -> Dict[int, List[str]]: + def _get_preallocations(self) -> dict[int, list[str]]: return {} diff --git a/skdecide/builders/domain/scheduling/precedence.py b/skdecide/builders/domain/scheduling/precedence.py index 66201f2f56..ae55ea5a78 100644 --- a/skdecide/builders/domain/scheduling/precedence.py +++ b/skdecide/builders/domain/scheduling/precedence.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Dict, List - from skdecide.builders.domain.scheduling.graph_toolbox import Graph from skdecide.builders.domain.scheduling.scheduling_domains_modelling import State @@ -15,32 +13,32 @@ class WithPrecedence: """A domain must inherit this class if there exist some predecence constraints between tasks.""" - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: """Return the successors of the tasks. Successors are given as a list for a task given as a key.""" raise NotImplementedError - def get_successors(self) -> Dict[int, List[int]]: + def get_successors(self) -> dict[int, list[int]]: """Return the successors of the tasks. Successors are given as a list for a task given as a key.""" return self._get_successors() - def _get_successors_task(self, task_id: int) -> List[int]: + def _get_successors_task(self, task_id: int) -> list[int]: return self.get_successors()[task_id] - def get_successors_task(self, task_id: int) -> List[int]: + def get_successors_task(self, task_id: int) -> list[int]: return self._get_successors_task(task_id=task_id) - def _get_predecessors(self) -> Dict[int, List[int]]: + def _get_predecessors(self) -> dict[int, list[int]]: """Return the predecessors of the task. Successors are given as a list for a task given as a key.""" return self.graph.predecessors_map() - def get_predecessors(self) -> Dict[int, List[int]]: + def get_predecessors(self) -> dict[int, list[int]]: """Return the predecessors of the task. Successors are given as a list for a task given as a key.""" return self._get_predecessors() - def _get_predecessors_task(self, task_id: int) -> List[int]: + def _get_predecessors_task(self, task_id: int) -> list[int]: return self.get_predecessors()[task_id] - def get_predecessors_task(self, task_id: int) -> List[int]: + def get_predecessors_task(self, task_id: int) -> list[int]: return self._get_predecessors_task(task_id=task_id) def compute_graph(self): @@ -89,7 +87,7 @@ def task_possible_to_launch_precedence(self, state: State): class WithoutPrecedence(WithPrecedence): """A domain must inherit this class if there are no predecence constraints between tasks.""" - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: """Return the successors of the tasks. Successors are given as a list for a task given as a key.""" ids = self.get_tasks_ids() succ = {} @@ -97,7 +95,7 @@ def _get_successors(self) -> Dict[int, List[int]]: succ[id] = [] return succ - def _get_predecessors(self) -> Dict[int, List[int]]: + def _get_predecessors(self) -> dict[int, list[int]]: """Return the successors of the tasks. Successors are given as a list for a task given as a key.""" ids = self.get_tasks_ids() prec = {} diff --git a/skdecide/builders/domain/scheduling/preemptivity.py b/skdecide/builders/domain/scheduling/preemptivity.py index 60297b84b6..a3d607dec2 100644 --- a/skdecide/builders/domain/scheduling/preemptivity.py +++ b/skdecide/builders/domain/scheduling/preemptivity.py @@ -4,12 +4,10 @@ from __future__ import annotations -from typing import Dict, List +from enum import Enum __all__ = ["WithPreemptivity", "WithoutPreemptivity"] -from enum import Enum - class ResumeType(Enum): NA = 0 @@ -20,7 +18,7 @@ class ResumeType(Enum): class WithPreemptivity: """A domain must inherit this class if there exist at least 1 task that can be paused.""" - def _get_task_preemptivity(self) -> Dict[int, bool]: + def _get_task_preemptivity(self) -> dict[int, bool]: """Return a dictionary where the key is a task id and the value a boolean indicating if the task can be paused or stopped. E.g. { @@ -34,7 +32,7 @@ def _get_task_preemptivity(self) -> Dict[int, bool]: """ raise NotImplementedError - def get_task_preemptivity(self) -> Dict[int, bool]: + def get_task_preemptivity(self) -> dict[int, bool]: """Return a dictionary where the key is a task id and the value a boolean indicating if the task can be paused or stopped. E.g. { @@ -48,7 +46,7 @@ def get_task_preemptivity(self) -> Dict[int, bool]: """ return self._get_task_preemptivity() - def _get_task_resuming_type(self) -> Dict[int, ResumeType]: + def _get_task_resuming_type(self) -> dict[int, ResumeType]: """Return a dictionary where the key is a task id and the value is of type ResumeType indicating if the task can be resumed (restarted from where it was paused with no time loss) or restarted (restarted from the start). @@ -63,7 +61,7 @@ def _get_task_resuming_type(self) -> Dict[int, ResumeType]: """ raise NotImplementedError - def get_task_resuming_type(self) -> Dict[int, ResumeType]: + def get_task_resuming_type(self) -> dict[int, ResumeType]: """Return a dictionary where the key is a task id and the value is of type ResumeType indicating if the task can be resumed (restarted from where it was paused with no time loss) or restarted (restarted from the start). @@ -78,7 +76,7 @@ def get_task_resuming_type(self) -> Dict[int, ResumeType]: """ return self._get_task_resuming_type() - def _get_task_paused_non_renewable_resource_returned(self) -> Dict[int, bool]: + def _get_task_paused_non_renewable_resource_returned(self) -> dict[int, bool]: """Return a dictionary where the key is a task id and the value is of type bool indicating if the non-renewable resources are consumed when the task is paused (False) or made available again (True). E.g. { @@ -88,7 +86,7 @@ def _get_task_paused_non_renewable_resource_returned(self) -> Dict[int, bool]: """ raise NotImplementedError - def get_task_paused_non_renewable_resource_returned(self) -> Dict[int, bool]: + def get_task_paused_non_renewable_resource_returned(self) -> dict[int, bool]: """Return a dictionary where the key is a task id and the value is of type bool indicating if the non-renewable resources are consumed when the task is paused (False) or made available again (True). E.g. { @@ -102,21 +100,21 @@ def get_task_paused_non_renewable_resource_returned(self) -> Dict[int, bool]: class WithoutPreemptivity(WithPreemptivity): """A domain must inherit this class if none of the task can be paused.""" - def _get_task_preemptivity(self) -> Dict[int, bool]: + def _get_task_preemptivity(self) -> dict[int, bool]: preemptivity = {} ids = self.get_tasks_ids() for id in ids: preemptivity[id] = False return preemptivity - def _get_task_resuming_type(self) -> Dict[int, ResumeType]: + def _get_task_resuming_type(self) -> dict[int, ResumeType]: resume_types = {} ids = self.get_tasks_ids() for id in ids: resume_types[id] = ResumeType.NA return resume_types - def _get_task_paused_non_renewable_resource_returned(self) -> Dict[int, bool]: + def _get_task_paused_non_renewable_resource_returned(self) -> dict[int, bool]: handling = {} ids = self.get_tasks_ids() for id in ids: diff --git a/skdecide/builders/domain/scheduling/resource_availability.py b/skdecide/builders/domain/scheduling/resource_availability.py index baaff2d6b4..312196b9a0 100644 --- a/skdecide/builders/domain/scheduling/resource_availability.py +++ b/skdecide/builders/domain/scheduling/resource_availability.py @@ -4,9 +4,6 @@ from __future__ import annotations -from enum import Enum -from typing import Dict, List, Optional, Union - __all__ = [ "UncertainResourceAvailabilityChanges", "DeterministicResourceAvailabilityChanges", diff --git a/skdecide/builders/domain/scheduling/resource_consumption.py b/skdecide/builders/domain/scheduling/resource_consumption.py index 69e60614b4..8aded74f35 100644 --- a/skdecide/builders/domain/scheduling/resource_consumption.py +++ b/skdecide/builders/domain/scheduling/resource_consumption.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Any, Dict, List, Set, Union - __all__ = ["VariableResourceConsumption", "ConstantResourceConsumption"] diff --git a/skdecide/builders/domain/scheduling/resource_costs.py b/skdecide/builders/domain/scheduling/resource_costs.py index fa13024d6f..44f6307389 100644 --- a/skdecide/builders/domain/scheduling/resource_costs.py +++ b/skdecide/builders/domain/scheduling/resource_costs.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Dict, List - __all__ = [ "WithModeCosts", "WithoutModeCosts", @@ -19,8 +17,8 @@ class WithModeCosts: def _get_mode_costs( self, - ) -> Dict[ - int, Dict[int, float] + ) -> dict[ + int, dict[int, float] ]: # TODO: To be handled by domain (in transition cost) """ Return a nested dictionary where the first key is the id of a task (int), the second key the id of a mode @@ -29,8 +27,8 @@ def _get_mode_costs( def get_mode_costs( self, - ) -> Dict[ - int, Dict[int, float] + ) -> dict[ + int, dict[int, float] ]: # TODO: To be handled by domain (in transition cost) """ Return a nested dictionary where the first key is the id of a task (int), the second key the id of a mode @@ -41,7 +39,7 @@ def get_mode_costs( class WithoutModeCosts(WithModeCosts): """A domain must inherit this class if there are no mode cost to consider.""" - def _get_mode_costs(self) -> Dict[int, Dict[int, float]]: + def _get_mode_costs(self) -> dict[int, dict[int, float]]: cost_dict = {} for task_id, modes in self.get_tasks_modes().items(): cost_dict[task_id] = {mode_id: 0.0 for mode_id in modes} @@ -53,7 +51,7 @@ class WithResourceCosts: def _get_resource_cost_per_time_unit( self, - ) -> Dict[str, float]: # TODO: To be handled by domain (in transition cost) + ) -> dict[str, float]: # TODO: To be handled by domain (in transition cost) """ Return a dictionary where the key is the name of a resource (str) and the value indicates the cost of using this resource per time unit.""" @@ -61,7 +59,7 @@ def _get_resource_cost_per_time_unit( def get_resource_cost_per_time_unit( self, - ) -> Dict[str, float]: # TODO: To be handled by domain (in transition cost) + ) -> dict[str, float]: # TODO: To be handled by domain (in transition cost) """ Return a dictionary where the key is the name of a resource (str) and the value indicates the cost of using this resource per time unit.""" @@ -71,7 +69,7 @@ def get_resource_cost_per_time_unit( class WithoutResourceCosts(WithResourceCosts): """A domain must inherit this class if there are no resource cost to consider.""" - def _get_resource_cost_per_time_unit(self) -> Dict[str, float]: + def _get_resource_cost_per_time_unit(self) -> dict[str, float]: cost_dict = {} for res in self.get_resource_types_names(): cost_dict[res] = 0.0 diff --git a/skdecide/builders/domain/scheduling/resource_renewability.py b/skdecide/builders/domain/scheduling/resource_renewability.py index 14a86454f9..0da633c2cb 100644 --- a/skdecide/builders/domain/scheduling/resource_renewability.py +++ b/skdecide/builders/domain/scheduling/resource_renewability.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Dict - from skdecide.builders.domain.scheduling.scheduling_domains_modelling import State __all__ = ["MixedRenewable", "RenewableOnly"] @@ -14,13 +12,13 @@ class MixedRenewable: """A domain must inherit this class if the resource available are non-renewable and renewable.""" - def get_resource_renewability(self) -> Dict[str, bool]: + def get_resource_renewability(self) -> dict[str, bool]: """ Return a dictionary where the key is a resource name (string) and the value whether this resource is renewable (True) or not (False).""" return self._get_resource_renewability() - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: """ Return a dictionary where the key is a resource name (string) and the value whether this resource is renewable (True) or not (False).""" @@ -68,7 +66,7 @@ def all_tasks_possible(self, state: State) -> bool: class RenewableOnly(MixedRenewable): """A domain must inherit this class if the resource available are ALL renewable.""" - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: """Return a dictionary where the key is a resource name (string) and the value whether this resource is renewable (True) or not (False).""" names = ( diff --git a/skdecide/builders/domain/scheduling/resource_type.py b/skdecide/builders/domain/scheduling/resource_type.py index fdbee3a3dc..ed3c6c6a00 100644 --- a/skdecide/builders/domain/scheduling/resource_type.py +++ b/skdecide/builders/domain/scheduling/resource_type.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Any, Dict, List - __all__ = [ "WithResourceTypes", "WithoutResourceTypes", @@ -18,11 +16,11 @@ class WithResourceTypes: """A domain must inherit this class if some of its resources are resource types.""" - def get_resource_types_names(self) -> List[str]: + def get_resource_types_names(self) -> list[str]: """Return the names (string) of all resource types as a list.""" return self._get_resource_types_names() - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: """Return the names (string) of all resource types as a list.""" raise NotImplementedError @@ -30,7 +28,7 @@ def _get_resource_types_names(self) -> List[str]: class WithoutResourceTypes(WithResourceTypes): """A domain must inherit this class if it only uses resource types.""" - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: """Return the names (string) of all resource types as a list.""" return [] @@ -38,20 +36,20 @@ def _get_resource_types_names(self) -> List[str]: class WithResourceUnits: """A domain must inherit this class if some of its resources are resource units.""" - def get_resource_units_names(self) -> List[str]: + def get_resource_units_names(self) -> list[str]: """Return the names (string) of all resource units as a list.""" return self._get_resource_units_names() - def _get_resource_units_names(self) -> List[str]: + def _get_resource_units_names(self) -> list[str]: """Return the names (string) of all resource units as a list.""" raise NotImplementedError - def get_resource_type_for_unit(self) -> Dict[str, str]: + def get_resource_type_for_unit(self) -> dict[str, str]: """Return a dictionary where the key is a resource unit name and the value a resource type name. An empty dictionary can be used if there are no resource unit matching a resource type.""" return self._get_resource_type_for_unit() - def _get_resource_type_for_unit(self) -> Dict[str, str]: + def _get_resource_type_for_unit(self) -> dict[str, str]: """Return a dictionary where the key is a resource unit name and the value a resource type name. An empty dictionary can be used if there are no resource unit matching a resource type.""" raise NotImplementedError @@ -60,18 +58,18 @@ def _get_resource_type_for_unit(self) -> Dict[str, str]: class SingleResourceUnit(WithResourceUnits): """A domain must inherit this class if there is no allocation to be done (i.e. there is a single resource).""" - def _get_resource_units_names(self) -> List[str]: + def _get_resource_units_names(self) -> list[str]: return ["single_resource"] - def _get_resource_type_for_unit(self) -> Dict[str, str]: + def _get_resource_type_for_unit(self) -> dict[str, str]: return {} class WithoutResourceUnit(SingleResourceUnit): """A domain must inherit this class if it only uses resource types.""" - def _get_resource_units_names(self) -> List[str]: + def _get_resource_units_names(self) -> list[str]: return [] - def _get_resource_type_for_unit(self) -> Dict[str, str]: + def _get_resource_type_for_unit(self) -> dict[str, str]: return {} diff --git a/skdecide/builders/domain/scheduling/scheduling_domains.py b/skdecide/builders/domain/scheduling/scheduling_domains.py index a96320bd85..3819b5c17e 100644 --- a/skdecide/builders/domain/scheduling/scheduling_domains.py +++ b/skdecide/builders/domain/scheduling/scheduling_domains.py @@ -5,9 +5,10 @@ from __future__ import annotations import random +from collections.abc import Iterable from enum import Enum from itertools import product -from typing import Dict, Iterable, List, Optional, Set, Tuple +from typing import Optional from skdecide import ( DiscreteDistribution, @@ -767,7 +768,7 @@ def update_resume_tasks_simulation(self, state: State, action: SchedulingAction) def check_if_action_can_be_started( self, state: State, action: SchedulingAction - ) -> Tuple[bool, Dict[str, int]]: + ) -> tuple[bool, dict[str, int]]: """Check if a start or resume action can be applied. It returns a boolean and a dictionary of resources to use.""" started_task = action.task if action.action == SchedulingActionEnum.START: @@ -795,7 +796,7 @@ def check_if_action_can_be_started( return b, resource_to_use def get_resource_used( - self, task: int, mode: int, resource_unit_names: Set[str], time_since_start: int + self, task: int, mode: int, resource_unit_names: set[str], time_since_start: int ): r_used = {} mode_details = self.get_tasks_modes() @@ -1107,11 +1108,11 @@ def _is_terminal(self, state: D.T_state) -> bool: ) # TODO, is there a cleaner way ? We can check completion of the sink task - def get_objectives(self) -> List[SchedulingObjectiveEnum]: + def get_objectives(self) -> list[SchedulingObjectiveEnum]: """Return the objectives to consider as a list. The items should be of SchedulingObjectiveEnum type.""" return self._get_objectives() - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: """Return the objectives to consider as a list. The items should be of SchedulingObjectiveEnum type.""" raise NotImplementedError @@ -1234,8 +1235,8 @@ def _get_elements(self) -> Iterable[T]: for choice in choices: if choice == SchedulingActionEnum.START: # task, mode, list of Ressources - task_possible_to_start: Dict[ - int, Dict[int, List[str]] + task_possible_to_start: dict[ + int, dict[int, list[str]] ] = self.domain.get_possible_starting_tasks(self.state) list_action += [ SchedulingAction( @@ -1314,8 +1315,8 @@ def _get_elements(self) -> Iterable[T]: for choice in choices: if choice == SchedulingActionEnum.START: # task, mode, list of Ressources - task_possible_to_start: Dict[ - int, Dict[int, List[str]] + task_possible_to_start: dict[ + int, dict[int, list[str]] ] = self.domain.get_possible_starting_tasks(self.state) for possible_to_start in task_possible_to_start: for mode in task_possible_to_start[possible_to_start]: @@ -1407,12 +1408,12 @@ def sample(self) -> T: random_choice = random.choice(choices) if random_choice in {SchedulingActionEnum.START, SchedulingActionEnum.RESUME}: if random_choice == SchedulingActionEnum.START: - task_possible_to_start: Dict[ - int, Dict[int, List[str]] + task_possible_to_start: dict[ + int, dict[int, list[str]] ] = self.domain.get_possible_starting_tasks(self.state) else: - task_possible_to_start: Dict[ - int, Dict[int, List[str]] + task_possible_to_start: dict[ + int, dict[int, list[str]] ] = self.domain.get_possible_resume_tasks(self.state) task_modes = [ (t, m) diff --git a/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py b/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py index 0f91ecb7f5..67709660f6 100644 --- a/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py +++ b/skdecide/builders/domain/scheduling/scheduling_domains_modelling.py @@ -4,20 +4,20 @@ from __future__ import annotations -from collections.abc import Collection +from collections.abc import Collection, Iterable from copy import copy, deepcopy from enum import Enum -from typing import Dict, Iterable, Optional, Set, Tuple, Union +from typing import Optional, Union from skdecide.builders.domain.scheduling.task import Task -def rebuild_tasks_complete_details_dict(state: State) -> Dict[int, Task]: +def rebuild_tasks_complete_details_dict(state: State) -> dict[int, Task]: tasks_complete_details = {p.value.id: p.value for p in state.tasks_complete_details} return tasks_complete_details -def rebuild_all_tasks_dict(state: State) -> Dict[int, Task]: +def rebuild_all_tasks_dict(state: State) -> dict[int, Task]: tasks_details = { task_id: Task(id=task_id, start=None, sampled_duration=None) for task_id in state.task_ids @@ -27,12 +27,12 @@ def rebuild_all_tasks_dict(state: State) -> Dict[int, Task]: return tasks_details -def rebuild_tasks_modes_dict(state: State) -> Dict[int, int]: +def rebuild_tasks_modes_dict(state: State) -> dict[int, int]: tasks_modes = {p.value[0]: p.value[1] for p in state.tasks_complete_mode} return tasks_modes -def rebuild_schedule_dict(state: State) -> Dict[int, Dict[str, int]]: +def rebuild_schedule_dict(state: State) -> dict[int, dict[str, int]]: schedule = { p.value.id: {"start_time": p.value.start, "end_time": p.value.end} for p in state.tasks_complete_details @@ -52,7 +52,7 @@ class SinglyLinkedList(Collection): def __init__(self, head=None): self.head = head - def push_front(self, value: Union[int, float, Task, Tuple[int, int]]): + def push_front(self, value: Union[int, float, Task, tuple[int, int]]): self.head = Node(value, self.head) def __iter__(self): @@ -129,26 +129,26 @@ class State: # TODO : code efficient hash/eq functions. will probably be mandatory in some planning algo. t: int - tasks_unsatisfiable: Set[int] - tasks_ongoing: Set[int] - tasks_complete: Set[int] - tasks_paused: Set[int] - tasks_progress: Dict[int, float] - tasks_mode: Dict[int, int] - resource_to_task: Dict[str, int] - resource_availability: Dict[str, int] - resource_used: Dict[str, int] - resource_used_for_task: Dict[int, Dict[str, int]] - tasks_details: Dict[ + tasks_unsatisfiable: set[int] + tasks_ongoing: set[int] + tasks_complete: set[int] + tasks_paused: set[int] + tasks_progress: dict[int, float] + tasks_mode: dict[int, int] + resource_to_task: dict[str, int] + resource_availability: dict[str, int] + resource_used: dict[str, int] + resource_used_for_task: dict[int, dict[str, int]] + tasks_details: dict[ int, Task ] # Use to store task stats, resource used etc... for post-processing purposes tasks_complete_details: SinglyLinkedList tasks_complete_progress: SinglyLinkedList tasks_complete_mode: SinglyLinkedList - _current_conditions: Set + _current_conditions: set # TODO : put the attributes in the __init__ ?! - def __init__(self, task_ids: Iterable[int], tasks_available: Set[int] = None): + def __init__(self, task_ids: Iterable[int], tasks_available: set[int] = None): """Initialize a scheduling state. # Parameters @@ -199,7 +199,7 @@ def copy(self): return s @property - def tasks_full_details(self) -> Dict[int, Task]: + def tasks_full_details(self) -> dict[int, Task]: return rebuild_all_tasks_dict(self) @property @@ -272,7 +272,7 @@ def __init__( action: SchedulingActionEnum, mode: Union[int, None], time_progress: bool, - resource_unit_names: Optional[Set[str]] = None, + resource_unit_names: Optional[set[str]] = None, ): self.task = task self.action = action diff --git a/skdecide/builders/domain/scheduling/skills.py b/skdecide/builders/domain/scheduling/skills.py index 589d788a2f..7f93a0a558 100644 --- a/skdecide/builders/domain/scheduling/skills.py +++ b/skdecide/builders/domain/scheduling/skills.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Any, Dict, List, Set +from typing import Any __all__ = ["WithResourceSkills", "WithoutResourceSkills"] @@ -13,7 +13,7 @@ class WithResourceSkills: """A domain must inherit this class if its resources (either resource types or resource units) have different set of skills.""" - def get_skills_names(self) -> Set[str]: + def get_skills_names(self) -> set[str]: """Return a list of all skill names as a list of str. Skill names are defined in the 2 dictionaries returned by the get_all_resources_skills and get_all_tasks_skills functions.""" all_names = set() @@ -29,35 +29,35 @@ def get_skills_names(self) -> Set[str]: all_names.add(key2) return all_names - def get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: + def get_all_resources_skills(self) -> dict[str, dict[str, Any]]: """Return a nested dictionary where the first key is the name of a resource type or resource unit and the second key is the name of a skill. The value defines the details of the skill. E.g. {unit: {skill: (detail of skill)}}""" return self._get_all_resources_skills() - def _get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: + def _get_all_resources_skills(self) -> dict[str, dict[str, Any]]: """Return a nested dictionary where the first key is the name of a resource type or resource unit and the second key is the name of a skill. The value defines the details of the skill. E.g. {unit: {skill: (detail of skill)}}""" raise NotImplementedError - def get_skills_of_resource(self, resource: str) -> Dict[str, Any]: + def get_skills_of_resource(self, resource: str) -> dict[str, Any]: """Return the skills of a given resource""" return self.get_all_resources_skills()[resource] - def get_all_tasks_skills(self) -> Dict[int, Dict[int, Dict[str, Any]]]: + def get_all_tasks_skills(self) -> dict[int, dict[int, dict[str, Any]]]: """Return a nested dictionary where the first key is the name of a task and the second key is the name of a skill. The value defines the details of the skill. E.g. {task: {skill: (detail of skill)}}""" return self._get_all_tasks_skills() - def _get_all_tasks_skills(self) -> Dict[int, Dict[int, Dict[str, Any]]]: + def _get_all_tasks_skills(self) -> dict[int, dict[int, dict[str, Any]]]: """Return a nested dictionary where the first key is the name of a task and the second key is the name of a skill. The value defines the details of the skill. E.g. {task: {skill: (detail of skill)}}""" raise NotImplementedError - def get_skills_of_task(self, task: int, mode: int) -> Dict[str, Any]: + def get_skills_of_task(self, task: int, mode: int) -> dict[str, Any]: """Return the skill requirements for a given task""" return { s: self.get_all_tasks_skills()[task][mode][s] @@ -65,7 +65,7 @@ def get_skills_of_task(self, task: int, mode: int) -> Dict[str, Any]: if self.get_all_tasks_skills()[task][mode][s] > 0 } - def find_one_ressource_to_do_one_task(self, task: int, mode: int) -> List[str]: + def find_one_ressource_to_do_one_task(self, task: int, mode: int) -> list[str]: """ For the common case when it is possible to do the task by one resource unit. For general case, it might just return no possible ressource unit. @@ -85,7 +85,7 @@ def find_one_ressource_to_do_one_task(self, task: int, mode: int) -> List[str]: return resources def check_if_skills_are_fulfilled( - self, task: int, mode: int, resource_used: Dict[str, int] + self, task: int, mode: int, resource_used: dict[str, int] ): skill_of_task = self.get_skills_of_task(task, mode) if len(skill_of_task) == 0: @@ -104,27 +104,27 @@ def check_if_skills_are_fulfilled( class WithoutResourceSkills(WithResourceSkills): """A domain must inherit this class if no resources skills have to be considered.""" - def _get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: + def _get_all_resources_skills(self) -> dict[str, dict[str, Any]]: """Return a nested dictionary where the first key is the name of a resource type or resource unit and the second key is the name of a skill. The value defines the details of the skill. E.g. {unit: {skill: (detail of skill)}}""" return {} - def get_skills_of_resource(self, resource: str) -> Dict[str, Any]: + def get_skills_of_resource(self, resource: str) -> dict[str, Any]: """Return the skills of a given resource""" return {} - def _get_all_tasks_skills(self) -> Dict[int, Dict[str, Any]]: + def _get_all_tasks_skills(self) -> dict[int, dict[str, Any]]: """Return a nested dictionary where the first key is the name of a task and the second key is the name of a skill. The value defines the details of the skill. E.g. {task: {skill: (detail of skill)}}""" return {} - def get_skills_of_task(self, task: int, mode: int) -> Dict[str, Any]: + def get_skills_of_task(self, task: int, mode: int) -> dict[str, Any]: """Return the skill requirements for a given task""" return {} def check_if_skills_are_fulfilled( - self, task: int, mode: int, resource_used: Dict[str, int] + self, task: int, mode: int, resource_used: dict[str, int] ): return True diff --git a/skdecide/builders/domain/scheduling/task.py b/skdecide/builders/domain/scheduling/task.py index c703e51fbe..0447dd7828 100644 --- a/skdecide/builders/domain/scheduling/task.py +++ b/skdecide/builders/domain/scheduling/task.py @@ -4,17 +4,7 @@ from __future__ import annotations -from enum import Enum -from typing import Dict, List, Optional - -# __all__ = ['Task', 'Status'] -# -# -# class Status(Enum): -# unreleased = 0 -# released = 1 -# ongoing = 2 -# complete = 3 +from typing import Optional class Task: @@ -24,8 +14,8 @@ class Task: end: int sampled_duration: int mode: int - paused: List[int] - resumed: List[int] + paused: list[int] + resumed: list[int] def __init__(self, id: int, start: int, sampled_duration: int): self.id = id diff --git a/skdecide/builders/domain/scheduling/task_duration.py b/skdecide/builders/domain/scheduling/task_duration.py index afd0a5f684..02c39f2eb7 100644 --- a/skdecide/builders/domain/scheduling/task_duration.py +++ b/skdecide/builders/domain/scheduling/task_duration.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Optional from skdecide.core import DiscreteDistribution, Distribution @@ -80,7 +80,7 @@ def get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: """Return the multivariate Distribution of the duration of the given task in the given mode. Multivariate seetings need to be provided.""" @@ -93,7 +93,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: """Return the multivariate Distribution of the duration of the given task in the given mode. Multivariate seetings need to be provided.""" @@ -115,7 +115,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: # TODO, problem here i think """Return the univariate Distribution of the duration of the given task in the given mode.""" raise NotImplementedError @@ -137,7 +137,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> DiscreteDistribution: """Return the Distribution of the duration of the given task in the given mode. The distribution returns values beween the defined lower and upper bounds.""" @@ -184,7 +184,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> DiscreteDistribution: """Return the Distribution of the duration of the given task in the given mode. The distribution is uniform between the defined lower and upper bounds.""" @@ -222,7 +222,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> DiscreteDistribution: """Return the Distribution of the duration of the given task in the given mode. as an Enumerable.""" @@ -273,7 +273,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ): """Return the Distribution of the duration of the given task in the given mode. Because the duration is deterministic, the distribution always returns the same duration.""" diff --git a/skdecide/builders/domain/scheduling/task_progress.py b/skdecide/builders/domain/scheduling/task_progress.py index a3f323ae65..e2dcd13f2d 100644 --- a/skdecide/builders/domain/scheduling/task_progress.py +++ b/skdecide/builders/domain/scheduling/task_progress.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Dict, List, Optional, Union +from typing import Optional __all__ = ["CustomTaskProgress", "DeterministicTaskProgress"] diff --git a/skdecide/builders/domain/scheduling/time_lag.py b/skdecide/builders/domain/scheduling/time_lag.py index 2fe05f7929..6c433262a6 100644 --- a/skdecide/builders/domain/scheduling/time_lag.py +++ b/skdecide/builders/domain/scheduling/time_lag.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Dict - __all__ = [ "TimeLag", "MinimumOnlyTimeLag", @@ -42,7 +40,7 @@ def __init__(self, maximum_time_lags): class WithTimeLag: """A domain must inherit this class if there are minimum and maximum time lags between some of its tasks.""" - def get_time_lags(self) -> Dict[int, Dict[int, TimeLag]]: + def get_time_lags(self) -> dict[int, dict[int, TimeLag]]: """ Return nested dictionaries where the first key is the id of a task (int) and the second key is the id of another task (int). @@ -65,7 +63,7 @@ def get_time_lags(self) -> Dict[int, Dict[int, TimeLag]]: """ return self._get_time_lags() - def _get_time_lags(self) -> Dict[int, Dict[int, TimeLag]]: + def _get_time_lags(self) -> dict[int, dict[int, TimeLag]]: """ Return nested dictionaries where the first key is the id of a task (int) and the second key is the id of another task (int). @@ -91,7 +89,7 @@ def _get_time_lags(self) -> Dict[int, Dict[int, TimeLag]]: class WithoutTimeLag(WithTimeLag): """A domain must inherit this class if there is no required time lag between its tasks.""" - def _get_time_lags(self) -> Dict[int, Dict[int, TimeLag]]: + def _get_time_lags(self) -> dict[int, dict[int, TimeLag]]: """ Return nested dictionaries where the first key is the id of a task (int) and the second key is the id of another task (int). diff --git a/skdecide/builders/domain/scheduling/time_windows.py b/skdecide/builders/domain/scheduling/time_windows.py index 0ac96cdd1a..3e679df270 100644 --- a/skdecide/builders/domain/scheduling/time_windows.py +++ b/skdecide/builders/domain/scheduling/time_windows.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Dict - __all__ = [ "TimeWindow", "ClassicTimeWindow", @@ -123,7 +121,7 @@ def __init__(self, max_horizon: int) -> None: class WithTimeWindow: """A domain must inherit this class if some tasks have time windows defined.""" - def get_time_window(self) -> Dict[int, TimeWindow]: + def get_time_window(self) -> dict[int, TimeWindow]: """ Return a dictionary where the key is the id of a task (int) and the value is a TimeWindow object. @@ -141,7 +139,7 @@ def get_time_window(self) -> Dict[int, TimeWindow]: """ return self._get_time_window() - def _get_time_window(self) -> Dict[int, TimeWindow]: + def _get_time_window(self) -> dict[int, TimeWindow]: """ Return a dictionary where the key is the id of a task (int) and the value is a TimeWindow object. @@ -164,7 +162,7 @@ def _get_time_window(self) -> Dict[int, TimeWindow]: class WithoutTimeWindow(WithTimeWindow): """A domain must inherit this class if none of the tasks have restrictions on start times or end times.""" - def _get_time_window(self) -> Dict[int, TimeWindow]: + def _get_time_window(self) -> dict[int, TimeWindow]: """ Return a dictionary where the key is the id of a task (int) and the value is a dictionary of EmptyTimeWindow object. diff --git a/skdecide/builders/solver/fromanystatesolvability.py b/skdecide/builders/solver/fromanystatesolvability.py index f0c61f198a..426096283e 100644 --- a/skdecide/builders/solver/fromanystatesolvability.py +++ b/skdecide/builders/solver/fromanystatesolvability.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Callable, Optional +from typing import TYPE_CHECKING, Optional from skdecide.builders.domain.initialization import Initializable from skdecide.core import D, autocast_all, autocastable diff --git a/skdecide/builders/solver/restorability.py b/skdecide/builders/solver/restorability.py index 3d3d93d7e1..487f6fe712 100644 --- a/skdecide/builders/solver/restorability.py +++ b/skdecide/builders/solver/restorability.py @@ -4,10 +4,6 @@ from __future__ import annotations -from typing import Callable - -from skdecide.core import D, autocastable - __all__ = ["Restorable"] diff --git a/skdecide/core.py b/skdecide/core.py index 278569d08c..095359aa07 100644 --- a/skdecide/core.py +++ b/skdecide/core.py @@ -8,20 +8,10 @@ import inspect import random import re +from collections import deque +from collections.abc import Callable, Iterable, Sequence from dataclasses import asdict, astuple, dataclass, replace -from typing import ( - Callable, - Deque, - Dict, - Generic, - Iterable, - List, - Optional, - Sequence, - Tuple, - TypeVar, - Union, -) +from typing import Generic, Optional, TypeVar, Union __all__ = [ "T", @@ -68,14 +58,14 @@ class D: # Tree (utility class) class Tree: - def __init__(self, type_: object, sub: List[Tree] = []): + def __init__(self, type_: object, sub: list[Tree] = []): self.type = type_ self.sub = sub # Castable (utility class) class Castable: - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): raise NotImplementedError @@ -218,7 +208,7 @@ def __init__(self, sample_function: Callable[[], T]) -> None: def sample(self) -> T: return self._sample_function() - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): def cast_sample_function(): result = self._sample_function() return cast(result, src_sub[0], dst_sub[0]) @@ -229,7 +219,7 @@ def cast_sample_function(): class DiscreteDistribution(Distribution[T]): """A discrete probability distribution.""" - def __init__(self, values: List[Tuple[T, float]]) -> None: + def __init__(self, values: list[tuple[T, float]]) -> None: """Initialize DiscreteDistribution. !!! tip @@ -253,7 +243,7 @@ def __init__(self, values: List[Tuple[T, float]]) -> None: def sample(self) -> T: return random.choices(self._population, self._weights)[0] - def get_values(self) -> List[Tuple[T, float]]: + def get_values(self) -> list[tuple[T, float]]: """Get the list of (element, probability) pairs. # Returns @@ -261,7 +251,7 @@ def get_values(self) -> List[Tuple[T, float]]: """ return self._values - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): return DiscreteDistribution( [(cast(e, src_sub[0], dst_sub[0]), p) for e, p in self._values] ) @@ -281,7 +271,7 @@ def __init__(self, value: T) -> None: def sample(self) -> T: return self._value - def get_values(self) -> List[Tuple[T, float]]: + def get_values(self) -> list[tuple[T, float]]: return [(self._value, 1.0)] def get_value(self) -> T: @@ -292,7 +282,7 @@ def get_value(self) -> T: """ return self._value - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): return SingleValueDistribution(cast(self._value, src_sub[0], dst_sub[0])) @@ -396,7 +386,7 @@ def __post_init__(self) -> None: else None ) - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): return EnvironmentOutcome( cast(self.observation, src_sub[0], dst_sub[0]), cast(self.value, src_sub[1], dst_sub[1]), @@ -443,7 +433,7 @@ def __post_init__(self) -> None: {k: None for k in self.state} if isinstance(self.state, dict) else None ) - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): return TransitionOutcome( cast(self.state, src_sub[0], dst_sub[0]), cast(self.value, src_sub[1], dst_sub[1]), @@ -453,12 +443,12 @@ def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): # Memory -class Memory(Deque[T]): +class Memory(deque[T]): pass # StrDict -class StrDict(Generic[T], Dict[str, T]): +class StrDict(Generic[T], dict[str, T]): """A dictionary with String keys (e.g. agent names).""" pass @@ -554,7 +544,7 @@ def check( def _is_constraint_dependent_on_next_state_(self) -> bool: return self._depends_on_next_state - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): def cast_check_function(memory, action, next_state): cast_memory = cast(memory, dst_sub[0], src_sub[0]) cast_action = cast(action, dst_sub[1], src_sub[1]) @@ -661,7 +651,7 @@ def get_bound(self) -> float: """ return self._bound - def _cast(self, src_sub: List[Tree], dst_sub: List[Tree]): + def _cast(self, src_sub: list[Tree], dst_sub: list[Tree]): def cast_evaluate_function(memory, action, next_state): cast_memory = cast(memory, dst_sub[0], src_sub[0]) cast_action = cast(action, dst_sub[1], src_sub[1]) @@ -694,17 +684,17 @@ def cast_evaluate_function(memory, action, next_state): (StrDict, StrDict): lambda obj, src, dst: { k: cast(v, src[0], dst[0]) for k, v in obj.items() }, - # (Set, Union): lambda obj, src, dst: cast(next(iter(obj)), src[0], dst[0]), - # (Union, Set): lambda obj, src, dst: {cast(obj, src[0], dst[0])}, - # (Set, Set): lambda obj, src, dst: {cast(x, src[0], dst[0]) for x in obj}, - (List, Union): lambda obj, src, dst: cast(obj[0], src[0], dst[0]), - (Union, List): lambda obj, src, dst: [cast(obj, src[0], dst[0])], - (List, List): lambda obj, src, dst: [cast(x, src[0], dst[0]) for x in obj], + # (set, Union): lambda obj, src, dst: cast(next(iter(obj)), src[0], dst[0]), + # (Union, set): lambda obj, src, dst: {cast(obj, src[0], dst[0])}, + # (set, set): lambda obj, src, dst: {cast(x, src[0], dst[0]) for x in obj}, + (list, Union): lambda obj, src, dst: cast(obj[0], src[0], dst[0]), + (Union, list): lambda obj, src, dst: [cast(obj, src[0], dst[0])], + (list, list): lambda obj, src, dst: [cast(x, src[0], dst[0]) for x in obj], (Union, Union): lambda obj, src, dst: cast(obj, src[0], dst[0]), (Optional, Optional): lambda obj, src, dst: cast(obj, src[0], dst[0]) if obj is not None else None, -} # (src_type, dst_type): (obj: src_type, src_sub_hintrees: List[Tree], dst_sub_hintrees: List[Tree]) -> dst_type +} # (src_type, dst_type): (obj: src_type, src_sub_hintrees: list[Tree], dst_sub_hintrees: list[Tree]) -> dst_type default_cast = ( lambda obj, src, dst: obj._cast(src, dst) if isinstance(obj, Castable) else obj @@ -731,7 +721,7 @@ def parse_hint(obj: object, hint: str, hint_obj: str) -> Tree: return Tree(type_, sub) -def get_args_dict(func: Callable, args: Tuple, kwargs: Dict) -> Dict: +def get_args_dict(func: Callable, args: tuple, kwargs: dict) -> dict: while hasattr( func, "__wrapped__" ): # get to the core function even if it was decorated diff --git a/skdecide/domains.py b/skdecide/domains.py index 0593a270ac..68ebd586cc 100644 --- a/skdecide/domains.py +++ b/skdecide/domains.py @@ -6,7 +6,7 @@ from __future__ import annotations import logging -from typing import Callable, NewType, Optional +from typing import NewType from skdecide.builders.domain.agent import MultiAgent, SingleAgent from skdecide.builders.domain.concurrency import Parallel, Sequential diff --git a/skdecide/hub/domain/flight_planning/aircraft_performance/base.py b/skdecide/hub/domain/flight_planning/aircraft_performance/base.py index 535183586e..8cd078734a 100644 --- a/skdecide/hub/domain/flight_planning/aircraft_performance/base.py +++ b/skdecide/hub/domain/flight_planning/aircraft_performance/base.py @@ -2,7 +2,7 @@ # typing import math from inspect import signature -from typing import Dict, Optional +from typing import Optional import numpy as np import openap @@ -33,7 +33,7 @@ def __init__(self, actype: str, perf_model: str = None): def compute_fuel_consumption( self, - values_current: Dict[str, float], + values_current: dict[str, float], delta_time: float, vs: Optional[float] = 0.0, ) -> float: @@ -54,7 +54,7 @@ def __init__(self, actype: str): def compute_fuel_consumption( self, - values_current: Dict[str, float], + values_current: dict[str, float], delta_time: float, vs: Optional[float] = 0.0, ) -> float: @@ -86,7 +86,7 @@ def __init__(self, actype: str): def compute_fuel_consumption( self, - values_current: Dict[str, float], + values_current: dict[str, float], delta_time: float, vs: Optional[float] = 0.0, ) -> float: diff --git a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/atmospheric_parameters.py b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/atmospheric_parameters.py index b864d34452..7b5daa166e 100644 --- a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/atmospheric_parameters.py +++ b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/atmospheric_parameters.py @@ -1,9 +1,6 @@ # math and data import math -# typing -from typing import Dict - import numpy as np from skdecide.hub.domain.flight_planning.aircraft_performance.poll_schumann_utils.parameters import ( @@ -180,14 +177,14 @@ def zero_lift_drag_coefficient(c_f: float, psi_0: float) -> float: def oswald_efficiency_factor( - c_drag_0: float, aircraft_parameters: Dict[str, float] + c_drag_0: float, aircraft_parameters: dict[str, float] ) -> float: """Calculate the Oswald efficiency factor. # Parameters c_drag_0 (float): Zero-lift drag coefficient, [:math:`-`] - aircraft_parameters (Dict[str, float]): + aircraft_parameters (dict[str, float]): Aircraft parameters. # Returns @@ -218,7 +215,7 @@ def _non_vortex_lift_dependent_drag_factor(c_drag_0: float, cos_sweep: float) -> def wave_drag_coefficient( - mach_num: float, c_lift: float, aircraft_parameters: Dict[str, float] + mach_num: float, c_lift: float, aircraft_parameters: dict[str, float] ) -> float: """Calculate the wave drag coefficient. @@ -227,7 +224,7 @@ def wave_drag_coefficient( Mach number, [:math:`-`] c_lift (float): Lift coefficient, [:math:`-`] - aircraft_parameters (Dict[str, float]): + aircraft_parameters (dict[str, float]): Aircraft parameters. # Returns @@ -344,7 +341,7 @@ def overall_propulsion_efficiency( mach_num: float, c_t: float, c_t_eta_b: float, - aircraft_parameters: Dict[str, float], + aircraft_parameters: dict[str, float], eta_over_eta_b_min: float, ) -> float: """Calculate overall propulsion efficiency. @@ -356,7 +353,7 @@ def overall_propulsion_efficiency( Thrust coefficient, [:math:`-`] c_t_eta_b (float): Thrust coefficient at maximum efficiency, [:math:`-`] - aircraft_parameters (Dict[str, float]): + aircraft_parameters (dict[str, float]): Aircraft parameters. eta_over_eta_b_min (float): Minimum engine efficiency, [:math:`-`] diff --git a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/jet.py b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/jet.py index 721083a828..5bd54060c2 100644 --- a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/jet.py +++ b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/jet.py @@ -47,7 +47,7 @@ def clip_mach_number( Maximum permitted operational Mach number for aircraft type. # Returns - Tuple[np.ndarray, np.ndarray]: Adjusted true airspeed and Mach number. + tuple[np.ndarray, np.ndarray]: Adjusted true airspeed and Mach number. """ mach_num = units.tas_to_mach_number(true_airspeed, air_temperature) diff --git a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/operational_limits.py b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/operational_limits.py index 69ccdc6e34..6fff99a480 100644 --- a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/operational_limits.py +++ b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/parameters/operational_limits.py @@ -1,6 +1,4 @@ # data -# typing -from typing import Dict import numpy as np @@ -60,7 +58,7 @@ def max_available_thrust_coefficient( air_temperature: float, mach_number: float, c_t_eta_b: float, - aircraft_parameters: Dict[str, float], + aircraft_parameters: dict[str, float], *, buffer: float = 0.05, ) -> float: diff --git a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/pollschumann.py b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/pollschumann.py index 0209a1f82b..d4f021d483 100644 --- a/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/pollschumann.py +++ b/skdecide/hub/domain/flight_planning/aircraft_performance/poll_schumann_utils/pollschumann.py @@ -2,7 +2,7 @@ import math # typing -from typing import Any, Dict, Optional +from typing import Optional import numpy as np @@ -52,14 +52,14 @@ def __init__(self, actype: str): def __call__( self, - values_current: Dict[str, float], + values_current: dict[str, float], delta_time: float, vs: Optional[float] = 0.0, ) -> float: """Compute fuel flow based on Poll-Schumann model. # Parameters - values_current (Dict[str, float]): + values_current (dict[str, float]): Dictionary with current values of altitude [:math:`ft`], speed [:math:`kts`], temperature [:math:`K`], and mass [:math:`Kg`]. delta_time (float): Time step in seconds [:math:`s`]. diff --git a/skdecide/hub/domain/flight_planning/domain.py b/skdecide/hub/domain/flight_planning/domain.py index 799469f4f5..b05edf607f 100644 --- a/skdecide/hub/domain/flight_planning/domain.py +++ b/skdecide/hub/domain/flight_planning/domain.py @@ -6,11 +6,10 @@ from math import asin, atan2, cos, radians, sin, sqrt # typing -from typing import Any, Callable, Dict, Optional, Tuple, Type, Union +from typing import Any, Optional, Union # plotting import matplotlib.pyplot as plt -import numpy as np import pandas as pd # aircraft performance model @@ -184,7 +183,7 @@ class State: """ trajectory: pd.DataFrame - pos: Tuple[int, int, int] + pos: tuple[int, int, int] def __init__(self, trajectory, pos): """Initialisation of a state @@ -363,7 +362,7 @@ class FlightPlanningDomain( T_state = State # Type of states T_observation = State # Type of observations - T_event = Tuple[H_Action, V_Action] # Type of events + T_event = tuple[H_Action, V_Action] # Type of events T_value = float # Type of transition values (rewards or costs) T_predicate = bool # Type of transition predicates (terminal states) T_info = None # Type of additional information in environment outcome @@ -386,8 +385,8 @@ def __init__( take_off_weight: Optional[int] = None, fuel_loaded: Optional[float] = None, fuel_loop: bool = False, - fuel_loop_solver_cls: Optional[Type[Solver]] = None, - fuel_loop_solver_kwargs: Optional[Dict[str, Any]] = None, + fuel_loop_solver_cls: Optional[type[Solver]] = None, + fuel_loop_solver_kwargs: Optional[dict[str, Any]] = None, fuel_loop_tol: float = 1e-3, climbing_slope: Optional[float] = None, descending_slope: Optional[float] = None, @@ -432,7 +431,7 @@ def __init__( Boolean to create a fuel loop to optimize the fuel loaded for the flight. Defaults to False fuel_loop_solver_cls (type[Solver], optional): Solver class used in the fuel loop. Defaults to LazyAstar. - fuel_loop_solver_kwargs (Dict[str, Any], optional): + fuel_loop_solver_kwargs (dict[str, Any], optional): Kwargs to initialize the solver used in the fuel loop. climbing_slope (float, optional): Climbing slope of the aircraft, has to be between 10.0 and 25.0. Defaults to None. @@ -1292,13 +1291,13 @@ def get_network(self): return self.network def flying( - self, from_: pd.DataFrame, to_: Tuple[float, float, int] + self, from_: pd.DataFrame, to_: tuple[float, float, int] ) -> pd.DataFrame: """Compute the trajectory of a flying object from a given point to a given point # Parameters from_ (pd.DataFrame): the trajectory of the object so far - to_ (Tuple[float, float]): the destination of the object + to_ (tuple[float, float]): the destination of the object # Returns pd.DataFrame: the final trajectory of the object @@ -1575,8 +1574,8 @@ def fuel_optimisation( actype: str, constraints: dict, weather_date: WeatherDate, - solver_cls: Type[Solver], - solver_kwargs: Dict[str, Any], + solver_cls: type[Solver], + solver_kwargs: dict[str, Any], max_steps: int = 100, fuel_tol: float = 1e-3, ) -> float: @@ -1605,7 +1604,7 @@ def fuel_optimisation( solver_cls (type[Solver]): Solver class used in the fuel loop. - solver_kwargs (Dict[str, Any]): + solver_kwargs (dict[str, Any]): Kwargs to initialize the solver used in the fuel loop. max_steps (int): diff --git a/skdecide/hub/domain/flight_planning/weather_interpolator/weather_tools/get_weather_noaa.py b/skdecide/hub/domain/flight_planning/weather_interpolator/weather_tools/get_weather_noaa.py index 875061db3d..374fbc5a7a 100644 --- a/skdecide/hub/domain/flight_planning/weather_interpolator/weather_tools/get_weather_noaa.py +++ b/skdecide/hub/domain/flight_planning/weather_interpolator/weather_tools/get_weather_noaa.py @@ -5,7 +5,7 @@ import os import urllib.request as request from functools import reduce -from typing import List, Optional +from typing import Optional import numpy as np @@ -31,7 +31,7 @@ def get_absolute_path(filename, relative_path): return os.path.abspath(os.path.join(os.path.dirname(filename), relative_path)) -def create_merged_matrix(list_files: List[str], params: Optional[List[str]]): +def create_merged_matrix(list_files: list[str], params: Optional[list[str]]): if params is None: params = ["u", "v", "t", "r"] diff --git a/skdecide/hub/domain/graph_domain/GraphDomain.py b/skdecide/hub/domain/graph_domain/GraphDomain.py index 03e3536bcf..2087bbecec 100644 --- a/skdecide/hub/domain/graph_domain/GraphDomain.py +++ b/skdecide/hub/domain/graph_domain/GraphDomain.py @@ -5,7 +5,8 @@ from __future__ import annotations import random -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union +from collections.abc import Iterable +from typing import Optional import networkx as nx @@ -40,7 +41,7 @@ def sample(self) -> T: def contains(self, x: T) -> bool: pass - def __init__(self, l: List[object]): + def __init__(self, l: list[object]): self.l = l def get_elements(self) -> Iterable[object]: @@ -64,11 +65,11 @@ class GraphDomainUncertain( def __init__( self, - next_state_map: Dict[ - D.T_state, Dict[D.T_event, Dict[D.T_state, Tuple[float, float]]] + next_state_map: dict[ + D.T_state, dict[D.T_event, dict[D.T_state, tuple[float, float]]] ], - state_terminal: Dict[D.T_state, bool], - state_goal: Dict[D.T_state, bool], + state_terminal: dict[D.T_state, bool], + state_goal: dict[D.T_state, bool], ): """ # Parameters @@ -152,9 +153,9 @@ class GraphDomain(DeterministicPlanningDomain): def __init__( self, - next_state_map: Dict[D.T_state, Dict[D.T_event, D.T_state]], - next_state_attributes: Dict[D.T_state, Dict[D.T_event, Dict[str, float]]], - targets: Optional[Set[D.T_state]] = None, + next_state_map: dict[D.T_state, dict[D.T_event, D.T_state]], + next_state_attributes: dict[D.T_state, dict[D.T_event, dict[str, float]]], + targets: Optional[set[D.T_state]] = None, attribute_weight="weight", ): """ diff --git a/skdecide/hub/domain/graph_domain/graph_domain_builders/DFS_Uncertain_Exploration.py b/skdecide/hub/domain/graph_domain/graph_domain_builders/DFS_Uncertain_Exploration.py index c4d8f71605..a8ad3a0cee 100644 --- a/skdecide/hub/domain/graph_domain/graph_domain_builders/DFS_Uncertain_Exploration.py +++ b/skdecide/hub/domain/graph_domain/graph_domain_builders/DFS_Uncertain_Exploration.py @@ -6,7 +6,7 @@ from heapq import heappop, heappush from itertools import count -from typing import Any, Dict, Optional, Tuple +from typing import Any, Optional from skdecide import D, GoalMDPDomain from skdecide.hub.domain.graph_domain.graph_domain_builders.GraphExploration import ( @@ -57,11 +57,11 @@ def build_graph_domain(self, init_state: Any = None) -> GraphDomainUncertain: nb_states = 1 nb_edges = 0 result = {initial_state} - next_state_map: Dict[ - D.T_state, Dict[D.T_event, Dict[D.T_state, Tuple[float, float]]] + next_state_map: dict[ + D.T_state, dict[D.T_event, dict[D.T_state, tuple[float, float]]] ] = {} - state_terminal: Dict[D.T_state, bool] = dict() - state_goal: Dict[D.T_state, bool] = dict() + state_terminal: dict[D.T_state, bool] = dict() + state_goal: dict[D.T_state, bool] = dict() state_terminal[initial_state] = self.domain.is_terminal(initial_state) state_goal[initial_state] = self.domain.is_goal(initial_state) while len(stack) > 0: diff --git a/skdecide/hub/domain/gym/gym.py b/skdecide/hub/domain/gym/gym.py index 564e22f7eb..8cae2bea2a 100644 --- a/skdecide/hub/domain/gym/gym.py +++ b/skdecide/hub/domain/gym/gym.py @@ -9,10 +9,11 @@ import random import struct from collections import OrderedDict +from collections.abc import Callable from copy import deepcopy from itertools import product from math import pi, tan -from typing import Any, Callable, List, Optional +from typing import Any, Optional import gymnasium as gym import numpy as np @@ -507,7 +508,7 @@ def nb_of_binary_features(self) -> int: ) ) - def binary_features(self, memory: D.T_memory[D.T_state]) -> List[bool]: + def binary_features(self, memory: D.T_memory[D.T_state]) -> list[bool]: """Transform state in a bit vector and call f on each true value of this vector # Parameters @@ -518,7 +519,7 @@ def binary_features(self, memory: D.T_memory[D.T_state]) -> List[bool]: memory = memory._state if isinstance(memory, GymDomainStateProxy) else memory return self._binary_features(self._gym_env.observation_space, memory) - def _binary_features(self, space: gym.spaces.Space, element: Any) -> List[bool]: + def _binary_features(self, space: gym.spaces.Space, element: Any) -> list[bool]: if isinstance(space, gym.spaces.box.Box): features = [] # compute the size of the bit vector encoding the largest float @@ -629,7 +630,7 @@ def elliptical_features(self, state: D.T_memory[D.T_state]): vS = np.array(self._get_variables(self._gym_env.observation_space, state)) return [f.evaluate(vS) for f in self._elliptical_features] - def _get_variables(self, space: gym.spaces.Space, element: Any) -> List: + def _get_variables(self, space: gym.spaces.Space, element: Any) -> list: if isinstance(space, gym.spaces.box.Box): var = [] for cell in np.nditer(element): diff --git a/skdecide/hub/domain/mastermind/mastermind.py b/skdecide/hub/domain/mastermind/mastermind.py index ff1831f96c..412df3ba46 100644 --- a/skdecide/hub/domain/mastermind/mastermind.py +++ b/skdecide/hub/domain/mastermind/mastermind.py @@ -5,7 +5,7 @@ # Original code by Patrik Haslum from __future__ import annotations -from typing import NamedTuple, Optional, Tuple +from typing import NamedTuple, Optional from skdecide import DiscreteDistribution, Distribution, GoalPOMDPDomain, Space, Value from skdecide.builders.domain import ( @@ -15,7 +15,7 @@ ) from skdecide.hub.space.gym import ListSpace, MultiDiscreteSpace -Row = Tuple[int] # a row of code pegs (solution or guess) +Row = tuple[int] # a row of code pegs (solution or guess) class Score(NamedTuple): diff --git a/skdecide/hub/domain/rcpsp/rcpsp_sk.py b/skdecide/hub/domain/rcpsp/rcpsp_sk.py index 5a49462602..27a6121fd8 100644 --- a/skdecide/hub/domain/rcpsp/rcpsp_sk.py +++ b/skdecide/hub/domain/rcpsp/rcpsp_sk.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional, Set, Union +from typing import Any, Optional, Union from skdecide import DiscreteDistribution, Distribution from skdecide.builders.domain.scheduling.modes import ( @@ -36,7 +36,7 @@ class MRCPSP(D): tasks_mode: dictionary giving details of resource consumption and duration for each tasks/modes : format is the following : {task_id: {mode_1: {"duration": 2, "res_1": 1}, mode_2: {"duration": 3, "res_2": 2}}} successors: dictionary of precedence constraint: - format is the following {task_id: List[task_id]}, where the values are the list of successor task of a given task_id + format is the following {task_id: list[task_id]}, where the values are the list of successor task of a given task_id max_horizon: the max horizon for scheduling resource_availability: for each resource, gives its (constant) capacity resource_renewable: for each resource, indicates if it's renewable or not @@ -44,13 +44,13 @@ class MRCPSP(D): def __init__( self, - resource_names: Optional[List[str]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + resource_names: Optional[list[str]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, int]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, int]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): self.resource_names = resource_names self.task_ids = task_ids @@ -75,19 +75,19 @@ def __init__( self.resource_renewable = resource_renewable self.initialize_domain() - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self.task_mode_dict - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return self.resource_renewable def _get_max_horizon(self) -> int: return self.max_horizon - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return self.successors - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self.task_ids def _get_task_duration( @@ -98,10 +98,10 @@ def _get_task_duration( def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: return self.resource_availability[resource] - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return self.resource_names - def _get_objectives(self) -> List[int]: + def _get_objectives(self) -> list[int]: return [SchedulingObjectiveEnum.MAKESPAN] @@ -118,7 +118,7 @@ class MRCPSPCalendar(D): tasks_mode: dictionary giving details of resource consumption and duration for each tasks/modes : format is the following : {task_id: {mode_1: {"duration": 2, "res_1": 1}, mode_2: {"duration": 3, "res_2": 2}}} successors: dictionary of precedence constraint: - format is the following {task_id: List[task_id]}, where the values are the list of successor task of a given task_id + format is the following {task_id: list[task_id]}, where the values are the list of successor task of a given task_id max_horizon: the max horizon for scheduling resource_availability: for each resource, gives its capacity through time as a list of integer resource_renewable: for each resource, indicates if it's renewable or not @@ -129,13 +129,13 @@ def _get_quantity_resource(self, resource: str, time: int, **kwargs) -> int: def __init__( self, - resource_names: Optional[List[str]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + resource_names: Optional[list[str]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, List[int]]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, list[int]]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): self.resource_names = resource_names self.task_ids = task_ids @@ -164,19 +164,19 @@ def __init__( self.resource_renewable = resource_renewable self.initialize_domain() - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self.task_mode_dict - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return self.resource_renewable def _get_max_horizon(self) -> int: return self.max_horizon - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return self.successors - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self.task_ids def _get_task_duration( @@ -187,10 +187,10 @@ def _get_task_duration( def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: return self.original_resource_availability[resource] - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return self.resource_names - def _get_objectives(self) -> List[int]: + def _get_objectives(self) -> list[int]: return [SchedulingObjectiveEnum.MAKESPAN] @@ -203,7 +203,7 @@ class RCPSP(MRCPSP, SingleMode): tasks_mode: dictionary giving details of resource consumption and duration for each tasks : format is the following : {task_id: {1: {"duration": 2, "res_1": 1}}, only 1 mode in this template successors: dictionary of precedence constraint: - format is the following {task_id: List[task_id]}, where the values are the list of successor task of a given task_id + format is the following {task_id: list[task_id]}, where the values are the list of successor task of a given task_id max_horizon: the max horizon for scheduling resource_availability: for each resource, gives its constant capacity resource_renewable: for each resource, indicates if it's renewable or not @@ -211,13 +211,13 @@ class RCPSP(MRCPSP, SingleMode): def __init__( self, - resource_names: Optional[List[str]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + resource_names: Optional[list[str]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, int]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, int]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): MRCPSP.__init__( self, @@ -233,7 +233,7 @@ def __init__( t: self.task_mode_dict[t][1] for t in self.task_mode_dict } - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return self.tasks_modes_rcpsp @@ -246,7 +246,7 @@ class RCPSPCalendar(MRCPSPCalendar, SingleMode): tasks_mode: dictionary giving details of resource consumption and duration for each tasks : format is the following : {task_id: {1: {"duration": 2, "res_1": 1}}, only 1 mode in this template successors: dictionary of precedence constraint: - format is the following {task_id: List[task_id]}, where the values are the list of successor task of a given task_id + format is the following {task_id: list[task_id]}, where the values are the list of successor task of a given task_id max_horizon: the max horizon for scheduling resource_availability: for each resource, gives its capacity through time resource_renewable: for each resource, indicates if it's renewable or not @@ -254,13 +254,13 @@ class RCPSPCalendar(MRCPSPCalendar, SingleMode): def __init__( self, - resource_names: Optional[List[str]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + resource_names: Optional[list[str]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, List[int]]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, list[int]]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): MRCPSPCalendar.__init__( self, @@ -276,7 +276,7 @@ def __init__( t: self.task_mode_dict[t][1] for t in self.task_mode_dict } - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return self.tasks_modes_rcpsp @@ -290,7 +290,7 @@ class Stochastic_RCPSP(MultiModeRCPSP_Stochastic_Durations): format is the following : {task_id: {1: {"res_1": 1}, 2: {"res_1": 2}} duration_distribution: dictionary giving distribution of task duration function of mode. successors: dictionary of precedence constraint: - format is the following {task_id: List[task_id]}, where the values are the list of successor task of a given task_id + format is the following {task_id: list[task_id]}, where the values are the list of successor task of a given task_id max_horizon: the max horizon for scheduling resource_availability: for each resource, gives its constant capacity resource_renewable: for each resource, indicates if it's renewable or not @@ -299,16 +299,16 @@ class Stochastic_RCPSP(MultiModeRCPSP_Stochastic_Durations): def _get_max_horizon(self) -> int: return self.max_horizon - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return self.successors - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self.task_ids - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self.task_mode_dict def _get_task_duration_distribution( @@ -316,28 +316,28 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: return self.duration_distribution[task][mode] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: return self.resource_availability[resource] - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return self.resource_names def __init__( self, - resource_names: Optional[List[str]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, ModeConsumption]]] = None, + resource_names: Optional[list[str]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, ModeConsumption]]] = None, duration_distribution: Optional[ - Dict[int, Dict[int, DiscreteDistribution]] + dict[int, dict[int, DiscreteDistribution]] ] = None, - successors: Optional[Dict[int, List[int]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, int]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, int]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): self.resource_names = resource_names self.task_ids = task_ids @@ -352,7 +352,7 @@ def __init__( self.initialize_domain() -def build_stochastic_from_deterministic(rcpsp: MRCPSP, task_to_noise: Set[int] = None): +def build_stochastic_from_deterministic(rcpsp: MRCPSP, task_to_noise: set[int] = None): if task_to_noise is None: task_to_noise = set(rcpsp.get_tasks_ids()) duration_distribution = {} @@ -438,7 +438,7 @@ class SMRCPSPCalendar(D): format is the following : {task_id: {1: {"res_1": 1}, 2: {"res_1": 2}} duration_distribution: dictionary giving distribution of task duration function of mode. successors: dictionary of precedence constraint: - format is the following {task_id: List[task_id]}, where the values are the list of successor task of a given task_id + format is the following {task_id: list[task_id]}, where the values are the list of successor task of a given task_id max_horizon: the max horizon for scheduling resource_availability: for each resource, gives its variable capacity resource_renewable: for each resource, indicates if it's renewable or not @@ -449,7 +449,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: return self.duration_distribution[task][mode] @@ -458,16 +458,16 @@ def _get_quantity_resource(self, resource: str, time: int, **kwargs) -> int: def __init__( self, - resource_names: Optional[List[str]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + resource_names: Optional[list[str]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, duration_distribution: Optional[ - Dict[int, Dict[int, DiscreteDistribution]] + dict[int, dict[int, DiscreteDistribution]] ] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, List[int]]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, list[int]]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): self.resource_names = resource_names self.task_ids = task_ids @@ -493,19 +493,19 @@ def __init__( self.duration_distribution = duration_distribution self.initialize_domain() - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self.task_mode_dict - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return self.resource_renewable def _get_max_horizon(self) -> int: return self.max_horizon - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return self.successors - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self.task_ids def _get_task_duration( @@ -517,10 +517,10 @@ def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: # return self.resource_availability[resource] return self.original_resource_availability[resource] - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return self.resource_names - def _get_objectives(self) -> List[int]: + def _get_objectives(self) -> list[int]: return [SchedulingObjectiveEnum.MAKESPAN] @@ -541,16 +541,16 @@ class MSRCPSP(D): def __init__( self, - skills_names: Optional[List[str]] = None, - resource_unit_names: Optional[List[str]] = None, - resource_type_names: Optional[List[str]] = None, - resource_skills: Optional[Dict[str, Dict[str, Any]]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + skills_names: Optional[list[str]] = None, + resource_unit_names: Optional[list[str]] = None, + resource_type_names: Optional[list[str]] = None, + resource_skills: Optional[dict[str, dict[str, Any]]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, int]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, int]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): self.skills_set = set(skills_names) self.resource_unit_names = resource_unit_names @@ -585,14 +585,14 @@ def __init__( self.resource_renewable = resource_renewable self.initialize_domain() - def _get_resource_units_names(self) -> List[str]: + def _get_resource_units_names(self) -> list[str]: """Return the names (string) of all resource units as a list.""" return self.resource_unit_names - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return self.resource_type_names - def _get_resource_type_for_unit(self) -> Dict[str, str]: + def _get_resource_type_for_unit(self) -> dict[str, str]: """Return a dictionary where the key is a resource unit name and the value a resource type name. An empty dictionary can be used if there are no resource unit matching a resource type.""" return None @@ -600,13 +600,13 @@ def _get_resource_type_for_unit(self) -> Dict[str, str]: def get_max_horizon(self) -> int: return self.max_horizon - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self.task_mode_dict - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return self.successors - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self.task_ids def _get_task_duration( @@ -617,16 +617,16 @@ def _get_task_duration( def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: return self.resource_availability[resource] - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return self.resource_renewable - def _get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: + def _get_all_resources_skills(self) -> dict[str, dict[str, Any]]: return self.resource_skills - def _get_all_tasks_skills(self) -> Dict[int, Dict[int, Dict[str, Any]]]: + def _get_all_tasks_skills(self) -> dict[int, dict[int, dict[str, Any]]]: return self.task_skills_dict - def _get_objectives(self) -> List[int]: + def _get_objectives(self) -> list[int]: return [SchedulingObjectiveEnum.MAKESPAN] @@ -648,16 +648,16 @@ def _get_quantity_resource(self, resource: str, time: int, **kwargs) -> int: def __init__( self, - skills_names: Optional[List[str]] = None, - resource_unit_names: Optional[List[str]] = None, - resource_type_names: Optional[List[str]] = None, - resource_skills: Optional[Dict[str, Dict[str, Any]]] = None, - task_ids: Optional[List[int]] = None, - tasks_mode: Optional[Dict[int, Dict[int, Dict[str, int]]]] = None, - successors: Optional[Dict[int, List[int]]] = None, + skills_names: Optional[list[str]] = None, + resource_unit_names: Optional[list[str]] = None, + resource_type_names: Optional[list[str]] = None, + resource_skills: Optional[dict[str, dict[str, Any]]] = None, + task_ids: Optional[list[int]] = None, + tasks_mode: Optional[dict[int, dict[int, dict[str, int]]]] = None, + successors: Optional[dict[int, list[int]]] = None, max_horizon: Optional[int] = None, - resource_availability: Optional[Dict[str, List[int]]] = None, - resource_renewable: Optional[Dict[str, bool]] = None, + resource_availability: Optional[dict[str, list[int]]] = None, + resource_renewable: Optional[dict[str, bool]] = None, ): self.skills_set = set(skills_names) self.resource_unit_names = resource_unit_names @@ -692,14 +692,14 @@ def __init__( self.resource_renewable = resource_renewable self.initialize_domain() - def _get_resource_units_names(self) -> List[str]: + def _get_resource_units_names(self) -> list[str]: """Return the names (string) of all resource units as a list.""" return self.resource_unit_names - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return self.resource_type_names - def _get_resource_type_for_unit(self) -> Dict[str, str]: + def _get_resource_type_for_unit(self) -> dict[str, str]: """Return a dictionary where the key is a resource unit name and the value a resource type name. An empty dictionary can be used if there are no resource unit matching a resource type.""" return None @@ -707,13 +707,13 @@ def _get_resource_type_for_unit(self) -> Dict[str, str]: def get_max_horizon(self) -> int: return self.max_horizon - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return self.task_mode_dict - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return self.successors - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return self.task_ids def _get_task_duration( @@ -724,14 +724,14 @@ def _get_task_duration( def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: return self.resource_availability[resource] - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return self.resource_renewable - def _get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: + def _get_all_resources_skills(self) -> dict[str, dict[str, Any]]: return self.resource_skills - def _get_all_tasks_skills(self) -> Dict[int, Dict[int, Dict[str, Any]]]: + def _get_all_tasks_skills(self) -> dict[int, dict[int, dict[str, Any]]]: return self.task_skills_dict - def _get_objectives(self) -> List[int]: + def _get_objectives(self) -> list[int]: return [SchedulingObjectiveEnum.MAKESPAN] diff --git a/skdecide/hub/domain/up/up.py b/skdecide/hub/domain/up/up.py index c4bea3af98..e8facb5a00 100644 --- a/skdecide/hub/domain/up/up.py +++ b/skdecide/hub/domain/up/up.py @@ -2,7 +2,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from typing import Dict, List, Optional, Tuple, Union +from typing import Optional, Union import numpy as np import unified_planning as up @@ -86,7 +86,7 @@ def __init__( self, up_action: Union[InstantaneousAction, ActionInstance], ungrounded_action: InstantaneousAction = None, - orig_params: Tuple[FNode, ...] = None, + orig_params: tuple[FNode, ...] = None, ): if not isinstance(up_action, (InstantaneousAction, ActionInstance)): raise RuntimeError( @@ -111,7 +111,7 @@ def up_action(self) -> InstantaneousAction: @property def up_parameters( self, - ) -> Union[List[up.model.parameter.Parameter], Tuple[up.model.FNode, ...]]: + ) -> Union[list[up.model.parameter.Parameter], tuple[up.model.FNode, ...]]: return ( self._orig_params if self._orig_params is not None @@ -147,7 +147,7 @@ def __str__(self) -> str: class D(DeterministicPlanningDomain): - T_state = Union[SkUPState, Dict, ArrayLike] # Type of states + T_state = Union[SkUPState, dict, ArrayLike] # Type of states T_observation = T_state # Type of observations T_event = SkUPAction # Type of events T_value = float # Type of transition values (rewards or costs) @@ -164,7 +164,7 @@ class UPDomain(D): def __init__( self, problem: Problem, - fluent_domains: Dict[FNode, Tuple[Union[int, float], Union[int, float]]] = None, + fluent_domains: dict[FNode, tuple[Union[int, float], Union[int, float]]] = None, state_encoding: str = "native", action_encoding: str = "native", **simulator_params, diff --git a/skdecide/hub/solver/aostar/aostar.py b/skdecide/hub/solver/aostar/aostar.py index 315d1320ca..04965b50b2 100644 --- a/skdecide/hub/solver/aostar/aostar.py +++ b/skdecide/hub/solver/aostar/aostar.py @@ -6,7 +6,7 @@ import os import sys -from typing import Callable, Dict, Set, Tuple +from collections.abc import Callable from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( FloatHyperparameter, @@ -229,12 +229,12 @@ def get_nb_explored_states(self) -> int: """ return self._solver.get_nb_explored_states() - def get_explored_states(self) -> Set[D.T_agent[D.T_observation]]: + def get_explored_states(self) -> set[D.T_agent[D.T_observation]]: """Get the set of states present in the search graph (i.e. the graph's state nodes minus the nodes' encapsulation and their children) # Returns - Set[D.T_agent[D.T_observation]]: Set of states present in the search graph + set[D.T_agent[D.T_observation]]: Set of states present in the search graph """ return self._solver.get_explored_states() @@ -269,9 +269,9 @@ def get_solving_time(self) -> int: def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], + tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: """Get the (partial) solution policy defined for the states for which the Q-value has been updated at least once (which is optimal for @@ -281,7 +281,7 @@ def get_policy( Only defined over the states reachable from the root solving state # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: Mapping from states to pairs of action and best Q-value """ return self._solver.get_policy() diff --git a/skdecide/hub/solver/ars/ars.py b/skdecide/hub/solver/ars/ars.py index d847d7067f..c58a4fac43 100755 --- a/skdecide/hub/solver/ars/ars.py +++ b/skdecide/hub/solver/ars/ars.py @@ -4,8 +4,7 @@ from __future__ import annotations -from collections.abc import Iterable -from typing import Callable +from collections.abc import Callable, Iterable import gymnasium as gym import numpy as np diff --git a/skdecide/hub/solver/astar/astar.py b/skdecide/hub/solver/astar/astar.py index 1b7aabcb7b..dbed2a71e5 100644 --- a/skdecide/hub/solver/astar/astar.py +++ b/skdecide/hub/solver/astar/astar.py @@ -6,7 +6,7 @@ import os import sys -from typing import Callable, Dict, List, Set, Tuple +from collections.abc import Callable from skdecide import Domain, Solver, hub from skdecide.builders.domain import ( @@ -203,12 +203,12 @@ def get_nb_explored_states(self) -> int: """ return self._solver.get_nb_explored_states() - def get_explored_states(self) -> Set[D.T_agent[D.T_observation]]: + def get_explored_states(self) -> set[D.T_agent[D.T_observation]]: """Get the set of states present in the search graph (i.e. the graph's state nodes minus the nodes' encapsulation and their neighbors) # Returns - Set[D.T_agent[D.T_observation]]: Set of states present in the search graph + set[D.T_agent[D.T_observation]]: Set of states present in the search graph """ return self._solver.get_explored_states() @@ -243,8 +243,8 @@ def get_solving_time(self) -> int: def get_plan( self, observation: D.T_agent[D.T_observation] - ) -> List[ - Tuple[ + ) -> list[ + tuple[ D.T_agent[D.T_observation], D.T_agent[D.T_concurrency[D.T_event]], D.T_value, @@ -262,7 +262,7 @@ def get_plan( to a goal state is requested # Returns - List[ Tuple[ D.T_agent[D.T_observation], D.T_agent[D.T_concurrency[D.T_event]], D.T_value, ] ]: + list[ tuple[ D.T_agent[D.T_observation], D.T_agent[D.T_concurrency[D.T_event]], D.T_value, ] ]: Sequence of tuples of state, action and transition cost (computed as the difference of g-scores between this state and the next one) visited along the execution of the plan @@ -271,9 +271,9 @@ def get_plan( def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], + tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: """Get the (partial) solution policy defined for the states for which a solution plan that goes through them has been previously computed at @@ -283,7 +283,7 @@ def get_policy( Only defined over the states reachable from the root solving state # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: Mapping from states to pairs of action and minimum cost-to-go """ return self._solver.get_policy() diff --git a/skdecide/hub/solver/bfws/bfws.py b/skdecide/hub/solver/bfws/bfws.py index 7b747c8b14..af18ef8d6c 100644 --- a/skdecide/hub/solver/bfws/bfws.py +++ b/skdecide/hub/solver/bfws/bfws.py @@ -6,7 +6,8 @@ import os import sys -from typing import Any, Callable, Dict, List, Set, Tuple +from collections.abc import Callable +from typing import Any from skdecide import Domain, Solver, hub from skdecide.builders.domain import ( @@ -212,12 +213,12 @@ def get_nb_explored_states(self) -> int: """ return self._solver.get_nb_explored_states() - def get_explored_states(self) -> Set[D.T_agent[D.T_observation]]: + def get_explored_states(self) -> set[D.T_agent[D.T_observation]]: """Get the set of states present in the search graph (i.e. the graph's state nodes minus the nodes' encapsulation and their neighbors) # Returns - Set[D.T_agent[D.T_observation]]: Set of states present in the search graph + set[D.T_agent[D.T_observation]]: Set of states present in the search graph """ return self._solver.get_explored_states() @@ -252,8 +253,8 @@ def get_solving_time(self) -> int: def get_plan( self, observation: D.T_agent[D.T_observation] - ) -> List[ - Tuple[ + ) -> list[ + tuple[ D.T_agent[D.T_observation], D.T_agent[D.T_concurrency[D.T_event]], D.T_value, @@ -271,7 +272,7 @@ def get_plan( to a goal state is requested # Returns - List[ Tuple[ D.T_agent[D.T_observation], D.T_agent[D.T_concurrency[D.T_event]], D.T_value, ] ]: + list[ tuple[ D.T_agent[D.T_observation], D.T_agent[D.T_concurrency[D.T_event]], D.T_value, ] ]: Sequence of tuples of state, action and transition cost (computed as the difference of g-scores between this state and the next one) visited along the execution of the plan @@ -280,9 +281,9 @@ def get_plan( def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], + tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: """Get the (partial) solution policy defined for the states for which a solution plan that goes through them has been previously computed at @@ -292,7 +293,7 @@ def get_policy( Only defined over the states reachable from the root solving state # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: Mapping from states to pairs of action and minimum cost-to-go """ return self._solver.get_policy() diff --git a/skdecide/hub/solver/cgp/cgp.py b/skdecide/hub/solver/cgp/cgp.py index 5f22cb7d0b..483e23aad8 100755 --- a/skdecide/hub/solver/cgp/cgp.py +++ b/skdecide/hub/solver/cgp/cgp.py @@ -4,8 +4,7 @@ from __future__ import annotations -from collections.abc import Iterable -from typing import Callable +from collections.abc import Callable, Iterable import gymnasium as gym import numpy as np diff --git a/skdecide/hub/solver/cgp/pycgp/cgpes.py b/skdecide/hub/solver/cgp/pycgp/cgpes.py index f5a0a1d96b..6be9681fe7 100644 --- a/skdecide/hub/solver/cgp/pycgp/cgpes.py +++ b/skdecide/hub/solver/cgp/pycgp/cgpes.py @@ -5,7 +5,8 @@ from __future__ import annotations # allow using CGPWrapper in annotations import os -from typing import TYPE_CHECKING, Callable +from collections.abc import Callable +from typing import TYPE_CHECKING import numpy as np from joblib import Parallel, delayed diff --git a/skdecide/hub/solver/do_solver/do_solver_scheduling.py b/skdecide/hub/solver/do_solver/do_solver_scheduling.py index 67b16434c3..a723bc6bd2 100644 --- a/skdecide/hub/solver/do_solver/do_solver_scheduling.py +++ b/skdecide/hub/solver/do_solver/do_solver_scheduling.py @@ -4,9 +4,10 @@ from __future__ import annotations +from collections.abc import Callable from copy import deepcopy from enum import Enum -from typing import Any, Callable, Dict, Optional, Tuple, Type, Union +from typing import Any, Optional, Union from discrete_optimization.generic_tools.callbacks.callback import Callback from discrete_optimization.generic_tools.do_problem import Problem @@ -63,9 +64,9 @@ class SolvingMethod(Enum): def build_solver( solving_method: Optional[SolvingMethod], - solver_type: Optional[Type[SolverDO]], + solver_type: Optional[type[SolverDO]], do_domain: Problem, -) -> Tuple[Type[SolverDO], Dict[str, Any]]: +) -> tuple[type[SolverDO], dict[str, Any]]: """Build the discrete-optimization solver for a given solving method # Parameters @@ -195,10 +196,10 @@ def __init__( domain_factory: Callable[[], Domain], policy_method_params: Optional[PolicyMethodParams] = None, method: Optional[SolvingMethod] = None, - do_solver_type: Optional[Type[SolverDO]] = None, - dict_params: Optional[Dict[Any, Any]] = None, + do_solver_type: Optional[type[SolverDO]] = None, + dict_params: Optional[dict[Any, Any]] = None, callback: Callable[[DOSolver], bool] = lambda solver: False, - policy_method_params_kwargs: Optional[Dict[str, Any]] = None, + policy_method_params_kwargs: Optional[dict[str, Any]] = None, ): Solver.__init__(self, domain_factory=domain_factory) self.callback = callback diff --git a/skdecide/hub/solver/do_solver/gphh.py b/skdecide/hub/solver/do_solver/gphh.py index f0bac94a7c..3a869b0d76 100644 --- a/skdecide/hub/solver/do_solver/gphh.py +++ b/skdecide/hub/solver/do_solver/gphh.py @@ -6,8 +6,9 @@ import operator import random +from collections.abc import Callable from enum import Enum -from typing import Any, Callable, Dict, List, Optional, Set +from typing import Any, Optional import numpy as np from deap import algorithms, creator, gp, tools @@ -285,7 +286,7 @@ class ParametersGPHH(Hyperparametrizable): ), ] + PolicyMethodParams.hyperparameters - set_feature: Set[FeatureEnum] = None + set_feature: set[FeatureEnum] = None set_primitves: PrimitiveSet = None tournament_ratio: float = None pop_size: int = None @@ -426,7 +427,7 @@ def fast_test(): ) @staticmethod - def default_for_set_features(set_feature: Set[FeatureEnum]): + def default_for_set_features(set_feature: set[FeatureEnum]): pset = PrimitiveSet("main", len(set_feature)) pset.addPrimitive(operator.add, 2) pset.addPrimitive(operator.sub, 2) @@ -464,7 +465,7 @@ class GPHH(Solver, DeterministicPolicies): ) ] - training_domains: List[T_domain] + training_domains: list[T_domain] verbose: bool weight: int pset: PrimitiveSet @@ -473,22 +474,22 @@ class GPHH(Solver, DeterministicPolicies): params_gphh: ParametersGPHH # policy: GPHHPolicy evaluation_method: EvaluationGPHH - reference_permutations: Dict + reference_permutations: dict permutation_distance: PermutationDistance def __init__( self, domain_factory: Callable[[], SchedulingDomain], - training_domains: List[T_domain], + training_domains: list[T_domain], domain_model: SchedulingDomain, weight: int, - # set_feature: Set[FeatureEnum]=None, + # set_feature: set[FeatureEnum]=None, params_gphh: Optional[ParametersGPHH] = None, reference_permutations=None, # reference_makespans=None, training_domains_names=None, verbose: bool = False, - params_gphh_kwargs: Optional[Dict[str, Any]] = None, + params_gphh_kwargs: Optional[dict[str, Any]] = None, ): """Genetic Programming based Hyper-Heuristics @@ -835,7 +836,7 @@ def __init__( domain: SchedulingDomain, domain_model: SchedulingDomain, func_heuristic, - features: List[FeatureEnum] = None, + features: list[FeatureEnum] = None, params_gphh=None, recompute_cpm=True, cpm_data=None, @@ -990,7 +991,7 @@ def __init__( func_heuristics, pool_aggregation_method: PoolAggregationMethod = PoolAggregationMethod.MEAN, remove_extremes_values: int = 0, - features: List[FeatureEnum] = None, + features: list[FeatureEnum] = None, params_gphh=None, ): self.domain = domain diff --git a/skdecide/hub/solver/do_solver/sgs_policies.py b/skdecide/hub/solver/do_solver/sgs_policies.py index 78648552a0..df66750f06 100644 --- a/skdecide/hub/solver/do_solver/sgs_policies.py +++ b/skdecide/hub/solver/do_solver/sgs_policies.py @@ -6,7 +6,7 @@ from enum import Enum from functools import partial -from typing import Dict, List, Optional, Union +from typing import Optional, Union from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( EnumHyperparameter, @@ -115,13 +115,13 @@ def __init__( self, domain: SchedulingDomain, policy_method_params: PolicyMethodParams, - permutation_task: List[int], - modes_dictionnary: Dict[int, int], + permutation_task: list[int], + modes_dictionnary: dict[int, int], schedule: Optional[ - Dict[int, Dict[str, int]] + dict[int, dict[str, int]] ] = None, # {id: {"start_time":, "end_time"}} - resource_allocation: Optional[Dict[int, List[str]]] = None, - resource_allocation_priority: Optional[Dict[int, List[str]]] = None, + resource_allocation: Optional[dict[int, list[str]]] = None, + resource_allocation_priority: Optional[dict[int, list[str]]] = None, ): self.domain = domain self.policy_method_params = policy_method_params diff --git a/skdecide/hub/solver/ilaostar/ilaostar.py b/skdecide/hub/solver/ilaostar/ilaostar.py index 1b9b44d992..927635e536 100644 --- a/skdecide/hub/solver/ilaostar/ilaostar.py +++ b/skdecide/hub/solver/ilaostar/ilaostar.py @@ -6,7 +6,7 @@ import os import sys -from typing import Callable, Dict, Set, Tuple +from collections.abc import Callable from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( FloatHyperparameter, @@ -221,12 +221,12 @@ def get_nb_of_explored_states(self) -> int: """ return self._solver.get_nb_of_explored_states() - def get_explored_states(self) -> Set[D.T_agent[D.T_observation]]: + def get_explored_states(self) -> set[D.T_agent[D.T_observation]]: """Get the set of states present in the search graph (i.e. the graph's state nodes minus the nodes' encapsulation and their children) # Returns - Set[D.T_agent[D.T_observation]]: Set of states present in the search graph + set[D.T_agent[D.T_observation]]: Set of states present in the search graph """ return self._solver.get_explored_states() @@ -249,9 +249,9 @@ def get_solving_time(self) -> int: def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], float], + tuple[D.T_agent[D.T_concurrency[D.T_event]], float], ]: """Get the (partial) solution policy defined for the states for which the Q-value has been updated at least once (which is optimal for @@ -261,7 +261,7 @@ def get_policy( Only defined over the states reachable from the root solving state # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: Mapping from states to pairs of action and best Q-value """ return self._solver.get_policy() diff --git a/skdecide/hub/solver/iw/iw.py b/skdecide/hub/solver/iw/iw.py index 1e8b179920..97e9bb40c6 100644 --- a/skdecide/hub/solver/iw/iw.py +++ b/skdecide/hub/solver/iw/iw.py @@ -6,7 +6,8 @@ import os import sys -from typing import Any, Callable, List, Set, Tuple +from collections.abc import Callable +from typing import Any from skdecide import Domain, Solver, hub from skdecide.builders.domain import ( @@ -215,12 +216,12 @@ def get_nb_explored_states(self) -> int: """ return self._solver.get_nb_explored_states() - def get_explored_states(self) -> Set[D.T_agent[D.T_observation]]: + def get_explored_states(self) -> set[D.T_agent[D.T_observation]]: """Get the set of states present in the search graph (i.e. the graph's state nodes minus the nodes' encapsulation and their neighbors) # Returns - Set[D.T_agent[D.T_observation]]: Set of states present in the search graph + set[D.T_agent[D.T_observation]]: set of states present in the search graph """ return self._solver.get_explored_states() @@ -264,13 +265,13 @@ def get_top_tip_state(self) -> D.T_agent[D.T_observation]: """ return self._solver.get_top_tip_state() - def get_intermediate_scores(self) -> List[Tuple[int, int, float]]: + def get_intermediate_scores(self) -> list[tuple[int, int, float]]: """Get the history of tuples of time point (in milliseconds), current width, and root state's f-score, recorded each time a goal state is encountered during the search # Returns - List[Tuple[int, int, float]]: List of tuples of time point (in milliseconds), + list[tuple[int, int, float]]: list of tuples of time point (in milliseconds), current width, and root state's f-score """ return self._solver.get_intermediate_scores() diff --git a/skdecide/hub/solver/lazy_astar/lazy_astar.py b/skdecide/hub/solver/lazy_astar/lazy_astar.py index 952df38357..e10d6a4b1f 100644 --- a/skdecide/hub/solver/lazy_astar/lazy_astar.py +++ b/skdecide/hub/solver/lazy_astar/lazy_astar.py @@ -4,9 +4,10 @@ from __future__ import annotations +from collections.abc import Callable from heapq import heappop, heappush from itertools import count -from typing import Callable, Dict, List, Optional +from typing import Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( FloatHyperparameter, @@ -88,13 +89,13 @@ def __init__( self._verbose = verbose self._render = render self._values = {} - self._plan: List[D.T_event] = [] + self._plan: list[D.T_event] = [] - def get_plan(self) -> List[D.T_event]: + def get_plan(self) -> list[D.T_event]: """Return the computed plan.""" return self._plan - def get_policy(self) -> Dict[D.T_observation, Optional[D.T_event]]: + def get_policy(self) -> dict[D.T_observation, Optional[D.T_event]]: """Return the computed policy.""" return self._policy @@ -209,7 +210,7 @@ def extender(node, label, explored): lbl, ), ) - self._policy: Dict[D.T_observation, Optional[D.T_event]] = {} + self._policy: dict[D.T_observation, Optional[D.T_event]] = {} for node, label in path: self._policy[node] = label["action"] if label is not None else None self._values[node] = estim_total - enqueued[node][0] diff --git a/skdecide/hub/solver/lrtastar/lrtastar.py b/skdecide/hub/solver/lrtastar/lrtastar.py index 1742b0f8a0..9495c72131 100644 --- a/skdecide/hub/solver/lrtastar/lrtastar.py +++ b/skdecide/hub/solver/lrtastar/lrtastar.py @@ -5,7 +5,8 @@ from __future__ import annotations -from typing import Callable, Dict, List, Optional +from collections.abc import Callable +from typing import Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( FloatHyperparameter, @@ -103,15 +104,15 @@ def __init__( self._weight = weight self.max_iter = max_iter self.max_depth = max_depth - self._plan: List[D.T_event] = [] + self._plan: list[D.T_event] = [] self.values = {} self._verbose = verbose self.heuristic_changed = False - self._policy: Dict[D.T_observation, Optional[D.T_event]] = {} + self._policy: dict[D.T_observation, Optional[D.T_event]] = {} - def get_policy(self) -> Dict[D.T_observation, Optional[D.T_event]]: + def get_policy(self) -> dict[D.T_observation, Optional[D.T_event]]: """Return the computed policy.""" return self._policy diff --git a/skdecide/hub/solver/lrtdp/lrtdp.py b/skdecide/hub/solver/lrtdp/lrtdp.py index 322e594dfe..738bcec2e1 100644 --- a/skdecide/hub/solver/lrtdp/lrtdp.py +++ b/skdecide/hub/solver/lrtdp/lrtdp.py @@ -6,7 +6,8 @@ import os import sys -from typing import Callable, Dict, Optional, Tuple +from collections.abc import Callable +from typing import Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -311,9 +312,9 @@ def get_solving_time(self) -> int: def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], + tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: """Get the (partial) solution policy defined for the states for which the Q-value has been updated at least once (which is optimal if the @@ -324,7 +325,7 @@ def get_policy( when node garbage was set to True in the LRTDP instance's constructor # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: Mapping from states to pairs of action and best Q-value """ return self._solver.get_policy() diff --git a/skdecide/hub/solver/mahd/mahd.py b/skdecide/hub/solver/mahd/mahd.py index 4d6a3c008f..6d6a5480ab 100644 --- a/skdecide/hub/solver/mahd/mahd.py +++ b/skdecide/hub/solver/mahd/mahd.py @@ -5,7 +5,8 @@ from __future__ import annotations import inspect -from typing import Any, Callable, List, Optional, Set, Tuple, Type +from collections.abc import Callable +from typing import Any, Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( SubBrickHyperparameter, @@ -47,10 +48,10 @@ class MAHD(Solver, DeterministicPolicies, Utilities, FromAnyState): def __init__( self, - multiagent_solver_class: Type[Solver], - singleagent_solver_class: Type[Solver], + multiagent_solver_class: type[Solver], + singleagent_solver_class: type[Solver], multiagent_domain_factory: Callable[[], Domain], - singleagent_domain_class: Optional[Type[Domain]] = None, + singleagent_domain_class: Optional[type[Domain]] = None, singleagent_domain_factory: Optional[Callable[[Domain, Any], Domain]] = None, multiagent_solver_kwargs=None, singleagent_solver_kwargs=None, @@ -185,7 +186,7 @@ def _get_utility(self, observation: D.T_agent[D.T_observation]) -> D.T_value: def _multiagent_heuristic( self, observation: D.T_agent[D.T_observation] - ) -> Tuple[D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]]]: + ) -> tuple[D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]]]: """Computes the multi-agent relaxed heuristics to be used by the higher-level multi-agent solver as a pair of 2 dictionaries: one from single agents to their individual heuristic estimates, and one from single agents to their @@ -201,7 +202,7 @@ def _multiagent_heuristic( then sampled for this agent # Returns - Tuple[D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]]]: + tuple[D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]]]: Pair of 2 dictionaries: one from single agents to their individual heuristic estimates, and one from single agents to their heuristic best actions in the given joint state @@ -330,7 +331,7 @@ def __call__(self, solver: Solver, *args, **kwargs): class CallbackList: - def __init__(self, callbacks: List[Callable[[...], bool]]): + def __init__(self, callbacks: list[Callable[[...], bool]]): self.callbacks = callbacks def __call__(self, *args, **kwargs): diff --git a/skdecide/hub/solver/martdp/martdp.py b/skdecide/hub/solver/martdp/martdp.py index 00456a026e..3296a41d03 100644 --- a/skdecide/hub/solver/martdp/martdp.py +++ b/skdecide/hub/solver/martdp/martdp.py @@ -6,7 +6,7 @@ import os import sys -from typing import Callable, Dict, Optional, Tuple +from collections.abc import Callable from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -83,7 +83,7 @@ def __init__( domain_factory: Callable[[], T_domain], heuristic: Callable[ [T_domain, D.T_state], - Tuple[ + tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]], ], @@ -110,7 +110,7 @@ def __init__( # Parameters domain_factory (Callable[[], T_domain], optional): The lambda function to create a domain instance. - heuristic (Callable[ [T_domain, D.T_state], Tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]], ], ], optional): + heuristic (Callable[ [T_domain, D.T_state], tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]], ], ], optional): Lambda function taking as arguments the domain and a state, and returning a pair of dictionary from agents to the individual heuristic estimates from the state to the goal, and of dictionary from agents to best guess individual actions. @@ -326,9 +326,9 @@ def get_solving_time(self) -> int: def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_agent[Value[D.T_value]]], + tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_agent[Value[D.T_value]]], ]: """Get the (partial) solution policy defined for the states for which the Q-value has been updated at least once (which is optimal if the @@ -339,7 +339,7 @@ def get_policy( when node garbage was set to True in the MA-RTDP instance's constructor # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_agent[Value[D.T_value]]], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_agent[Value[D.T_value]]], ]: Mapping from joint states to pairs of joint action and best Q-value """ return self._solver.get_policy() diff --git a/skdecide/hub/solver/maxent_irl/maxent_irl.py b/skdecide/hub/solver/maxent_irl/maxent_irl.py index ec29d9fb6a..6a74f46031 100755 --- a/skdecide/hub/solver/maxent_irl/maxent_irl.py +++ b/skdecide/hub/solver/maxent_irl/maxent_irl.py @@ -5,8 +5,7 @@ from __future__ import annotations import os -from collections.abc import Iterable -from typing import Callable +from collections.abc import Callable, Iterable import gymnasium as gym import numpy as np diff --git a/skdecide/hub/solver/mcts/mcts.py b/skdecide/hub/solver/mcts/mcts.py index b5900df9f1..7ef08c1b7b 100644 --- a/skdecide/hub/solver/mcts/mcts.py +++ b/skdecide/hub/solver/mcts/mcts.py @@ -7,9 +7,10 @@ import os import random as rd import sys +from collections.abc import Callable from enum import Enum from math import sqrt -from typing import Callable, Dict, List, Optional, Tuple +from typing import Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -152,7 +153,7 @@ def __init__( heuristic: Optional[ Callable[ [T_domain, D.T_agent[D.T_observation]], - Tuple[D.T_agent[Value[D.T_value]], int], + tuple[D.T_agent[Value[D.T_value]], int], ] ] = None, state_expansion_rate: float = 0.1, @@ -192,7 +193,7 @@ def __init__( custom_policy (Callable[ [T_domain, D.T_agent[D.T_observation]], D.T_agent[D.T_concurrency[D.T_event]], ], optional): Custom policy function to use in the rollout policy from non-expanded state nodes when the rollout policy is `MCTS.RolloutPolicy.CUSTOM`. Defaults to None (no custom policy in use). - heuristic (Callable[ [T_domain, D.T_agent[D.T_observation]], Tuple[D.T_agent[Value[D.T_value]], int], ], optional): + heuristic (Callable[ [T_domain, D.T_agent[D.T_observation]], tuple[D.T_agent[Value[D.T_value]], int], ], optional): Optional Heuristic function to initialize non-expanded state nodes (returns a pair of value estimate and fake number of visit counts). Defaults to None (no heuristic in use). state_expansion_rate (float, optional): Value $rs$ used when the expander is `MCTS.Expander.PARTIAL` @@ -441,9 +442,9 @@ def get_solving_time(self) -> int: def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], float], + tuple[D.T_agent[D.T_concurrency[D.T_event]], float], ]: """Get the (partial) solution policy defined for the states for which the best value according to the execution action selector has been updated @@ -454,13 +455,13 @@ def get_policy( when node garbage was set to True in the MCTS instance's constructor # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], float], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], float], ]: Mapping from states to pairs of action and best value according to the execution action selector """ return self._solver.get_policy() - def get_action_prefix(self) -> List[D.T_agent[D.T_observation]]: + def get_action_prefix(self) -> list[D.T_agent[D.T_observation]]: """Get the list of actions returned by the solver so far after each call to the `MCTS.get_next_action` method (mostly internal use in order to rebuild the sequence of visited states until reaching the current @@ -469,7 +470,7 @@ def get_action_prefix(self) -> List[D.T_agent[D.T_observation]]: state of the domain) # Returns - List[D.T_agent[D.T_observation]]: List of actions executed by the solver + list[D.T_agent[D.T_observation]]: List of actions executed by the solver so far after each call to the `MCTS.get_next_action` method """ return self._solver.get_action_prefix() @@ -498,7 +499,7 @@ def __init__( online_node_garbage: bool = False, heuristic: Callable[ [MCTS.T_domain, D.T_state], - Tuple[ + tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]] ], ] = None, @@ -539,7 +540,7 @@ def __init__( (for optimization or execution) is `MCTS.ActionSelector.UCB1`. Defaults to 1.0/sqrt(2.0). online_node_garbage (bool, optional): Boolean indicating whether the search graph which is no more reachable from the root solving state should be deleted (True) or not (False). Defaults to False. - heuristic (Callable[ [MCTS.T_domain, D.T_state], Tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]] ], ], optional): + heuristic (Callable[ [MCTS.T_domain, D.T_state], tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]] ], ], optional): Multi-agent compound heuristic as returned by the `MAHD` algorithm from independent agent heuristic contributions. Defaults to None (no heuristic in use). heuristic_confidence (int, optional): Fake state node visits set on non-expanded state nodes for which the @@ -637,7 +638,7 @@ def _reset(self) -> None: def _value_heuristic( self, domain: MCTS.T_domain, observation: D.T_agent[D.T_observation] - ) -> Tuple[D.T_agent[Value[D.T_value]], int]: + ) -> tuple[D.T_agent[Value[D.T_value]], int]: """Reconstitutes the MCTS heuristic used to initialize the value of non-expanded state nodes from the multi-agent compound heuristic computed by the `MAHD` algorithm @@ -648,7 +649,7 @@ def _value_heuristic( the heuristic must be computed # Returns - Tuple[D.T_agent[Value[D.T_value]], int]: MCTS heuristic value at the given state + tuple[D.T_agent[Value[D.T_value]], int]: MCTS heuristic value at the given state """ if observation not in self._heuristic_records: self._heuristic_records[observation] = self._compound_heuristic( @@ -718,7 +719,7 @@ def __init__( ] = None, heuristic: Callable[ [MCTS.T_domain, D.T_agent[D.T_observation]], - Tuple[D.T_agent[Value[D.T_value]], int], + tuple[D.T_agent[Value[D.T_value]], int], ] = None, transition_mode: MCTS.TransitionMode = MCTS.TransitionMode.DISTRIBUTION, rollout_policy: MCTS.RolloutPolicy = MCTS.RolloutPolicy.RANDOM, @@ -750,7 +751,7 @@ def __init__( custom_policy (Callable[ [MCTS.T_domain, D.T_agent[D.T_observation]], D.T_agent[D.T_concurrency[D.T_event]], ], optional): Custom policy function to use in the rollout policy from non-expanded state nodes when the rollout policy is `MCTS.RolloutPolicy.CUSTOM`. Defaults to None (no custom policy in use). - heuristic (Callable[ [MCTS.T_domain, D.T_agent[D.T_observation]], Tuple[D.T_agent[Value[D.T_value]], int], ], optional): + heuristic (Callable[ [MCTS.T_domain, D.T_agent[D.T_observation]], tuple[D.T_agent[Value[D.T_value]], int], ], optional): Optional Heuristic function to initialize non-expanded state nodes (returns a pair of value estimate and fake number of visit counts). Defaults to None (no heuristic in use). transition_mode (MCTS.TransitionMode, optional): Transition mode enum (one of `MCTS.TransitionMode.STEP`, @@ -842,7 +843,7 @@ def __init__( online_node_garbage: float = False, heuristic: Callable[ [MCTS.T_domain, D.T_state], - Tuple[ + tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]] ], ] = None, @@ -874,7 +875,7 @@ def __init__( (for optimization or execution) is `MCTS.ActionSelector.UCB1`. Defaults to 1.0/sqrt(2.0). online_node_garbage (bool, optional): Boolean indicating whether the search graph which is no more reachable from the root solving state should be deleted (True) or not (False). Defaults to False. - heuristic (Callable[ [MCTS.T_domain, D.T_state], Tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]] ], ], optional): + heuristic (Callable[ [MCTS.T_domain, D.T_state], tuple[ D.T_agent[Value[D.T_value]], D.T_agent[D.T_concurrency[D.T_event]] ], ], optional): Multi-agent compound heuristic as returned by the `MAHD` algorithm from independent agent heuristic contributions. Defaults to None (no heuristic in use). heuristic_confidence (int, optional): Fake state node visits set on non-expanded state nodes for which the diff --git a/skdecide/hub/solver/meta_policy_scheduling/meta_policies.py b/skdecide/hub/solver/meta_policy_scheduling/meta_policies.py index dd5fb11b4a..44b46b537e 100644 --- a/skdecide/hub/solver/meta_policy_scheduling/meta_policies.py +++ b/skdecide/hub/solver/meta_policy_scheduling/meta_policies.py @@ -5,7 +5,7 @@ from __future__ import annotations import logging -from typing import Any, Dict +from typing import Any from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( IntegerHyperparameter, @@ -33,7 +33,7 @@ class MetaPolicy(DeterministicPolicies): def __init__( self, - policies: Dict[Any, DeterministicPolicies], + policies: dict[Any, DeterministicPolicies], domain: SchedulingDomain, nb_rollout_estimation=1, verbose=True, diff --git a/skdecide/hub/solver/meta_policy_scheduling/policy_evaluator.py b/skdecide/hub/solver/meta_policy_scheduling/policy_evaluator.py index 49aaa98c04..0ef584b3b0 100644 --- a/skdecide/hub/solver/meta_policy_scheduling/policy_evaluator.py +++ b/skdecide/hub/solver/meta_policy_scheduling/policy_evaluator.py @@ -5,7 +5,7 @@ from __future__ import annotations from collections import defaultdict -from typing import Any, Dict, List, Set, Tuple +from typing import Any import numpy as np @@ -42,7 +42,7 @@ def my_custom_rollout( def rollout_based_policy_estimation( domain: GoalMDPDomain, policy: DeterministicPolicies, nb_rollout: int = 1 -) -> Tuple[Dict[Any, Any], Dict[Any, Any], Dict[Any, Set[Any]], Dict[Any, Set[Any]]]: +) -> tuple[dict[Any, Any], dict[Any, Any], dict[Any, set[Any]], dict[Any, set[Any]]]: policy_dict = {} nb_visit_dict = {} summed_value = {} @@ -75,7 +75,7 @@ def rollout_based_policy_estimation( def rollout_based_policy_estimation_fast_scheduling( domain: SchedulingDomain, policy: DeterministicPolicies, nb_rollout: int = 1 -) -> Tuple[Dict[Any, Any], Dict[Any, Any], Dict[Any, Set[Any]], Dict[Any, Set[Any]]]: +) -> tuple[dict[Any, Any], dict[Any, Any], dict[Any, set[Any]], dict[Any, set[Any]]]: policy_dict = {} nb_visit_dict = {} summed_value = {} @@ -97,7 +97,7 @@ def rollout_based_policy_estimation_fast_scheduling( def construct_dict_policy( domain: GoalMDPDomain, policy: DeterministicPolicies -) -> Tuple[Dict[Any, Any], Dict[Any, Set[Any]], Dict[Any, List[Tuple[Any, float]]]]: +) -> tuple[dict[Any, Any], dict[Any, set[Any]], dict[Any, list[tuple[Any, float]]]]: stack = [domain.get_initial_state()] # We store predecessors to make it easier to retrieve the expected costs # later on @@ -125,9 +125,9 @@ def construct_dict_policy( def expected_costs_for_policy( domain: GoalMDPDomain, - policy_dict: Dict[D.T_state, D.T_event], - preds: Dict[D.T_state, Set[D.T_state]], - succs: Dict[D.T_state, List[Tuple[D.T_state, float]]], + policy_dict: dict[D.T_state, D.T_event], + preds: dict[D.T_state, set[D.T_state]], + succs: dict[D.T_state, list[tuple[D.T_state, float]]], ): # Compute value function for states that are explored by the policy. opt_val = dict() diff --git a/skdecide/hub/solver/pile_policy_scheduling/pile_policy.py b/skdecide/hub/solver/pile_policy_scheduling/pile_policy.py index 5f69f20926..a3fe4da7fe 100644 --- a/skdecide/hub/solver/pile_policy_scheduling/pile_policy.py +++ b/skdecide/hub/solver/pile_policy_scheduling/pile_policy.py @@ -5,8 +5,8 @@ from __future__ import annotations import random +from collections.abc import Callable from enum import Enum -from typing import Callable import networkx as nx import numpy as np diff --git a/skdecide/hub/solver/pomcp/pomcp.py b/skdecide/hub/solver/pomcp/pomcp.py index 477061547f..bc8b78a798 100644 --- a/skdecide/hub/solver/pomcp/pomcp.py +++ b/skdecide/hub/solver/pomcp/pomcp.py @@ -9,7 +9,7 @@ import math import random -from typing import Callable +from collections.abc import Callable from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( IntegerHyperparameter, diff --git a/skdecide/hub/solver/ray_rllib/ray_rllib.py b/skdecide/hub/solver/ray_rllib/ray_rllib.py index 67c6fc9b4b..745e57c758 100644 --- a/skdecide/hub/solver/ray_rllib/ray_rllib.py +++ b/skdecide/hub/solver/ray_rllib/ray_rllib.py @@ -4,7 +4,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Set, Type, Union +from collections.abc import Callable +from typing import TYPE_CHECKING, Any, Optional, Union import gymnasium as gym import numpy as np @@ -102,15 +103,15 @@ class RayRLlib(Solver, Policies, Restorable): def __init__( self, domain_factory: Callable[[], Domain], - algo_class: Type[Algorithm], + algo_class: type[Algorithm], train_iterations: int, config: Optional[AlgorithmConfig] = None, - policy_configs: Optional[Dict[str, Dict]] = None, + policy_configs: Optional[dict[str, dict]] = None, policy_mapping_fn: Optional[ Callable[[str, Optional["EpisodeV2"], Optional["RolloutWorker"]], str] ] = None, - action_embed_sizes: Optional[Dict[str, int]] = None, - config_kwargs: Optional[Dict[str, Any]] = None, + action_embed_sizes: Optional[dict[str, int]] = None, + config_kwargs: Optional[dict[str, Any]] = None, callback: Callable[[RayRLlib], bool] = lambda solver: False, **kwargs, ) -> None: @@ -188,7 +189,7 @@ def __init__( if kwargs: self._config.update_from_dict(kwargs) - def get_policy(self) -> Dict[str, Policy]: + def get_policy(self) -> dict[str, Policy]: """Return the computed policy.""" return { policy_id: self._algo.get_policy(policy_id=policy_id) @@ -433,7 +434,7 @@ def forget_callback(self): # use it in algo config & evaluation_config, worker config, and for algo.callbacks, worker.callbacks self._set_callbackclass(callbacks_class=callbacks_class) - def _set_callbackclass(self, callbacks_class: Type[DefaultCallbacks]): + def _set_callbackclass(self, callbacks_class: type[DefaultCallbacks]): _set_callbackclass_in_config( callbacks_class=callbacks_class, config=self._config ) @@ -473,7 +474,7 @@ def _set_callbackclass(self, callbacks_class: Type[DefaultCallbacks]): def _set_callbackclass_in_config( - callbacks_class: Type[DefaultCallbacks], config: AlgorithmConfig + callbacks_class: type[DefaultCallbacks], config: AlgorithmConfig ) -> None: is_frozen = config._is_frozen if is_frozen: @@ -511,7 +512,7 @@ def __init__( self._domain = domain super().__init__(old_env=old_env, render_mode=render_mode) - def get_agent_ids(self) -> Set[str]: + def get_agent_ids(self) -> set[str]: return self._domain.get_agents() @@ -720,7 +721,7 @@ class SolveEarlyStop(Exception): def generate_rllibcallback_class( callback: _CallbackWrapper, solver: RayRLlib, classname=None -) -> Type[BaseRLlibCallback]: +) -> type[BaseRLlibCallback]: if classname is None: classname = f"MyCallbackClass{id(solver)}" return type( diff --git a/skdecide/hub/solver/riw/riw.py b/skdecide/hub/solver/riw/riw.py index 5e8626bdb4..e223d2af58 100644 --- a/skdecide/hub/solver/riw/riw.py +++ b/skdecide/hub/solver/riw/riw.py @@ -6,7 +6,8 @@ import os import sys -from typing import Any, Callable, Dict, List, Optional, Tuple +from collections.abc import Callable +from typing import Any, Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -335,9 +336,9 @@ def get_solving_time(self) -> int: def get_policy( self, - ) -> Dict[ + ) -> dict[ D.T_agent[D.T_observation], - Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], + tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: """Get the (partial) solution policy defined for the states for which the Q-value has been updated at least once (which is optimal if the @@ -348,12 +349,12 @@ def get_policy( when node garbage was set to True in the RIW instance's constructor # Returns - Dict[ D.T_agent[D.T_observation], Tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: + dict[ D.T_agent[D.T_observation], tuple[D.T_agent[D.T_concurrency[D.T_event]], D.T_value], ]: Mapping from states to pairs of action and best Q-value """ return self._solver.get_policy() - def get_action_prefix(self) -> List[D.T_agent[D.T_observation]]: + def get_action_prefix(self) -> list[D.T_agent[D.T_observation]]: """Get the list of actions returned by the solver so far after each call to the RIW.get_next_action method (mostly internal use in order to rebuild the sequence of visited states until reaching the current @@ -362,7 +363,7 @@ def get_action_prefix(self) -> List[D.T_agent[D.T_observation]]: transition function with steps that hide the current state of the environment) # Returns - List[D.T_agent[D.T_observation]]: List of actions executed by the solver + list[D.T_agent[D.T_observation]]: List of actions executed by the solver so far after each call to the `RIW.get_next_action` method """ return self._solver.get_action_prefix() diff --git a/skdecide/hub/solver/simple_greedy/simple_greedy.py b/skdecide/hub/solver/simple_greedy/simple_greedy.py index 91ef1d1d76..dbbc797ef1 100644 --- a/skdecide/hub/solver/simple_greedy/simple_greedy.py +++ b/skdecide/hub/solver/simple_greedy/simple_greedy.py @@ -4,8 +4,6 @@ from __future__ import annotations -from typing import Callable - from skdecide import DeterministicPolicySolver, Domain, EnumerableSpace, Memory from skdecide.builders.domain import EnumerableTransitions, FullyObservable, SingleAgent diff --git a/skdecide/hub/solver/stable_baselines/stable_baselines.py b/skdecide/hub/solver/stable_baselines/stable_baselines.py index beb74125a8..7f4cfa7daf 100644 --- a/skdecide/hub/solver/stable_baselines/stable_baselines.py +++ b/skdecide/hub/solver/stable_baselines/stable_baselines.py @@ -4,7 +4,8 @@ from __future__ import annotations -from typing import Any, Callable, Dict, Optional, Type, Union +from collections.abc import Callable +from typing import Any, Optional, Union from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -85,9 +86,9 @@ class StableBaseline(Solver, Policies, Restorable): def __init__( self, domain_factory: Callable[[], Domain], - algo_class: Type[BaseAlgorithm], - baselines_policy: Union[str, Type[BasePolicy]], - learn_config: Optional[Dict[str, Any]] = None, + algo_class: type[BaseAlgorithm], + baselines_policy: Union[str, type[BasePolicy]], + learn_config: Optional[dict[str, Any]] = None, callback: Callable[[StableBaseline], bool] = lambda solver: False, **kwargs: Any, ) -> None: diff --git a/skdecide/hub/solver/up/up.py b/skdecide/hub/solver/up/up.py index c90befbba7..fa3d94c810 100644 --- a/skdecide/hub/solver/up/up.py +++ b/skdecide/hub/solver/up/up.py @@ -4,7 +4,8 @@ from __future__ import annotations -from typing import Any, Callable, Dict, List, Optional +from collections.abc import Callable +from typing import Any, Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( CategoricalHyperparameter, @@ -54,7 +55,7 @@ def __init__( self, domain_factory: Callable[[], Domain], operation_mode: Engine, - engine_params: Optional[Dict[str, Any]] = None, + engine_params: Optional[dict[str, Any]] = None, **operation_mode_params, ) -> None: """Initialize UPSolver. @@ -117,10 +118,10 @@ def _is_policy_defined_for(self, observation: D.T_agent[D.T_observation]) -> boo def _get_utility(self, observation: D.T_agent[D.T_observation]) -> D.T_value: return self._values[observation] - def get_policy(self) -> Dict[D.T_agent[D.T_observation], SkUPAction]: + def get_policy(self) -> dict[D.T_agent[D.T_observation], SkUPAction]: """Return the computed policy.""" return self._policy - def get_plan(self) -> List[SkUPAction]: + def get_plan(self) -> list[SkUPAction]: """Return the computed plan.""" return self._plan diff --git a/skdecide/hub/space/gym/gym.py b/skdecide/hub/space/gym/gym.py index 57c11b5b17..6af959df6a 100644 --- a/skdecide/hub/space/gym/gym.py +++ b/skdecide/hub/space/gym/gym.py @@ -5,9 +5,10 @@ from __future__ import annotations import itertools +from collections.abc import Iterable, Sequence from dataclasses import asdict from enum import EnumMeta -from typing import Any, Dict, Generic, Iterable, List, Sequence, Tuple, Union +from typing import Any, Generic, Union import gymnasium as gym import gymnasium.spaces as gym_spaces @@ -188,7 +189,7 @@ class TupleSpace(GymSpace[T]): """ def __init__( - self, spaces: Tuple[Union[GymSpace[T], gym.Space]], element_class=tuple + self, spaces: tuple[Union[GymSpace[T], gym.Space]], element_class=tuple ): super().__init__( gym_space=gym_spaces.Tuple( @@ -243,7 +244,7 @@ class DictSpace(GymSpace[T]): def __init__( self, - spaces: Dict[Any, Union[GymSpace[T], gym.Space]] = None, + spaces: dict[Any, Union[GymSpace[T], gym.Space]] = None, element_class=dict, **spaces_kwargs, ): @@ -453,7 +454,7 @@ class DataSpace(GymSpace[T]): def __init__( self, data_class: type, - spaces: Union[Dict[str, gym.Space], List[Tuple[str, gym.Space]]], + spaces: Union[dict[str, gym.Space], list[tuple[str, gym.Space]]], ) -> None: """Initialize DataSpace. @@ -503,9 +504,9 @@ def unwrapped(self) -> gym_spaces.Dict: """ return super().unwrapped() - def to_unwrapped(self, sample_n: Iterable[T]) -> Iterable[Dict]: + def to_unwrapped(self, sample_n: Iterable[T]) -> Iterable[dict]: return [asdict(sample) for sample in sample_n] - def from_unwrapped(self, sample_n: Iterable[Dict]) -> Iterable[T]: + def from_unwrapped(self, sample_n: Iterable[dict]) -> Iterable[T]: # TODO: convert to simple types (get rid of ndarray created by gym dict space...)? return [self._data_class(**sample) for sample in sample_n] diff --git a/skdecide/optuna_utils.py b/skdecide/optuna_utils.py index 365d7c3b61..8fa9f59f4b 100644 --- a/skdecide/optuna_utils.py +++ b/skdecide/optuna_utils.py @@ -8,7 +8,8 @@ import logging import time from collections import defaultdict -from typing import Any, Callable, Dict, List, Optional, Tuple, Type +from collections.abc import Callable +from typing import Any, Optional from discrete_optimization.generic_tools.hyperparameters.hyperparameter import ( Hyperparameter, @@ -40,13 +41,13 @@ def generic_optuna_experiment_monoproblem( domain_factory: Callable[[], Domain], - solver_classes: List[Type[Solver]], - kwargs_fixed_by_solver: Optional[Dict[Type[Solver], Dict[str, Any]]] = None, + solver_classes: list[type[Solver]], + kwargs_fixed_by_solver: Optional[dict[type[Solver], dict[str, Any]]] = None, suggest_optuna_kwargs_by_name_by_solver: Optional[ - Dict[Type[Solver], Dict[str, Dict[str, Any]]] + dict[type[Solver], dict[str, dict[str, Any]]] ] = None, additional_hyperparameters_by_solver: Optional[ - Dict[Type[Solver], List[Hyperparameter]] + dict[type[Solver], list[Hyperparameter]] ] = None, n_trials: int = 150, allow_retry_same_trial: bool = False, @@ -65,11 +66,11 @@ def generic_optuna_experiment_monoproblem( Callable[ [ Solver, - List[ - Tuple[ - List[D.T_agent[D.T_observation]], - List[D.T_agent[D.T_concurrency[D.T_event]]], - List[D.T_agent[Value[D.T_value]]], + list[ + tuple[ + list[D.T_agent[D.T_observation]], + list[D.T_agent[D.T_concurrency[D.T_event]]], + list[D.T_agent[Value[D.T_value]]], ] ], ], @@ -78,7 +79,7 @@ def generic_optuna_experiment_monoproblem( ] = None, optuna_tuning_direction: str = "maximize", alternative_domain_factory: Optional[ - Dict[Type[Solver], Callable[[], Domain]] + dict[type[Solver], Callable[[], Domain]] ] = None, ) -> optuna.Study: """Create and run an optuna study to tune solvers hyperparameters for a given domain factory. @@ -179,11 +180,11 @@ def aggreg_outcome_rewards( def objective( solver: Solver, - episodes: List[ - Tuple[ - List[D.T_agent[D.T_observation]], - List[D.T_agent[D.T_concurrency[D.T_event]]], - List[D.T_agent[Value[D.T_value]]], + episodes: list[ + tuple[ + list[D.T_agent[D.T_observation]], + list[D.T_agent[D.T_concurrency[D.T_event]]], + list[D.T_agent[Value[D.T_value]]], ] ], ) -> float: @@ -201,7 +202,7 @@ def objective( # we need to map the classes to a unique string, to be seen as a categorical hyperparameter by optuna # by default, we use the class name, but if there are identical names, f"{cls.__module__}.{cls.__name__}" could be used. - solvers_by_name: Dict[str, Type[Solver]] = { + solvers_by_name: dict[str, type[Solver]] = { cls.__name__: cls for cls in solver_classes } diff --git a/skdecide/solvers.py b/skdecide/solvers.py index 41eca045c0..5578123d32 100644 --- a/skdecide/solvers.py +++ b/skdecide/solvers.py @@ -5,7 +5,8 @@ """This module contains base classes for quickly building solvers.""" from __future__ import annotations -from typing import Callable, List, Optional, Type +from collections.abc import Callable +from typing import Optional from discrete_optimization.generic_tools.hyperparameters.hyperparametrizable import ( Hyperparametrizable, @@ -66,7 +67,7 @@ def cast_domain_factory(): self._original_domain_factory = domain_factory @classmethod - def get_domain_requirements(cls) -> List[type]: + def get_domain_requirements(cls) -> list[type]: """Get domain requirements for this solver class to be applicable. Domain requirements are classes from the #skdecide.builders.domain package that the domain needs to inherit from. @@ -181,7 +182,7 @@ def __exit__(self, type, value, tb): """ self._cleanup() - def autocast(self, domain_cls: Optional[Type[Domain]] = None) -> None: + def autocast(self, domain_cls: Optional[type[Domain]] = None) -> None: """Autocast itself to the level corresponding to the given domain class. # Parameters diff --git a/skdecide/utils.py b/skdecide/utils.py index 12b5838d08..e5758685c6 100644 --- a/skdecide/utils.py +++ b/skdecide/utils.py @@ -12,8 +12,9 @@ import os import sys import time +from collections.abc import Callable, Iterable from enum import Enum -from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type, Union +from typing import Any, Optional, Union from skdecide import ( D, @@ -88,7 +89,7 @@ def get_data_home(data_home: Optional[str] = None) -> str: return data_home -def _get_registered_entries(entry_type: str) -> List[str]: +def _get_registered_entries(entry_type: str) -> list[str]: if ( sys.version_info.minor < 10 and sys.version_info.major == 3 ): # different behaviour for 3.8 and 3.9 @@ -121,28 +122,28 @@ def _load_registered_entry(entry_type: str, entry_name: str) -> Optional[Any]: logger.warning(rf"/!\ {entry_name} could not be loaded ({e}).") -def get_registered_domains() -> List[str]: +def get_registered_domains() -> list[str]: return _get_registered_entries("skdecide.domains") -def get_registered_solvers() -> List[str]: +def get_registered_solvers() -> list[str]: return _get_registered_entries("skdecide.solvers") -def load_registered_domain(name: str) -> Type[Domain]: +def load_registered_domain(name: str) -> type[Domain]: return _load_registered_entry("skdecide.domains", name) -def load_registered_solver(name: str) -> Type[Solver]: +def load_registered_solver(name: str) -> type[Solver]: return _load_registered_entry("skdecide.solvers", name) # TODO: implement ranking heuristic def match_solvers( domain: Domain, - candidates: Optional[Iterable[Type[Solver]]] = None, + candidates: Optional[Iterable[type[Solver]]] = None, ranked: bool = False, -) -> Union[List[Type[Solver]], List[Tuple[Type[Solver], int]]]: +) -> Union[list[type[Solver]], list[tuple[type[Solver], int]]]: if candidates is None: candidates = [load_registered_solver(s) for s in get_registered_solvers()] candidates = [ @@ -199,7 +200,7 @@ class ReplaySolver(DeterministicPolicies): def __init__( self, - actions: List[D.T_agent[D.T_concurrency[D.T_event]]], + actions: list[D.T_agent[D.T_concurrency[D.T_event]]], out_of_action_method: ReplayOutOfActionMethod = ReplayOutOfActionMethod.LAST, ): self.actions = actions @@ -247,11 +248,11 @@ def rollout( goal_logging_level: int = logging.INFO, rollout_callback: Optional[RolloutCallback] = None, ) -> Optional[ - List[ - Tuple[ - List[D.T_agent[D.T_observation]], - List[D.T_agent[D.T_concurrency[D.T_event]]], - List[D.T_agent[Value[D.T_value]]], + list[ + tuple[ + list[D.T_agent[D.T_observation]], + list[D.T_agent[D.T_concurrency[D.T_event]]], + list[D.T_agent[Value[D.T_value]]], ] ] ]: @@ -324,11 +325,11 @@ def is_policy_defined_for( solver = RandomWalk() autocast_all(solver, solver.T_domain, domain) - episodes: List[ - Tuple[ - List[D.T_agent[D.T_observation]], - List[D.T_agent[D.T_concurrency[D.T_event]]], - List[D.T_agent[Value[D.T_value]]], + episodes: list[ + tuple[ + list[D.T_agent[D.T_observation]], + list[D.T_agent[D.T_concurrency[D.T_event]]], + list[D.T_agent[Value[D.T_value]]], ] ] = [] @@ -371,9 +372,9 @@ def is_policy_defined_for( # Run episode step = 1 - observations: List[D.T_agent[D.T_observation]] = [] - actions: List[D.T_agent[D.T_concurrency[D.T_event]]] = [] - values: List[D.T_agent[Value[D.T_value]]] = [] + observations: list[D.T_agent[D.T_observation]] = [] + actions: list[D.T_agent[D.T_concurrency[D.T_event]]] = [] + values: list[D.T_agent[Value[D.T_value]]] = [] # save the initial observation observations.append(observation) diff --git a/tests/domains/test_gym.py b/tests/domains/test_gym.py index cf4f521439..3177d83e49 100644 --- a/tests/domains/test_gym.py +++ b/tests/domains/test_gym.py @@ -1,5 +1,5 @@ from collections import OrderedDict -from typing import Callable +from collections.abc import Callable import gymnasium as gym import numpy as np diff --git a/tests/scheduling/test_scheduling.py b/tests/scheduling/test_scheduling.py index e2e20ea9a1..62a822b111 100644 --- a/tests/scheduling/test_scheduling.py +++ b/tests/scheduling/test_scheduling.py @@ -1,7 +1,7 @@ import logging import random from enum import Enum -from typing import Any, Dict, List, Optional, Set, Union +from typing import Any, Optional, Union import pytest from discrete_optimization.generic_tools.cp_tools import CPSolverName @@ -66,7 +66,7 @@ def random_seed(): class ToyRCPSPDomain(SingleModeRCPSP): - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -75,13 +75,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5]) - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -90,7 +90,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 5: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_task_duration( @@ -105,10 +105,10 @@ def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: class ToyMRCPSPDomain_WithCost(MultiModeRCPSPWithCost): - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return {"r1": True, "r2": True} - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return { 1: {1: ConstantModeConsumption({"r1": 0, "r2": 0})}, 2: { @@ -126,7 +126,7 @@ def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: 5: {1: ConstantModeConsumption({"r1": 0, "r2": 0})}, } - def _get_mode_costs(self) -> Dict[int, Dict[int, float]]: + def _get_mode_costs(self) -> dict[int, dict[int, float]]: return { 1: {1: 0.0}, 2: {1: 1.0, 2: 2.0}, @@ -135,10 +135,10 @@ def _get_mode_costs(self) -> Dict[int, Dict[int, float]]: 5: {1: 0.0}, } - def _get_resource_cost_per_time_unit(self) -> Dict[str, float]: + def _get_resource_cost_per_time_unit(self) -> dict[str, float]: return {"r1": 1, "r2": 2} - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.COST] def __init__(self): @@ -147,13 +147,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5]) - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_task_duration( @@ -171,7 +171,7 @@ class ToyMS_RCPSPDomain(MultiModeMultiSkillRCPSP): def __init__(self): self.initialize_domain() - def _get_resource_units_names(self) -> List[str]: + def _get_resource_units_names(self) -> list[str]: return ["employee-1", "employee-2", "employee-3"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -187,16 +187,16 @@ def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: def _get_max_horizon(self) -> int: return 50 - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return {1, 2, 3, 4, 5} - def _get_tasks_modes(self) -> Dict[int, Dict[int, ModeConsumption]]: + def _get_tasks_modes(self) -> dict[int, dict[int, ModeConsumption]]: return { 1: {1: ConstantModeConsumption({"r1": 0, "r2": 0})}, 2: { @@ -220,13 +220,13 @@ def _get_task_duration( all_durations = {1: 0, 2: 5, 3: 6, 4: 4, 5: 0} return all_durations[task] - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] - def _get_resource_type_for_unit(self) -> Dict[str, str]: + def _get_resource_type_for_unit(self) -> dict[str, str]: return None - def _get_resource_renewability(self) -> Dict[str, bool]: + def _get_resource_renewability(self) -> dict[str, bool]: return { "r1": True, "r2": True, @@ -235,7 +235,7 @@ def _get_resource_renewability(self) -> Dict[str, bool]: "employee-3": True, } - def _get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: + def _get_all_resources_skills(self) -> dict[str, dict[str, Any]]: return { "employee-1": {"S1": 1}, "employee-2": {"S2": 1}, @@ -244,7 +244,7 @@ def _get_all_resources_skills(self) -> Dict[str, Dict[str, Any]]: "r2": {}, } - def _get_all_tasks_skills(self) -> Dict[int, Dict[int, Dict[str, Any]]]: + def _get_all_tasks_skills(self) -> dict[int, dict[int, dict[str, Any]]]: return { 1: {1: {}}, 2: {1: {"S1": 1}, 2: {"S2": 1}}, @@ -260,7 +260,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: all_distributions = {} all_distributions[1] = DiscreteDistribution([(0, 1.0)]) @@ -271,7 +271,7 @@ def _get_task_duration_distribution( return all_distributions[task] - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -280,13 +280,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 20 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [5], 4: [5], 5: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5]) - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -295,7 +295,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 5: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -313,7 +313,7 @@ class ToyCondSRCPSPDomain(SingleModeRCPSP_Stochastic_Durations_WithConditionalTa def _get_all_condition_items(self) -> Enum: return ConditionElementsExample - def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution]]: + def _get_task_on_completion_added_conditions(self) -> dict[int, list[Distribution]]: completion_conditions_dict = {} completion_conditions_dict[2] = [ @@ -335,7 +335,7 @@ def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distributio return completion_conditions_dict - def _get_task_existence_conditions(self) -> Dict[int, List[int]]: + def _get_task_existence_conditions(self) -> dict[int, list[int]]: existence_conditions_dict = { 5: [self.get_all_condition_items().PROBLEM_OPERATION_2], 6: [self.get_all_condition_items().PROBLEM_OPERATION_3], @@ -347,7 +347,7 @@ def _get_task_duration_distribution( task: int, mode: Optional[int] = 1, progress_from: Optional[float] = 0.0, - multivariate_settings: Optional[Dict[str, int]] = None, + multivariate_settings: Optional[dict[str, int]] = None, ) -> Distribution: all_distributions = {} all_distributions[1] = DiscreteDistribution([(0, 1.0)]) @@ -360,7 +360,7 @@ def _get_task_duration_distribution( return all_distributions[task] - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -369,13 +369,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [7], 4: [7], 5: [7], 6: [7], 7: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return set([1, 2, 3, 4, 5, 6, 7]) - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -386,7 +386,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 7: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -400,7 +400,7 @@ class ToySimulatedCondSRCPSPDomain( def _get_all_condition_items(self) -> Enum: return ConditionElementsExample - def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distribution]]: + def _get_task_on_completion_added_conditions(self) -> dict[int, list[Distribution]]: completion_conditions_dict = {} completion_conditions_dict[2] = [ @@ -422,14 +422,14 @@ def _get_task_on_completion_added_conditions(self) -> Dict[int, List[Distributio return completion_conditions_dict - def _get_task_existence_conditions(self) -> Dict[int, List[int]]: + def _get_task_existence_conditions(self) -> dict[int, list[int]]: existence_conditions_dict = { 5: [self.get_all_condition_items().PROBLEM_OPERATION_2], 6: [self.get_all_condition_items().PROBLEM_OPERATION_3], } return existence_conditions_dict - def _get_objectives(self) -> List[SchedulingObjectiveEnum]: + def _get_objectives(self) -> list[SchedulingObjectiveEnum]: return [SchedulingObjectiveEnum.MAKESPAN] def __init__(self): @@ -438,13 +438,13 @@ def __init__(self): def _get_max_horizon(self) -> int: return 50 - def _get_successors(self) -> Dict[int, List[int]]: + def _get_successors(self) -> dict[int, list[int]]: return {1: [2, 3], 2: [4], 3: [7], 4: [7], 5: [7], 6: [7], 7: []} - def _get_tasks_ids(self) -> Union[Set[int], Dict[int, Any], List[int]]: + def _get_tasks_ids(self) -> Union[set[int], dict[int, Any], list[int]]: return {1, 2, 3, 4, 5, 6, 7} - def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: + def _get_tasks_mode(self) -> dict[int, ModeConsumption]: return { 1: ConstantModeConsumption({"r1": 0, "r2": 0}), 2: ConstantModeConsumption({"r1": 1, "r2": 1}), @@ -455,7 +455,7 @@ def _get_tasks_mode(self) -> Dict[int, ModeConsumption]: 7: ConstantModeConsumption({"r1": 0, "r2": 0}), } - def _get_resource_types_names(self) -> List[str]: + def _get_resource_types_names(self) -> list[str]: return ["r1", "r2"] def _get_original_quantity_resource(self, resource: str, **kwargs) -> int: @@ -495,14 +495,14 @@ def test_rollout(domain, random_seed): check_rollout_consistency(domain, states) -def check_rollout_consistency(domain, states: List[State]): +def check_rollout_consistency(domain, states: list[State]): check_precedence(domain, states) check_task_duration(domain, states) check_resource_constraints(domain, states) check_skills(domain, states) -def check_precedence(domain, states: List[State]): +def check_precedence(domain, states: list[State]): # Check precedence tasks_complete_dict = rebuild_tasks_complete_details_dict(states[-1]) for id in domain.get_tasks_ids(): @@ -519,7 +519,7 @@ def check_precedence(domain, states: List[State]): ) -def check_task_duration(domain, states: List[State]): +def check_task_duration(domain, states: list[State]): # Check task durations on deterministic domains if isinstance(domain, DeterministicTaskDuration): tasks_complete_dict = rebuild_tasks_complete_details_dict(states[-1]) @@ -546,7 +546,7 @@ def check_task_duration(domain, states: List[State]): ), "duration different than expected for task " + str(id) -def check_resource_constraints(domain, states: List[State]): +def check_resource_constraints(domain, states: list[State]): # Check resource constraints on deterministic non-preemtive domains if ( isinstance(domain, DeterministicResourceAvailabilityChanges) @@ -578,7 +578,7 @@ def check_resource_constraints(domain, states: List[State]): ) -def check_skills(domain, states: List[State]): +def check_skills(domain, states: list[State]): if isinstance(domain, ToyMS_RCPSPDomain): ressource_units = domain.get_resource_units_names() tasks_complete_dict = rebuild_tasks_complete_details_dict(states[-1]) diff --git a/tests/solvers/python/test_optuna_rayrllib.py b/tests/solvers/python/test_optuna_rayrllib.py index 1741bc8a4e..96daeaf056 100644 --- a/tests/solvers/python/test_optuna_rayrllib.py +++ b/tests/solvers/python/test_optuna_rayrllib.py @@ -2,7 +2,7 @@ import logging import os -from typing import Any, Dict, List, Type +from typing import Any import ray @@ -15,7 +15,7 @@ class FakeRayRLlib(RayRLlib): - generated_configs: List[Dict[str, Any]] + generated_configs: list[dict[str, Any]] def _solve(self) -> None: FakeRayRLlib.generated_configs.append(self._config.to_dict())