discrete_optimization.gpdp.solvers package
Submodules
discrete_optimization.gpdp.solvers.gpdp_solver module
- class discrete_optimization.gpdp.solvers.gpdp_solver.GpdpSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]
Bases:
SolverDO
- problem: GpdpProblem
discrete_optimization.gpdp.solvers.lp_iterative module
- class discrete_optimization.gpdp.solvers.lp_iterative.BaseLinearFlowGpdpSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]
Bases:
MilpSolver
,GpdpSolver
- convert_temporaryresults(temporary_results: list[TemporaryResult]) list[tuple[Solution, float | TupleFitness]] [source]
- convert_to_variable_values(solution: Solution) dict[gurobipy.Var, float] [source]
Not used here by set_warm_start().
- Parameters:
solution
Returns:
- init_model(**kwargs: Any) None [source]
Initialize internal model used to solve.
Can initialize a ortools, milp, gurobi, … model.
- lazy: bool = False
Flag to know if contraints are added via a callback in a lazy way.
Should only be True in GurobiLazyConstraintLinearFlowGpdpSolver.
- one_visit_per_clusters(nodes_of_interest: Iterable[Hashable], variables_edges: dict[int, dict[tuple[Hashable, Hashable], Any]]) None [source]
- one_visit_per_node(nodes_of_interest: Iterable[Hashable], variables_edges: dict[int, dict[tuple[Hashable, Hashable], Any]]) None [source]
- problem: GpdpProblem
- resources_constraint(variables_edges: dict[int, dict[tuple[Hashable, Hashable], Any]]) dict[str, dict[str, dict[Hashable, Any]]] [source]
- retrieve_current_solution(get_var_value_for_current_solution: Callable[[Any], float], get_obj_value_for_current_solution: Callable[[], float]) GpdpSolution [source]
Not used here as solve() is overriden
- retrieve_current_temporaryresult(get_var_value_for_current_solution: Callable[[Any], float], get_obj_value_for_current_solution: Callable[[], float]) TemporaryResult [source]
- set_warm_start(solution: GpdpSolution) None [source]
Make the solver warm start from the given solution.
Will be ignored if arg warm_start is not None in call to solve().
- simple_capacity_constraint(variables_edges: dict[int, dict[tuple[Hashable, Hashable], Any]]) dict[str, dict[int, dict[str, Any]]] [source]
- solve(parameters_milp: ParametersMilp | None = None, time_limit_subsolver: float | None = 30.0, do_lns: bool = True, nb_iteration_max: int = 10, json_dump_folder: str | None = None, warm_start: dict[Any, Any] | None = None, callbacks: list[Callback] | None = None, **kwargs: Any) ResultStorage [source]
Generic solving function.
- Parameters:
callbacks – list of callbacks used to hook into the various stage of the solve
**kwargs – any argument specific to the solver
Solvers deriving from SolverDo should use callbacks methods .on_step_end(), … during solve(). But some solvers are not yet updated and are just ignoring it.
Returns (ResultStorage): a result object containing potentially a pool of solutions to a discrete-optimization problem
- solve_iterative(parameters_milp: ParametersMilp | None = None, time_limit_subsolver: float | None = 30.0, do_lns: bool = True, nb_iteration_max: int = 10, json_dump_folder: str | None = None, warm_start: dict[Any, Any] | None = None, callbacks: list[Callback] | None = None, **kwargs: Any) ResultStorage [source]
- Parameters:
parameters_milp
time_limit_subsolver – the solve process of the LP subsolver stops after this time limit (in seconds). If None, no time limit is applied.
do_lns
nb_iteration_max
json_dump_folder – if not None, solution will be dumped in this folder at each iteration
warm_start
**kwargs
Returns:
- abstract solve_one_iteration(parameters_milp: ParametersMilp | None = None, time_limit: float | None = 30.0, **kwargs: Any) list[TemporaryResult] [source]
- time_evolution(variables_edges: dict[int, dict[tuple[Hashable, Hashable], Any]]) dict[str, dict[Hashable, Any]] [source]
- warm_start: GpdpSolution | None = None
- class discrete_optimization.gpdp.solvers.lp_iterative.ConstraintHandlerOrWarmStart(linear_solver: BaseLinearFlowGpdpSolver, problem: GpdpProblem, do_lns: bool = True)[source]
Bases:
object
- class discrete_optimization.gpdp.solvers.lp_iterative.GurobiLazyConstraintLinearFlowGpdpSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]
Bases:
GurobiLinearFlowGpdpSolver
- lazy: bool = True
Flag to know if contraints are added via a callback in a lazy way.
Should only be True in GurobiLazyConstraintLinearFlowGpdpSolver.
- retrieve_ith_temporaryresult(i: int) TemporaryResult [source]
- solve_one_iteration(parameters_milp: ParametersMilp | None = None, time_limit: float | None = 30.0, **kwargs: Any) list[TemporaryResult] [source]
- class discrete_optimization.gpdp.solvers.lp_iterative.GurobiLinearFlowGpdpSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]
Bases:
GurobiMilpSolver
,BaseLinearFlowGpdpSolver
- convert_to_variable_values(solution: Solution) dict[gurobipy.Var, float] [source]
Convert a solution to a mapping between model variables and their values.
Will be used by set_warm_start().
Override it in subclasses to have a proper warm start. You can also override set_warm_start() if default behaviour is not sufficient.
- init_model(**kwargs)[source]
Initialize internal model used to solve.
Can initialize a ortools, milp, gurobi, … model.
- model: 'gurobipy.Model' | None = None
- set_warm_start(solution: GpdpSolution) None [source]
Make the solver warm start from the given solution.
By default, this is using convert_to_variable_values(). If not sufficient, you can override it. (And for instance make implementation of convert_to_variable_values() raise a NotImplementedError.)
- solve(parameters_milp: ParametersMilp | None = None, time_limit_subsolver: float | None = 30.0, do_lns: bool = True, nb_iteration_max: int = 10, json_dump_folder: str | None = None, warm_start: dict[Any, Any] | None = None, callbacks: list[Callback] | None = None, **kwargs: Any) ResultStorage [source]
Generic solving function.
- Parameters:
callbacks – list of callbacks used to hook into the various stage of the solve
**kwargs – any argument specific to the solver
Solvers deriving from SolverDo should use callbacks methods .on_step_end(), … during solve(). But some solvers are not yet updated and are just ignoring it.
Returns (ResultStorage): a result object containing potentially a pool of solutions to a discrete-optimization problem
- solve_one_iteration(parameters_milp: ParametersMilp | None = None, time_limit: float | None = 30.0, **kwargs: Any) list[TemporaryResult] [source]
- class discrete_optimization.gpdp.solvers.lp_iterative.MathOptLinearFlowGpdpSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]
Bases:
OrtoolsMathOptMilpSolver
,BaseLinearFlowGpdpSolver
- convert_to_variable_values(solution: Solution) dict[Variable, float] [source]
Convert a solution to a mapping between model variables and their values.
Will be used by set_warm_start() to provide a suitable SolutionHint.variable_values. See https://or-tools.github.io/docs/pdoc/ortools/math_opt/python/model_parameters.html#SolutionHint for more information.
Override it in subclasses to have a proper warm start.
- set_warm_start(solution: GpdpSolution) None [source]
Make the solver warm start from the given solution.
- solve(parameters_milp: ParametersMilp | None = None, time_limit_subsolver: float | None = 30.0, do_lns: bool = True, nb_iteration_max: int = 10, json_dump_folder: str | None = None, warm_start: dict[Any, Any] | None = None, callbacks: list[Callback] | None = None, **kwargs: Any) ResultStorage [source]
Solve with OR-Tools MathOpt API
- Parameters:
callbacks – list of callbacks used to hook into the various stage of the solve
parameters_milp – parameters passed to the MILP solver
mathopt_solver_type – underlying solver type to use. Passed as solver_type to mathopt.solve()
time_limit – the solve process stops after this time limit (in seconds). If None, no time limit is applied.
mathopt_enable_output – turn on mathopt logging
mathopt_model_parameters – passed to mathopt.solve() as model_params
mathopt_additional_solve_parameters – passed to mathopt.solve() as params, except that parameters defined by above time_limit and parameters_milp will be overriden by them.
**kwargs – passed to init_model() if model not yet existing
Returns:
- solve_one_iteration(parameters_milp: ParametersMilp | None = None, time_limit: float | None = 30.0, mathopt_solver_type: SolverType = SolverType.CP_SAT, mathopt_enable_output: bool = False, mathopt_model_parameters: ModelSolveParameters | None = None, mathopt_additional_solve_parameters: SolveParameters | None = None, **kwargs: Any) list[TemporaryResult] [source]
- class discrete_optimization.gpdp.solvers.lp_iterative.SubtourAddingConstraint(problem: GpdpProblem, linear_solver: BaseLinearFlowGpdpSolver, lazy: bool = False, cluster: bool = False, do_order: bool = False, consider_only_first_component: bool = True)[source]
Bases:
object
- adding_component_constraints(list_solution: list[TemporaryResult]) None [source]
- class discrete_optimization.gpdp.solvers.lp_iterative.TemporaryResult(flow_solution: dict[int, dict[tuple[Hashable, Hashable], int]], graph_merge: DiGraph, graph_vehicle: dict[int, DiGraph], obj: float, all_variables: dict[str, dict[Any, Any]] | None = None)[source]
Bases:
object
- class discrete_optimization.gpdp.solvers.lp_iterative.TemporaryResultGurobiCallback(do_solver: GurobiLinearFlowGpdpSolver)[source]
Bases:
GurobiCallback
- class discrete_optimization.gpdp.solvers.lp_iterative.TemporaryResultMathOptCallback(do_solver: MathOptLinearFlowGpdpSolver)[source]
Bases:
MathOptCallback
- discrete_optimization.gpdp.solvers.lp_iterative.build_graph_solution(results: dict[str, dict[Hashable, Any]], obj: float, graph: Graph) TemporaryResult [source]
- discrete_optimization.gpdp.solvers.lp_iterative.build_graph_solutions(solutions: list[tuple[dict, float]], graph: Graph) list[TemporaryResult] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.build_path_from_vehicle_type_flow(result_from_retrieve: dict[str, dict[Hashable, Any]], problem: GpdpProblem) dict[int, list[Hashable]] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.build_the_cycles(flow_solution: dict[tuple[Hashable, Hashable], int], component: set[Hashable], start_index: Hashable, end_index: Hashable) tuple[list[Hashable], dict[Hashable, int]] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.construct_edges_in_out_dict(variables_edges: dict[int, dict[tuple[Hashable, Hashable], Any]], clusters_dict: dict[Hashable, Hashable]) tuple[dict[Hashable, set[tuple[int, tuple[Hashable, Hashable]]]], dict[Hashable, set[tuple[int, tuple[Hashable, Hashable]]]], dict[int, dict[Hashable, set[tuple[Hashable, Hashable]]]], dict[int, dict[Hashable, set[tuple[Hashable, Hashable]]]], dict[Hashable, set[tuple[int, tuple[Hashable, Hashable]]]], dict[Hashable, set[tuple[int, tuple[Hashable, Hashable]]]], dict[int, dict[Hashable, set[tuple[Hashable, Hashable]]]], dict[int, dict[Hashable, set[tuple[Hashable, Hashable]]]]] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.convert_temporaryresult_to_gpdpsolution(temporaryresult: TemporaryResult, problem: GpdpProblem) GpdpSolution [source]
- discrete_optimization.gpdp.solvers.lp_iterative.rebuild_routine(sorted_connected_component: list[tuple[set[Hashable], int]], paths_component: dict[int, list[Hashable]], node_to_component: dict[Hashable, int], indexes: dict[int, dict[Hashable, int]], graph: DiGraph, edges: set[tuple[Hashable, Hashable]], evaluate_function_indexes: Callable[[Hashable, Hashable], float], start_index: Hashable, end_index: Hashable) list[Hashable] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.rebuild_routine_variant(sorted_connected_component: list[tuple[set[Hashable], int]], paths_component: dict[int, list[Hashable]], node_to_component: dict[Hashable, int], indexes: dict[int, dict[Hashable, int]], graph: DiGraph, edges: set[tuple[Hashable, Hashable]], evaluate_function_indexes: Callable[[Hashable, Hashable], float], start_index: Hashable, end_index: Hashable) list[Hashable] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.reevaluate_result(temporary_result: TemporaryResult, problem: GpdpProblem, variant_rebuilt: bool = True, possible_subcycle_in_component: bool = True) TemporaryResult [source]
- discrete_optimization.gpdp.solvers.lp_iterative.retrieve_current_solution(get_var_value_for_current_solution: Callable[[Any], float], get_obj_value_for_current_solution: Callable[[], float], variable_decisions: dict[str, Any]) tuple[dict[str, dict[Hashable, Any]], float] [source]
- discrete_optimization.gpdp.solvers.lp_iterative.update_model_generic(problem: GpdpProblem, lp_solver: BaseLinearFlowGpdpSolver, components_global: list[tuple[set[Hashable], int]], edges_in_all_vehicles: dict[Hashable, set[tuple[int, tuple[Hashable, Hashable]]]], edges_out_all_vehicles: dict[Hashable, set[tuple[int, tuple[Hashable, Hashable]]]], lazy: bool = False, cluster: bool = False, consider_only_first_component: bool = True, do_order: bool = False) list[Any] [source]
discrete_optimization.gpdp.solvers.ortools_routing module
- class discrete_optimization.gpdp.solvers.ortools_routing.FirstSolutionStrategy(value)
Bases:
Enum
Enumeration of first solution strategies.
Extracted from ortools Enum-like class. https://developers.google.com/optimization/routing/routing_options#first_solution_strategy
- ALL_UNPERFORMED = 6
- AUTOMATIC = 15
- BEST_INSERTION = 7
- CHRISTOFIDES = 13
- EVALUATOR_STRATEGY = 5
- FIRST_UNBOUND_MIN_VALUE = 12
- GLOBAL_CHEAPEST_ARC = 1
- LOCAL_CHEAPEST_ARC = 2
- LOCAL_CHEAPEST_COST_INSERTION = 16
- LOCAL_CHEAPEST_INSERTION = 9
- PARALLEL_CHEAPEST_INSERTION = 8
- PATH_CHEAPEST_ARC = 3
- PATH_MOST_CONSTRAINED_ARC = 4
- SAVINGS = 10
- SEQUENTIAL_CHEAPEST_INSERTION = 14
- SWEEP = 11
- UNSET = 0
- class discrete_optimization.gpdp.solvers.ortools_routing.LocalSearchMetaheuristic(value)
Bases:
Enum
Enumeration of local search meta-heuristic.
Extracted from ortools Enum-like class. https://developers.google.com/optimization/routing/routing_options#local_search_options
- AUTOMATIC = 6
- GENERIC_TABU_SEARCH = 5
- GREEDY_DESCENT = 1
- GUIDED_LOCAL_SEARCH = 2
- SIMULATED_ANNEALING = 3
- TABU_SEARCH = 4
- UNSET = 0
- class discrete_optimization.gpdp.solvers.ortools_routing.NodePosition(value)[source]
Bases:
Enum
Node position inside a trajectory.
Useful e.g. to distinguish between the starting node and ending node when the trajectory is a loop.
- END = 'end'
- INTERMEDIATE = 'intermediate'
- START = 'start'
- class discrete_optimization.gpdp.solvers.ortools_routing.OrtoolsGpdpSolver(problem: GpdpProblem, factor_multiplier_distance: float = 1, factor_multiplier_time: float = 1, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]
Bases:
GpdpSolver
,WarmstartMixin
- hyperparameters: list[Hyperparameter] = [EnumHyperparameter(name='first_solution_strategy', default=<FirstSolutionStrategy.SAVINGS: 10>, depends_on=None, name_in_kwargs='first_solution_strategy'), EnumHyperparameter(name='local_search_metaheuristic', default=<LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH: 2>, depends_on=None, name_in_kwargs='local_search_metaheuristic'), CategoricalHyperparameter(name='use_lns', default=True, depends_on=None, name_in_kwargs='use_lns'), CategoricalHyperparameter(name='use_cp', default=True, depends_on=None, name_in_kwargs='use_cp'), CategoricalHyperparameter(name='use_cp_sat', default=False, depends_on=None, name_in_kwargs='use_cp_sat')]
Hyperparameters available for this solver.
- These hyperparameters are to be feed to **kwargs found in
__init__()
init_model() (when available)
solve()
- init_model(**kwargs: Any) None [source]
Initialize internal model used to solve.
Can initialize a ortools, milp, gurobi, … model.
- initial_solution: GpdpSolution | None = None
Initial solution used for warm start.
- problem: GpdpProblem
- set_warm_start(solution: GpdpSolution) None [source]
Make the solver warm start from the given solution.
Will be ignored if arg init_solution, is not None in call to solve().
- solve(search_parameters: RoutingSearchParameters | None = None, callbacks: list[Callback] | None = None, **kwargs: Any) ResultStorage [source]
Generic solving function.
- Parameters:
callbacks – list of callbacks used to hook into the various stage of the solve
**kwargs – any argument specific to the solver
Solvers deriving from SolverDo should use callbacks methods .on_step_end(), … during solve(). But some solvers are not yet updated and are just ignoring it.
Returns (ResultStorage): a result object containing potentially a pool of solutions to a discrete-optimization problem
- class discrete_optimization.gpdp.solvers.ortools_routing.ParametersCost(dimension_name: str, global_span: bool = True, sum_over_vehicles: bool = False, coefficient_vehicles: float | list[float] = 100)[source]
Bases:
object
- static default() ParametersCost [source]
- class discrete_optimization.gpdp.solvers.ortools_routing.RoutingMonitor(do_solver: OrtoolsGpdpSolver, callback: Callback)[source]
Bases:
SearchMonitor
- discrete_optimization.gpdp.solvers.ortools_routing.apply_cost(list_parameters_cost: list[ParametersCost], routing: RoutingModel) None [source]
- discrete_optimization.gpdp.solvers.ortools_routing.convert_to_gpdpsolution(problem: GpdpProblem, sol: tuple[dict[int, list[int]], dict[tuple[int, int, NodePosition], dict[str, tuple[float, float, float]]], float, float, float]) GpdpSolution [source]
- discrete_optimization.gpdp.solvers.ortools_routing.status_description = {0: 'ROUTING_NOT_SOLVED', 1: 'ROUTING_SUCCESS', 2: 'ROUTING_PARTIAL_SUCCESS_LOCAL_OPTIMUM_NOT_REACHED', 3: 'ROUTING_FAIL', 4: 'ROUTING_FAIL_TIMEOUT', 5: 'ROUTING_INVALID', 6: 'ROUTING_INFEASIBLE', 7: 'ROUTING_OPTIMAL'}
Mapping from status integer to description string.
This maps the integer returned by routing_model.status to the corresponding string.
We use the attributes of RoutingModel to construct the dictionary. https://developers.google.com/optimization/routing/routing_options#search_status