discrete_optimization.rcpsp package
Subpackages
- discrete_optimization.rcpsp.solvers package
- Subpackages
- Submodules
- discrete_optimization.rcpsp.solvers.cp_mzn module
CPMultimodeWithFakeTaskRcpspSolver()CpModesMultimodeRcpspSolverCpMultimodePreemptiveRcpspSolverCpMultimodePreemptiveRcpspSolver.add_hard_special_constraints()CpMultimodePreemptiveRcpspSolver.constraint_duration_string_preemptive_i()CpMultimodePreemptiveRcpspSolver.constraint_duration_to_min_duration_preemptive()CpMultimodePreemptiveRcpspSolver.constraint_end_time_string()CpMultimodePreemptiveRcpspSolver.constraint_minduration_all_tasks()CpMultimodePreemptiveRcpspSolver.constraint_objective_equal_makespan()CpMultimodePreemptiveRcpspSolver.constraint_objective_makespan()CpMultimodePreemptiveRcpspSolver.constraint_objective_max_time_set_of_jobs()CpMultimodePreemptiveRcpspSolver.constraint_ressource_requirement_at_time_t()CpMultimodePreemptiveRcpspSolver.constraint_start_time_precomputed()CpMultimodePreemptiveRcpspSolver.constraint_start_time_string()CpMultimodePreemptiveRcpspSolver.constraint_start_time_string_preemptive_i()CpMultimodePreemptiveRcpspSolver.constraint_sum_of_ending_time()CpMultimodePreemptiveRcpspSolver.constraint_sum_of_starting_time()CpMultimodePreemptiveRcpspSolver.constraint_task_to_mode()CpMultimodePreemptiveRcpspSolver.index_in_minizincCpMultimodePreemptiveRcpspSolver.init_model()CpMultimodePreemptiveRcpspSolver.mode_dict_task_mode_to_index_minizincCpMultimodePreemptiveRcpspSolver.modeindex_mapCpMultimodePreemptiveRcpspSolver.problemCpMultimodePreemptiveRcpspSolver.retrieve_solution()
CpMultimodeRcpspSolverCpMultimodeRcpspSolver.add_hard_special_constraints()CpMultimodeRcpspSolver.constraint_end_time_string()CpMultimodeRcpspSolver.constraint_objective_equal_makespan()CpMultimodeRcpspSolver.constraint_objective_makespan()CpMultimodeRcpspSolver.constraint_objective_max_time_set_of_jobs()CpMultimodeRcpspSolver.constraint_start_time_string()CpMultimodeRcpspSolver.constraint_sum_of_ending_time()CpMultimodeRcpspSolver.constraint_sum_of_starting_time()CpMultimodeRcpspSolver.constraint_task_to_mode()CpMultimodeRcpspSolver.hyperparametersCpMultimodeRcpspSolver.index_in_minizincCpMultimodeRcpspSolver.init_model()CpMultimodeRcpspSolver.keys_in_instanceCpMultimodeRcpspSolver.mode_dict_task_mode_to_index_minizincCpMultimodeRcpspSolver.modeindex_mapCpMultimodeRcpspSolver.problemCpMultimodeRcpspSolver.retrieve_solution()
CpNoBoolMultimodeRcpspSolverCpNoBoolMultimodeRcpspSolver.constraint_end_time_string()CpNoBoolMultimodeRcpspSolver.constraint_objective_equal_makespan()CpNoBoolMultimodeRcpspSolver.constraint_objective_makespan()CpNoBoolMultimodeRcpspSolver.constraint_objective_max_time_set_of_jobs()CpNoBoolMultimodeRcpspSolver.constraint_start_time_string()CpNoBoolMultimodeRcpspSolver.index_in_minizincCpNoBoolMultimodeRcpspSolver.init_model()CpNoBoolMultimodeRcpspSolver.problemCpNoBoolMultimodeRcpspSolver.retrieve_solution()
CpPreemptiveRcpspSolverCpRcpspSolverCpRcpspSolver.add_hard_special_constraints()CpRcpspSolver.constraint_end_time_string()CpRcpspSolver.constraint_objective_equal_makespan()CpRcpspSolver.constraint_objective_makespan()CpRcpspSolver.constraint_objective_max_time_set_of_jobs()CpRcpspSolver.constraint_start_time_string()CpRcpspSolver.constraint_sum_of_ending_time()CpRcpspSolver.constraint_sum_of_starting_time()CpRcpspSolver.get_stats()CpRcpspSolver.hyperparametersCpRcpspSolver.init_model()CpRcpspSolver.keys_in_instanceCpRcpspSolver.problemCpRcpspSolver.retrieve_solution()
add_constraints_string()add_fake_task_cp_data()add_hard_special_constraints()add_hard_special_constraints_mrcpsp()add_soft_special_constraints()add_soft_special_constraints_mrcpsp()define_second_part_objective()hard_end_window()hard_start_after_nunit()hard_start_after_nunit_mrcpsp()hard_start_at_end()hard_start_at_end_mrcpsp()hard_start_at_end_plus_offset()hard_start_at_end_plus_offset_mrcpsp()hard_start_times()hard_start_times_mrcpsp()hard_start_together()hard_start_together_mrcpsp()hard_start_window()precompute_possible_starting_time_interval()soft_end_window()soft_end_window_mrcpsp()soft_start_after_nunit()soft_start_after_nunit_mrcpsp()soft_start_at_end()soft_start_at_end_mrcpsp()soft_start_at_end_plus_offset()soft_start_at_end_plus_offset_mrcpsp()soft_start_times()soft_start_times_mrcpsp()soft_start_together()soft_start_together_mrcpsp()soft_start_window()soft_start_window_mrcpsp()
- discrete_optimization.rcpsp.solvers.cp_mzn_models module
CpModelEnumCpModelEnum.MODESCpModelEnum.MULTICpModelEnum.MULTI_CALENDARCpModelEnum.MULTI_CALENDAR_BOXESCpModelEnum.MULTI_FAKETASKSCpModelEnum.MULTI_NO_BOOLCpModelEnum.MULTI_PREEMPTIVECpModelEnum.MULTI_PREEMPTIVE_CALENDARCpModelEnum.MULTI_RESOURCE_FEASIBILITYCpModelEnum.SINGLECpModelEnum.SINGLE_PREEMPTIVECpModelEnum.SINGLE_PREEMPTIVE_CALENDAR
- discrete_optimization.rcpsp.solvers.cp_mzn_multiscenario module
- discrete_optimization.rcpsp.solvers.cpm module
- discrete_optimization.rcpsp.solvers.cpsat module
CpSatCumulativeResourceRcpspSolverCpSatCumulativeResourceRcpspSolver.add_lexico_constraint()CpSatCumulativeResourceRcpspSolver.create_cumulative_constraint_and_resource_capa()CpSatCumulativeResourceRcpspSolver.create_resource_capacity_var()CpSatCumulativeResourceRcpspSolver.get_lexico_objective_value()CpSatCumulativeResourceRcpspSolver.get_lexico_objectives_available()CpSatCumulativeResourceRcpspSolver.hyperparametersCpSatCumulativeResourceRcpspSolver.implements_lexico_api()CpSatCumulativeResourceRcpspSolver.init_model()CpSatCumulativeResourceRcpspSolver.retrieve_solution()CpSatCumulativeResourceRcpspSolver.set_lexico_objective()
CpSatRcpspSolverCpSatRcpspSolver.add_classical_precedence_constraints()CpSatRcpspSolver.add_one_mode_selected_per_task()CpSatRcpspSolver.cp_solverCpSatRcpspSolver.create_cumulative_constraint()CpSatRcpspSolver.create_fake_tasks()CpSatRcpspSolver.create_mode_pair_constraint()CpSatRcpspSolver.get_global_makespan_variable()CpSatRcpspSolver.get_task_mode_is_present_variable()CpSatRcpspSolver.get_task_start_or_end_variable()CpSatRcpspSolver.init_model()CpSatRcpspSolver.init_temporal_variable()CpSatRcpspSolver.problemCpSatRcpspSolver.retrieve_solution()CpSatRcpspSolver.set_warm_start()CpSatRcpspSolver.variables
CpSatResourceRcpspSolverCpSatResourceRcpspSolver.add_lexico_constraint()CpSatResourceRcpspSolver.create_cumulative_constraint_and_used_resource()CpSatResourceRcpspSolver.get_lexico_objective_value()CpSatResourceRcpspSolver.get_lexico_objectives_available()CpSatResourceRcpspSolver.implements_lexico_api()CpSatResourceRcpspSolver.init_model()CpSatResourceRcpspSolver.retrieve_solution()CpSatResourceRcpspSolver.set_lexico_objective()
- discrete_optimization.rcpsp.solvers.dp module
DpRcpspModelingDpRcpspSolverDpRcpspSolver.hyperparametersDpRcpspSolver.init_model()DpRcpspSolver.init_model_multimode()DpRcpspSolver.init_model_multimode_calendar()DpRcpspSolver.init_model_task()DpRcpspSolver.init_model_task_time()DpRcpspSolver.init_model_task_time_calendar()DpRcpspSolver.init_model_task_upd()DpRcpspSolver.modelingDpRcpspSolver.problemDpRcpspSolver.retrieve_solution()DpRcpspSolver.retrieve_solution_multimode()DpRcpspSolver.retrieve_solution_task()DpRcpspSolver.retrieve_solution_task_time()DpRcpspSolver.set_warm_start()DpRcpspSolver.transitions
create_resource_consumption_from_calendar()
- discrete_optimization.rcpsp.solvers.ga module
- discrete_optimization.rcpsp.solvers.lns_cp module
- discrete_optimization.rcpsp.solvers.lns_cp_preemptive module
- discrete_optimization.rcpsp.solvers.lns_lp module
- discrete_optimization.rcpsp.solvers.lp module
- discrete_optimization.rcpsp.solvers.lp_gantt module
- discrete_optimization.rcpsp.solvers.optal module
OptalRcpspSolverOptalRcpspSolver.create_cumulative_constraints()OptalRcpspSolver.create_fake_tasks()OptalRcpspSolver.create_interval_vars()OptalRcpspSolver.create_precedence_constraints()OptalRcpspSolver.get_task_interval_variable()OptalRcpspSolver.get_task_mode_is_present_variable()OptalRcpspSolver.init_model()OptalRcpspSolver.problemOptalRcpspSolver.retrieve_solution()OptalRcpspSolver.set_warm_start()
- discrete_optimization.rcpsp.solvers.pile module
- discrete_optimization.rcpsp.solvers.rcpsp_solver module
- discrete_optimization.rcpsp.solvers.tempo module
- discrete_optimization.rcpsp.solvers.toulbar module
- Module contents
Submodules
discrete_optimization.rcpsp.fast_function module
- discrete_optimization.rcpsp.fast_function.compute_mean_ressource(modes_array: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], start_array: ndarray[tuple[Any, ...], dtype[int64]], end_array: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]]) float[source]
- discrete_optimization.rcpsp.fast_function.compute_ressource_consumption(modes_array: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], start_array: ndarray[tuple[Any, ...], dtype[int64]], end_array: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]]) dict[int, ndarray[tuple[Any, ...], dtype[int64]]][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast(permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], minimum_starting_time_array: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, tuple[int, int]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_partial_schedule(current_time: int, permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], completed_task_indicator: ndarray[tuple[Any, ...], dtype[int64]], completed_task_times: ndarray[tuple[Any, ...], dtype[int64]], scheduled_task: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], minimum_starting_time_array: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, tuple[int, int]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_partial_schedule_incomplete_permutation_tasks(current_time: int, permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], completed_task_indicator: ndarray[tuple[Any, ...], dtype[int64]], completed_task_times: ndarray[tuple[Any, ...], dtype[int64]], scheduled_task: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], minimum_starting_time_array: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, tuple[int, int]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_partial_schedule_preemptive(current_time: int, permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], completed_task_indicator: ndarray[tuple[Any, ...], dtype[int64]], partial_schedule_starts: ndarray[tuple[Any, ...], dtype[int64]], partial_schedule_ends: ndarray[tuple[Any, ...], dtype[int64]], preemptive_tag: ndarray[tuple[Any, ...], dtype[bool]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], minimum_starting_time_array: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, ndarray[tuple[Any, ...], dtype[int64]]], dict[int, ndarray[tuple[Any, ...], dtype[int64]]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_partial_schedule_preemptive_minduration(current_time: int, permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], completed_task_indicator: ndarray[tuple[Any, ...], dtype[int64]], partial_schedule_starts: ndarray[tuple[Any, ...], dtype[int64]], partial_schedule_ends: ndarray[tuple[Any, ...], dtype[int64]], preemptive_tag: ndarray[tuple[Any, ...], dtype[bool]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], min_duration_preemptive_bool: ndarray[tuple[Any, ...], dtype[bool]], min_duration_preemptive: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, ndarray[tuple[Any, ...], dtype[int64]]], dict[int, ndarray[tuple[Any, ...], dtype[int64]]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_preemptive(permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], preemptive_tag: ndarray[tuple[Any, ...], dtype[bool]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], minimum_starting_time_array: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, ndarray[tuple[Any, ...], dtype[int64]]], dict[int, ndarray[tuple[Any, ...], dtype[int64]]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_preemptive_minduration(permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], preemptive_tag: ndarray[tuple[Any, ...], dtype[bool]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]], min_duration_preemptive_bool: ndarray[tuple[Any, ...], dtype[bool]], min_duration_preemptive: ndarray[tuple[Any, ...], dtype[int64]]) tuple[dict[int, ndarray[tuple[Any, ...], dtype[int64]]], dict[int, ndarray[tuple[Any, ...], dtype[int64]]], bool][source]
- discrete_optimization.rcpsp.fast_function.sgs_fast_preemptive_some_special_constraints(permutation_task: ndarray[tuple[Any, ...], dtype[int64]], modes_array: ndarray[tuple[Any, ...], dtype[int64]], consumption_array: ndarray[tuple[Any, ...], dtype[int64]], duration_array: ndarray[tuple[Any, ...], dtype[int64]], preemptive_tag: ndarray[tuple[Any, ...], dtype[bool]], predecessors: ndarray[tuple[Any, ...], dtype[int64]], successors: ndarray[tuple[Any, ...], dtype[int64]], start_at_end_plus_offset: ndarray[tuple[Any, ...], dtype[int64]], start_after_nunit: ndarray[tuple[Any, ...], dtype[int64]], minimum_starting_time_array: ndarray[tuple[Any, ...], dtype[int64]], horizon: int, ressource_available: ndarray[tuple[Any, ...], dtype[int64]], ressource_renewable: ndarray[tuple[Any, ...], dtype[bool]]) tuple[dict[int, ndarray[tuple[Any, ...], dtype[int64]]], dict[int, ndarray[tuple[Any, ...], dtype[int64]]], bool][source]
discrete_optimization.rcpsp.parser module
- discrete_optimization.rcpsp.parser.get_data_available(data_folder: str | None = None, data_home: str | None = None) list[str][source]
Get datasets available for rcpsp.
- Params:
- data_folder: folder where datasets for rcpsp whould be find.
If None, we look in “rcpsp” subdirectory of data_home.
- data_home: root directory for all datasets. Is None, set by
default to “~/discrete_optimization_data “
- discrete_optimization.rcpsp.parser.parse_file(file_path: str) RcpspProblem[source]
- discrete_optimization.rcpsp.parser.parse_patterson(input_data: str) RcpspProblem[source]
- discrete_optimization.rcpsp.parser.parse_psplib(input_data: str) RcpspProblem[source]
discrete_optimization.rcpsp.problem module
- class discrete_optimization.rcpsp.problem.RcpspProblem(resources: dict[str, int | list[int]], non_renewable_resources: list[str], mode_details: dict[Hashable, dict[int, dict[str, int]]], successors: dict[Hashable, list[Hashable]], horizon: int, horizon_multiplier: int = 1, tasks_list: list[Hashable] | None = None, source_task: Hashable | None = None, sink_task: Hashable | None = None, name_task: dict[Hashable, str] | None = None, calendar_details: dict[str, list[list[int]]] | None = None, special_constraints: SpecialConstraintsDescription | None = None, relax_the_start_at_end: bool = True, fixed_permutation: list[int] | None = None, fixed_modes: list[int] | None = None, **kwargs: Any)[source]
Bases:
MultimodeProblem[Hashable],SchedulingProblem[Hashable],PrecedenceProblem[Hashable]Main class for RCPSP problem.
- resources
mapping: name -> number of resources available, either at each time (-if an integer), or time step by time step (if a list of integers).
- Type:
dict[str, Union[int, list[int]
- non_renewable_resources
list of resources (specified by name) that are non-renewable
- Type:
list[str]
- mode_details
task -> (mode number -> resource needs and duration) Ex: >>> mode_details = { “task1” : … { # task1 details … 1: { “duration”: 2, “R1”: 1, “R2”: 0, “R3”: 4 }, # task1, mode 1: duration = 2, resource needs: R1=1, R3=4 … 2: { “duration”: 10, “R1”: 0, “R2”: 2, “R3”: 0 }, # task1, mode 1: duration = 10, resource needs: R2=2 … }, … # [other tasks] … }
- Type:
dict[Hashable, dict[int, dict[str, int]]]
- successors
successors in the precedence graph of each task
- Type:
dict[Hashable, list[Hashable]]
- horizon
max number of time steps allowed
- Type:
int
- horizon_multiplier
not used
- tasks_list
list of tasks. Must correspond to mode_details. If not given will be equal to list(mode_details).
- Type:
list[Hashable]
- source_task
the id for the source task (i.e. the root in the precedence graph, all other tasks must follow it). If not given and tasks_list is made of integers, the lowest one
- Type:
Hashable
- sink_task
the id for the source task (i.e. the last task in the precedence graph, follows all other tasks). If not given and tasks_list is made of integers, the highest one.
- Type:
Hashable
- tasks_list_non_dummy
tasks list excluding source and sink. Same order as tasks_list
- Type:
list[Hashable]
- name_task
mapping task ids to task names. Default to id -> str(id)
- Type:
dict[Hashable, str]
- n_jobs
numer of tasks (i.e. len(tasks_list))
- Type:
int
- n_jobs_non_dummy
number of tasks excluding dummy activities Start (0) and End (n). (i.e. n_jobs - 2)
- Type:
int
- index_task
mapping task id to index among all tasks (from 0 to n_jobs)
- Type:
dict[Hashable, int]
- index_task_non_dummy
mapping task id to index among all non-dummy tasks (from 0 to n_jobs_non_dummy)
- Type:
dict[Hashable, int]
- special_constraints
special additional constraints
- do_special_constraints
True if they are special constraints to take into account
- Type:
bool
- relax_the_start_at_end
relax some conditions, only if do_special_constraints.
- Type:
bool
- fixed_permutation
To be used by solutions specifying only rcpsp_modes, e.g. in alternating genetic algorithms, that are updating only one solution attribute at a time. See RcpspSolution for more details.
- Type:
Optional[list[int]]
- fixed_modes
To be used by solutions specifying only the rpsp_permutation, e.g. in alternating genetic algorithms, that are updating only one solution attribute at a time. See RcpspSolution for more details.
- Type:
Optional[list[int]]
Example
Initializing a simple RCPSP problem with 4 tasks, 2 resources, and precedence constraints, then generating a baseline schedule.
>>> from discrete_optimization.rcpsp.problem import RcpspProblem >>> from discrete_optimization.rcpsp.solution import RcpspSolution >>> # Define resources >>> resources = {"R1": 5, "R2": 2} >>> non_renewable_resources = [] # Empty if all resources replenish when a task ends >>> # Define mode details >>> # Format: { task_id: { mode_id: { "duration": int, "resource_name": amount } } } >>> mode_details = { ... "source": {1: {"duration": 0, "R1": 0, "R2": 0}}, # Source (Dummy) ... "task-1": {1: {"duration": 4, "R1": 2, "R2": 2}}, ... "task-2": {1: {"duration": 3, "R1": 3, "R2": 0}}, ... "task-3": {1: {"duration": 5, "R1": 2, "R2": 1}}, ... "task-4": {1: {"duration": 2, "R1": 1, "R2": 1}}, ... "sink": {1: {"duration": 0, "R1": 0, "R2": 0}}, # Sink (Dummy) ... } >>> # Define precedence graph >>> successors = { ... "source": ["task-1", "task-2"], # First tasks: 1 and 2 ... "task-1": ["task-3"], # Task 1 must finish before 3 ... "task-2": ["task-4"], # Task 2 must finish before 4 ... "task-3": ["sink"], # Task 3 leads to Sink ... "task-4": ["sink"], # Task 4 leads to Sink ... "sink": [], # Sink has no successors ... } >>> # Initialize the Problem >>> problem = RcpspProblem( ... resources=resources, ... non_renewable_resources=non_renewable_resources, ... mode_details=mode_details, ... successors=successors, ... horizon=20, # Maximum time allowed for the project ... source_task="source", ... sink_task="sink" ... ) >>> # Get a dummy solution: use serial sgs on trivial permutation >>> # See RcpspSolution docstring for more information. >>> sol = problem.get_dummy_solution() >>> print(sol.rcpsp_schedule) {'source': {'start_time': 0, 'end_time': 0}, 'task-1': {'start_time': 0, 'end_time': 4}, 'task-2': {'start_time': 0, 'end_time': 3}, 'task-3': {'start_time': 4, 'end_time': 9}, 'task-4': {'start_time': 4, 'end_time': 6}, 'sink': {'start_time': 9, 'end_time': 9}} >>> # index_task vs index_task_non_dummy >>> problem.index_task # index among all tasks: task-1 -> 1 {'source': 0, 'task-1': 1, 'task-2': 2, 'task-3': 3, 'task-4': 4, 'sink': 5} >>> problem.index_task_non_dummy # index among only non-dummy tasks: task-1 -> 0 {'task-1': 0, 'task-2': 1, 'task-3': 2, 'task-4': 3} >>> # Convert permutation of tasks into a list opf non-dummy indices >>> problem.convert_task_ids_to_permutation(["task-3", "task-2", "task-4", "task-1"]) [2, 1, 3, 0]
- compute_resource_consumption(rcpsp_sol: RcpspSolution) ndarray[tuple[Any, ...], dtype[int64]][source]
- convert_task_ids_to_permutation(tasks: list[Hashable]) list[int][source]
Convert list of task ids into a permutation in proper format for RcpspSolution.
remove source and sink if present
use the indices among non-dummy tasks
- Parameters:
tasks
Returns:
- copy() RcpspProblem[source]
- evaluate(variable: RcpspSolution) dict[str, float][source]
Evaluate a given solution object for the given problem.
This method should return a dictionnary of KPI, that can be then used for mono or multiobjective optimization.
- Parameters:
variable (Solution) – the Solution object to evaluate.
Returns: dictionnary of float kpi for the solution.
- evaluate_function(rcpsp_sol: RcpspSolution) tuple[int, float, int][source]
- evaluate_mobj(variable: RcpspSolution) TupleFitness[source]
Default implementation of multiobjective evaluation.
It consists in flattening the evaluate() function and put in an array. User should probably custom this to be more efficient.
- Parameters:
variable (Solution) – the Solution object to evaluate.
Returns (TupleFitness): a flattened tuple fitness object representing the multi-objective criteria.
- evaluate_mobj_from_dict(dict_values: dict[str, float]) TupleFitness[source]
Return an multiobjective fitness from a dictionnary of kpi (output of evaluate function).
It consists in flattening the evaluate() function and put in an array. User should probably custom this to be more efficient.
- Parameters:
dict_values – output of evaluate() function
Returns (TupleFitness): a flattened tuple fitness object representing the multi-objective criteria.
- get_attribute_register() EncodingRegister[source]
Returns how the Solution should be encoded.
Useful to find automatically available mutations for local search. Used by genetic algorithms Ga and Nsga.
This needs only to be implemented in child classes when GA or LS solvers are to be used.
Returns (EncodingRegister): content of the encoding of the solution
- get_dummy_solution() RcpspSolution[source]
Apply serial sgs on the trivial task permutation.
See RcpspSolution about details on conversion permutation -> schedule.
Returns:
- get_last_tasks() list[Hashable][source]
Get a sublist of tasks that are candidate to be the last one scheduled.
Default to all tasks.
- get_objective_register() ObjectiveRegister[source]
Returns the objective definition.
Returns (ObjectiveRegister): object defining the objective criteria.
- get_precedence_constraints() dict[Hashable, Iterable[Hashable]][source]
Map each task to the tasks that need to be performed after it.
- get_solution_type() type[Solution][source]
Returns the class implementation of a Solution.
Returns (class): class object of the given Problem.
- get_task_modes(task: Hashable) set[int][source]
Retrieve mode found for given task.
- Parameters:
task
Returns:
- plot_ressource_view(rcpsp_sol: RcpspSolution) None[source]
- satisfy(variable: RcpspSolution) bool[source]
Computes if a solution satisfies or not the constraints of the problem.
- Parameters:
variable – the Solution object to check satisfability
Returns (bool): boolean true if the constraints are fulfilled, false elsewhere.
- set_fixed_attributes(attribute_name: str, solution: RcpspSolution) None[source]
Fix some solution attribute.
Useful when applying successively GA on different attribute of the solution, fixing the others.
Should be implemented at least for attributes described by attribute_register.
- Parameters:
attribute_name – an attribute name
solution
Returns:
- property tasks_list: list[Hashable]
List of all tasks to schedule or allocate to.
- class discrete_optimization.rcpsp.problem.ScheduleGenerationScheme(*values)[source]
Bases:
Enum- PARALLEL_SGS = 1
- SERIAL_SGS = 0
- discrete_optimization.rcpsp.problem.check_pair_mode_constraint(solution: RcpspSolution, pair_mode_constraint: PairModeConstraint)[source]
- discrete_optimization.rcpsp.problem.check_solution_with_special_constraints(problem: RcpspProblem, solution: RcpspSolution, relax_the_start_at_end: bool = True) bool[source]
- discrete_optimization.rcpsp.problem.compute_constraints_details(solution: RcpspSolution, constraints: SpecialConstraintsDescription) list[tuple[str, Hashable, Hashable, int | None, int | None, int]][source]
- discrete_optimization.rcpsp.problem.compute_details_mode_constraint(solution: RcpspSolution, pair_mode_constraint: PairModeConstraint)[source]
- discrete_optimization.rcpsp.problem.create_np_data_and_jit_functions(rcpsp_problem: RcpspProblem) tuple[Callable[[...], tuple[dict[int, tuple[int, int]], bool]], Callable[[...], tuple[dict[int, tuple[int, int]], bool]], Callable[[...], float]][source]
- discrete_optimization.rcpsp.problem.evaluate_constraints(solution: RcpspSolution, constraints: SpecialConstraintsDescription) int[source]
discrete_optimization.rcpsp.problem_preemptive module
- class discrete_optimization.rcpsp.problem_preemptive.PartialPreemptiveRcpspSolution(task_mode: dict[int, int] = None, start_times: dict[int, int] = None, end_times: dict[int, int] = None, partial_permutation: list[int] = None, list_partial_order: list[list[int]] = None, start_together: list[tuple[int, int]] = None, start_at_end: list[tuple[int, int]] = None, start_at_end_plus_offset: list[tuple[int, int, int]] = None, start_after_nunit: list[tuple[int, int, int]] = None, disjunctive_tasks: list[tuple[int, int]] = None, start_times_window: dict[Hashable, tuple[int, int]] = None, end_times_window: dict[Hashable, tuple[int, int]] = None)[source]
Bases:
object
- class discrete_optimization.rcpsp.problem_preemptive.PreemptiveRcpspProblem(resources: dict[str, int] | dict[str, list[int]], non_renewable_resources: list[str], mode_details: dict[Hashable, dict[str | int, dict[str, int]]], successors: dict[int | str, list[str | int]], horizon, horizon_multiplier=1, tasks_list: list[int | str] = None, source_task=None, sink_task=None, preemptive_indicator: dict[Hashable, bool] = None, duration_subtask: dict[Hashable, tuple[bool, int]] = None, name_task: dict[int, str] = None)[source]
Bases:
Problem- compute_resource_consumption(rcpsp_sol: PreemptiveRcpspSolution)[source]
- evaluate(variable: PreemptiveRcpspSolution) dict[str, float][source]
Evaluate a given solution object for the given problem.
This method should return a dictionnary of KPI, that can be then used for mono or multiobjective optimization.
- Parameters:
variable (Solution) – the Solution object to evaluate.
Returns: dictionnary of float kpi for the solution.
- evaluate_function(rcpsp_sol: PreemptiveRcpspSolution)[source]
- evaluate_mobj(variable: PreemptiveRcpspSolution)[source]
Default implementation of multiobjective evaluation.
It consists in flattening the evaluate() function and put in an array. User should probably custom this to be more efficient.
- Parameters:
variable (Solution) – the Solution object to evaluate.
Returns (TupleFitness): a flattened tuple fitness object representing the multi-objective criteria.
- evaluate_mobj_from_dict(dict_values: dict[str, float]) TupleFitness[source]
Return an multiobjective fitness from a dictionnary of kpi (output of evaluate function).
It consists in flattening the evaluate() function and put in an array. User should probably custom this to be more efficient.
- Parameters:
dict_values – output of evaluate() function
Returns (TupleFitness): a flattened tuple fitness object representing the multi-objective criteria.
- get_attribute_register() EncodingRegister[source]
Returns how the Solution should be encoded.
Useful to find automatically available mutations for local search. Used by genetic algorithms Ga and Nsga.
This needs only to be implemented in child classes when GA or LS solvers are to be used.
Returns (EncodingRegister): content of the encoding of the solution
- get_dummy_solution()[source]
Create a trivial solution for the problem.
Should satisfy the problem ideally. Does not exist for all kind of problems.
- get_modes_dict(rcpsp_solution: PreemptiveRcpspSolution)[source]
- get_objective_register() ObjectiveRegister[source]
Returns the objective definition.
Returns (ObjectiveRegister): object defining the objective criteria.
- get_solution_type() type[Solution][source]
Returns the class implementation of a Solution.
Returns (class): class object of the given Problem.
- mode_details: dict[Hashable, dict[int, dict[str, int]]]
- n_jobs: int
- non_renewable_resources: list[str]
- plot_ressource_view(rcpsp_sol: PreemptiveRcpspSolution)[source]
- resources: dict[str, int] | dict[str, list[int]]
- satisfy(variable: PreemptiveRcpspSolution) bool[source]
Computes if a solution satisfies or not the constraints of the problem.
- Parameters:
variable – the Solution object to check satisfability
Returns (bool): boolean true if the constraints are fulfilled, false elsewhere.
- successors: dict[int, list[int]]
- class discrete_optimization.rcpsp.problem_preemptive.PreemptiveRcpspSolution(problem: PreemptiveRcpspProblem, rcpsp_permutation: list[int] | ndarray | None = None, rcpsp_schedule: dict[Hashable, dict[str, list[int]]] | None = None, rcpsp_modes: list[int] | None = None, rcpsp_schedule_feasible: bool | None = None, standardised_permutation: list[int] | ndarray | None = None)[source]
Bases:
Solution- change_problem(new_problem: Problem)[source]
If relevant to the optimisation problem, change the underlying problem instance for the solution.
This method can be used to evaluate a solution for different instance of problems. It should be implemented in child classes when caching subresults depending on the problem.
- Parameters:
new_problem (Problem) – another problem instance from which the solution can be evaluated
Returns: None
- copy()[source]
Deep copy of the solution.
The copy() function should return a new object containing the same input as the current object, that respects the following expected behaviour: -y = x.copy() -if do some inplace change of y, the changes are not done in x.
Returns: a new object from which you can manipulate attributes without changing the original object.
- generate_schedule_from_permutation_serial_sgs_2(current_t=0, completed_tasks: set[Hashable] | None = None, partial_schedule: dict[Hashable, dict[str, list[int]]] | None = None, do_fast=True)[source]
- lazy_copy()[source]
This function should return a new object but possibly with mutable attributes from the original objects.
A typical use of lazy copy is in evolutionary algorithms or genetic algorithm where the use of local move don’t need to do a possibly costly deepcopy.
Returns (Solution): copy (possibly shallow) of the Solution
- problem: PreemptiveRcpspProblem
- rcpsp_modes: list[int]
- rcpsp_permutation: list[int] | ndarray
- rcpsp_schedule: dict[Hashable, dict[str, list[int]]]
- standardised_permutation: list[int] | ndarray
- class discrete_optimization.rcpsp.problem_preemptive.ScheduleGenerationScheme(*values)[source]
Bases:
Enum- PARALLEL_SGS = 1
- SERIAL_SGS = 0
- discrete_optimization.rcpsp.problem_preemptive.compute_mean_resource_reserve(solution: PreemptiveRcpspSolution, rcpsp_problem: PreemptiveRcpspProblem)[source]
- discrete_optimization.rcpsp.problem_preemptive.compute_resource(solution: PreemptiveRcpspSolution, rcpsp_problem: PreemptiveRcpspProblem)[source]
- discrete_optimization.rcpsp.problem_preemptive.create_np_data_and_jit_functions(rcpsp_problem: PreemptiveRcpspProblem)[source]
- discrete_optimization.rcpsp.problem_preemptive.generate_schedule_from_permutation_serial_sgs(solution: PreemptiveRcpspSolution, rcpsp_problem: PreemptiveRcpspProblem)[source]
- discrete_optimization.rcpsp.problem_preemptive.generate_schedule_from_permutation_serial_sgs_partial_schedule(solution: PreemptiveRcpspSolution, rcpsp_problem: PreemptiveRcpspProblem, partial_schedule: dict[Hashable, dict[str, list[int]]], current_t: int, completed_tasks: set[Hashable]) tuple[dict[int, dict[str, list[int]]], bool][source]
- discrete_optimization.rcpsp.problem_preemptive.get_rcpsp_problemp_preemptive(rcpsp_problem)[source]
- discrete_optimization.rcpsp.problem_preemptive.permutation_do_to_permutation_sgs_fast(rcpsp_problem: PreemptiveRcpspProblem, permutation_do: Iterable[int]) ndarray[tuple[Any, ...], dtype[int64]][source]
discrete_optimization.rcpsp.problem_robust module
- class discrete_optimization.rcpsp.problem_robust.AggregRcpspProblem(list_problem: Sequence[RcpspProblem], method_aggregating: MethodAggregating)[source]
Bases:
RobustProblem,RcpspProblem- evaluate(variable: RcpspSolution) dict[str, float][source]
Aggregated evaluate function.
- Parameters:
variable (Solution) – Solution to evaluate on the different scenarios.
Returns (dict[str,float]): aggregated kpi on different scenarios.
- evaluate_from_encoding(int_vector: list[int], encoding_name: str) dict[str, float][source]
Evaluate a solution represented by its encoding.
Necessary to apply a genetic algorithm.
- Parameters:
int_vector – solution attribute seen as a list of integer
encoding_name – name of the solution attribute used. Should be an entry of self.get_attribute_register().
Returns:
- get_dummy_solution() RcpspSolution[source]
Create a trivial solution for the problem.
Should satisfy the problem ideally. Does not exist for all kind of problems.
- get_unique_rcpsp_problem() RcpspProblem[source]
- list_problem: Sequence[RcpspProblem]
- class discrete_optimization.rcpsp.problem_robust.MethodBaseRobustification(*values)[source]
Bases:
Enum- AVERAGE = 0
- BEST_CASE = 2
- PERCENTILE = 3
- SAMPLE = 4
- WORST_CASE = 1
- class discrete_optimization.rcpsp.problem_robust.MethodRobustification(method_base: MethodBaseRobustification, percentile: float = 50)[source]
Bases:
object- method_base: MethodBaseRobustification
- percentile: float
- class discrete_optimization.rcpsp.problem_robust.UncertainRcpspProblem(base_rcpsp_problem: RcpspProblem, poisson_laws: dict[Hashable, dict[int, dict[str, tuple[int, int, int]]]], uniform_law: bool = True)[source]
Bases:
object- create_rcpsp_problem(method_robustification: MethodRobustification) RcpspProblem[source]
- probas: dict[Hashable, dict[int, dict[str, dict[str, Any]]]]
- discrete_optimization.rcpsp.problem_robust.create_poisson_laws(base_rcpsp_problem: RcpspProblem, range_around_mean_resource: int = 1, range_around_mean_duration: int = 3, do_uncertain_resource: bool = True, do_uncertain_duration: bool = True) dict[Hashable, dict[int, dict[str, tuple[int, int, int]]]][source]
- discrete_optimization.rcpsp.problem_robust.create_poisson_laws_duration(rcpsp_problem: RcpspProblem, range_around_mean: int = 3) dict[Hashable, dict[int, dict[str, tuple[int, int, int]]]][source]
- discrete_optimization.rcpsp.problem_robust.create_poisson_laws_resource(rcpsp_problem: RcpspProblem, range_around_mean: int = 1) dict[Hashable, dict[int, dict[str, tuple[int, int, int]]]][source]
discrete_optimization.rcpsp.problem_specialized_constraints module
- class discrete_optimization.rcpsp.problem_specialized_constraints.SpecialConstraintsPreemptiveRcpspProblem(resources: dict[str, int] | dict[str, list[int]], non_renewable_resources: list[str], mode_details: dict[Hashable, dict[str | int, dict[str, int]]], successors: dict[int | str, list[str | int]], horizon, special_constraints: SpecialConstraintsDescription = None, preemptive_indicator: dict[Hashable, bool] = None, relax_the_start_at_end: bool = True, tasks_list: list[int | str] = None, source_task=None, sink_task=None, name_task: dict[int, str] = None, **kwargs)[source]
Bases:
PreemptiveRcpspProblem- evaluate(variable: PreemptiveRcpspSolution) dict[str, float][source]
Evaluate a given solution object for the given problem.
This method should return a dictionnary of KPI, that can be then used for mono or multiobjective optimization.
- Parameters:
variable (Solution) – the Solution object to evaluate.
Returns: dictionnary of float kpi for the solution.
- evaluate_function(rcpsp_sol: PreemptiveRcpspSolution)[source]
- get_dummy_solution(random_perm: bool = False)[source]
Create a trivial solution for the problem.
Should satisfy the problem ideally. Does not exist for all kind of problems.
- get_objective_register() ObjectiveRegister[source]
Returns the objective definition.
Returns (ObjectiveRegister): object defining the objective criteria.
- get_solution_type() type[Solution][source]
Returns the class implementation of a Solution.
Returns (class): class object of the given Problem.
- satisfy(variable: PreemptiveRcpspSolution)[source]
Computes if a solution satisfies or not the constraints of the problem.
- Parameters:
variable – the Solution object to check satisfability
Returns (bool): boolean true if the constraints are fulfilled, false elsewhere.
- class discrete_optimization.rcpsp.problem_specialized_constraints.SpecialPreemptiveRcpspSolution(problem: PreemptiveRcpspProblem, rcpsp_permutation: list[int] | ndarray | None = None, rcpsp_schedule: dict[Hashable, dict[str, list[int]]] | None = None, rcpsp_modes: list[int] | None = None, rcpsp_schedule_feasible: bool | None = None, standardised_permutation: list[int] | ndarray | None = None)[source]
Bases:
PreemptiveRcpspSolution- change_problem(new_problem: Problem)[source]
If relevant to the optimisation problem, change the underlying problem instance for the solution.
This method can be used to evaluate a solution for different instance of problems. It should be implemented in child classes when caching subresults depending on the problem.
- Parameters:
new_problem (Problem) – another problem instance from which the solution can be evaluated
Returns: None
- copy()[source]
Deep copy of the solution.
The copy() function should return a new object containing the same input as the current object, that respects the following expected behaviour: -y = x.copy() -if do some inplace change of y, the changes are not done in x.
Returns: a new object from which you can manipulate attributes without changing the original object.
- generate_schedule_from_permutation_serial_sgs_2(current_t: int = 0, completed_tasks: set[Hashable] | None = None, partial_schedule: dict[Hashable, dict[str, list[int]]] | None = None, do_fast: bool = True)[source]
- lazy_copy()[source]
This function should return a new object but possibly with mutable attributes from the original objects.
A typical use of lazy copy is in evolutionary algorithms or genetic algorithm where the use of local move don’t need to do a possibly costly deepcopy.
Returns (Solution): copy (possibly shallow) of the Solution
- discrete_optimization.rcpsp.problem_specialized_constraints.check_solution(problem: SpecialConstraintsPreemptiveRcpspProblem, solution: SpecialPreemptiveRcpspSolution | RcpspSolution | PreemptiveRcpspSolution, relax_the_start_at_end: bool = True)[source]
- discrete_optimization.rcpsp.problem_specialized_constraints.compute_constraints_details(solution: RcpspSolution | PreemptiveRcpspSolution, constraints: SpecialConstraintsDescription)[source]
- discrete_optimization.rcpsp.problem_specialized_constraints.create_np_data_and_jit_functions(rcpsp_problem: SpecialConstraintsPreemptiveRcpspProblem)[source]
- discrete_optimization.rcpsp.problem_specialized_constraints.evaluate_constraints(solution: RcpspSolution | PreemptiveRcpspSolution, constraints: SpecialConstraintsDescription)[source]
- discrete_optimization.rcpsp.problem_specialized_constraints.generate_schedule_from_permutation_serial_sgs_partial_schedule_preempptive(solution, rcpsp_problem, partial_schedule: dict[Hashable, dict[str, list[int]]], current_t, completed_tasks)[source]
- discrete_optimization.rcpsp.problem_specialized_constraints.generate_schedule_from_permutation_serial_sgs_preemptive(solution, rcpsp_problem: SpecialConstraintsPreemptiveRcpspProblem)[source]
discrete_optimization.rcpsp.sgs_without_array module
- class discrete_optimization.rcpsp.sgs_without_array.SgsWithoutArray(rcpsp_problem: RcpspProblem)[source]
Bases:
object- static add_event_delta_in_absolute(sdict: SortedDict, time_start: int, delta: int, time_end: int, liberate: bool = True) None[source]
- generate_schedule_from_permutation_serial_sgs(solution: RcpspSolution, rcpsp_problem: RcpspProblem) tuple[dict[Hashable, dict[str, int]], bool, dict[str, SortedDict]][source]
discrete_optimization.rcpsp.solution module
- class discrete_optimization.rcpsp.solution.PartialSolution(task_mode: dict[int, int] | None = None, start_times: dict[int, int] | None = None, end_times: dict[int, int] | None = None, partial_permutation: list[int] | None = None, list_partial_order: list[list[int]] | None = None, start_together: list[tuple[int, int]] | None = None, start_at_end: list[tuple[int, int]] | None = None, start_at_end_plus_offset: list[tuple[int, int, int]] | None = None, start_after_nunit: list[tuple[int, int, int]] | None = None, disjunctive_tasks: list[tuple[int, int]] | None = None, start_times_window: dict[Hashable, tuple[int, int]] | None = None, end_times_window: dict[Hashable, tuple[int, int]] | None = None)[source]
Bases:
object
- class discrete_optimization.rcpsp.solution.RcpspSolution(problem: RcpspProblem, rcpsp_permutation: list[int] | None = None, rcpsp_schedule: dict[Hashable, dict[str, int]] | None = None, rcpsp_modes: list[int] | None = None, rcpsp_schedule_feasible: bool = True, standardised_permutation: list[int] | None = None, fast: bool = True)[source]
Bases:
SchedulingSolution[Hashable],MultimodeSolution[Hashable]Solution to RcpspProblem problems.
- problem
RCPSP problem for which this is a solution
- Type:
- rcpsp_permutation
Tasks permutation, i.e. list of tasks indices among non-dummy tasks (i.e. excluding source and sink tasks). See below how it is related to the schedule. If given and schedule not given, used to reconstruct the schedule. if not given, deduced from schedule. If not given and schedule not given, it is set to problem.fixed_permutation (useful for alternating genetic algorithms)
- rcpsp_schedule
Tasks schedule. ( task -> “start_time” or “end_time” -> time) If given used to construct standardised_permutation. If given and rcpsp_permutation not given, used to construct rcpsp_permutation. If given and rcpsp_permutation given, no consistency check. If not given, deduced from rcpsp_permutation if possible. If not possible, rcpsp_schedule_feasible set to False and rcpsp_schedule set to a partially filled schedule. In case of Aggreg_RcpspModel, kept empty.
- rcpsp_modes
Mode used for each task. Same order as problem.tasks_list_non_dummy. If not given we use problem.fixed_modes if existing, else 1 for each task.
- rcpsp_schedule_feasible
True if a schedule can be deduced from permutation. False if it leads to incoherency preventing a schedule generation. Recomputed when schedule is (re)computed from permutation.
- standardised_permutation
Permutation deduced uniquely from schedule. If given, not recomputed. Can be different from rcpsp_permutation as different permutations can lead to same schedule.
- fast
boolean indicating if we use the fast functions to generate schedule from permutation.
## More about conversion permutation <-> schedule:
### Schedule -> permutation Take the list of tasks indices among non-dummy tasks (i.e. excluding source and sink tasks), sorted by their starting times.
### Permutation -> schedule: serial-SGS (Schedule Generation Scheme) - Initialization:
the source task is set at time 0
the resource availability is set to the initial calendar given by the problem
- Loop: the schedule is filled task by task, in the order given by the permutation, and taking into account
the precedence constraints: a task starts after the end of the tasks before it in the precedence graph
the resource constraints: during the task, the needed resource must be available
When a new task has been inserted, the availability of each resource is updated accordingly, i.e. we remove the necessary resources for the task (according to the chosen mode set by rcpsp_modes) for the task duration, and after if the resource is non-renewable.
When hitting an impossibility (e.g. inserting a task after one of its successor, or when the resources are not enough available until the problem horizon) the permutation is set infeasible (so rcpsp_schedule_feasible is set to False).
See “Compute a dummy solution for RCPSP” in the tutorial “notebooks/RCPSP tutorials/RCPSP-1 Introduction.ipynb” for more details.
Example
This example demonstrates how a permutation of non-dummy tasks is transformed into a schedule, adhering to precedence and resource constraints.
>>> from discrete_optimization.rcpsp.problem import RcpspProblem >>> from discrete_optimization.rcpsp.solution import RcpspSolution >>> # Define resources >>> resources = {"R1": 5, "R2": 2} >>> non_renewable_resources = [] # Empty if all resources replenish when a task ends >>> # Define mode details >>> # Format: { task_id: { mode_id: { "duration": int, "resource_name": amount } } } >>> mode_details = { ... "source": {1: {"duration": 0, "R1": 0, "R2": 0}}, # Source (Dummy) ... "task-1": {1: {"duration": 4, "R1": 2, "R2": 2}}, ... "task-2": {1: {"duration": 3, "R1": 3, "R2": 0}}, ... "task-3": {1: {"duration": 5, "R1": 2, "R2": 1}}, ... "task-4": {1: {"duration": 2, "R1": 1, "R2": 1}}, ... "sink": {1: {"duration": 0, "R1": 0, "R2": 0}}, # Sink (Dummy) ... } >>> # Define precedence graph >>> successors = { ... "source": ["task-1", "task-2"], # First tasks: 1 and 2 ... "task-1": ["task-3"], # Task 1 must finish before 3 ... "task-2": ["task-4"], # Task 2 must finish before 4 ... "task-3": ["sink"], # Task 3 leads to Sink ... "task-4": ["sink"], # Task 4 leads to Sink ... "sink": [], # Sink has no successors ... } >>> # Initialize the Problem >>> problem = RcpspProblem( ... resources=resources, ... non_renewable_resources=non_renewable_resources, ... mode_details=mode_details, ... successors=successors, ... horizon=20, # Maximum time allowed for the project ... source_task="source", ... sink_task="sink" ... ) >>> # Create solution >>> # Convert list of task ids into a licit permutation (using indices among non-dummy tasks) >>> rcpsp_permutation = problem.convert_task_ids_to_permutation(["task-2", "task-1", "task-4", "task-3"]) >>> print(rcpsp_permutation) [1, 0, 3, 2] >>> solution = RcpspSolution( ... problem=problem, ... rcpsp_permutation=rcpsp_permutation, ... rcpsp_modes=[1, 1, 1, 1] # same mode for each task ... ) >>> # The Serial SGS calculates the start/end times according: >>> print(solution.rcpsp_schedule["task-2"]) # Task 2 {'start_time': 0, 'end_time': 3} >>> print(solution.rcpsp_schedule["task-1"]) # Task 1 follows Task 2 in permutation {'start_time': 0, 'end_time': 4} >>> print(solution.rcpsp_schedule["task-4"]) # Task 4 can start after Task 2, but only when ressources are available (thus after task 1) {'start_time': 4, 'end_time': 6} >>> print(solution.rcpsp_schedule["task-3"]) # Task 3 can start after Task 1 (and ressources are available) {'start_time': 4, 'end_time': 9}
- change_problem(new_problem: RcpspProblem) None[source]
If relevant to the optimisation problem, change the underlying problem instance for the solution.
This method can be used to evaluate a solution for different instance of problems. It should be implemented in child classes when caching subresults depending on the problem.
- Parameters:
new_problem (Problem) – another problem instance from which the solution can be evaluated
Returns: None
- copy() RcpspSolution[source]
Deep copy of the solution.
The copy() function should return a new object containing the same input as the current object, that respects the following expected behaviour: -y = x.copy() -if do some inplace change of y, the changes are not done in x.
Returns: a new object from which you can manipulate attributes without changing the original object.
- generate_schedule_from_permutation_serial_sgs_2(current_t: int = 0, completed_tasks: dict[Hashable, TaskDetails] | None = None, scheduled_tasks_start_times: dict[Hashable, int] | None = None, do_fast: bool = True) None[source]
- lazy_copy() RcpspSolution[source]
This function should return a new object but possibly with mutable attributes from the original objects.
A typical use of lazy copy is in evolutionary algorithms or genetic algorithm where the use of local move don’t need to do a possibly costly deepcopy.
Returns (Solution): copy (possibly shallow) of the Solution
- problem: RcpspProblem
- discrete_optimization.rcpsp.solution.compute_mean_resource_reserve(solution: RcpspSolution, rcpsp_problem: RcpspProblem) float[source]
- discrete_optimization.rcpsp.solution.generate_schedule_from_permutation_serial_sgs(solution: RcpspSolution, rcpsp_problem: RcpspProblem) tuple[dict[Hashable, dict[str, int]], bool][source]
- discrete_optimization.rcpsp.solution.generate_schedule_from_permutation_serial_sgs_partial_schedule(solution: RcpspSolution, rcpsp_problem: RcpspProblem, current_t: int, completed_tasks: dict[Hashable, TaskDetails], scheduled_tasks_start_times: dict[Hashable, int]) tuple[dict[Hashable, dict[str, int]], bool][source]
- discrete_optimization.rcpsp.solution.generate_schedule_from_permutation_serial_sgs_partial_schedule_specialized_constraints(solution: RcpspSolution, rcpsp_problem: RcpspProblem, current_t: int, completed_tasks: dict[Hashable, TaskDetails], scheduled_tasks_start_times: dict[Hashable, int]) tuple[dict[Hashable, dict[str, int]], bool][source]
- discrete_optimization.rcpsp.solution.generate_schedule_from_permutation_serial_sgs_special_constraints(solution: RcpspSolution, rcpsp_problem: RcpspProblem) tuple[dict[Hashable, dict[str, int]], bool][source]
- discrete_optimization.rcpsp.solution.permutation_do_to_permutation_sgs_fast(rcpsp_problem: RcpspProblem, permutation_do: Iterable[int]) npt.NDArray[np.int_][source]
discrete_optimization.rcpsp.solvers_map module
- discrete_optimization.rcpsp.solvers_map.get_solver_default_arguments(method: type[RcpspSolver] | type[GenericRcpspSolver]) dict[str, Any][source]
- discrete_optimization.rcpsp.solvers_map.look_for_solver(domain: RcpspProblem | PreemptiveRcpspProblem | SpecialConstraintsPreemptiveRcpspProblem) list[type[RcpspSolver] | type[GenericRcpspSolver]][source]
- discrete_optimization.rcpsp.solvers_map.look_for_solver_class(class_domain: type[RcpspProblem | PreemptiveRcpspProblem | SpecialConstraintsPreemptiveRcpspProblem]) list[type[RcpspSolver] | type[GenericRcpspSolver]][source]
- discrete_optimization.rcpsp.solvers_map.return_solver(method: type[RcpspSolver] | type[GenericRcpspSolver], problem: RcpspProblem | PreemptiveRcpspProblem | SpecialConstraintsPreemptiveRcpspProblem, **kwargs: Any) RcpspSolver | GenericRcpspSolver[source]
- discrete_optimization.rcpsp.solvers_map.solve(method: type[RcpspSolver] | type[GenericRcpspSolver], problem: RcpspProblem | PreemptiveRcpspProblem | SpecialConstraintsPreemptiveRcpspProblem, **kwargs: Any) ResultStorage[source]
- discrete_optimization.rcpsp.solvers_map.solve_return_solver(method: type[RcpspSolver] | type[GenericRcpspSolver], problem: RcpspProblem | PreemptiveRcpspProblem | SpecialConstraintsPreemptiveRcpspProblem, **kwargs: Any) tuple[ResultStorage, RcpspSolver | GenericRcpspSolver][source]
discrete_optimization.rcpsp.special_constraints module
- class discrete_optimization.rcpsp.special_constraints.PairModeConstraint(allowed_mode_assignment: dict[tuple[Hashable, Hashable], set[tuple[int, int]]] | None = None, same_score_mode: set[tuple[Hashable, Hashable]] | None = None, score_mode: dict[tuple[Hashable, int], int] = None)[source]
Bases:
objectThis data structure exists to express the following constraints : if allowed_mode_assignment is not None : for each key of the dictionary (activity_1, activity_2), the allowed modes assignment to those 2 activity are listed in allowed_mode_assignment[(activity_1, activity_2)] This can be used to express that a given resource has to do both activities.
Another way of expressing the constraint is : -each interesting tuple (task,mode) is given an int score. (score_mode) -We get a set of pairs of activities (same_score_mode) : indicating that the score_mode of the 2 activity should be equal.
- class discrete_optimization.rcpsp.special_constraints.SpecialConstraintsDescription(task_mode: dict[Hashable, int] | None = None, start_times: dict[Hashable, int] | None = None, end_times: dict[Hashable, int] | None = None, start_times_window: dict[Hashable, tuple[int | None, int | None]] | None = None, end_times_window: dict[Hashable, tuple[int | None, int | None]] | None = None, partial_permutation: list[Hashable] | None = None, list_partial_order: list[list[Hashable]] | None = None, start_together: list[tuple[Hashable, Hashable]] | None = None, start_at_end: list[tuple[Hashable, Hashable]] | None = None, start_at_end_plus_offset: list[tuple[Hashable, Hashable, int]] | None = None, start_after_nunit: list[tuple[Hashable, Hashable, int]] | None = None, disjunctive_tasks: list[tuple[Hashable, Hashable]] | None = None, pair_mode_constraint: PairModeConstraint | None = None)[source]
Bases:
object
discrete_optimization.rcpsp.transform_problem module
- discrete_optimization.rcpsp.transform_problem.from_rcpsp_problem(rcpsp_problem: RcpspProblem, constraints: SpecialConstraintsDescription, preemptive=False) RcpspProblem[source]
discrete_optimization.rcpsp.utils module
- discrete_optimization.rcpsp.utils.all_diff_start_time(rcpsp_sols: tuple[RcpspSolution, RcpspSolution]) dict[Hashable, int][source]
- discrete_optimization.rcpsp.utils.compute_graph_rcpsp(rcpsp_problem: RcpspProblem) Graph[source]
- discrete_optimization.rcpsp.utils.compute_nice_resource_consumption(rcpsp_problem: RcpspProblem, rcpsp_sol: RcpspSolution, list_resources: list[str] | None = None) tuple[dict[int, npt.NDArray[np.int_]], dict[int, npt.NDArray[np.int_]]][source]
- discrete_optimization.rcpsp.utils.compute_resource_consumption(rcpsp_problem: RcpspProblem, rcpsp_sol: RcpspSolution, list_resources: list[str] | None = None, future_view: bool = True) tuple[npt.NDArray[np.int_], npt.NDArray[np.int_]][source]
- discrete_optimization.rcpsp.utils.compute_schedule_per_resource_individual(rcpsp_problem: RcpspProblem, rcpsp_sol: RcpspSolution, resource_types_to_consider: list[str] | None = None) dict[str, dict[str, Any]][source]
- discrete_optimization.rcpsp.utils.create_fake_tasks(rcpsp_problem: RcpspProblem) list[dict[str, int]][source]
- discrete_optimization.rcpsp.utils.get_end_bounds_from_additional_constraint(rcpsp_problem: RcpspProblem, activity: Hashable) tuple[int, int][source]
- discrete_optimization.rcpsp.utils.get_max_time_solution(solution: PreemptiveRcpspSolution | RcpspSolution) int[source]
- discrete_optimization.rcpsp.utils.get_start_bounds_from_additional_constraint(rcpsp_problem: RcpspProblem, activity: Hashable) tuple[int, int][source]
- discrete_optimization.rcpsp.utils.get_tasks_ending_between_two_times(solution: PreemptiveRcpspSolution | RcpspSolution, time_1: int, time_2: int) list[Hashable][source]
- discrete_optimization.rcpsp.utils.intersect(i1: Sequence[int], i2: Sequence[int]) list[int] | None[source]
- discrete_optimization.rcpsp.utils.kendall_tau_similarity(rcpsp_sols: tuple[RcpspSolution, RcpspSolution]) float[source]
- discrete_optimization.rcpsp.utils.plot_resource_individual_gantt(rcpsp_problem: RcpspProblem, rcpsp_sol: RcpspSolution, resource_types_to_consider: list[str] | None = None, title_figure: str = '', x_lim: list[int] | None = None, fig: plt.Figure | None = None, ax: npt.NDArray[np.object_] | None = None, current_t: int | None = None) plt.Figure[source]
- discrete_optimization.rcpsp.utils.plot_ressource_view(rcpsp_problem: RcpspProblem, rcpsp_sol: RcpspSolution, list_resource: list[str] | None = None, title_figure: str = '', x_lim: list[int] | None = None, fig: plt.Figure | None = None, ax: npt.NDArray[np.object_] | None = None) plt.Figure[source]
- discrete_optimization.rcpsp.utils.plot_task_gantt(rcpsp_problem: RcpspProblem, rcpsp_sol: RcpspSolution, fig: plt.Figure | None = None, ax: plt.Axes | None = None, x_lim: list[int] | None = None, title: str | None = None) plt.Figure[source]
discrete_optimization.rcpsp.utils_preemptive module
- discrete_optimization.rcpsp.utils_preemptive.compute_nice_resource_consumption(rcpsp_problem: PreemptiveRcpspProblem, rcpsp_sol: PreemptiveRcpspSolution, list_resources: list[int | str] = None)[source]
- discrete_optimization.rcpsp.utils_preemptive.compute_resource_consumption(rcpsp_problem: PreemptiveRcpspProblem, rcpsp_sol: PreemptiveRcpspSolution, list_resources: list[int | str] = None, future_view=True)[source]
- discrete_optimization.rcpsp.utils_preemptive.compute_schedule_per_resource_individual(rcpsp_problem: PreemptiveRcpspProblem, rcpsp_sol: PreemptiveRcpspSolution, resource_types_to_consider: list[str] = None)[source]
- discrete_optimization.rcpsp.utils_preemptive.plot_resource_individual_gantt(rcpsp_problem: PreemptiveRcpspProblem, rcpsp_sol: PreemptiveRcpspSolution, resource_types_to_consider: list[str] = None, title_figure='', x_lim=None, fig=None, ax=None, current_t=None)[source]
- discrete_optimization.rcpsp.utils_preemptive.plot_ressource_view(rcpsp_problem: PreemptiveRcpspProblem, rcpsp_sol: PreemptiveRcpspSolution, list_resource: list[int | str] = None, title_figure='', x_lim=None, fig=None, ax=None)[source]
- discrete_optimization.rcpsp.utils_preemptive.plot_task_gantt(rcpsp_problem: PreemptiveRcpspProblem, rcpsp_sol: PreemptiveRcpspSolution, fig=None, ax=None, x_lim=None, title=None, current_t=None)[source]