discrete_optimization.rcpsp_multiskill.solvers package

Submodules

discrete_optimization.rcpsp_multiskill.solvers.cp_mzn module

class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.CpMultiskillRcpspSolver(problem: MultiskillRcpspProblem, cp_solver_name: CpSolverName = CpSolverName.CHUFFED, params_objective_function: ParamsObjectiveFunction = None, silent_solve_error: bool = False, **kwargs)[source]

Bases: MinizincCpSolver

add_hard_special_constraints(partial_solution)[source]
constraint_end_time_string(task, end_time, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_objective_equal_makespan(task_sink)[source]
constraint_objective_max_time_set_of_jobs(set_of_jobs)[source]
constraint_start_time_string(task, start_time, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_sum_of_ending_time(set_subtasks: set[Hashable])[source]
constraint_sum_of_starting_time(set_subtasks: set[Hashable])[source]
constraint_task_to_mode(task_id, mode)[source]
constraint_used_employee(task, employee, indicator: bool = False)[source]
init_model(**args)[source]

Instantiate a CP model instance

Afterwards, self.instance should not be None anymore.

manual_cumulative_resource_constraints(instance)[source]
manual_starting_time(instance)[source]
problem: MultiskillRcpspProblem
retrieve_solution(_output_item: str | None = None, **kwargs: Any) MultiskillRcpspSolution[source]

Return a d-o solution from the variables computed by minizinc.

Parameters:
  • _output_item – string representing the minizinc solver output passed by minizinc to the solution constructor

  • **kwargs – keyword arguments passed by minzinc to the solution contructor containing the objective value (key “objective”), and the computed variables as defined in minizinc model.

Returns:

write_search_strategy_chuffed(instance)[source]
class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.CpPartialPreemptiveMultiskillRcpspSolver(problem: MultiskillRcpspProblem, cp_solver_name: CpSolverName = CpSolverName.CHUFFED, params_objective_function: ParamsObjectiveFunction = None, silent_solve_error: bool = False, **kwargs)[source]

Bases: CpPreemptiveMultiskillRcpspSolver

init_model(**args)[source]

Instantiate a CP model instance

Afterwards, self.instance should not be None anymore.

class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.CpPreemptiveMultiskillRcpspSolver(problem: MultiskillRcpspProblem, cp_solver_name: CpSolverName = CpSolverName.CHUFFED, params_objective_function: ParamsObjectiveFunction = None, silent_solve_error: bool = False, **kwargs)[source]

Bases: MinizincCpSolver

add_hard_special_constraints(partial_solution)[source]
constraint_duration_string_preemptive_i(task, duration, part_id=1, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_duration_to_min_duration_preemptive(task, min_duration)[source]
constraint_end_time_string(task, end_time, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_is_paused(task, is_paused)[source]
constraint_objective_equal_makespan(task_sink)[source]
constraint_objective_max_time_set_of_jobs(set_of_jobs)[source]
constraint_start_time_string(task, start_time, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_start_time_string_preemptive_i(task, start_time, part_id=1, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_sum_of_ending_time(set_subtasks: set[Hashable])[source]
constraint_sum_of_starting_time(set_subtasks: set[Hashable])[source]
constraint_task_to_mode(task_id, mode)[source]
constraint_used_employee(task, employee, part_id=1, indicator: bool = False)[source]
init_model(**args)[source]

Instantiate a CP model instance

Afterwards, self.instance should not be None anymore.

problem: MultiskillRcpspProblem
retrieve_solution(_output_item: str | None = None, **kwargs: Any) PreemptiveMultiskillRcpspSolution[source]

Return a d-o solution from the variables computed by minizinc.

Parameters:
  • _output_item – string representing the minizinc solver output passed by minizinc to the solution constructor

  • **kwargs – keyword arguments passed by minzinc to the solution contructor containing the objective value (key “objective”), and the computed variables as defined in minizinc model.

Returns:

class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.PrecomputeEmployeesForTasks(ms_rcpsp_problem: MultiskillRcpspProblem, cp_solver_name: CpSolverName = CpSolverName.CHUFFED)[source]

Bases: object

init_model(**kwargs)[source]
instance: Instance
retrieve_solutions(result, parameters_cp: ParametersCp)[source]
solve(parameters_cp: ParametersCp | None = None, time_limit: float | None = 100.0, nr_solutions: int = 100, all_solutions: bool = False, **args)[source]

Solve the CP problem with minizinc

Parameters:
  • parameters_cp – parameters specific to CP solvers

  • time_limit – the solve process stops after this time limit (in seconds). If None, no time limit is applied.

  • nr_solutions – of not all_solutions, the solve stops after finding nr_solutions

  • all_solutions – if True, do not stop when reaching nr_solutions

  • **args – passed to init_model()

Returns:

class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.SearchStrategyMultiskillRcpsp(*values)[source]

Bases: Enum

NONE = 'none'
PRIORITY_SEARCH_START_UNIT_USED = 'priority_smallest'
START_THEN_USED_UNIT = 'durThenStartThenMode'
class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.SolutionPrecomputeEmployeesForTasks(unit_used, worker_type_used, mode_dict, overskill_unit, overskill_type)[source]

Bases: object

discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.add_constraints_string(child_instance, list_of_strings)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.add_fake_task_cp_data(rcpsp_problem: MultiskillRcpspProblem, ignore_fake_task: bool = True, max_time_to_consider: int = None)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.add_hard_special_constraints(partial_solution: PartialSolution, cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.add_soft_special_constraints(partial_solution: PartialSolution, cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.define_second_part_objective(weights, name_penalty, equal=False)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_end_window(end_times_window: dict[Hashable, tuple[int, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_start_after_nunit(list_start_after_nunit: list[tuple[Hashable, Hashable, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_start_at_end(list_start_at_end: list[tuple[Hashable, Hashable]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_start_at_end_plus_offset(list_start_at_end_plus_offset, cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_start_times(dict_start_times: dict[Hashable, int], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_start_together(list_start_together: list[tuple[Hashable, Hashable]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.hard_start_window(start_times_window: dict[Hashable, tuple[int, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_end_window(end_times_window: dict[Hashable, tuple[int, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_start_after_nunit(list_start_after_nunit: list[tuple[Hashable, Hashable, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_start_at_end(list_start_at_end: list[tuple[Hashable, Hashable]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_start_at_end_plus_offset(list_start_at_end_plus_offset: list[tuple[Hashable, Hashable, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_start_times(dict_start_times: dict[Hashable, int], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_start_together(list_start_together: list[tuple[Hashable, Hashable]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.soft_start_window(start_times_window: dict[Hashable, tuple[int, int]], cp_solver: CpMultiskillRcpspSolver | CpPreemptiveMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.stick_to_solution(solution: RcpspSolution, cp_solver: CpMultiskillRcpspSolver)[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn.stick_to_solution_preemptive(solution: PreemptiveRcpspSolution, cp_solver: CpPreemptiveMultiskillRcpspSolver)[source]

discrete_optimization.rcpsp_multiskill.solvers.cp_mzn_mspsp_instlib module

class discrete_optimization.rcpsp_multiskill.solvers.cp_mzn_mspsp_instlib.CpMspspMznMultiskillRcpspSolver(problem: MultiskillRcpspProblem, cp_solver_name: CpSolverName = CpSolverName.CHUFFED, params_objective_function: ParamsObjectiveFunction = None, silent_solve_error: bool = False, **kwargs)[source]

Bases: MinizincCpSolver

constraint_end_time_string(task, end_time, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_objective_equal_makespan(task_sink)[source]
constraint_objective_makespan()[source]
constraint_objective_max_time_set_of_jobs(set_of_jobs)[source]
constraint_start_time_string(task, start_time, sign: SignEnum = SignEnum.EQUAL) str[source]
constraint_sum_of_ending_time(set_subtasks: set[Hashable])[source]
constraint_sum_of_starting_time(set_subtasks: set[Hashable])[source]
constraint_task_to_mode(task_id, mode)[source]
constraint_used_employee(task, employee, indicator: bool = False)[source]
init_from_model(**args)[source]
init_model(**args)[source]

Instantiate a CP model instance

Afterwards, self.instance should not be None anymore.

problem: MultiskillRcpspProblem
retrieve_solution(_output_item: str | None = None, **kwargs: Any) MultiskillRcpspSolution[source]

Return a d-o solution from the variables computed by minizinc.

Parameters:
  • _output_item – string representing the minizinc solver output passed by minizinc to the solution constructor

  • **kwargs – keyword arguments passed by minzinc to the solution contructor containing the objective value (key “objective”), and the computed variables as defined in minizinc model.

Returns:

discrete_optimization.rcpsp_multiskill.solvers.cp_mzn_mspsp_instlib.chuffed_specific_code()[source]
discrete_optimization.rcpsp_multiskill.solvers.cp_mzn_mspsp_instlib.create_usefull_res_data(rcpsp_problem: MultiskillRcpspProblem)[source]

discrete_optimization.rcpsp_multiskill.solvers.cpsat module

class discrete_optimization.rcpsp_multiskill.solvers.cpsat.CpSatMultiskillRcpspSolver(problem: Problem, **kwargs: Any)[source]

Bases: GenericSchedulingCpSatSolver[Hashable, Hashable, str, str]

add_lexico_constraint(obj: str, value: float) Iterable[Constraint][source]

Add a constraint on a computed sub-objective

Parameters:
  • obj – a string representing the desired objective. Should be one of self.get_lexico_objectives_available().

  • value – the limiting value. If the optimization direction is maximizing, this is a lower bound, else this is an upper bound.

Returns:

the created constraints.

constraint_mode()[source]
constraint_redundant_cumulative_skills()[source]
constraint_redundant_cumulative_worker()[source]
create_base_variable()[source]
create_constraint_resource()[source]
create_cost_objective_function()[source]
create_disjunctive_worker()[source]
create_employee_intervals(one_worker_per_task: bool, one_skill_per_task: bool)[source]
create_opt_variable_modes()[source]
create_skills_constraint_to_mode()[source]
create_skills_constraint_worker(**args)[source]
create_skills_constraints_v2(**args)[source]

using skills_used variable

create_skills_variables()[source]
create_workload_variables()[source]
get_global_makespan_variable() Any[source]

Construct and get the variable tracking the global makespan.

Default implementation uses get_subtasks_makespan_variable on last tasks. Beware: a further call to get_subtasks_makespan_variable with another subset of tasks can change the constraints on this variable and thus make it obsolete.

Returns:

objective variable to minimize

get_lb_ub_start_end(task: Hashable) tuple[int, int, int, int][source]
get_lexico_objective_value(obj: str, res: ResultStorage) float[source]

Get best internal model objective value found by last call to solve().

The default implementation consists in using the fit of the last solution in result_storage. This assumes: - that the last solution is the best one for the objective considered - that no aggregation was performed but rather that the fitness is a TupleFitness

with values in the same order as self.problem.get_objective_names().

Parameters:
  • obj – a string representing the desired objective. Should be one of self.get_lexico_objectives_available().

  • res – result storage returned by last call to solve().

Returns:

get_lexico_objectives_available() list[str][source]

List objectives available for lexico optimization

It corresponds to the labels accepted for obj argument for - set_lexico_objective() - add_lexico_constraint() - get_lexico_objective_value()

Default to self.problem.get_objective_names().

Returns:

get_task_mode_interval(task: Hashable, mode: int) IntervalVar[source]

Get the interval variable corresponding to given task and mode.

get_task_mode_is_present_variable(task: Hashable, mode: int) LinearExpr | IntVar | int | int8 | uint8 | int32 | uint32 | int64 | uint64[source]

Retrieve the 0-1 variable/expression telling if the mode is used for the task.

Parameters:
  • task

  • mode

Returns:

get_task_start_or_end_variable(task: Hashable, start_or_end: StartOrEnd) LinearExpr | IntVar | int | int8 | uint8 | int32 | uint32 | int64 | uint64[source]

Retrieve the variable storing the start or end time of given task.

Parameters:
  • task

  • start_or_end

Returns:

get_task_unary_resource_interval(task: Hashable, unary_resource: Hashable) IntervalVar[source]

Get the interval variable corresponding to given task conditioned to allocation of the given unary resource.

The method may return an error (no variable existing) if self.problem.is_compatible_task_unary_resource(task=task, unary_resource=unary_resource) is false.

get_task_unary_resource_is_present_variable(task: Hashable, unary_resource: Hashable) LinearExpr | IntVar | int | int8 | uint8 | int32 | uint32 | int64 | uint64[source]

Return a 0-1 variable/expression telling if the unary_resource is used for the task.

NB: sometimes the given resource is never to be used by a task and the variable has not been created. The convention is to return 0 in that case.

hyperparameters: list[Hyperparameter] = [CategoricalHyperparameter(name='redundant_skill_cumulative', default=True, depends_on=None, name_in_kwargs='redundant_skill_cumulative'), CategoricalHyperparameter(name='redundant_worker_cumulative', default=True, depends_on=None, name_in_kwargs='redundant_worker_cumulative')]

Hyperparameters available for this solver.

These hyperparameters are to be feed to **kwargs found in
  • __init__()

  • init_model() (when available)

  • solve()

static implements_lexico_api() bool[source]

Tell whether this solver is implementing the api for lexicographic optimization.

Should return True only if

  • set_lexico_objective()

  • add_lexico_constraint()

  • get_lexico_objective_value()

have been really implemented, i.e. - calling set_lexico_objective() and add_lexico_constraint()

should actually change the next call to solve(),

  • get_lexico_objective_value() should correspond to the internal model objective

init_model(**args: Any) None[source]

Init cp model and reset stored variables if any.

is_compatible_task_unary_resource(task: Hashable, unary_resource: Hashable) bool[source]

Should return False if the unary_resource can never be allocated to task.

This is only a hint used to reduce the number of variables or constraints generated. Default to use problem.is_compatible_task_unary_resource().

But you can override it if you want to have more constraints in the solver than in the problem.

problem: MultiskillRcpspProblem
retrieve_solution(cpsolvercb: CpSolverSolutionCallback) Solution[source]

Construct a do solution from the cpsat solver internal solution.

It will be called each time the cpsat solver find a new solution. At that point, value of internal variables are accessible via cpsolvercb.Value(VARIABLE_NAME).

Parameters:

cpsolvercb – the ortools callback called when the cpsat solver finds a new solution.

Returns:

the intermediate solution, at do format.

set_lexico_objective(obj: str) None[source]

Update internal model objective.

Parameters:

obj – a string representing the desired objective. Should be one of self.get_lexico_objectives_available().

Returns:

discrete_optimization.rcpsp_multiskill.solvers.cpsat_auto module

class discrete_optimization.rcpsp_multiskill.solvers.cpsat_auto.CpSatAutoMultiskillRcpspSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]

Bases: GenericSchedulingAutoCpSatSolver[Hashable, Hashable, str, str]

convert_task_variables_to_solution(temp_sol: TemporarySolution[Hashable, Hashable]) Solution[source]

Convert solution from autosolver format into do format.

To be used in self.retrieve_solution().

Parameters:

temp_sol

Returns:

create_skills_constraint_worker()[source]
create_skills_constraints_v2()[source]

using skills_used variable

create_skills_per_task_variables()[source]
create_skills_used_per_worker()[source]
create_total_cost_variable()[source]
create_workload_variables()[source]
hyperparameters: list[Hyperparameter] = [CategoricalHyperparameter(name='redundant_skill_cumulative', default=True, depends_on=None, name_in_kwargs='redundant_skill_cumulative'), CategoricalHyperparameter(name='redundant_worker_cumulative', default=True, depends_on=None, name_in_kwargs='redundant_worker_cumulative')]

Hyperparameters available for this solver.

These hyperparameters are to be feed to **kwargs found in
  • __init__()

  • init_model() (when available)

  • solve()

include_constraint_on_cumulative_resource(resource: str) bool[source]

Whether the cp model should take into account the constraint on the given cumulative resource.

The constraints on skills as cumulative resources and on number of employees are to be added according to redundant_skill_cumulative and redundant_worker_cumulative hyperparameters.

Parameters:

resource

Returns:

init_model(**kwargs: Any) None[source]

Init cp model and reset stored variables if any.

is_compatible_task_unary_resource(task: Hashable, unary_resource: Hashable) bool[source]

Should return False if the unary_resource can never be allocated to task.

This is only a hint used to reduce the number of variables or constraints generated. Default to use problem.is_compatible_task_unary_resource().

But you can override it if you want to have more constraints in the solver than in the problem.

problem: MultiskillRcpspProblem
retrieve_tasks_variables(cpsolvercb: CpSolverSolutionCallback) TemporarySolution[Hashable, Hashable][source]

Construct each task variable from the cpsat solver internal solution.

It will be called each time the cpsat solver find a new solution. At that point, value of internal variables are accessible via cpsolvercb.value(VARIABLE_NAME).

We override the method from generic auto solver to add the worker skills contribution and internal objective value.

Parameters:

cpsolvercb – the ortools callback called when the cpsat solver finds a new solution.

Returns:

the task variables for the intermediate solution

discrete_optimization.rcpsp_multiskill.solvers.ga module

class discrete_optimization.rcpsp_multiskill.solvers.ga.GaMultiskillRcpspSolver(problem: Problem, params_objective_function: ParamsObjectiveFunction | None = None, **kwargs: Any)[source]

Bases: SolverDO

problem: RcpspProblem
solve(parameters_ga: ParametersAltGa = None, **args)[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

discrete_optimization.rcpsp_multiskill.solvers.lns_lp module

class discrete_optimization.rcpsp_multiskill.solvers.lns_lp.InitialMultiskillRcpspSolution(problem: MultiskillRcpspProblem, params_objective_function: ParamsObjectiveFunction = None, initial_method: InitialRcpspMethod = InitialRcpspMethod.PILE)[source]

Bases: InitialSolution

get_starting_solution() ResultStorage[source]

discrete_optimization.rcpsp_multiskill.solvers.lns_post_process module

class discrete_optimization.rcpsp_multiskill.solvers.lns_post_process.MultiskillRcpspPostProcessSolution(problem: MultiskillRcpspProblem, params_objective_function: ParamsObjectiveFunction = None)[source]

Bases: PostProcessSolution

build_other_solution(result_storage: ResultStorage) ResultStorage[source]
class discrete_optimization.rcpsp_multiskill.solvers.lns_post_process.PreemptiveMultiskillRcpspPostProcessSolution(problem: MultiskillRcpspProblem, params_objective_function: ParamsObjectiveFunction = None)[source]

Bases: PostProcessSolution

build_other_solution(result_storage: ResultStorage) ResultStorage[source]
discrete_optimization.rcpsp_multiskill.solvers.lns_post_process.compute_schedule_per_employees(solution: PreemptiveMultiskillRcpspSolution | MultiskillRcpspSolution, problem: MultiskillRcpspProblem, predecessors_dict)[source]
discrete_optimization.rcpsp_multiskill.solvers.lns_post_process.sgs_variant(solution: MultiskillRcpspSolution, problem: MultiskillRcpspProblem, predecessors_dict)[source]
discrete_optimization.rcpsp_multiskill.solvers.lns_post_process.sgs_variant_preemptive(solution: PreemptiveMultiskillRcpspSolution, problem: MultiskillRcpspProblem, predecessors_dict)[source]
discrete_optimization.rcpsp_multiskill.solvers.lns_post_process.shift_left_method(solution: PreemptiveMultiskillRcpspSolution | MultiskillRcpspSolution, problem: MultiskillRcpspProblem, predecessors_dict)[source]

discrete_optimization.rcpsp_multiskill.solvers.lp module

class discrete_optimization.rcpsp_multiskill.solvers.lp.MathOptMultiskillRcpspSolver(problem: MultiskillRcpspProblem, params_objective_function: ParamsObjectiveFunction = None, **kwargs)[source]

Bases: OrtoolsMathOptMilpSolver

convert_to_variable_values(solution: MultiskillRcpspSolution) dict[Variable, int][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.

Implement it in subclasses to have a proper warm start.

init_model(**args)[source]

Initialize internal model used to solve.

Can initialize a ortools, milp, gurobi, … model.

problem: MultiskillRcpspProblem
retrieve_current_solution(get_var_value_for_current_solution: Callable[[Any], float], get_obj_value_for_current_solution: Callable[[], float]) MultiskillRcpspSolution[source]

Retrieve current solution from internal gurobi solution.

This converts internal gurobi solution into a discrete-optimization Solution. This method can be called after the solve in retrieve_solutions() or during solve within a gurobi/pymilp/cplex callback. The difference will be the get_var_value_for_current_solution and get_obj_value_for_current_solution callables passed.

Parameters:
  • get_var_value_for_current_solution – function extracting the value of the given variable for the current solution will be different when inside a callback or after the solve is finished

  • get_obj_value_for_current_solution – function extracting the value of the objective for the current solution.

Returns:

the converted solution at d-o format

solve(parameters_milp: ParametersMilp | None = None, time_limit: float | None = 30.0, **args) 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.

  • store_mathopt_res – whether to store the mathopt.SolveResult generated by mathopt.solve()

  • extract_solutions_from_mathopt_res – whether to extract solutions from the mathopt.SolveResult generated by mathopt.solve(). If False, the solutions are rather extracted on the fly inside a callback at each mip solution improvement. By default, this is False except for HiGHS solver type, as its OR-Tools wrapper does not yet integrate callbacks.

  • **kwargs – passed to init_model() if model not yet existing

Returns:

discrete_optimization.rcpsp_multiskill.solvers.multimode_transposition module

class discrete_optimization.rcpsp_multiskill.solvers.multimode_transposition.MultimodeTranspositionMultiskillRcpspSolver(problem: MultiskillRcpspProblem, multimode_problem: RcpspProblem | PreemptiveRcpspProblem = None, worker_type_to_worker: dict[str, set[str | int]] = None, params_objective_function: ParamsObjectiveFunction = None, solver_multimode_rcpsp: SolverDO = None, limit_number_of_mode_per_task: bool = True, max_number_of_mode: int = 3, check_resource_compliance: bool = True, reconstruction_cp_time_limit: int = 3600, **kwargs)[source]

Bases: SolverDO

problem: MultiskillRcpspProblem
solve(**kwargs) ResultStorage[source]

Solve the multi-skill RCPSP using two-stage decomposition. The idea is to transform MS-RCPSP to multi-mode RCPSP by abstracting employees as worker types.

Returns:

ResultStorage containing the reconstructed multi-skill RCPSP solutions

discrete_optimization.rcpsp_multiskill.solvers.multimode_transposition.rebuild_multiskill_solution(multiskill_rcpsp_problem: MultiskillRcpspProblem, multimode_rcpsp_problem: RcpspProblem | PreemptiveRcpspProblem, worker_type_to_worker: dict[str, set[str | int]], solution_rcpsp: RcpspSolution | PreemptiveRcpspSolution) MultiskillRcpspSolution | PreemptiveMultiskillRcpspSolution[source]

This function takes the schedule from the RCPSP solution and rebuilds the solution for the multiskill problem. NOTE: need review, this function is currently not used.

discrete_optimization.rcpsp_multiskill.solvers.multimode_transposition.rebuild_multiskill_solution_cp_based(multiskill_rcpsp_problem: MultiskillRcpspProblem, multimode_rcpsp_problem: RcpspProblem | PreemptiveRcpspProblem, worker_type_to_worker: dict[str, set[str | int]], solution_rcpsp: RcpspSolution | PreemptiveRcpspSolution, time_limit: int = 3600) ResultStorage[source]

Reconstructs a valid multi-skill RCPSP solution from the schedule from an RCPSP solution by assigning specific employees to tasks.

Parameters:
  • multiskill_rcpsp_problem – The multi-skill RCPSP problem

  • multimode_rcpsp_problem – The multimode RCPSP problem (for reference)

  • worker_type_to_worker – Mapping from worker types to employee sets

  • solution_rcpsp – The RCPSP solution to constrain to

  • time_limit – Time limit in seconds for CP solver

Returns:

containing the reconstructed multi-skill RCPSP solutions

Return type:

ResultStorage

discrete_optimization.rcpsp_multiskill.solvers.optal module

class discrete_optimization.rcpsp_multiskill.solvers.optal.OptalMSRcpspSolver(problem: MultiskillRcpspProblem, params_objective_function: ParamsObjectiveFunction | None = None, **args)[source]

Bases: SchedulingOptalSolver[Hashable], MultimodeOptalSolver[Hashable], AllocationOptalSolver[Hashable, Hashable]

add_employees_calendar_constraint()[source]
add_non_renewable_resources_constraint(res: str)[source]
add_renewable_resources_constraint(res: str)[source]
add_resource_calendar_constraint()[source]
all_skills_for_task(task: Hashable) list[Hashable][source]
constraint_precedence()[source]
constraint_redundant_cumulative_skills()[source]
constraint_redundant_cumulative_worker()[source]
create_cost_objective_function()[source]
create_employee_intervals(one_worker_per_task: bool, one_skill_per_task: bool)[source]
create_main_and_modes_variables()[source]
create_skills_allocated_constraint()[source]
create_skills_req()[source]
get_task_interval_variable(task: Task) cp.IntervalVar[source]

Retrieve the interval variable of given task.

get_task_mode_is_present_variable(task: Task, mode: int) cp.BoolExpr[source]

Retrieve the 0-1 variable/expression telling if the mode is used for the task.

Parameters:
  • task

  • mode

Returns:

get_task_unary_resource_is_present_variable(task: Task, unary_resource: UnaryResource) cp.BoolExpr[source]

Return a 0-1 variable/expression telling if the unary_resource is used for the task.

NB: sometimes the given resource is never to be used by a task and the variable has not been created. The convention is to return 0 in that case.

hyperparameters = [CategoricalHyperparameter(name='redundant_skill_cumulative', default=True, depends_on=None, name_in_kwargs='redundant_skill_cumulative'), CategoricalHyperparameter(name='redundant_worker_cumulative', default=True, depends_on=None, name_in_kwargs='redundant_worker_cumulative')]

Hyperparameters available for this solver.

These hyperparameters are to be feed to **kwargs found in
  • __init__()

  • init_model() (when available)

  • solve()

init_model(**args: Any) None[source]

Instantiate a CP model instance

Afterwards, self.instance should not be None anymore.

problem: MultiskillRcpspProblem
retrieve_solution(result: cp.SolveResult) MultiskillRcpspSolution[source]

Return a d-o solution from the variables computed by minizinc.

Parameters:

result – output of the cp.solve

Returns:

worker_can_do_task(task: Hashable, worker: Hashable, one_worker_per_task: bool) bool[source]

discrete_optimization.rcpsp_multiskill.solvers.rcpsp_based module

class discrete_optimization.rcpsp_multiskill.solvers.rcpsp_based.RcpspBasedMultiskillRcpspSolver(problem: MultiskillRcpspProblem | VariantMultiskillRcpspProblem, method, params_objective_function: ParamsObjectiveFunction = None, **args)[source]

Bases: SolverDO

problem: MultiskillRcpspProblem | VariantMultiskillRcpspProblem
solve(**kwargs)[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

Module contents