# Copyright (c) 2022 AIRBUS and its affiliates.
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from enum import Enum
from discrete_optimization.generic_rcpsp_tools.graph_tools_rcpsp import (
GraphRCPSP,
build_graph_rcpsp_object,
)
from discrete_optimization.generic_rcpsp_tools.neighbor_tools_rcpsp import (
BasicConstraintBuilder,
ConstraintHandlerMultiskillAllocation,
ConstraintHandlerScheduling,
EquilibrateMultiskillAllocation,
EquilibrateMultiskillAllocationNonPreemptive,
NeighborBuilderMix,
NeighborBuilderSubPart,
NeighborBuilderTimeWindow,
NeighborConstraintBreaks,
NeighborRandom,
NeighborRandomAndNeighborGraph,
ObjectiveSubproblem,
ParamsConstraintBuilder,
)
from discrete_optimization.generic_rcpsp_tools.typing import ANY_RCPSP
from discrete_optimization.generic_tools.lns_cp import (
ConstraintHandler,
ConstraintHandlerMix,
)
from discrete_optimization.rcpsp_multiskill.rcpsp_multiskill import (
MS_RCPSPModel,
MS_RCPSPModel_Variant,
)
[docs]
class OptionNeighborRandom(Enum):
MIX_ALL = 0
MIX_FAST = 1
MIX_LARGE_NEIGH = 2
LARGE = 4
DEBUG = 5
NO_CONSTRAINT = 6
[docs]
def return_random_basic_constraint_handler(
rcpsp_model: ANY_RCPSP,
graph=None,
fraction_to_fix=0.9,
minus_delta=100,
plus_delta=100,
minus_delta_2=4000,
plus_delta_2=4000,
):
return BasicConstraintBuilder(
params_constraint_builder=ParamsConstraintBuilder(
minus_delta_primary=minus_delta,
plus_delta_primary=plus_delta,
minus_delta_secondary=minus_delta_2,
plus_delta_secondary=plus_delta_2,
),
neighbor_builder=NeighborRandom(
problem=rcpsp_model, graph=graph, fraction_subproblem=fraction_to_fix
),
)
[docs]
class Params:
def __init__(self, fraction_to_fix, minus_delta, plus_delta):
self.fraction_to_fix = fraction_to_fix
self.minus_delta = minus_delta
self.plus_delta = plus_delta
[docs]
def build_neighbor_random(
option_neighbor: OptionNeighborRandom, rcpsp_model: ANY_RCPSP
) -> ConstraintHandler:
graph = build_graph_rcpsp_object(rcpsp_problem=rcpsp_model)
params_use_case = [
ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=BasicConstraintBuilder(
params_constraint_builder=ParamsConstraintBuilder(
minus_delta_primary=100,
plus_delta_primary=100,
minus_delta_secondary=4000,
plus_delta_secondary=4000,
),
neighbor_builder=NeighborRandom(
problem=rcpsp_model, graph=graph, fraction_subproblem=0.75
),
),
params_list=[
ParamsConstraintBuilder(
minus_delta_primary=100,
plus_delta_primary=100,
minus_delta_secondary=4000,
plus_delta_secondary=4000,
)
],
use_makespan_of_subtasks=False,
)
]
params_all = [
ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=return_random_basic_constraint_handler(
rcpsp_model,
graph,
fraction_to_fix=p.fraction_to_fix,
minus_delta=p.minus_delta,
plus_delta=p.plus_delta,
minus_delta_2=4000,
plus_delta_2=4000,
),
params_list=[
ParamsConstraintBuilder(
p.minus_delta,
p.plus_delta,
4000,
4000,
constraint_max_time_to_current_solution=True,
)
],
use_makespan_of_subtasks=False,
)
for p in [
Params(fraction_to_fix=0.9, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.85, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=0.9, minus_delta=4, plus_delta=4),
Params(fraction_to_fix=0.9, minus_delta=4, plus_delta=4),
Params(fraction_to_fix=0.92, minus_delta=10, plus_delta=0),
Params(fraction_to_fix=0.88, minus_delta=0, plus_delta=10),
Params(fraction_to_fix=0.9, minus_delta=10, plus_delta=0),
Params(fraction_to_fix=0.8, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.85, minus_delta=15, plus_delta=15),
Params(fraction_to_fix=0.9, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=1.0, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.85, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.8, minus_delta=2, plus_delta=2),
Params(fraction_to_fix=0.85, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.85, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.85, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.85, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.95, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.95, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.85, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.9, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.9, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.8, minus_delta=2, plus_delta=2),
Params(fraction_to_fix=0.98, minus_delta=2, plus_delta=2),
Params(fraction_to_fix=0.9, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=0.98, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=0.98, minus_delta=8, plus_delta=8),
Params(fraction_to_fix=0.98, minus_delta=10, plus_delta=10),
]
]
params_fast = [
ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=return_random_basic_constraint_handler(
rcpsp_model,
graph,
fraction_to_fix=p.fraction_to_fix,
minus_delta=p.minus_delta,
plus_delta=p.plus_delta,
minus_delta_2=4000,
plus_delta_2=4000,
),
params_list=[
ParamsConstraintBuilder(
p.minus_delta,
p.plus_delta,
4000,
4000,
constraint_max_time_to_current_solution=False,
)
],
use_makespan_of_subtasks=False,
)
for p in [
Params(fraction_to_fix=0.9, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.8, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.8, minus_delta=2, plus_delta=2),
Params(fraction_to_fix=0.9, minus_delta=1, plus_delta=1),
Params(fraction_to_fix=0.92, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=0.98, minus_delta=7, plus_delta=7),
Params(fraction_to_fix=0.95, minus_delta=5, plus_delta=5),
]
]
params_debug = [
ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=return_random_basic_constraint_handler(
rcpsp_model,
graph,
fraction_to_fix=p.fraction_to_fix,
minus_delta=p.minus_delta,
plus_delta=p.plus_delta,
minus_delta_2=4000,
plus_delta_2=4000,
),
params_list=[
ParamsConstraintBuilder(
p.minus_delta,
p.plus_delta,
4000,
4000,
constraint_max_time_to_current_solution=False,
)
],
use_makespan_of_subtasks=False,
)
for p in [Params(fraction_to_fix=1.0, minus_delta=0, plus_delta=0)]
]
params_large = [
ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=return_random_basic_constraint_handler(
rcpsp_model,
graph,
fraction_to_fix=p.fraction_to_fix,
minus_delta=p.minus_delta,
plus_delta=p.plus_delta,
minus_delta_2=4000,
plus_delta_2=4000,
),
params_list=[
ParamsConstraintBuilder(
minus_delta_primary=p.minus_delta,
plus_delta_primary=p.plus_delta,
minus_delta_secondary=4000,
plus_delta_secondary=4000,
constraint_max_time_to_current_solution=False,
)
],
use_makespan_of_subtasks=False,
)
for p in [
Params(fraction_to_fix=0.9, minus_delta=12, plus_delta=12),
Params(fraction_to_fix=0.8, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=0.7, minus_delta=12, plus_delta=12),
Params(fraction_to_fix=0.7, minus_delta=5, plus_delta=5),
Params(fraction_to_fix=0.6, minus_delta=3, plus_delta=3),
Params(fraction_to_fix=0.4, minus_delta=2, plus_delta=2),
Params(fraction_to_fix=0.9, minus_delta=4, plus_delta=4),
Params(fraction_to_fix=0.7, minus_delta=4, plus_delta=4),
Params(fraction_to_fix=0.8, minus_delta=5, plus_delta=5),
]
]
params_no_constraint = [
ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=return_random_basic_constraint_handler(
rcpsp_model,
graph,
fraction_to_fix=p.fraction_to_fix,
minus_delta=p.minus_delta,
plus_delta=p.plus_delta,
minus_delta_2=10000,
plus_delta_2=10000,
),
params_list=[
ParamsConstraintBuilder(
p.minus_delta,
p.plus_delta,
4000,
4000,
constraint_max_time_to_current_solution=False,
)
],
use_makespan_of_subtasks=False,
)
for p in [Params(0.0, 4000, 4000)]
]
constraints_handler = None
if option_neighbor.name == OptionNeighborRandom.MIX_ALL.name:
constraints_handler = params_all
if option_neighbor.name == OptionNeighborRandom.MIX_FAST.name:
constraints_handler = params_fast
if option_neighbor.name == OptionNeighborRandom.MIX_LARGE_NEIGH.name:
constraints_handler = params_large
if option_neighbor.name == OptionNeighborRandom.DEBUG.name:
constraints_handler = params_debug
if option_neighbor.name == OptionNeighborRandom.LARGE.name:
constraints_handler = params_use_case
if option_neighbor.name == OptionNeighborRandom.NO_CONSTRAINT.name:
constraints_handler = params_no_constraint
probas = [1 / len(constraints_handler)] * len(constraints_handler)
constraint_handler = ConstraintHandlerMix(
problem=rcpsp_model,
list_constraints_handler=constraints_handler,
list_proba=probas,
)
return constraint_handler
[docs]
def build_constraint_handler_cut_part(rcpsp_problem: ANY_RCPSP, graph=None, **kwargs):
n1 = NeighborBuilderSubPart(
problem=rcpsp_problem, graph=graph, nb_cut_part=kwargs.get("nb_cut_part", 10)
)
basic_constraint_builder = BasicConstraintBuilder(
neighbor_builder=n1,
preemptive=kwargs.get("preemptive", False),
multiskill=kwargs.get("multiskill", False),
)
params_list = kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=6000,
plus_delta_primary=6000,
minus_delta_secondary=400,
plus_delta_secondary=400,
constraint_max_time_to_current_solution=False,
),
ParamsConstraintBuilder(
minus_delta_primary=6000,
plus_delta_primary=6000,
minus_delta_secondary=0,
plus_delta_secondary=0,
constraint_max_time_to_current_solution=False,
),
],
)
constraint_handler = ConstraintHandlerScheduling(
problem=rcpsp_problem,
basic_constraint_builder=basic_constraint_builder,
params_list=params_list,
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", False),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
)
return constraint_handler
[docs]
def build_basic_random_constraint_handler(rcpsp_problem: ANY_RCPSP, graph, **kwargs):
return ConstraintHandlerScheduling(
problem=rcpsp_problem,
basic_constraint_builder=BasicConstraintBuilder(
neighbor_builder=NeighborRandom(
problem=rcpsp_problem,
graph=graph,
fraction_subproblem=kwargs.get("fraction_subproblem", 0.1),
delta_abs_time_from_makespan_to_not_fix=kwargs.get(
"delta_abs_time_from_makespan_to_not_fix", 5
),
delta_rel_time_from_makespan_to_not_fix=kwargs.get(
"delta_rel_time_from_makespan_to_not_fix", 0.1
),
),
multiskill=kwargs.get("multiskill", False),
preemptive=kwargs.get("preemptive", False),
),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=100,
plus_delta_primary=100,
minus_delta_secondary=0,
plus_delta_secondary=0,
)
],
),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", True),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
)
[docs]
def build_basic_time_window_constraint_handler(
rcpsp_problem: ANY_RCPSP, graph, **kwargs
):
return ConstraintHandlerScheduling(
problem=rcpsp_problem,
basic_constraint_builder=BasicConstraintBuilder(
neighbor_builder=NeighborBuilderTimeWindow(
problem=rcpsp_problem,
graph=graph,
time_window_length=kwargs.get("time_window_length", 10),
),
multiskill=kwargs.get("multiskill", False),
preemptive=kwargs.get("preemptive", False),
),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=100,
plus_delta_primary=100,
minus_delta_secondary=0,
plus_delta_secondary=0,
)
],
),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", True),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
)
[docs]
def build_basic_random_and_neighbor(rcpsp_problem: ANY_RCPSP, graph, **kwargs):
return ConstraintHandlerScheduling(
problem=rcpsp_problem,
basic_constraint_builder=BasicConstraintBuilder(
neighbor_builder=NeighborRandomAndNeighborGraph(
problem=rcpsp_problem,
graph=graph,
fraction_subproblem=kwargs.get("fraction_subproblem", 0.1),
),
multiskill=kwargs.get("multiskill", False),
preemptive=kwargs.get("preemptive", False),
),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=100,
plus_delta_primary=100,
minus_delta_secondary=0,
plus_delta_secondary=0,
)
],
),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", True),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
)
[docs]
def build_neighbor_mixing_methods(
rcpsp_model: ANY_RCPSP, graph: GraphRCPSP = None, **kwargs
):
if graph is None:
graph = build_graph_rcpsp_object(rcpsp_problem=rcpsp_model)
n1 = NeighborBuilderSubPart(
problem=rcpsp_model, graph=graph, nb_cut_part=kwargs.get("cut_part", 10)
)
n2 = NeighborRandomAndNeighborGraph(
problem=rcpsp_model,
graph=graph,
fraction_subproblem=kwargs.get("fraction_subproblem", 0.05),
)
n3 = NeighborConstraintBreaks(
problem=rcpsp_model,
graph=graph,
fraction_subproblem=kwargs.get("fraction_subproblem", 0.05),
other_constraint_handler=n1,
)
n_mix = NeighborBuilderMix(
list_neighbor=[n1, n2, n3], weight_neighbor=[0.3, 0.3, 0.4]
)
basic_constraint_builder = BasicConstraintBuilder(
params_constraint_builder=ParamsConstraintBuilder(
minus_delta_primary=6000,
plus_delta_primary=6000,
minus_delta_secondary=400,
plus_delta_secondary=400,
constraint_max_time_to_current_solution=False,
),
neighbor_builder=n_mix,
preemptive=rcpsp_model.is_preemptive(),
multiskill=isinstance(rcpsp_model, (MS_RCPSPModel_Variant, MS_RCPSPModel)),
)
params_list = kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=6000,
plus_delta_primary=6000,
minus_delta_secondary=10,
plus_delta_secondary=10,
constraint_max_time_to_current_solution=False,
)
],
)
constraint_handler = ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=basic_constraint_builder,
params_list=params_list,
)
return constraint_handler
[docs]
def build_neighbor_mixing_cut_parts(
rcpsp_model: ANY_RCPSP, graph: GraphRCPSP = None, **kwargs
):
if graph is None:
graph = build_graph_rcpsp_object(rcpsp_problem=rcpsp_model)
n1_s = [
NeighborBuilderSubPart(problem=rcpsp_model, graph=graph, nb_cut_part=c_part)
for c_part in [4, 5, 6, 7]
]
n2_s = []
n_mix = NeighborBuilderMix(
list_neighbor=n1_s + n2_s,
weight_neighbor=[1 / (len(n1_s) + len(n2_s))] * (len(n1_s) + len(n2_s)),
)
basic_constraint_builder = BasicConstraintBuilder(
params_constraint_builder=ParamsConstraintBuilder(
minus_delta_primary=6000,
plus_delta_primary=6000,
minus_delta_secondary=400,
plus_delta_secondary=400,
constraint_max_time_to_current_solution=False,
),
neighbor_builder=n_mix,
preemptive=rcpsp_model.is_preemptive(),
multiskill=isinstance(rcpsp_model, (MS_RCPSPModel_Variant, MS_RCPSPModel)),
)
params_list = kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=6000,
plus_delta_primary=6000,
minus_delta_secondary=10,
plus_delta_secondary=10,
constraint_max_time_to_current_solution=False,
)
],
)
constraint_handler = ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=basic_constraint_builder,
params_list=params_list,
)
return constraint_handler
[docs]
def mix_both(
rcpsp_model: ANY_RCPSP,
option_neighbor_random: OptionNeighborRandom,
graph: GraphRCPSP = None,
**kwargs
):
a_s = [
build_neighbor_random(
option_neighbor=option_neighbor_random, rcpsp_model=rcpsp_model
)
]
b = build_neighbor_mixing_methods(rcpsp_model, graph=graph, **kwargs)
list_c = a_s + [b]
return ConstraintHandlerMix(
problem=rcpsp_model,
list_constraints_handler=list_c,
list_proba=[1 / len(list_c)] * len(list_c),
update_proba=False,
)
[docs]
def random_neigh(rcpsp_model, fraction_subproblem: float = 0.35, **kwargs):
return build_basic_random_constraint_handler(
rcpsp_problem=rcpsp_model,
graph=build_graph_rcpsp_object(rcpsp_problem=rcpsp_model),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=10,
plus_delta_primary=10,
minus_delta_secondary=2,
plus_delta_secondary=2,
constraint_max_time_to_current_solution=True,
)
],
),
preemptive=kwargs.get("preemptive", rcpsp_model.is_preemptive()),
multiskill=kwargs.get("multiskill", rcpsp_model.is_multiskill()),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", False),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
fraction_subproblem=fraction_subproblem,
delta_rel_time_from_makespan_to_not_fix=0.1,
delta_abs_time_from_makespan_to_not_fix=5,
)
[docs]
def time_window_neigh(rcpsp_model, **kwargs):
return build_basic_time_window_constraint_handler(
rcpsp_problem=rcpsp_model,
graph=build_graph_rcpsp_object(rcpsp_problem=rcpsp_model),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=10,
plus_delta_primary=10,
minus_delta_secondary=2,
plus_delta_secondary=2,
constraint_max_time_to_current_solution=True,
)
],
),
preemptive=kwargs.get("preemptive", rcpsp_model.is_preemptive()),
multiskill=kwargs.get("multiskill", rcpsp_model.is_multiskill()),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", False),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
time_window_length=kwargs.get("time_window_length", 10),
)
[docs]
def constraint_neigh(rcpsp_model, fraction_subproblem: float = 0.35, **kwargs):
gr = build_graph_rcpsp_object(rcpsp_problem=rcpsp_model)
n1 = NeighborBuilderSubPart(
problem=rcpsp_model,
graph=build_graph_rcpsp_object(rcpsp_problem=rcpsp_model),
nb_cut_part=kwargs.get("nb_cut_part", 3),
)
n2 = NeighborConstraintBreaks(
problem=rcpsp_model,
graph=gr,
fraction_subproblem=fraction_subproblem,
other_constraint_handler=n1,
)
return ConstraintHandlerScheduling(
problem=rcpsp_model,
basic_constraint_builder=BasicConstraintBuilder(
neighbor_builder=n2,
preemptive=kwargs.get("preemptive", rcpsp_model.is_preemptive()),
multiskill=kwargs.get("multiskill", rcpsp_model.is_multiskill()),
),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=100,
plus_delta_primary=100,
minus_delta_secondary=0,
plus_delta_secondary=0,
fraction_of_task_assigned_multiskill=0.8,
constraint_max_time_to_current_solution=False,
)
],
),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", False),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
)
[docs]
def cut_parts(rcpsp_model, nb_cut_part=4, **kwargs):
constraint_handler = build_constraint_handler_cut_part(
rcpsp_problem=rcpsp_model,
nb_cut_part=nb_cut_part,
preemptive=kwargs.get("preemptive", rcpsp_model.is_preemptive()),
multiskill=kwargs.get("multiskill", rcpsp_model.is_multiskill()),
graph=build_graph_rcpsp_object(rcpsp_problem=rcpsp_model),
params_list=kwargs.get(
"params_list",
[
ParamsConstraintBuilder(
minus_delta_primary=10,
plus_delta_primary=10,
minus_delta_secondary=1,
plus_delta_secondary=1,
constraint_max_time_to_current_solution=True,
)
],
),
use_makespan_of_subtasks=kwargs.get("use_makespan_of_subtasks", False),
objective_subproblem=kwargs.get(
"objective_subproblem", ObjectiveSubproblem.GLOBAL_MAKESPAN
),
verbose=True,
)
return constraint_handler
[docs]
def mix(rcpsp_model, nb_cut_part=3, fraction_subproblem=0.25):
c1 = cut_parts(rcpsp_model, nb_cut_part)
c2 = random_neigh(rcpsp_model, fraction_subproblem=fraction_subproblem)
return ConstraintHandlerMix(
problem=rcpsp_model,
list_constraints_handler=[c1, c2],
list_proba=[0.5, 0.5],
update_proba=True,
tag_constraint_handler=["cut_parts", "random"],
)
[docs]
def mix_lot(rcpsp_model, nb_cut_parts, fraction_subproblems, **kwargs):
c1 = [cut_parts(rcpsp_model, nb_cut_part, **kwargs) for nb_cut_part in nb_cut_parts]
c2 = [
random_neigh(rcpsp_model, fraction_subproblem=fraction_subproblem, **kwargs)
for fraction_subproblem in fraction_subproblems
]
tags = ["cut_parts_" + str(c) for c in nb_cut_parts]
tags += ["random_" + str(f) for f in fraction_subproblems]
if (
"generalized_precedence_constraint" in kwargs
and kwargs["generalized_precedence_constraint"]
):
c3 = [constraint_neigh(rcpsp_model, fraction_subproblem=0.25, **kwargs)]
tags += ["generalized_precedence_constraint"]
else:
c3 = []
c4 = []
if "time_windows" in kwargs and kwargs["time_windows"]:
c4 = [time_window_neigh(rcpsp_model=rcpsp_model, **kwargs)]
tags += ["time_windows"]
c5 = []
if kwargs.get("equilibrate_multiskill", False):
if rcpsp_model.is_preemptive():
c5 = [
EquilibrateMultiskillAllocation(problem=rcpsp_model)
for i in range(max(1, int((len(c1) + len(c2) + len(c3)) / 2)))
]
tags += ["equilibrate_" + str(i) for i in range(len(c5))]
else:
c5 = [
EquilibrateMultiskillAllocationNonPreemptive(problem=rcpsp_model)
for i in range(max(1, int((len(c1) + len(c2) + len(c3)) / 2)))
]
tags += ["equilibrate_" + str(i) for i in range(len(c5))]
if kwargs.get("equilibrate_multiskill_v2", False):
c5 = [
ConstraintHandlerMultiskillAllocation(problem=rcpsp_model)
for i in range(max(1, int((len(c1) + len(c2) + len(c3)) / 2)))
]
tags += ["equilibrate_" + str(i) for i in range(len(c5))]
return ConstraintHandlerMix(
problem=rcpsp_model,
list_constraints_handler=c1 + c2 + c3 + c4 + c5,
list_proba=[1 / (len(c1) + len(c2) + len(c3) + len(c4) + len(c5))]
* (len(c1) + len(c2) + len(c3) + len(c4) + len(c5)),
update_proba=False,
tag_constraint_handler=tags,
)