Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 209 additions & 73 deletions tsp_simple.cc
Original file line number Diff line number Diff line change
Expand Up @@ -341,88 +341,198 @@ void RelationBuilder(const TSPTWDataDT& data, RoutingModel& routing,
RoutingModel::DisjunctionIndex current_disjunction_index;
std::vector<int64> previous_vehicle_index_set;
std::vector<int64> current_vehicle_index_set;
std::vector<IntVar*> previous_active_var_set;
std::vector<IntVar*> current_active_var_set;
std::vector<IntVar*> current_active_index_set;
std::vector<IntVar*> previous_active_next_var_set;
std::vector<IntVar*> current_active_next_var_set;
std::vector<IntVar*> previous_vehicle_var_set;
std::vector<IntVar*> current_vehicle_var_set;
std::vector<IntVar*> previous_active_cumul_var_set;
std::vector<IntVar*> current_active_cumul_var_set;

switch (relation.type) {
case Sequence:
// int64 new_current_index;
previous_index = data.IdIndex(relation.linked_ids[0]);
for (int link_index = 1; link_index < relation.linked_ids.size(); ++link_index) {
previous_indices.push_back(previous_index);
for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

pairs.push_back(std::make_pair(previous_index, current_index));
current_active_var_set.clear();
current_active_cumul_var_set.clear();
current_vehicle_var_set.clear();
current_active_next_var_set.clear();
current_active_index_set.clear();
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
IntVar* const active_node = routing.ActiveVar(alternative_index);
current_vehicle_var_set.push_back(
solver->MakeProd(active_node, routing.VehicleVar(alternative_index))
->Var());

IntVar* const previous_active_var = routing.ActiveVar(previous_index);
IntVar* const active_var = routing.ActiveVar(current_index);
solver->AddConstraint(solver->MakeLessOrEqual(active_var, previous_active_var));
// routing.AddPickupAndDelivery(previous_index, current_index);
// The next var of the current active alternative
current_active_next_var_set.push_back(
solver->MakeProd(active_node, routing.NextVar(alternative_index))->Var());

IntVar* const previous_vehicle_var = routing.VehicleVar(previous_index);
IntVar* const vehicle_var = routing.VehicleVar(current_index);
IntExpr* const isConstraintActive =
solver->MakeProd(previous_active_var, active_var)->Var();
routing.NextVar(current_index)->RemoveValues(previous_indices);
// The index of the current alternative
current_active_index_set.push_back(
solver->MakeProd(active_node, alternative_index)->Var());

solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(isConstraintActive, previous_vehicle_var),
solver->MakeProd(isConstraintActive, vehicle_var)));
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(isConstraintActive, routing.NextVar(previous_index)),
solver->MakeProd(isConstraintActive, current_index)));
previous_index = current_index;
current_active_var_set.push_back(active_node);
current_active_cumul_var_set.push_back(
solver
->MakeProd(active_node, routing.GetMutableDimension(kTime)->CumulVar(
alternative_index))
->Var());
routing.NextVar(alternative_index)->RemoveValues(previous_indices);
previous_indices.push_back(alternative_index);
}

if (link_index >= 1) {
// The constraint is only active if both of the services have one active
// alternative
IntVar* active_constraint =
solver
->MakeProd(solver->MakeMax(previous_active_var_set),
solver->MakeMax(current_active_var_set))
->Var();
// The current set may be active only if the predecessor set is active
solver->AddConstraint(
solver->MakeLessOrEqual(solver->MakeMax(current_active_var_set),
solver->MakeMax(previous_active_var_set)));

// The current active alternative node should belong to the same route than the
// active predecessor
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(active_constraint,
solver->MakeMax(previous_vehicle_var_set)),
solver->MakeProd(active_constraint,
solver->MakeMax(current_vehicle_var_set))));

// The successor of the predecessor should be the current active alternative
// node
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(active_constraint,
solver->MakeMax(previous_active_next_var_set)),
solver->MakeProd(active_constraint,
solver->MakeMax(current_active_index_set))));

// The current active alternative should start after the active predecessor
solver->AddConstraint(solver->MakeLessOrEqual(
solver->MakeProd(active_constraint,
solver->MakeMax(previous_active_cumul_var_set)),
solver->MakeProd(active_constraint,
solver->MakeMax(current_active_cumul_var_set))));
}
previous_active_var_set = current_active_var_set;
previous_active_next_var_set = current_active_next_var_set;
previous_vehicle_var_set = current_vehicle_var_set;
previous_active_cumul_var_set = current_active_cumul_var_set;
}
if (relation.linked_ids.size() > 1)
solver->AddConstraint(solver->MakePathPrecedenceConstraint(next_vars, pairs));
break;
case Order:
previous_index = data.IdIndex(relation.linked_ids[0]);
previous_indices.push_back(previous_index);
for (int link_index = 1; link_index < relation.linked_ids.size(); ++link_index) {
for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

pairs.push_back(std::make_pair(previous_index, current_index));
// routing.AddPickupAndDelivery(previous_index, current_index);
IntVar* const previous_active_var = routing.ActiveVar(previous_index);
IntVar* const active_var = routing.ActiveVar(current_index);
current_active_var_set.clear();
current_vehicle_var_set.clear();
current_active_cumul_var_set.clear();

IntVar* const previous_vehicle_var = routing.VehicleVar(previous_index);
IntVar* const vehicle_var = routing.VehicleVar(current_index);
routing.NextVar(current_index)->RemoveValues(previous_indices);
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
IntVar* active_node = routing.ActiveVar(alternative_index);
current_active_var_set.push_back(active_node);
current_vehicle_var_set.push_back(routing.VehicleVar(alternative_index));
current_active_cumul_var_set.push_back(
solver
->MakeProd(active_node, routing.GetMutableDimension(kTime)->CumulVar(
alternative_index))
->Var());
routing.NextVar(alternative_index)->RemoveValues(previous_indices);
previous_indices.push_back(alternative_index);
}

solver->AddConstraint(solver->MakeLessOrEqual(active_var, previous_active_var));
IntExpr* const isConstraintActive =
solver->MakeProd(previous_active_var, active_var);
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(isConstraintActive, previous_vehicle_var),
solver->MakeProd(isConstraintActive, vehicle_var)));
previous_indices.push_back(current_index);
previous_index = current_index;
if (link_index >= 1) {
// The constraint is only active if both of the services have one active
// alternative
IntVar* active_constraint =
solver
->MakeProd(solver->MakeMax(previous_active_var_set),
solver->MakeMax(current_active_var_set))
->Var();

// The current set may be active only if the predessor set is active
solver->AddConstraint(
solver->MakeLessOrEqual(solver->MakeMax(current_active_var_set),
solver->MakeMax(previous_active_var_set)));
// The active alternatives should belong to the same route
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(active_constraint,
solver->MakeMax(previous_vehicle_var_set)),
solver->MakeProd(active_constraint,
solver->MakeMax(current_vehicle_var_set))));

// The current active alternative should start after the active predecessor
solver->AddConstraint(solver->MakeLessOrEqual(
solver->MakeProd(active_constraint,
solver->MakeMax(previous_active_cumul_var_set)),
solver->MakeProd(active_constraint,
solver->MakeMax(current_active_cumul_var_set))));
}
previous_active_var_set = current_active_var_set;
previous_vehicle_var_set = current_vehicle_var_set;
previous_active_cumul_var_set = current_active_cumul_var_set;
}
if (relation.linked_ids.size() > 1)
solver->AddConstraint(solver->MakePathPrecedenceConstraint(next_vars, pairs));
break;
case SameRoute:
previous_index = data.IdIndex(relation.linked_ids[0]);
for (int link_index = 1; link_index < relation.linked_ids.size(); ++link_index) {
for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

IntVar* const previous_active_var = routing.ActiveVar(previous_index);
IntVar* const active_var = routing.ActiveVar(current_index);
current_active_var_set.clear();
current_vehicle_var_set.clear();
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
IntVar* const active_node = routing.ActiveVar(alternative_index);
current_active_var_set.push_back(active_node);
// Current vehicle var is active only if one of the previous active var is
// active and if the current alternative is active
current_vehicle_var_set.push_back(
solver
->MakeProd(solver->MakeProd(solver->MakeMax(previous_active_var_set),
active_node),
routing.VehicleVar(alternative_index))
->Var());
}

IntVar* const previous_vehicle_var = routing.VehicleVar(previous_index);
IntVar* const vehicle_var = routing.VehicleVar(current_index);
if (link_index >= 1) {
// The constraint is only active if both of the services have one active
// alternative
IntVar* active_constraint =
solver
->MakeProd(solver->MakeMax(previous_active_var_set),
solver->MakeMax(current_active_var_set))
->Var();

solver->AddConstraint(solver->MakeLessOrEqual(active_var, previous_active_var));
IntVar* const isConstraintActive =
solver->MakeProd(previous_active_var, active_var)->Var();
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(previous_vehicle_var, isConstraintActive),
solver->MakeProd(vehicle_var, isConstraintActive)));
previous_index = current_index;
// The current set may be active only if the predessor set is active
solver->AddConstraint(
solver->MakeLessOrEqual(solver->MakeMax(current_active_var_set),
solver->MakeMax(previous_active_var_set)));
// The active alternatives should belong to the same route
solver->AddConstraint(solver->MakeEquality(
solver->MakeProd(active_constraint,
solver->MakeMax(previous_vehicle_var_set)),
solver->MakeProd(active_constraint,
solver->MakeMax(current_vehicle_var_set))));
}
previous_active_var_set = current_active_var_set;
previous_vehicle_var_set = current_vehicle_var_set;
}
break;
case MinimumDayLapse:
Expand Down Expand Up @@ -502,18 +612,20 @@ void RelationBuilder(const TSPTWDataDT& data, RoutingModel& routing,
IntVar* const active_node = routing.ActiveVar(alternative_index);
current_active_cumul_var_set.push_back(
solver
->MakeProd(active_node,
routing.GetMutableDimension(kTime)->CumulVar(current_index))
->MakeProd(active_node, routing.GetMutableDimension(kTime)->CumulVar(
alternative_index))
->Var());
}

if (link_index >= 1) {
routing.AddPickupAndDeliverySets(previous_disjunction_index,
current_disjunction_index);
// The active alternatives should belong to the same route
solver->AddConstraint(
solver->MakeEquality(solver->MakeMax(previous_vehicle_var_set),
solver->MakeMax(current_vehicle_var_set)));

// The current active alternative should start after the active predecessor
solver->AddConstraint(
solver->MakeLessOrEqual(solver->MakeMax(previous_active_cumul_var_set),
solver->MakeMax(current_active_cumul_var_set)));
Expand Down Expand Up @@ -607,12 +719,18 @@ void RelationBuilder(const TSPTWDataDT& data, RoutingModel& routing,
case NeverFirst:
for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

for (std::size_t v = 0; v < data.Vehicles().size(); ++v) {
int64 start_index = routing.Start(v);
// int64 end_index = routing.End(v);
IntVar* const next_var = routing.NextVar(start_index);
next_var->RemoveValue(current_index);
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
for (std::size_t v = 0; v < data.Vehicles().size(); ++v) {
int64 start_index = routing.Start(v);
// int64 end_index = routing.End(v);
IntVar* const next_var = routing.NextVar(start_index);
next_var->RemoveValue(alternative_index);
}
}
}
break;
Expand All @@ -623,12 +741,18 @@ void RelationBuilder(const TSPTWDataDT& data, RoutingModel& routing,

for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

intermediate_values.push_back(current_index);
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
intermediate_values.push_back(alternative_index);

std::vector<int64>::iterator it =
std::find(values.begin(), values.end(), current_index);
values.erase(it);
std::vector<int64>::iterator it =
std::find(values.begin(), values.end(), alternative_index);
values.erase(it);
}
}

for (int index : values) {
Expand All @@ -639,19 +763,31 @@ void RelationBuilder(const TSPTWDataDT& data, RoutingModel& routing,
case NeverLast:
for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

IntVar* const next_var = routing.NextVar(current_index);
for (std::size_t v = 0; v < data.Vehicles().size(); ++v) {
int64 end_index = routing.End(v);
next_var->RemoveValue(end_index);
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
IntVar* const next_var = routing.NextVar(alternative_index);
for (std::size_t v = 0; v < data.Vehicles().size(); ++v) {
int64 end_index = routing.End(v);
next_var->RemoveValue(end_index);
}
}
}
break;
case ForceLast:
for (int link_index = 0; link_index < relation.linked_ids.size(); ++link_index) {
current_index = data.IdIndex(relation.linked_ids[link_index]);
int32 service_index =
data.ProblemIndex(RoutingIndexManager::NodeIndex(current_index));
alternative_size = data.AlternativeSize(service_index);

values.push_back(current_index);
for (int64 alternative_index = current_index;
alternative_index < current_index + alternative_size; ++alternative_index) {
values.push_back(alternative_index);
}
}
intermediate_values.insert(intermediate_values.end(), values.begin(), values.end());
for (std::size_t v = 0; v < data.Vehicles().size(); ++v) {
Expand Down Expand Up @@ -732,7 +868,7 @@ void RelationBuilder(const TSPTWDataDT& data, RoutingModel& routing,
default:
std::cout << "ERROR: Relation type (" << relation.type << ") is not implemented"
<< std::endl;
throw - 1;
throw -1;
}
}
}
Expand Down
Loading