I’m beginner in constraint programming and I’m using Google or-tools library in my c# program.
In my problem nodes belong to zones, characterised by a maximum number of vehicles in transit towards them (for example if a zone has the limit set to 1, only one vehicles can execute a mission that belong to that zone).
I tried to resolve in 3 different ways but with no result. At first i tried with dimension capacity:
int demandCallbackIndexZone = routing.RegisterUnaryTransitCallback((long fromIndex) =>
{
// Convert from routing variable Index to
// demand NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var index = data.Zones.FindIndex(z => z.Contains(fromNode));
return zone_limits[index];
});
routing.AddDimensionWithVehicleCapacity(demandCallbackIndex, 0,
zone_limits,
true,
“Capacity”);
Where Zones is a List<int[]> where every int[] is a zone and its element the nodes that belong to it. zone_limits in an array that contains the limit for every zone.
In the second way i tried to resolve with boolVar:
//// Create a boolVar for every couple (mission,zone), that indicates if the mission is in execution in that zone
IntVar[][] inZone = new IntVar[data.Zones.Count][];
for (int z = 0; z < data.Zones.Count; z++)
{
inZone[z] = new IntVar[data.Zones[z].Length];
for (int i = 0; i < data.Zones[z].Length; i++)
{
inZone[z][i] = solver.MakeIntVar(0, 1, $"mission_{data.Zones[z][i]}_in_zone_{z}");
}
}
for (int z = 0; z < data.Zones.Count; z++)
{
int count = 0;
IntVar[] missionsInZone = new IntVar[data.Zones[z].Length];
for (int i = 0; i < data.Zones[z].Length; i++)
{
missionsInZone[i] = inZone[z][i];
count++;
}
// the sum of the missions in zone (z) must be less than the limit
solver.Add(solver.MakeSum(missionsInZone) <= zone_limits[z]);
}
In the last try i used the MakeFixedDurationIntervalVar to block the node for a fixed duration (transition from the last node assign to vehicle to the node with limit). In this solution i need a callback that give me the last node assign to vehicle dynamically, so i tried with callback but i don’t know ho to recall it or if it possible to use it.
int StartIndexCallBack = routing.RegisterUnaryTransitCallback((long fromIndex) =>
{
return fromIndex;
});
int maxMissions = 1;
long duration = 0;
Solver solver = routing.solver();
for (int i = 0; i < data.Zones.Count; ++i)
{
IntervalVar[] intervals = new IntervalVar[data.Zones[i].Length];
for (int j = 0; j < data.Zones[i].Length; ++j)
{
// get index
long missionIndex = manager.NodeToIndex(data.Zones[i][j]);
long StartIndex = callback node....
duration = data.TimeMatrix[StartIndex, missionIndex];
// Add load duration at start of routes
intervals[j] = solver.MakeFixedDurationIntervalVar(timeDimension.CumulVar(StartIndex),
duration, "interval_engaged");
}
long[] resource_usage = Enumerable.Repeat<long>(1, intervals.Length).ToArray();
solver.Add(solver.MakeCumulative(intervals, resource_usage, maxMissions, "SharedRessource"));
}
Luca Maini is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.