Add .Net routing samples
This commit is contained in:
@@ -522,7 +522,13 @@ test_dotnet_algorithms_samples: ;
|
||||
test_dotnet_constraint_solver_samples:
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/SimpleRoutingProgram.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/Tsp.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/TspDistanceMatrix.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/Vrp.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/VrpCapacity.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/VrpDropNodes.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/VrpGlobalSpan.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/VrpStartsEnds.cs
|
||||
$(MAKE) run SOURCE=ortools/constraint_solver/samples/VrpTimeWindows.cs
|
||||
|
||||
.PHONY: test_dotnet_graph_samples # Build and Run all .Net LP Samples (located in ortools/graph/samples)
|
||||
test_dotnet_graph_samples: ;
|
||||
|
||||
@@ -21,10 +21,7 @@ using Google.OrTools.ConstraintSolver;
|
||||
/// This is a sample using the routing library .Net wrapper.
|
||||
/// </summary>
|
||||
public class SimpleRoutingProgram {
|
||||
/// <summary>
|
||||
/// Solves the current routing problem.
|
||||
/// </summary>
|
||||
static void Solve() {
|
||||
public static void Main(String[] args) {
|
||||
// Instantiate the data problem.
|
||||
// [START data]
|
||||
const int num_location = 5;
|
||||
@@ -81,8 +78,5 @@ public class SimpleRoutingProgram {
|
||||
Console.WriteLine("Distance of the route: {0}m", route_distance);
|
||||
// [END print_solution]
|
||||
}
|
||||
|
||||
public static void Main(String[] args) {
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
// [END program]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2018 Google
|
||||
// Copyright 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
|
||||
@@ -11,22 +11,23 @@
|
||||
// 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>
|
||||
/// This is a sample using the routing library .Net wrapper to solve a TSP
|
||||
/// problem.
|
||||
/// Minimal TSP.
|
||||
/// A description of the problem can be found here:
|
||||
/// http://en.wikipedia.org/wiki/Travelling_salesman_problem.
|
||||
/// </summary>
|
||||
public class TSP {
|
||||
class DataProblem {
|
||||
private int[,] locations_;
|
||||
|
||||
public class Tsp {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataProblem() {
|
||||
public DataModel() {
|
||||
locations_ = new int[,] {
|
||||
{4, 4},
|
||||
{2, 0}, {8, 0},
|
||||
@@ -44,38 +45,36 @@ public class TSP {
|
||||
locations_[i, 1] *= 80;
|
||||
}
|
||||
}
|
||||
|
||||
public ref readonly int[,] GetLocations() { return ref locations_;}
|
||||
public int GetVehicleNumber() { return 1;}
|
||||
public int GetDepot() { return 0;}
|
||||
|
||||
private int[,] locations_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
|
||||
// [START manhattan_distance]
|
||||
/// <summary>
|
||||
/// Manhattan distance implemented as a callback. It uses an array of
|
||||
/// positions and computes the Manhattan distance between the two
|
||||
/// positions of two different indices.
|
||||
/// </summary>
|
||||
class ManhattanDistance : LongLongToLong {
|
||||
private int[,] distances_;
|
||||
private RoutingIndexManager manager_;
|
||||
|
||||
public ManhattanDistance(in DataProblem data,
|
||||
in RoutingIndexManager manager) {
|
||||
public ManhattanDistance(
|
||||
in DataModel data,
|
||||
in RoutingIndexManager manager) {
|
||||
// precompute distance between location to have distance callback in O(1)
|
||||
int locationNumber = data.GetLocations().GetLength(0);
|
||||
distances_ = new int[locationNumber, locationNumber];
|
||||
manager_ = manager;
|
||||
distancesMatrix_ = new long[locationNumber, locationNumber];
|
||||
indexManager_ = manager;
|
||||
for (int fromNode = 0; fromNode < locationNumber; fromNode++) {
|
||||
for (int toNode = 0; toNode < locationNumber; toNode++) {
|
||||
if (fromNode == toNode)
|
||||
distances_[fromNode, toNode] = 0;
|
||||
distancesMatrix_[fromNode, toNode] = 0;
|
||||
else
|
||||
distances_[fromNode, toNode] =
|
||||
Math.Abs(data.GetLocations()[toNode, 0] -
|
||||
data.GetLocations()[fromNode, 0]) +
|
||||
Math.Abs(data.GetLocations()[toNode, 1] -
|
||||
data.GetLocations()[fromNode, 1]);
|
||||
distancesMatrix_[fromNode, toNode] =
|
||||
Math.Abs(data.GetLocations()[toNode, 0] - data.GetLocations()[fromNode, 0]) +
|
||||
Math.Abs(data.GetLocations()[toNode, 1] - data.GetLocations()[fromNode, 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,67 +83,84 @@ public class TSP {
|
||||
/// Returns the manhattan distance between the two nodes
|
||||
/// </summary>
|
||||
public override long Run(long FromIndex, long ToIndex) {
|
||||
int FromNode = manager_.IndexToNode(FromIndex);
|
||||
int ToNode = manager_.IndexToNode(ToIndex);
|
||||
return distances_[FromNode, ToNode];
|
||||
int FromNode = indexManager_.IndexToNode(FromIndex);
|
||||
int ToNode = indexManager_.IndexToNode(ToIndex);
|
||||
return distancesMatrix_[FromNode, ToNode];
|
||||
}
|
||||
private long[,] distancesMatrix_;
|
||||
private RoutingIndexManager indexManager_;
|
||||
};
|
||||
// [END manhattan_distance]
|
||||
|
||||
// [START solution_printer]
|
||||
/// <summary>
|
||||
/// Print the solution
|
||||
/// Print the solution.
|
||||
/// </summary>
|
||||
static void PrintSolution(
|
||||
in DataProblem data,
|
||||
in RoutingModel routing,
|
||||
in RoutingIndexManager manager,
|
||||
in Assignment solution) {
|
||||
Console.WriteLine("Objective: {0}", solution.ObjectiveValue());
|
||||
// Inspect solution.
|
||||
var index = routing.Start(0);
|
||||
Console.WriteLine("Route for Vehicle 0:");
|
||||
long distance = 0;
|
||||
long routeDistance = 0;
|
||||
var index = routing.Start(0);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
Console.Write("{0} -> ", manager.IndexToNode((int)index));
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
distance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", distance);
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
}
|
||||
// [END solution_printer]
|
||||
|
||||
/// <summary>
|
||||
/// Solves the current routing problem.
|
||||
/// </summary>
|
||||
static void Solve() {
|
||||
public static void Main(String[] args) {
|
||||
// Instantiate the data problem.
|
||||
DataProblem data = new DataProblem();
|
||||
// [START data]
|
||||
DataModel data = new DataModel();
|
||||
// [END data]
|
||||
|
||||
// Create Routing Model
|
||||
// Create Routing Index Manager
|
||||
// [START index_manager]
|
||||
RoutingIndexManager manager = new RoutingIndexManager(
|
||||
data.GetLocations().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END index_manager]
|
||||
|
||||
// Define weight of each edge
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
LongLongToLong distanceEvaluator = new ManhattanDistance(data, manager);
|
||||
//protect callbacks from the GC
|
||||
GC.KeepAlive(distanceEvaluator);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(
|
||||
routing.RegisterTransitCallback(distanceEvaluator));
|
||||
int transitCostIndex = routing.RegisterTransitCallback(distanceEvaluator);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Setting first solution heuristic (cheapest addition).
|
||||
// Setting first solution heuristic.
|
||||
// [START parameters]
|
||||
RoutingSearchParameters searchParameters =
|
||||
operations_research_constraint_solver.DefaultRoutingSearchParameters();
|
||||
operations_research_constraint_solver.DefaultRoutingSearchParameters();
|
||||
searchParameters.FirstSolutionStrategy =
|
||||
FirstSolutionStrategy.Types.Value.PathCheapestArc;
|
||||
FirstSolutionStrategy.Types.Value.PathCheapestArc;
|
||||
// [END parameters]
|
||||
|
||||
// Solve the problem.
|
||||
// [START solve]
|
||||
Assignment solution = routing.SolveWithParameters(searchParameters);
|
||||
PrintSolution(data, routing, manager, solution);
|
||||
}
|
||||
// [END solve]
|
||||
|
||||
public static void Main(String[] args) {
|
||||
Solve();
|
||||
// Print solution on console.
|
||||
// [START print_solution]
|
||||
PrintSolution(routing, manager, solution);
|
||||
// [END print_solution]
|
||||
}
|
||||
}
|
||||
// [END program]
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Tsp.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0-*" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
130
ortools/constraint_solver/samples/TspDistanceMatrix.cs
Normal file
130
ortools/constraint_solver/samples/TspDistanceMatrix.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright 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 TspDistanceMatrix {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataModel() {
|
||||
distancesMatrix_ = new long[,] {
|
||||
{0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
|
||||
{548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
|
||||
{776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
|
||||
{696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
|
||||
{582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
|
||||
{274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
|
||||
{502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
|
||||
{194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
|
||||
{308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
|
||||
{194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
|
||||
{536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
|
||||
{502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
|
||||
{388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
|
||||
{354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
|
||||
{468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
|
||||
{776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
|
||||
{662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0}
|
||||
};
|
||||
}
|
||||
public ref readonly long[,] GetDistanceMatrix() { return ref distancesMatrix_;}
|
||||
public int GetVehicleNumber() { return 1;}
|
||||
public int GetDepot() { return 0;}
|
||||
|
||||
private long[,] distancesMatrix_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
// [START solution_printer]
|
||||
/// <summary>
|
||||
/// Print the solution.
|
||||
/// </summary>
|
||||
static void PrintSolution(
|
||||
in RoutingModel routing,
|
||||
in RoutingIndexManager manager,
|
||||
in Assignment solution) {
|
||||
Console.WriteLine("Objective: {0}", solution.ObjectiveValue());
|
||||
// Inspect solution.
|
||||
Console.WriteLine("Route for Vehicle 0:");
|
||||
long routeDistance = 0;
|
||||
var index = routing.Start(0);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
Console.Write("{0} -> ", manager.IndexToNode((int)index));
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
}
|
||||
// [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.GetDistanceMatrix().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
// [END index_manager]
|
||||
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetDistanceMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// 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(routing, manager, solution);
|
||||
// [END print_solution]
|
||||
}
|
||||
}
|
||||
// [END program]
|
||||
20
ortools/constraint_solver/samples/TspDistanceMatrix.csproj
Normal file
20
ortools/constraint_solver/samples/TspDistanceMatrix.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="TspDistanceMatrix.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2018 Google
|
||||
// Copyright 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
|
||||
@@ -11,171 +11,126 @@
|
||||
// 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>
|
||||
/// This is a sample using the routing library .Net wrapper to solve a VRP problem.
|
||||
/// A description of the problem can be found here:
|
||||
/// http://en.wikipedia.org/wiki/Vehicle_routing_problem.
|
||||
/// Minimal TSP using distance matrix.
|
||||
/// </summary>
|
||||
public class VRP {
|
||||
class DataProblem {
|
||||
private int[,] locations_;
|
||||
|
||||
public class Vrp {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataProblem() {
|
||||
locations_ = new int[,] {
|
||||
{4, 4},
|
||||
{2, 0}, {8, 0},
|
||||
{0, 1}, {1, 1},
|
||||
{5, 2}, {7, 2},
|
||||
{3, 3}, {6, 3},
|
||||
{5, 5}, {8, 5},
|
||||
{1, 6}, {2, 6},
|
||||
{3, 7}, {6, 7},
|
||||
{0, 8}, {7, 8}
|
||||
public DataModel() {
|
||||
distancesMatrix_ = new long[,] {
|
||||
{0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
|
||||
{548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
|
||||
{776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
|
||||
{696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
|
||||
{582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
|
||||
{274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
|
||||
{502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
|
||||
{194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
|
||||
{308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
|
||||
{194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
|
||||
{536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
|
||||
{502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
|
||||
{388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
|
||||
{354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
|
||||
{468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
|
||||
{776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
|
||||
{662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0}
|
||||
};
|
||||
|
||||
// Compute locations in meters using the block dimension defined as follow
|
||||
// Manhattan average block: 750ft x 264ft -> 228m x 80m
|
||||
// here we use: 114m x 80m city block
|
||||
// src: https://nyti.ms/2GDoRIe "NY Times: Know Your distance"
|
||||
int[] cityBlock = {228/2, 80};
|
||||
for (int i=0; i < locations_.GetLength(0); i++) {
|
||||
locations_[i, 0] = locations_[i, 0] * cityBlock[0];
|
||||
locations_[i, 1] = locations_[i, 1] * cityBlock[1];
|
||||
}
|
||||
}
|
||||
|
||||
public ref readonly long[,] GetDistanceMatrix() { return ref distancesMatrix_;}
|
||||
public int GetVehicleNumber() { return 4;}
|
||||
public ref readonly int[,] GetLocations() { return ref locations_;}
|
||||
public int GetLocationNumber() { return locations_.GetLength(0);}
|
||||
public int GetDepot() { return 0;}
|
||||
|
||||
private long[,] distancesMatrix_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
|
||||
// [START solution_printer]
|
||||
/// <summary>
|
||||
/// Manhattan distance implemented as a callback. It uses an array of
|
||||
/// positions and computes the Manhattan distance between the two
|
||||
/// positions of two different indices.
|
||||
/// </summary>
|
||||
class ManhattanDistance : LongLongToLong {
|
||||
private int[,] distances_;
|
||||
private RoutingIndexManager manager_;
|
||||
|
||||
public ManhattanDistance(in DataProblem data,
|
||||
in RoutingIndexManager manager) {
|
||||
// precompute distance between location to have distance callback in O(1)
|
||||
distances_ = new int[data.GetLocationNumber(), data.GetLocationNumber()];
|
||||
manager_ = manager;
|
||||
for (int fromNode = 0; fromNode < data.GetLocationNumber(); fromNode++) {
|
||||
for (int toNode = 0; toNode < data.GetLocationNumber(); toNode++) {
|
||||
if (fromNode == toNode)
|
||||
distances_[fromNode, toNode] = 0;
|
||||
else
|
||||
distances_[fromNode, toNode] =
|
||||
Math.Abs(data.GetLocations()[toNode, 0] -
|
||||
data.GetLocations()[fromNode, 0]) +
|
||||
Math.Abs(data.GetLocations()[toNode, 1] -
|
||||
data.GetLocations()[fromNode, 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the manhattan distance between the two nodes
|
||||
/// </summary>
|
||||
public override long Run(long FromIndex, long ToIndex) {
|
||||
int FromNode = manager_.IndexToNode(FromIndex);
|
||||
int ToNode = manager_.IndexToNode(ToIndex);
|
||||
return distances_[FromNode, ToNode];
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Add distance Dimension
|
||||
/// </summary>
|
||||
static void AddDistanceDimension(
|
||||
in DataProblem data,
|
||||
in RoutingModel routing,
|
||||
in int distance_index) {
|
||||
String distance = "Distance";
|
||||
routing.AddDimension(
|
||||
distance_index,
|
||||
0, // null slack
|
||||
3000, // maximum distance per vehicle
|
||||
true, // start cumul to zero
|
||||
distance);
|
||||
RoutingDimension distanceDimension = routing.GetDimensionOrDie(distance);
|
||||
// Try to minimize the max distance among vehicles.
|
||||
// /!\ It doesn't mean the standard deviation is minimized
|
||||
distanceDimension.SetGlobalSpanCostCoefficient(100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print the solution
|
||||
/// Print the solution.
|
||||
/// </summary>
|
||||
static void PrintSolution(
|
||||
in DataProblem data,
|
||||
in DataModel data,
|
||||
in RoutingModel routing,
|
||||
in RoutingIndexManager manager,
|
||||
in Assignment solution) {
|
||||
Console.WriteLine("Objective: {0}", solution.ObjectiveValue());
|
||||
// Inspect solution.
|
||||
long totalDistance = 0;
|
||||
for (int i=0; i < data.GetVehicleNumber(); ++i) {
|
||||
Console.WriteLine("Route for Vehicle " + i + ":");
|
||||
long distance = 0;
|
||||
for (int i = 0; i < data.GetVehicleNumber(); ++i) {
|
||||
Console.WriteLine("Route for Vehicle {0}:", i);
|
||||
long routeDistance = 0;
|
||||
var index = routing.Start(i);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
Console.Write("{0} -> ", manager.IndexToNode((int)index));
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
distance += routing.GetArcCostForVehicle(previousIndex, index, i);
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", distance);
|
||||
totalDistance += distance;
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
totalDistance += routeDistance;
|
||||
}
|
||||
Console.WriteLine("Total Distance of all routes: {0}m", totalDistance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Solves the current routing problem.
|
||||
/// </summary>
|
||||
static void Solve() {
|
||||
// Instantiate the data problem.
|
||||
DataProblem data = new DataProblem();
|
||||
|
||||
// Create Routing Model
|
||||
RoutingIndexManager manager = new RoutingIndexManager(
|
||||
data.GetLocationNumber(),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
|
||||
// Define weight of each edge
|
||||
LongLongToLong distanceEvaluator = new ManhattanDistance(data, manager);
|
||||
//protect callbacks from the GC
|
||||
GC.KeepAlive(distanceEvaluator);
|
||||
int distance_index = routing.RegisterTransitCallback(distanceEvaluator);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(distance_index);
|
||||
|
||||
AddDistanceDimension(data, routing, distance_index);
|
||||
|
||||
// Setting first solution heuristic (cheapest addition).
|
||||
RoutingSearchParameters searchParameters =
|
||||
operations_research_constraint_solver.DefaultRoutingSearchParameters();
|
||||
searchParameters.FirstSolutionStrategy =
|
||||
FirstSolutionStrategy.Types.Value.PathCheapestArc;
|
||||
|
||||
Assignment solution = routing.SolveWithParameters(searchParameters);
|
||||
PrintSolution(data, routing, manager, solution);
|
||||
}
|
||||
// [END solution_printer]
|
||||
|
||||
public static void Main(String[] args) {
|
||||
Solve();
|
||||
// Instantiate the data problem.
|
||||
// [START data]
|
||||
DataModel data = new DataModel();
|
||||
// [END data]
|
||||
|
||||
// Create Routing Index Manager
|
||||
// [START index_manager]
|
||||
RoutingIndexManager manager = new RoutingIndexManager(
|
||||
data.GetDistanceMatrix().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
// [END index_manager]
|
||||
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetDistanceMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// 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]
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Vrp.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0-*" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
162
ortools/constraint_solver/samples/VrpCapacity.cs
Normal file
162
ortools/constraint_solver/samples/VrpCapacity.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright 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 VrpCapacity {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataModel() {
|
||||
distancesMatrix_ = new long[,] {
|
||||
{0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
|
||||
{548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
|
||||
{776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
|
||||
{696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
|
||||
{582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
|
||||
{274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
|
||||
{502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
|
||||
{194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
|
||||
{308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
|
||||
{194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
|
||||
{536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
|
||||
{502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
|
||||
{388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
|
||||
{354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
|
||||
{468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
|
||||
{776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
|
||||
{662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0}
|
||||
};
|
||||
demands_ = new long[] {0, 1, 1, 2, 4, 2, 4, 8, 8, 1, 2, 1, 2, 4, 4, 8, 8};
|
||||
vehicleCapacities_ = new long[] {15, 15, 15, 15};
|
||||
}
|
||||
public ref readonly long[,] GetDistanceMatrix() { return ref distancesMatrix_;}
|
||||
public ref readonly long[] GetDemands() { return ref demands_;}
|
||||
public int GetVehicleNumber() { return 4;}
|
||||
public ref readonly long[] GetVehicleCapacities() { return ref vehicleCapacities_;}
|
||||
public int GetDepot() { return 0;}
|
||||
|
||||
private long[,] distancesMatrix_;
|
||||
private long[] demands_;
|
||||
private long[] vehicleCapacities_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
// [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());
|
||||
// Inspect solution.
|
||||
long totalDistance = 0;
|
||||
long totalLoad = 0;
|
||||
for (int i = 0; i < data.GetVehicleNumber(); ++i) {
|
||||
Console.WriteLine("Route for Vehicle {0}:", i);
|
||||
long routeDistance = 0;
|
||||
long routeLoad = 0;
|
||||
var index = routing.Start(i);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
long nodeIndex = manager.IndexToNode(index);
|
||||
routeLoad += data.GetDemands()[nodeIndex];
|
||||
Console.Write("{0} Load({1}) -> ", nodeIndex, routeLoad);
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
totalDistance += routeDistance;
|
||||
totalLoad += routeLoad;
|
||||
}
|
||||
Console.WriteLine("Total Distance of all routes: {0}m", totalDistance);
|
||||
Console.WriteLine("Total Load of all routes: {0}m", totalLoad);
|
||||
}
|
||||
// [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.GetDistanceMatrix().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
// [END index_manager]
|
||||
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetDistanceMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Add Capacity constraint.
|
||||
// [START capacity_constraint]
|
||||
int demandCostIndex = routing.RegisterUnaryTransitCallback(
|
||||
(long fromIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
return data.GetDemands()[fromNode]; }
|
||||
);
|
||||
routing.AddDimensionWithVehicleCapacity(
|
||||
demandCostIndex, 0, // null capacity slack
|
||||
data.GetVehicleCapacities(), // vehicle maximum capacities
|
||||
true, // start cumul to zero
|
||||
"Capacity");
|
||||
// [END capacity_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]
|
||||
20
ortools/constraint_solver/samples/VrpCapacity.csproj
Normal file
20
ortools/constraint_solver/samples/VrpCapacity.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="VrpCapacity.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
180
ortools/constraint_solver/samples/VrpDropNodes.cs
Normal file
180
ortools/constraint_solver/samples/VrpDropNodes.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
// Copyright 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 Vrp with drop nodes.
|
||||
/// </summary>
|
||||
public class VrpDropNodes {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataModel() {
|
||||
distancesMatrix_ = new long[,] {
|
||||
{0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
|
||||
{548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
|
||||
{776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
|
||||
{696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
|
||||
{582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
|
||||
{274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
|
||||
{502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
|
||||
{194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
|
||||
{308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
|
||||
{194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
|
||||
{536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
|
||||
{502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
|
||||
{388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
|
||||
{354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
|
||||
{468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
|
||||
{776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
|
||||
{662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0}
|
||||
};
|
||||
demands_ = new long[] {0, 1, 1, 3, 6, 3, 6, 8, 8, 1, 2, 1, 2, 6, 6, 8, 8};
|
||||
vehicleCapacities_ = new long[] {15, 15, 15, 15};
|
||||
}
|
||||
public ref readonly long[,] GetDistanceMatrix() { return ref distancesMatrix_;}
|
||||
public ref readonly long[] GetDemands() { return ref demands_;}
|
||||
public int GetVehicleNumber() { return 4;}
|
||||
public ref readonly long[] GetVehicleCapacities() { return ref vehicleCapacities_;}
|
||||
public int GetDepot() { return 0;}
|
||||
|
||||
private long[,] distancesMatrix_;
|
||||
private long[] demands_;
|
||||
private long[] vehicleCapacities_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
// [START solution_printer]
|
||||
/// <summary>
|
||||
/// Print the solution.
|
||||
/// </summary>
|
||||
static void PrintSolution(
|
||||
in DataModel data,
|
||||
in RoutingModel routing,
|
||||
in RoutingIndexManager manager,
|
||||
in Assignment solution) {
|
||||
// Solution cost.
|
||||
Console.WriteLine("Objective: {0}", solution.ObjectiveValue());
|
||||
// Display dropped nodes.
|
||||
string droppedNodes = "Dropped nodes:";
|
||||
for (int index = 0; index < routing.Size(); ++index) {
|
||||
if (routing.IsStart(index) || routing.IsEnd(index)) {
|
||||
continue;
|
||||
}
|
||||
if (solution.Value(routing.NextVar(index)) == index) {
|
||||
droppedNodes += " " + manager.IndexToNode(index);
|
||||
}
|
||||
}
|
||||
Console.WriteLine("{0}", droppedNodes);
|
||||
// Inspect solution.
|
||||
long totalDistance = 0;
|
||||
long totalLoad = 0;
|
||||
for (int i = 0; i < data.GetVehicleNumber(); ++i) {
|
||||
Console.WriteLine("Route for Vehicle {0}:", i);
|
||||
long routeDistance = 0;
|
||||
long routeLoad = 0;
|
||||
var index = routing.Start(i);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
long nodeIndex = manager.IndexToNode(index);
|
||||
routeLoad += data.GetDemands()[nodeIndex];
|
||||
Console.Write("{0} Load({1}) -> ", nodeIndex, routeLoad);
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
totalDistance += routeDistance;
|
||||
totalLoad += routeLoad;
|
||||
}
|
||||
Console.WriteLine("Total Distance of all routes: {0}m", totalDistance);
|
||||
Console.WriteLine("Total Load of all routes: {0}m", totalLoad);
|
||||
}
|
||||
// [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.GetDistanceMatrix().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
// [END index_manager]
|
||||
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetDistanceMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Add Capacity constraint.
|
||||
// [START capacity_constraint]
|
||||
int demandCostIndex = routing.RegisterUnaryTransitCallback(
|
||||
(long fromIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
return data.GetDemands()[fromNode]; }
|
||||
);
|
||||
routing.AddDimensionWithVehicleCapacity(
|
||||
demandCostIndex, 0, // null capacity slack
|
||||
data.GetVehicleCapacities(), // vehicle maximum capacities
|
||||
true, // start cumul to zero
|
||||
"Capacity");
|
||||
// Allow to drop nodes.
|
||||
long penalty = 1000;
|
||||
for (int i = 1; i < data.GetDistanceMatrix().GetLength(0); ++i) {
|
||||
routing.AddDisjunction(
|
||||
new long[] {manager.NodeToIndex(i)}, penalty);
|
||||
}
|
||||
// [END capacity_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]
|
||||
20
ortools/constraint_solver/samples/VrpDropNodes.csproj
Normal file
20
ortools/constraint_solver/samples/VrpDropNodes.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="VrpDropNodes.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
146
ortools/constraint_solver/samples/VrpGlobalSpan.cs
Normal file
146
ortools/constraint_solver/samples/VrpGlobalSpan.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright 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 VrpGlobalSpan {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataModel() {
|
||||
distancesMatrix_ = new long[,] {
|
||||
{0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
|
||||
{548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
|
||||
{776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
|
||||
{696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
|
||||
{582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
|
||||
{274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
|
||||
{502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
|
||||
{194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
|
||||
{308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
|
||||
{194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
|
||||
{536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
|
||||
{502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
|
||||
{388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
|
||||
{354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
|
||||
{468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
|
||||
{776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
|
||||
{662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0}
|
||||
};
|
||||
}
|
||||
public ref readonly long[,] GetDistanceMatrix() { return ref distancesMatrix_;}
|
||||
public int GetVehicleNumber() { return 4;}
|
||||
public int GetDepot() { return 0;}
|
||||
|
||||
private long[,] distancesMatrix_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
// [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());
|
||||
// Inspect solution.
|
||||
long totalDistance = 0;
|
||||
for (int i = 0; i < data.GetVehicleNumber(); ++i) {
|
||||
Console.WriteLine("Route for Vehicle {0}:", i);
|
||||
long routeDistance = 0;
|
||||
var index = routing.Start(i);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
Console.Write("{0} -> ", manager.IndexToNode((int)index));
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
totalDistance += routeDistance;
|
||||
}
|
||||
Console.WriteLine("Total Distance of all routes: {0}m", totalDistance);
|
||||
}
|
||||
// [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.GetDistanceMatrix().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetDepot());
|
||||
|
||||
// [END index_manager]
|
||||
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetDistanceMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Add Distance constraint.
|
||||
// [START distance_constraint]
|
||||
routing.AddDimension(transitCostIndex, 0, 3000,
|
||||
true, // start cumul to zero
|
||||
"Distance");
|
||||
RoutingDimension distanceDimension = routing.GetMutableDimension("Distance");
|
||||
distanceDimension.SetGlobalSpanCostCoefficient(100);
|
||||
// [END distance_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]
|
||||
20
ortools/constraint_solver/samples/VrpGlobalSpan.csproj
Normal file
20
ortools/constraint_solver/samples/VrpGlobalSpan.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="VrpGlobalSpan.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
152
ortools/constraint_solver/samples/VrpStartsEnds.cs
Normal file
152
ortools/constraint_solver/samples/VrpStartsEnds.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 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 VrpStartsEnds {
|
||||
// [START data_model]
|
||||
class DataModel {
|
||||
// Constructor:
|
||||
public DataModel() {
|
||||
distancesMatrix_ = new long[,] {
|
||||
{0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
|
||||
{548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
|
||||
{776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
|
||||
{696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
|
||||
{582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
|
||||
{274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
|
||||
{502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
|
||||
{194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
|
||||
{308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
|
||||
{194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
|
||||
{536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
|
||||
{502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
|
||||
{388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
|
||||
{354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
|
||||
{468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
|
||||
{776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
|
||||
{662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0}
|
||||
};
|
||||
starts_ = new int[] {1, 2, 15, 16};
|
||||
ends_ = new int[] {0, 0, 0, 0};
|
||||
}
|
||||
public ref readonly long[,] GetDistanceMatrix() { return ref distancesMatrix_;}
|
||||
public int GetVehicleNumber() { return 4;}
|
||||
public ref readonly int[] GetStarts() { return ref starts_;}
|
||||
public ref readonly int[] GetEnds() { return ref ends_;}
|
||||
|
||||
private long[,] distancesMatrix_;
|
||||
private int[] starts_;
|
||||
private int[] ends_;
|
||||
};
|
||||
// [END data_model]
|
||||
|
||||
// [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());
|
||||
// Inspect solution.
|
||||
long totalDistance = 0;
|
||||
for (int i = 0; i < data.GetVehicleNumber(); ++i) {
|
||||
Console.WriteLine("Route for Vehicle {0}:", i);
|
||||
long routeDistance = 0;
|
||||
var index = routing.Start(i);
|
||||
while (routing.IsEnd(index) == false) {
|
||||
Console.Write("{0} -> ", manager.IndexToNode((int)index));
|
||||
var previousIndex = index;
|
||||
index = solution.Value(routing.NextVar(index));
|
||||
routeDistance += routing.GetArcCostForVehicle(previousIndex, index, 0);
|
||||
}
|
||||
Console.WriteLine("{0}", manager.IndexToNode((int)index));
|
||||
Console.WriteLine("Distance of the route: {0}m", routeDistance);
|
||||
totalDistance += routeDistance;
|
||||
}
|
||||
Console.WriteLine("Total Distance of all routes: {0}m", totalDistance);
|
||||
}
|
||||
// [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.GetDistanceMatrix().GetLength(0),
|
||||
data.GetVehicleNumber(),
|
||||
data.GetStarts(),
|
||||
data.GetEnds());
|
||||
|
||||
// [END index_manager]
|
||||
|
||||
// Create Routing Model.
|
||||
// [START routing_model]
|
||||
RoutingModel routing = new RoutingModel(manager);
|
||||
// [END routing_model]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetDistanceMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Add Distance constraint.
|
||||
// [START distance_constraint]
|
||||
routing.AddDimension(transitCostIndex, 0, 2000,
|
||||
true, // start cumul to zero
|
||||
"Distance");
|
||||
RoutingDimension distanceDimension = routing.GetMutableDimension("Distance");
|
||||
distanceDimension.SetGlobalSpanCostCoefficient(100);
|
||||
// [END distance_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]
|
||||
20
ortools/constraint_solver/samples/VrpStartsEnds.csproj
Normal file
20
ortools/constraint_solver/samples/VrpStartsEnds.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="VrpStartsEnds.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
200
ortools/constraint_solver/samples/VrpTimeWindows.cs
Normal file
200
ortools/constraint_solver/samples/VrpTimeWindows.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright 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]
|
||||
|
||||
// [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]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
int transitCostIndex = routing.RegisterTransitCallback(
|
||||
(long fromIndex, long toIndex) => {
|
||||
var fromNode = manager.IndexToNode(fromIndex);
|
||||
var toNode = manager.IndexToNode(toIndex);
|
||||
return data.GetTimeMatrix()[fromNode, toNode]; }
|
||||
);
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Add Distance constraint.
|
||||
// [START time_constraint]
|
||||
routing.AddDimension(
|
||||
transitCostIndex, // 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]
|
||||
20
ortools/constraint_solver/samples/VrpTimeWindows.csproj
Normal file
20
ortools/constraint_solver/samples/VrpTimeWindows.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="VrpTimeWindows.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.0.6170-*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user