Reputation: 309
How to write alternative constraint with interval variable in or-tools? I thought something like this would work but the method AddAlternative doesn´t exist. Another question is how to know if interval variable is active
from ortools.sat.python import cp_model
# Crear el modelo
model = cp_model.CpModel()
# Crear la variable de intervalo
interval = model.NewIntervalVar(start, end, duration, 'interval')
# Crear los intervalos alternativos
alt_interval1 = model.NewIntervalVar(start1, end1, duration1, 'alt_interval1')
alt_interval2 = model.NewIntervalVar(start2, end2, duration2, 'alt_interval2')
# Agregar los intervalos alternativos a la variable de intervalo
model.AddAlternative(interval, [alt_interval1, alt_interval2])
# Resolver el modelo
solver = cp_model.CpSolver()
status = solver.Solve(model)
My code is:
# VARIABLES#
x = [
model.NewIntervalVar(
start=model.NewIntVar(es, lf, f"start_{row.id_pozo}"),
size=model.NewIntVar(es, lf, f"size_{row.id_pozo}"),
end=model.NewIntVar(es, lf, f"end_{row.id_pozo}"),
name="pozo_intv_{}".format(row.id_pozo),
)
for row in pozos.itertuples()
]
y = [
model.NewOptionalIntervalVar(
start=model.NewIntVar(row.dia_inicio, row.dia_fin, f"start_{idx}"),
size=row.tiempo_total,
end=model.NewIntVar(row.dia_inicio, row.dia_fin, f"end_{idx}"),
is_present=True,
name="pte_intv_{}".format(idx),
)
for idx, row in pozo_time_equipment.iterrows()
]
Upvotes: 1
Views: 1100
Reputation: 789
This is a flexible job shop problem. In the OR tools source there is a working example. The basics are, firstly creating the main interval for each task:
# Create main interval for the task.
suffix_name = '_j%i_t%i' % (job_id, task_id)
start = model.NewIntVar(0, horizon, 'start' + suffix_name)
duration = model.NewIntVar(min_duration, max_duration,
'duration' + suffix_name)
end = model.NewIntVar(0, horizon, 'end' + suffix_name)
interval = model.NewIntervalVar(start, duration, end,
'interval' + suffix_name)
Then for each alternative, create an additional interval:
alt_suffix = '_j%i_t%i_a%i' % (job_id, task_id, alt_id)
l_presence = model.NewBoolVar('presence' + alt_suffix)
l_start = model.NewIntVar(0, horizon, 'start' + alt_suffix)
l_duration = task[alt_id][0]
l_end = model.NewIntVar(0, horizon, 'end' + alt_suffix)
l_interval = model.NewOptionalIntervalVar(
l_start, l_duration, l_end, l_presence,
'interval' + alt_suffix)
l_presences.append(l_presence)
The alternative is linked to the main interval, only if the alternative is selected:
# Link the primary/global variables with the local ones.
model.Add(start == l_start).OnlyEnforceIf(l_presence)
model.Add(duration == l_duration).OnlyEnforceIf(l_presence)
model.Add(end == l_end).OnlyEnforceIf(l_presence)
Then finally, add a constraint to ensure that only one of the alternatives is selected:
# Select exactly one presence variable.
model.AddExactlyOne(l_presences)
Upvotes: 4