Created
February 6, 2019 14:01
-
-
Save Muhammad-Altabba/c552d5fde89dfe8e6bcc91f06e399cbd to your computer and use it in GitHub Desktop.
Sample Time Window Constraints backward compatible with Google OR-Tools 7.0.6150-beta
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file is cloned from https://github.com/google/or-tools/blob/master/ortools/constraint_solver/samples/VrpTimeWindows.cs | |
// It is just modified to work with 7.0.6150-beta | |
// Copyright 2010-2018 Google LLC | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// [START program] | |
// [START import] | |
using System; | |
using System.Collections.Generic; | |
using Google.OrTools.ConstraintSolver; | |
// [END import] | |
/// <summary> | |
/// Minimal TSP using distance matrix. | |
/// </summary> | |
public class VrpTimeWindows | |
{ | |
// [START data_model] | |
class DataModel | |
{ | |
// Constructor: | |
public DataModel() | |
{ | |
timeMatrix_ = new long[,] { | |
{0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7}, | |
{6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14}, | |
{9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9}, | |
{8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16}, | |
{7, 2, 10, 1, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14}, | |
{3, 6, 6, 7, 6, 0, 2, 3, 2, 2, 7, 9, 7, 7, 6, 12, 8}, | |
{6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5}, | |
{2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 8, 5, 4, 3, 7, 8, 10}, | |
{3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6}, | |
{2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5}, | |
{6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4}, | |
{6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 3, 10}, | |
{4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 6, 4, 8}, | |
{4, 8, 13, 9, 8, 7, 10, 3, 7, 4, 8, 3, 2, 0, 4, 5, 6}, | |
{5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 6, 4, 0, 9, 2}, | |
{9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9}, | |
{7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0}, | |
}; | |
timeWindows_ = new long[,] { | |
{0, 0}, | |
{10, 15}, | |
{10, 15}, | |
{5, 10}, | |
{5, 10}, | |
{0, 5}, | |
{5, 10}, | |
{0, 5}, | |
{5, 10}, | |
{0, 5}, | |
{10, 15}, | |
{10, 15}, | |
{0, 5}, | |
{5, 10}, | |
{5, 10}, | |
{10, 15}, | |
{5, 10}, | |
}; | |
} | |
public ref readonly long[,] GetTimeMatrix() { return ref timeMatrix_; } | |
public ref readonly long[,] GetTimeWindows() { return ref timeWindows_; } | |
public int GetVehicleNumber() { return 4; } | |
public int GetDepot() { return 0; } | |
private long[,] timeMatrix_; | |
private long[,] timeWindows_; | |
}; | |
// [END data_model] | |
class TimeCallback : LongLongToLong | |
{ | |
private long[,] timeMatrix; | |
private RoutingIndexManager indexManager; | |
public TimeCallback(DataModel data, RoutingIndexManager manager) | |
{ | |
timeMatrix = data.GetTimeMatrix(); | |
indexManager = manager; | |
} | |
override public long Run(long fromIndex, long toIndex) | |
{ | |
// Convert from routing variable Index to time matrix NodeIndex. | |
int fromNode = indexManager.IndexToNode(fromIndex); | |
int toNode = indexManager.IndexToNode(toIndex); | |
return timeMatrix[fromNode, toNode]; | |
} | |
} | |
// [START solution_printer] | |
/// <summary> | |
/// Print the solution. | |
/// </summary> | |
static void PrintSolution( | |
in DataModel data, | |
in RoutingModel routing, | |
in RoutingIndexManager manager, | |
in Assignment solution) | |
{ | |
Console.WriteLine("Objective: {0}", solution.ObjectiveValue()); | |
RoutingDimension timeDimension = routing.GetMutableDimension("Time"); | |
// Inspect solution. | |
long totalTime = 0; | |
for (int i = 0; i < data.GetVehicleNumber(); ++i) | |
{ | |
Console.WriteLine("Route for Vehicle {0}:", i); | |
long routeTime = 0; | |
var index = routing.Start(i); | |
while (routing.IsEnd(index) == false) | |
{ | |
var timeVar = timeDimension.CumulVar(index); | |
var slackVar = timeDimension.SlackVar(index); | |
Console.Write("{0} Time({1},{2}) Slack({3},{4}) -> ", | |
manager.IndexToNode(index), | |
solution.Min(timeVar), | |
solution.Max(timeVar), | |
solution.Min(slackVar), | |
solution.Max(slackVar)); | |
var previousIndex = index; | |
index = solution.Value(routing.NextVar(index)); | |
routeTime += routing.GetArcCostForVehicle(previousIndex, index, 0); | |
} | |
var endTimeVar = timeDimension.CumulVar(index); | |
Console.WriteLine("{0} Time({1},{2})", | |
manager.IndexToNode(index), | |
solution.Min(endTimeVar), | |
solution.Max(endTimeVar)); | |
Console.WriteLine("Time of the route: {0}m", routeTime); | |
totalTime += routeTime; | |
} | |
Console.WriteLine("Total Distance of all routes: {0}m", totalTime); | |
} | |
// [END solution_printer] | |
public static void Main(String[] args) | |
{ | |
// Instantiate the data problem. | |
// [START data] | |
DataModel data = new DataModel(); | |
// [END data] | |
// Create Routing Index Manager | |
// [START index_manager] | |
RoutingIndexManager manager = new RoutingIndexManager( | |
data.GetTimeMatrix().GetLength(0), | |
data.GetVehicleNumber(), | |
data.GetDepot()); | |
// [END index_manager] | |
// Create Routing Model. | |
// [START routing_model] | |
RoutingModel routing = new RoutingModel(manager); | |
// [END routing_model] | |
// Create and register a transit callback. | |
// [START transit_callback] | |
LongLongToLong timeCallback = new TimeCallback(data, manager); | |
int transitCallbackIndex = routing.RegisterTransitCallback(timeCallback); | |
//const int transitCallbackIndex = routing.RegisterTransitCallback( | |
// (long fromIndex, long toIndex) => { | |
// // Convert from routing variable Index to distance matrix NodeIndex. | |
// var fromNode = manager.IndexToNode(fromIndex); | |
// var toNode = manager.IndexToNode(toIndex); | |
// return data.GetTimeMatrix()[fromNode, toNode]; | |
// } | |
//); | |
// [END transit_callback] | |
// Define cost of each arc. | |
// [START arc_cost] | |
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); | |
// [END arc_cost] | |
// Add Distance constraint. | |
// [START time_constraint] | |
routing.AddDimension( | |
transitCallbackIndex, // transit callback | |
30, // allow waiting time | |
30, // vehicle maximum capacities | |
false, // start cumul to zero | |
"Time"); | |
RoutingDimension timeDimension = routing.GetMutableDimension("Time"); | |
// Add time window constraints for each location except depot | |
// and 'copy' the slack var in the solution object (aka Assignment) to print it | |
for (int i = 1; i < data.GetTimeWindows().GetLength(0); ++i) | |
{ | |
long index = manager.NodeToIndex(i); | |
timeDimension.CumulVar(index).SetRange( | |
data.GetTimeWindows()[i, 0], | |
data.GetTimeWindows()[i, 1]); | |
routing.AddToAssignment(timeDimension.SlackVar(index)); | |
} | |
// Add time window constraints for each vehicle start node | |
// and 'copy' the slack var in the solution object (aka Assignment) to print | |
// it | |
for (int i = 0; i < data.GetVehicleNumber(); ++i) | |
{ | |
long index = routing.Start(i); | |
timeDimension.CumulVar(index).SetRange( | |
data.GetTimeWindows()[0, 0], | |
data.GetTimeWindows()[0, 1]); | |
routing.AddToAssignment(timeDimension.SlackVar(index)); | |
} | |
// [END time_constraint] | |
// Setting first solution heuristic. | |
// [START parameters] | |
RoutingSearchParameters searchParameters = | |
operations_research_constraint_solver.DefaultRoutingSearchParameters(); | |
searchParameters.FirstSolutionStrategy = | |
FirstSolutionStrategy.Types.Value.PathCheapestArc; | |
// [END parameters] | |
// Solve the problem. | |
// [START solve] | |
Assignment solution = routing.SolveWithParameters(searchParameters); | |
// [END solve] | |
// Print solution on console. | |
// [START print_solution] | |
PrintSolution(data, routing, manager, solution); | |
// [END print_solution] | |
} | |
} | |
// [END program] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment