diff --git a/makefiles/Makefile.cpp.mk b/makefiles/Makefile.cpp.mk
index 8e3d2fcd8b..fc0d74061e 100755
--- a/makefiles/Makefile.cpp.mk
+++ b/makefiles/Makefile.cpp.mk
@@ -370,6 +370,8 @@ test_cc_constraint_solver_samples: \
rcc_simple_ls_program \
rcc_simple_routing_program \
rcc_tsp \
+ rcc_tsp_cities \
+ rcc_tsp_circuit_board \
rcc_tsp_distance_matrix \
rcc_vrp \
rcc_vrp_capacity \
diff --git a/makefiles/Makefile.dotnet.mk b/makefiles/Makefile.dotnet.mk
index 09e8b345e3..c29bd4df66 100644
--- a/makefiles/Makefile.dotnet.mk
+++ b/makefiles/Makefile.dotnet.mk
@@ -442,6 +442,8 @@ 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/TspCities.cs
+ $(MAKE) run SOURCE=ortools/constraint_solver/samples/TspCircuitBoard.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
diff --git a/makefiles/Makefile.java.mk b/makefiles/Makefile.java.mk
index d6a78ca577..90dcff1d48 100755
--- a/makefiles/Makefile.java.mk
+++ b/makefiles/Makefile.java.mk
@@ -375,6 +375,8 @@ test_java_algorithms_samples: \
test_java_constraint_solver_samples: \
rjava_SimpleRoutingProgram \
rjava_Tsp \
+ rjava_TspCities \
+ rjava_TspCircuitBoard \
rjava_TspDistanceMatrix \
rjava_Vrp \
rjava_VrpCapacity \
diff --git a/makefiles/Makefile.python.mk b/makefiles/Makefile.python.mk
index 80695d8d17..a64c28f157 100755
--- a/makefiles/Makefile.python.mk
+++ b/makefiles/Makefile.python.mk
@@ -501,6 +501,8 @@ test_python_constraint_solver_samples: \
rpy_simple_cp_program \
rpy_simple_routing_program \
rpy_tsp \
+ rpy_tsp_cities \
+ rpy_tsp_circuit_board \
rpy_tsp_distance_matrix \
rpy_vrp \
rpy_vrp_capacity \
diff --git a/ortools/constraint_solver/samples/TspCircuitBoard.cs b/ortools/constraint_solver/samples/TspCircuitBoard.cs
new file mode 100644
index 0000000000..d515720173
--- /dev/null
+++ b/ortools/constraint_solver/samples/TspCircuitBoard.cs
@@ -0,0 +1,187 @@
+// 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]
+
+///
+/// Minimal TSP.
+/// A description of the problem can be found here:
+/// http://en.wikipedia.org/wiki/Travelling_salesman_problem.
+///
+public class TspCircuitBoard {
+ // [START data_model]
+ class DataModel {
+ public int[,] Locations = {
+ {288, 149}, {288, 129}, {270, 133}, {256, 141}, {256, 157}, {246, 157},
+ {236, 169}, {228, 169}, {228, 161}, {220, 169}, {212, 169}, {204, 169},
+ {196, 169}, {188, 169}, {196, 161}, {188, 145}, {172, 145}, {164, 145},
+ {156, 145}, {148, 145}, {140, 145}, {148, 169}, {164, 169}, {172, 169},
+ {156, 169}, {140, 169}, {132, 169}, {124, 169}, {116, 161}, {104, 153},
+ {104, 161}, {104, 169}, {90, 165}, {80, 157}, {64, 157}, {64, 165},
+ {56, 169}, {56, 161}, {56, 153}, {56, 145}, {56, 137}, {56, 129},
+ {56, 121}, {40, 121}, {40, 129}, {40, 137}, {40, 145}, {40, 153},
+ {40, 161}, {40, 169}, {32, 169}, {32, 161}, {32, 153}, {32, 145},
+ {32, 137}, {32, 129}, {32, 121}, {32, 113}, {40, 113}, {56, 113},
+ {56, 105}, {48, 99}, {40, 99}, {32, 97}, {32, 89}, {24, 89}, {16, 97},
+ {16, 109}, {8, 109}, {8, 97}, {8, 89}, {8, 81}, {8, 73}, {8, 65},
+ {8, 57}, {16, 57}, {8, 49}, {8, 41}, {24, 45}, {32, 41}, {32, 49},
+ {32, 57}, {32, 65}, {32, 73}, {32, 81}, {40, 83}, {40, 73}, {40, 63},
+ {40, 51}, {44, 43}, {44, 35}, {44, 27}, {32, 25}, {24, 25}, {16, 25},
+ {16, 17}, {24, 17}, {32, 17}, {44, 11}, {56, 9}, {56, 17}, {56, 25},
+ {56, 33}, {56, 41}, {64, 41}, {72, 41}, {72, 49}, {56, 49}, {48, 51},
+ {56, 57}, {56, 65}, {48, 63}, {48, 73}, {56, 73}, {56, 81}, {48, 83},
+ {56, 89}, {56, 97}, {104, 97}, {104, 105}, {104, 113}, {104, 121},
+ {104, 129}, {104, 137}, {104, 145}, {116, 145}, {124, 145}, {132, 145},
+ {132, 137}, {140, 137}, {148, 137}, {156, 137}, {164, 137}, {172, 125},
+ {172, 117}, {172, 109}, {172, 101}, {172, 93}, {172, 85}, {180, 85},
+ {180, 77}, {180, 69}, {180, 61}, {180, 53}, {172, 53}, {172, 61},
+ {172, 69}, {172, 77}, {164, 81}, {148, 85}, {124, 85}, {124, 93},
+ {124, 109}, {124, 125}, {124, 117}, {124, 101}, {104, 89}, {104, 81},
+ {104, 73}, {104, 65}, {104, 49}, {104, 41}, {104, 33}, {104, 25},
+ {104, 17}, {92, 9}, {80, 9}, {72, 9}, {64, 21}, {72, 25}, {80, 25},
+ {80, 25}, {80, 41}, {88, 49}, {104, 57}, {124, 69}, {124, 77}, {132, 81},
+ {140, 65}, {132, 61}, {124, 61}, {124, 53}, {124, 45}, {124, 37},
+ {124, 29}, {132, 21}, {124, 21}, {120, 9}, {128, 9}, {136, 9}, {148, 9},
+ {162, 9}, {156, 25}, {172, 21}, {180, 21}, {180, 29}, {172, 29},
+ {172, 37}, {172, 45}, {180, 45}, {180, 37}, {188, 41}, {196, 49},
+ {204, 57}, {212, 65}, {220, 73}, {228, 69}, {228, 77}, {236, 77},
+ {236, 69}, {236, 61}, {228, 61}, {228, 53}, {236, 53}, {236, 45},
+ {228, 45}, {228, 37}, {236, 37}, {236, 29}, {228, 29}, {228, 21},
+ {236, 21}, {252, 21}, {260, 29}, {260, 37}, {260, 45}, {260, 53},
+ {260, 61}, {260, 69}, {260, 77}, {276, 77}, {276, 69}, {276, 61},
+ {276, 53}, {284, 53}, {284, 61}, {284, 69}, {284, 77}, {284, 85},
+ {284, 93}, {284, 101}, {288, 109}, {280, 109}, {276, 101}, {276, 93},
+ {276, 85}, {268, 97}, {260, 109}, {252, 101}, {260, 93}, {260, 85},
+ {236, 85}, {228, 85}, {228, 93}, {236, 93}, {236, 101}, {228, 101},
+ {228, 109}, {228, 117}, {228, 125}, {220, 125}, {212, 117}, {204, 109},
+ {196, 101}, {188, 93}, {180, 93}, {180, 101}, {180, 109}, {180, 117},
+ {180, 125}, {196, 145}, {204, 145}, {212, 145}, {220, 145}, {228, 145},
+ {236, 145}, {246, 141}, {252, 125}, {260, 129}, {280, 133},
+ };
+ public int VehicleNumber = 1;
+ public int Depot = 0;
+ };
+ // [END data_model]
+
+ // [START euclidean_distance]
+ ///
+ /// Euclidean distance implemented as a callback. It uses an array of
+ /// positions and computes the Euclidean distance between the two
+ /// positions of two different indices.
+ ///
+ static long[,] ComputeEuclideanDistanceMatrix(in int[,] locations) {
+ // Calculate the distance matrix using Euclidean distance.
+ int locationNumber = locations.GetLength(0);
+ long[,] distanceMatrix = new long[locationNumber, locationNumber];
+ for (int fromNode = 0; fromNode < locationNumber; fromNode++) {
+ for (int toNode = 0; toNode < locationNumber; toNode++) {
+ if (fromNode == toNode)
+ distanceMatrix[fromNode, toNode] = 0;
+ else
+ distanceMatrix[fromNode, toNode] =
+ (long)Math.Sqrt(
+ Math.Pow(locations[toNode, 0] -
+ locations[fromNode, 0], 2) +
+ Math.Pow(locations[toNode, 1] -
+ locations[fromNode, 1], 2)
+ );
+ }
+ }
+ return distanceMatrix;
+ }
+ // [END euclidean_distance]
+
+ // [START solution_printer]
+ ///
+ /// Print the solution.
+ ///
+ static void PrintSolution(
+ in RoutingModel routing,
+ in RoutingIndexManager manager,
+ in Assignment solution) {
+ Console.WriteLine("Objective: {0}", solution.ObjectiveValue());
+ // Inspect solution.
+ Console.WriteLine("Route:");
+ 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("Route distance: {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.Locations.GetLength(0),
+ data.VehicleNumber,
+ data.Depot);
+ // [END index_manager]
+
+ // Create Routing Model.
+ // [START routing_model]
+ RoutingModel routing = new RoutingModel(manager);
+ // [END routing_model]
+
+ // Define cost of each arc.
+ // [START transit_callback]
+ long[,] distanceMatrix = ComputeEuclideanDistanceMatrix(data.Locations);
+ 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 distanceMatrix[fromNode, toNode]; }
+ );
+ // [END transit_callback]
+
+ // [START arc_cost
+ routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
+ // [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]
diff --git a/ortools/constraint_solver/samples/TspCircuitBoard.csproj b/ortools/constraint_solver/samples/TspCircuitBoard.csproj
new file mode 100644
index 0000000000..a5beab7657
--- /dev/null
+++ b/ortools/constraint_solver/samples/TspCircuitBoard.csproj
@@ -0,0 +1,20 @@
+
+
+ Exe
+ 7.2
+ netcoreapp2.1
+ false
+ ../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json
+
+
+
+ full
+ true
+ true
+
+
+
+
+
+
+
diff --git a/ortools/constraint_solver/samples/TspCircuitBoard.java b/ortools/constraint_solver/samples/TspCircuitBoard.java
new file mode 100644
index 0000000000..7ecb4d46e1
--- /dev/null
+++ b/ortools/constraint_solver/samples/TspCircuitBoard.java
@@ -0,0 +1,177 @@
+// 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]
+
+import com.google.ortools.constraintsolver.Assignment;
+import com.google.ortools.constraintsolver.FirstSolutionStrategy;
+import com.google.ortools.constraintsolver.RoutingIndexManager;
+import com.google.ortools.constraintsolver.RoutingModel;
+import com.google.ortools.constraintsolver.RoutingSearchParameters;
+import com.google.ortools.constraintsolver.main;
+import java.util.logging.Logger;
+
+// [END import]
+
+/** Minimal TSP. */
+public class TspCircuitBoard {
+ static {
+ System.loadLibrary("jniortools");
+ }
+
+ private static final Logger logger = Logger.getLogger(TspCircuitBoard.class.getName());
+
+ // [START data_model]
+ static class DataModel {
+ public final int[][] locations = {{288, 149}, {288, 129}, {270, 133}, {256, 141}, {256, 157},
+ {246, 157}, {236, 169}, {228, 169}, {228, 161}, {220, 169}, {212, 169}, {204, 169},
+ {196, 169}, {188, 169}, {196, 161}, {188, 145}, {172, 145}, {164, 145}, {156, 145},
+ {148, 145}, {140, 145}, {148, 169}, {164, 169}, {172, 169}, {156, 169}, {140, 169},
+ {132, 169}, {124, 169}, {116, 161}, {104, 153}, {104, 161}, {104, 169}, {90, 165},
+ {80, 157}, {64, 157}, {64, 165}, {56, 169}, {56, 161}, {56, 153}, {56, 145}, {56, 137},
+ {56, 129}, {56, 121}, {40, 121}, {40, 129}, {40, 137}, {40, 145}, {40, 153}, {40, 161},
+ {40, 169}, {32, 169}, {32, 161}, {32, 153}, {32, 145}, {32, 137}, {32, 129}, {32, 121},
+ {32, 113}, {40, 113}, {56, 113}, {56, 105}, {48, 99}, {40, 99}, {32, 97}, {32, 89},
+ {24, 89}, {16, 97}, {16, 109}, {8, 109}, {8, 97}, {8, 89}, {8, 81}, {8, 73}, {8, 65},
+ {8, 57}, {16, 57}, {8, 49}, {8, 41}, {24, 45}, {32, 41}, {32, 49}, {32, 57}, {32, 65},
+ {32, 73}, {32, 81}, {40, 83}, {40, 73}, {40, 63}, {40, 51}, {44, 43}, {44, 35}, {44, 27},
+ {32, 25}, {24, 25}, {16, 25}, {16, 17}, {24, 17}, {32, 17}, {44, 11}, {56, 9}, {56, 17},
+ {56, 25}, {56, 33}, {56, 41}, {64, 41}, {72, 41}, {72, 49}, {56, 49}, {48, 51}, {56, 57},
+ {56, 65}, {48, 63}, {48, 73}, {56, 73}, {56, 81}, {48, 83}, {56, 89}, {56, 97}, {104, 97},
+ {104, 105}, {104, 113}, {104, 121}, {104, 129}, {104, 137}, {104, 145}, {116, 145},
+ {124, 145}, {132, 145}, {132, 137}, {140, 137}, {148, 137}, {156, 137}, {164, 137},
+ {172, 125}, {172, 117}, {172, 109}, {172, 101}, {172, 93}, {172, 85}, {180, 85}, {180, 77},
+ {180, 69}, {180, 61}, {180, 53}, {172, 53}, {172, 61}, {172, 69}, {172, 77}, {164, 81},
+ {148, 85}, {124, 85}, {124, 93}, {124, 109}, {124, 125}, {124, 117}, {124, 101}, {104, 89},
+ {104, 81}, {104, 73}, {104, 65}, {104, 49}, {104, 41}, {104, 33}, {104, 25}, {104, 17},
+ {92, 9}, {80, 9}, {72, 9}, {64, 21}, {72, 25}, {80, 25}, {80, 25}, {80, 41}, {88, 49},
+ {104, 57}, {124, 69}, {124, 77}, {132, 81}, {140, 65}, {132, 61}, {124, 61}, {124, 53},
+ {124, 45}, {124, 37}, {124, 29}, {132, 21}, {124, 21}, {120, 9}, {128, 9}, {136, 9},
+ {148, 9}, {162, 9}, {156, 25}, {172, 21}, {180, 21}, {180, 29}, {172, 29}, {172, 37},
+ {172, 45}, {180, 45}, {180, 37}, {188, 41}, {196, 49}, {204, 57}, {212, 65}, {220, 73},
+ {228, 69}, {228, 77}, {236, 77}, {236, 69}, {236, 61}, {228, 61}, {228, 53}, {236, 53},
+ {236, 45}, {228, 45}, {228, 37}, {236, 37}, {236, 29}, {228, 29}, {228, 21}, {236, 21},
+ {252, 21}, {260, 29}, {260, 37}, {260, 45}, {260, 53}, {260, 61}, {260, 69}, {260, 77},
+ {276, 77}, {276, 69}, {276, 61}, {276, 53}, {284, 53}, {284, 61}, {284, 69}, {284, 77},
+ {284, 85}, {284, 93}, {284, 101}, {288, 109}, {280, 109}, {276, 101}, {276, 93}, {276, 85},
+ {268, 97}, {260, 109}, {252, 101}, {260, 93}, {260, 85}, {236, 85}, {228, 85}, {228, 93},
+ {236, 93}, {236, 101}, {228, 101}, {228, 109}, {228, 117}, {228, 125}, {220, 125},
+ {212, 117}, {204, 109}, {196, 101}, {188, 93}, {180, 93}, {180, 101}, {180, 109},
+ {180, 117}, {180, 125}, {196, 145}, {204, 145}, {212, 145}, {220, 145}, {228, 145},
+ {236, 145}, {246, 141}, {252, 125}, {260, 129}, {280, 133}};
+ public final int vehicleNumber = 1;
+ public final int depot = 0;
+ }
+ // [END data_model]
+
+ // [START euclidean_distance]
+ /// @brief Compute Euclidean distance matrix from locations array.
+ /// @details It uses an array of locations and computes
+ /// the Euclidean distance between any two locations.
+ private static long[][] computeEuclideanDistanceMatrix(int[][] locations) {
+ // Calculate distance matrix using Euclidean distance.
+ long[][] distanceMatrix = new long[locations.length][locations.length];
+ for (int fromNode = 0; fromNode < locations.length; ++fromNode) {
+ for (int toNode = 0; toNode < locations.length; ++toNode) {
+ if (fromNode == toNode) {
+ distanceMatrix[fromNode][toNode] = 0;
+ } else {
+ distanceMatrix[fromNode][toNode] =
+ (long) Math.hypot(locations[toNode][0] - locations[fromNode][0],
+ locations[toNode][1] - locations[fromNode][1]);
+ }
+ }
+ }
+ return distanceMatrix;
+ }
+ // [END euclidean_distance]
+
+ // [START solution_printer]
+ /// @brief Print the solution.
+ static void printSolution(
+ DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
+ // Solution cost.
+ logger.info("Objective: " + solution.objectiveValue());
+ // Inspect solution.
+ logger.info("Route:");
+ long routeDistance = 0;
+ String route = "";
+ long index = routing.start(0);
+ while (!routing.isEnd(index)) {
+ route += manager.indexToNode(index) + " -> ";
+ long previousIndex = index;
+ index = solution.value(routing.nextVar(index));
+ routing.getArcCostForVehicle(previousIndex, index, 0);
+ }
+ route += manager.indexToNode(routing.end(0));
+ logger.info(route);
+ logger.info("Route distance: " + routeDistance);
+ }
+ // [END solution_printer]
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the data problem.
+ // [START data]
+ final DataModel data = new DataModel();
+ // [END data]
+
+ // Create Routing Index Manager
+ // [START index_manager]
+ RoutingIndexManager manager =
+ new RoutingIndexManager(data.locations.length, data.vehicleNumber, data.depot);
+ // [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]
+ final long[][] distanceMatrix = computeEuclideanDistanceMatrix(data.locations);
+ final int transitCallbackIndex =
+ routing.registerTransitCallback((long fromIndex, long toIndex) -> {
+ // Convert from routing variable Index to user NodeIndex.
+ int fromNode = manager.indexToNode(fromIndex);
+ int toNode = manager.indexToNode(toIndex);
+ return distanceMatrix[fromNode][toNode];
+ });
+ // [END transit_callback]
+
+ // Define cost of each arc.
+ // [START arc_cost]
+ routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
+ // [END arc_cost]
+
+ // Setting first solution heuristic.
+ // [START parameters]
+ RoutingSearchParameters searchParameters =
+ main.defaultRoutingSearchParameters()
+ .toBuilder()
+ .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
+ .build();
+ // [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]
diff --git a/ortools/constraint_solver/samples/TspCities.cs b/ortools/constraint_solver/samples/TspCities.cs
new file mode 100644
index 0000000000..48a2a5bc3b
--- /dev/null
+++ b/ortools/constraint_solver/samples/TspCities.cs
@@ -0,0 +1,124 @@
+// 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]
+
+///
+/// Minimal TSP using distance matrix.
+///
+public class TspCities {
+ // [START data_model]
+ class DataModel {
+ public long[,] DistanceMatrix = {
+ {0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972},
+ {2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579},
+ {713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260},
+ {1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987},
+ {1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371},
+ {1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999},
+ {2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701},
+ {213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099},
+ {2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600},
+ {875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162},
+ {1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200},
+ {2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504},
+ {1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0},
+ };
+ public int VehicleNumber = 1;
+ public int Depot = 0;
+ };
+ // [END data_model]
+
+ // [START solution_printer]
+ ///
+ /// Print the solution.
+ ///
+ static void PrintSolution(
+ in RoutingModel routing,
+ in RoutingIndexManager manager,
+ in Assignment solution) {
+ Console.WriteLine("Objective: {0} miles", solution.ObjectiveValue());
+ // Inspect solution.
+ Console.WriteLine("Route:");
+ 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("Route distance: {0}miles", 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.DistanceMatrix.GetLength(0),
+ data.VehicleNumber,
+ data.Depot);
+ // [END index_manager]
+
+ // Create Routing Model.
+ // [START routing_model]
+ RoutingModel routing = new RoutingModel(manager);
+ // [END routing_model]
+
+ // [START transit_callback]
+ 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.DistanceMatrix[fromNode, toNode]; }
+ );
+ // [END transit_callback]
+
+ // Define cost of each arc.
+ // [START arc_cost]
+ routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
+ // [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]
diff --git a/ortools/constraint_solver/samples/TspCities.csproj b/ortools/constraint_solver/samples/TspCities.csproj
new file mode 100644
index 0000000000..696d466ad0
--- /dev/null
+++ b/ortools/constraint_solver/samples/TspCities.csproj
@@ -0,0 +1,20 @@
+
+
+ Exe
+ 7.2
+ netcoreapp2.1
+ false
+ ../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json
+
+
+
+ full
+ true
+ true
+
+
+
+
+
+
+
diff --git a/ortools/constraint_solver/samples/TspCities.java b/ortools/constraint_solver/samples/TspCities.java
new file mode 100644
index 0000000000..ca36c7a88a
--- /dev/null
+++ b/ortools/constraint_solver/samples/TspCities.java
@@ -0,0 +1,132 @@
+// 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]
+import com.google.ortools.constraintsolver.Assignment;
+import com.google.ortools.constraintsolver.FirstSolutionStrategy;
+import com.google.ortools.constraintsolver.RoutingIndexManager;
+import com.google.ortools.constraintsolver.RoutingModel;
+import com.google.ortools.constraintsolver.RoutingSearchParameters;
+import com.google.ortools.constraintsolver.main;
+import java.util.logging.Logger;
+
+// [END import]
+
+/** Minimal TSP using distance matrix. */
+public class TspCities {
+ static {
+ System.loadLibrary("jniortools");
+ }
+
+ private static final Logger logger = Logger.getLogger(TspCities.class.getName());
+
+ // [START data_model]
+ static class DataModel {
+ public final long[][] distanceMatrix = {
+ {0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972},
+ {2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579},
+ {713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260},
+ {1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987},
+ {1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371},
+ {1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999},
+ {2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701},
+ {213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099},
+ {2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600},
+ {875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162},
+ {1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200},
+ {2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504},
+ {1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0},
+ };
+ public final int vehicleNumber = 1;
+ public final int depot = 0;
+ }
+ // [END data_model]
+
+ // [START solution_printer]
+ /// @brief Print the solution.
+ static void printSolution(
+ DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
+ // Solution cost.
+ logger.info("Objective: " + solution.objectiveValue() + "miles");
+ // Inspect solution.
+ logger.info("Route:");
+ long routeDistance = 0;
+ String route = "";
+ long index = routing.start(0);
+ while (!routing.isEnd(index)) {
+ route += manager.indexToNode(index) + " -> ";
+ long previousIndex = index;
+ index = solution.value(routing.nextVar(index));
+ routeDistance += routing.getArcCostForVehicle(previousIndex, index, 0);
+ }
+ route += manager.indexToNode(routing.end(0));
+ logger.info(route);
+ logger.info("Route distance: " + routeDistance + "miles");
+ }
+ // [END solution_printer]
+
+ public static void main(String[] args) throws Exception {
+ // Instantiate the data problem.
+ // [START data]
+ final DataModel data = new DataModel();
+ // [END data]
+
+ // Create Routing Index Manager
+ // [START index_manager]
+ RoutingIndexManager manager =
+ new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
+ // [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]
+ final int transitCallbackIndex =
+ routing.registerTransitCallback((long fromIndex, long toIndex) -> {
+ // Convert from routing variable Index to user NodeIndex.
+ int fromNode = manager.indexToNode(fromIndex);
+ int toNode = manager.indexToNode(toIndex);
+ return data.distanceMatrix[fromNode][toNode];
+ });
+ // [END transit_callback]
+
+ // Define cost of each arc.
+ // [START arc_cost]
+ routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
+ // [END arc_cost]
+
+ // Setting first solution heuristic.
+ // [START parameters]
+ RoutingSearchParameters searchParameters =
+ main.defaultRoutingSearchParameters()
+ .toBuilder()
+ .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
+ .build();
+ // [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]
diff --git a/ortools/constraint_solver/samples/tsp_circuit_board.cc b/ortools/constraint_solver/samples/tsp_circuit_board.cc
new file mode 100644
index 0000000000..174c89a9d8
--- /dev/null
+++ b/ortools/constraint_solver/samples/tsp_circuit_board.cc
@@ -0,0 +1,175 @@
+// 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]
+#include
+#include
+#include "ortools/constraint_solver/routing.h"
+#include "ortools/constraint_solver/routing_enums.pb.h"
+#include "ortools/constraint_solver/routing_index_manager.h"
+#include "ortools/constraint_solver/routing_parameters.h"
+// [END import]
+
+namespace operations_research {
+// [START distance_matrix]
+// @brief Generate distance matrix.
+std::vector> GenerateDistanceMatrix(
+ const std::vector>& locations) {
+ std::vector> distances = std::vector>(
+ locations.size(), std::vector(locations.size(), int64{0}));
+ for (int fromNode = 0; fromNode < locations.size(); fromNode++) {
+ for (int toNode = 0; toNode < locations.size(); toNode++) {
+ if (fromNode != toNode)
+ distances[fromNode][toNode] = static_cast(
+ std::hypot((locations[toNode][0] - locations[fromNode][0]),
+ (locations[toNode][1] - locations[fromNode][1])));
+ }
+ }
+ return distances;
+}
+// [END distance_matrix]
+
+// [START solution_printer]
+//! @brief Print the solution
+//! @param[in] manager Index manager used.
+//! @param[in] routing Routing solver used.
+//! @param[in] solution Solution found by the solver.
+void PrintSolution(const RoutingIndexManager& manager,
+ const RoutingModel& routing, const Assignment& solution) {
+ LOG(INFO) << "Objective: " << solution.ObjectiveValue();
+ // Inspect solution.
+ int64 index = routing.Start(0);
+ LOG(INFO) << "Route:";
+ int64 distance{0};
+ std::stringstream route;
+ while (routing.IsEnd(index) == false) {
+ route << manager.IndexToNode(index).value() << " -> ";
+ int64 previous_index = index;
+ index = solution.Value(routing.NextVar(index));
+ distance += const_cast(routing).GetArcCostForVehicle(
+ previous_index, index, int64{0});
+ }
+ LOG(INFO) << route.str() << manager.IndexToNode(index).value();
+ LOG(INFO) << "Route distance: " << distance << "miles";
+ LOG(INFO) << "";
+ LOG(INFO) << "Advanced usage:";
+ LOG(INFO) << "Problem solved in " << routing.solver()->wall_time() << "ms";
+}
+// [END solution_printer]
+
+void Tsp() {
+ // Instantiate the data problem.
+ // [START data]
+ const std::vector> locations = {
+ {288, 149}, {288, 129}, {270, 133}, {256, 141}, {256, 157}, {246, 157},
+ {236, 169}, {228, 169}, {228, 161}, {220, 169}, {212, 169}, {204, 169},
+ {196, 169}, {188, 169}, {196, 161}, {188, 145}, {172, 145}, {164, 145},
+ {156, 145}, {148, 145}, {140, 145}, {148, 169}, {164, 169}, {172, 169},
+ {156, 169}, {140, 169}, {132, 169}, {124, 169}, {116, 161}, {104, 153},
+ {104, 161}, {104, 169}, {90, 165}, {80, 157}, {64, 157}, {64, 165},
+ {56, 169}, {56, 161}, {56, 153}, {56, 145}, {56, 137}, {56, 129},
+ {56, 121}, {40, 121}, {40, 129}, {40, 137}, {40, 145}, {40, 153},
+ {40, 161}, {40, 169}, {32, 169}, {32, 161}, {32, 153}, {32, 145},
+ {32, 137}, {32, 129}, {32, 121}, {32, 113}, {40, 113}, {56, 113},
+ {56, 105}, {48, 99}, {40, 99}, {32, 97}, {32, 89}, {24, 89},
+ {16, 97}, {16, 109}, {8, 109}, {8, 97}, {8, 89}, {8, 81},
+ {8, 73}, {8, 65}, {8, 57}, {16, 57}, {8, 49}, {8, 41},
+ {24, 45}, {32, 41}, {32, 49}, {32, 57}, {32, 65}, {32, 73},
+ {32, 81}, {40, 83}, {40, 73}, {40, 63}, {40, 51}, {44, 43},
+ {44, 35}, {44, 27}, {32, 25}, {24, 25}, {16, 25}, {16, 17},
+ {24, 17}, {32, 17}, {44, 11}, {56, 9}, {56, 17}, {56, 25},
+ {56, 33}, {56, 41}, {64, 41}, {72, 41}, {72, 49}, {56, 49},
+ {48, 51}, {56, 57}, {56, 65}, {48, 63}, {48, 73}, {56, 73},
+ {56, 81}, {48, 83}, {56, 89}, {56, 97}, {104, 97}, {104, 105},
+ {104, 113}, {104, 121}, {104, 129}, {104, 137}, {104, 145}, {116, 145},
+ {124, 145}, {132, 145}, {132, 137}, {140, 137}, {148, 137}, {156, 137},
+ {164, 137}, {172, 125}, {172, 117}, {172, 109}, {172, 101}, {172, 93},
+ {172, 85}, {180, 85}, {180, 77}, {180, 69}, {180, 61}, {180, 53},
+ {172, 53}, {172, 61}, {172, 69}, {172, 77}, {164, 81}, {148, 85},
+ {124, 85}, {124, 93}, {124, 109}, {124, 125}, {124, 117}, {124, 101},
+ {104, 89}, {104, 81}, {104, 73}, {104, 65}, {104, 49}, {104, 41},
+ {104, 33}, {104, 25}, {104, 17}, {92, 9}, {80, 9}, {72, 9},
+ {64, 21}, {72, 25}, {80, 25}, {80, 25}, {80, 41}, {88, 49},
+ {104, 57}, {124, 69}, {124, 77}, {132, 81}, {140, 65}, {132, 61},
+ {124, 61}, {124, 53}, {124, 45}, {124, 37}, {124, 29}, {132, 21},
+ {124, 21}, {120, 9}, {128, 9}, {136, 9}, {148, 9}, {162, 9},
+ {156, 25}, {172, 21}, {180, 21}, {180, 29}, {172, 29}, {172, 37},
+ {172, 45}, {180, 45}, {180, 37}, {188, 41}, {196, 49}, {204, 57},
+ {212, 65}, {220, 73}, {228, 69}, {228, 77}, {236, 77}, {236, 69},
+ {236, 61}, {228, 61}, {228, 53}, {236, 53}, {236, 45}, {228, 45},
+ {228, 37}, {236, 37}, {236, 29}, {228, 29}, {228, 21}, {236, 21},
+ {252, 21}, {260, 29}, {260, 37}, {260, 45}, {260, 53}, {260, 61},
+ {260, 69}, {260, 77}, {276, 77}, {276, 69}, {276, 61}, {276, 53},
+ {284, 53}, {284, 61}, {284, 69}, {284, 77}, {284, 85}, {284, 93},
+ {284, 101}, {288, 109}, {280, 109}, {276, 101}, {276, 93}, {276, 85},
+ {268, 97}, {260, 109}, {252, 101}, {260, 93}, {260, 85}, {236, 85},
+ {228, 85}, {228, 93}, {236, 93}, {236, 101}, {228, 101}, {228, 109},
+ {228, 117}, {228, 125}, {220, 125}, {212, 117}, {204, 109}, {196, 101},
+ {188, 93}, {180, 93}, {180, 101}, {180, 109}, {180, 117}, {180, 125},
+ {196, 145}, {204, 145}, {212, 145}, {220, 145}, {228, 145}, {236, 145},
+ {246, 141}, {252, 125}, {260, 129}, {280, 133},
+ };
+ const int num_vehicles(1);
+ const RoutingIndexManager::NodeIndex depot(0);
+ // [END data]
+ // Create Routing Index Manager
+ // [START index_manager]
+ RoutingIndexManager manager(locations.size(), num_vehicles, depot);
+ // [END index_manager]
+
+ // Create Routing Model.
+ // [START routing_model]
+ RoutingModel routing(manager);
+ // [END routing_model]
+
+ // [START transit_callback]
+ const auto distance_matrix = GenerateDistanceMatrix(locations);
+ const int transit_callback_index = routing.RegisterTransitCallback(
+ [&distance_matrix, &manager](int64 from_index, int64 to_index) -> int64 {
+ // Convert from routing variable Index to distance matrix NodeIndex.
+ auto from_node = manager.IndexToNode(from_index).value();
+ auto to_node = manager.IndexToNode(to_index).value();
+ return distance_matrix[from_node][to_node];
+ });
+ // [End transit_callback]
+
+ // Define cost of each arc.
+ // [START arc_cost]
+ routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index);
+ // [END arc_cost]
+
+ // Setting first solution heuristic.
+ // [START parameters]
+ RoutingSearchParameters searchParameters = DefaultRoutingSearchParameters();
+ searchParameters.set_first_solution_strategy(
+ FirstSolutionStrategy::PATH_CHEAPEST_ARC);
+ // [END parameters]
+
+ // Solve the problem.
+ // [START solve]
+ const Assignment* solution = routing.SolveWithParameters(searchParameters);
+ // [END solve]
+
+ // Print solution on console.
+ // [START print_solution]
+ PrintSolution(manager, routing, *solution);
+ // [END print_solution]
+}
+} // namespace operations_research
+
+int main(int argc, char** argv) {
+ operations_research::Tsp();
+ return EXIT_SUCCESS;
+}
+// [END program]
diff --git a/ortools/constraint_solver/samples/tsp_circuit_board.py b/ortools/constraint_solver/samples/tsp_circuit_board.py
new file mode 100644
index 0000000000..ae766b1d66
--- /dev/null
+++ b/ortools/constraint_solver/samples/tsp_circuit_board.py
@@ -0,0 +1,410 @@
+# 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]
+"""Simple travelling salesman problem on a circuit board."""
+
+# [START import]
+from __future__ import print_function
+import math
+from ortools.constraint_solver import routing_enums_pb2
+from ortools.constraint_solver import pywrapcp
+# [END import]
+
+
+# [START data_model]
+def create_data_model():
+ """Stores the data for the problem."""
+ data = {}
+ # Locations in block units
+ data['locations'] = [
+ [288, 149],
+ [288, 129],
+ [270, 133],
+ [256, 141],
+ [256, 157],
+ [246, 157],
+ [236, 169],
+ [228, 169],
+ [228, 161],
+ [220, 169],
+ [212, 169],
+ [204, 169],
+ [196, 169],
+ [188, 169],
+ [196, 161],
+ [188, 145],
+ [172, 145],
+ [164, 145],
+ [156, 145],
+ [148, 145],
+ [140, 145],
+ [148, 169],
+ [164, 169],
+ [172, 169],
+ [156, 169],
+ [140, 169],
+ [132, 169],
+ [124, 169],
+ [116, 161],
+ [104, 153],
+ [104, 161],
+ [104, 169],
+ [90, 165],
+ [80, 157],
+ [64, 157],
+ [64, 165],
+ [56, 169],
+ [56, 161],
+ [56, 153],
+ [56, 145],
+ [56, 137],
+ [56, 129],
+ [56, 121],
+ [40, 121],
+ [40, 129],
+ [40, 137],
+ [40, 145],
+ [40, 153],
+ [40, 161],
+ [40, 169],
+ [32, 169],
+ [32, 161],
+ [32, 153],
+ [32, 145],
+ [32, 137],
+ [32, 129],
+ [32, 121],
+ [32, 113],
+ [40, 113],
+ [56, 113],
+ [56, 105],
+ [48, 99],
+ [40, 99],
+ [32, 97],
+ [32, 89],
+ [24, 89],
+ [16, 97],
+ [16, 109],
+ [8, 109],
+ [8, 97],
+ [8, 89],
+ [8, 81],
+ [8, 73],
+ [8, 65],
+ [8, 57],
+ [16, 57],
+ [8, 49],
+ [8, 41],
+ [24, 45],
+ [32, 41],
+ [32, 49],
+ [32, 57],
+ [32, 65],
+ [32, 73],
+ [32, 81],
+ [40, 83],
+ [40, 73],
+ [40, 63],
+ [40, 51],
+ [44, 43],
+ [44, 35],
+ [44, 27],
+ [32, 25],
+ [24, 25],
+ [16, 25],
+ [16, 17],
+ [24, 17],
+ [32, 17],
+ [44, 11],
+ [56, 9],
+ [56, 17],
+ [56, 25],
+ [56, 33],
+ [56, 41],
+ [64, 41],
+ [72, 41],
+ [72, 49],
+ [56, 49],
+ [48, 51],
+ [56, 57],
+ [56, 65],
+ [48, 63],
+ [48, 73],
+ [56, 73],
+ [56, 81],
+ [48, 83],
+ [56, 89],
+ [56, 97],
+ [104, 97],
+ [104, 105],
+ [104, 113],
+ [104, 121],
+ [104, 129],
+ [104, 137],
+ [104, 145],
+ [116, 145],
+ [124, 145],
+ [132, 145],
+ [132, 137],
+ [140, 137],
+ [148, 137],
+ [156, 137],
+ [164, 137],
+ [172, 125],
+ [172, 117],
+ [172, 109],
+ [172, 101],
+ [172, 93],
+ [172, 85],
+ [180, 85],
+ [180, 77],
+ [180, 69],
+ [180, 61],
+ [180, 53],
+ [172, 53],
+ [172, 61],
+ [172, 69],
+ [172, 77],
+ [164, 81],
+ [148, 85],
+ [124, 85],
+ [124, 93],
+ [124, 109],
+ [124, 125],
+ [124, 117],
+ [124, 101],
+ [104, 89],
+ [104, 81],
+ [104, 73],
+ [104, 65],
+ [104, 49],
+ [104, 41],
+ [104, 33],
+ [104, 25],
+ [104, 17],
+ [92, 9],
+ [80, 9],
+ [72, 9],
+ [64, 21],
+ [72, 25],
+ [80, 25],
+ [80, 25],
+ [80, 41],
+ [88, 49],
+ [104, 57],
+ [124, 69],
+ [124, 77],
+ [132, 81],
+ [140, 65],
+ [132, 61],
+ [124, 61],
+ [124, 53],
+ [124, 45],
+ [124, 37],
+ [124, 29],
+ [132, 21],
+ [124, 21],
+ [120, 9],
+ [128, 9],
+ [136, 9],
+ [148, 9],
+ [162, 9],
+ [156, 25],
+ [172, 21],
+ [180, 21],
+ [180, 29],
+ [172, 29],
+ [172, 37],
+ [172, 45],
+ [180, 45],
+ [180, 37],
+ [188, 41],
+ [196, 49],
+ [204, 57],
+ [212, 65],
+ [220, 73],
+ [228, 69],
+ [228, 77],
+ [236, 77],
+ [236, 69],
+ [236, 61],
+ [228, 61],
+ [228, 53],
+ [236, 53],
+ [236, 45],
+ [228, 45],
+ [228, 37],
+ [236, 37],
+ [236, 29],
+ [228, 29],
+ [228, 21],
+ [236, 21],
+ [252, 21],
+ [260, 29],
+ [260, 37],
+ [260, 45],
+ [260, 53],
+ [260, 61],
+ [260, 69],
+ [260, 77],
+ [276, 77],
+ [276, 69],
+ [276, 61],
+ [276, 53],
+ [284, 53],
+ [284, 61],
+ [284, 69],
+ [284, 77],
+ [284, 85],
+ [284, 93],
+ [284, 101],
+ [288, 109],
+ [280, 109],
+ [276, 101],
+ [276, 93],
+ [276, 85],
+ [268, 97],
+ [260, 109],
+ [252, 101],
+ [260, 93],
+ [260, 85],
+ [236, 85],
+ [228, 85],
+ [228, 93],
+ [236, 93],
+ [236, 101],
+ [228, 101],
+ [228, 109],
+ [228, 117],
+ [228, 125],
+ [220, 125],
+ [212, 117],
+ [204, 109],
+ [196, 101],
+ [188, 93],
+ [180, 93],
+ [180, 101],
+ [180, 109],
+ [180, 117],
+ [180, 125],
+ [196, 145],
+ [204, 145],
+ [212, 145],
+ [220, 145],
+ [228, 145],
+ [236, 145],
+ [246, 141],
+ [252, 125],
+ [260, 129],
+ [280, 133],
+ ]
+ data['num_vehicles'] = 1
+ data['depot'] = 0
+ return data
+ # [END data_model]
+
+
+# [START distance_callback]
+def compute_euclidean_distance_matrix(data):
+ """Creates callback to return distance between points."""
+ distances = {}
+ for from_counter, from_node in enumerate(data['locations']):
+ distances[from_counter] = {}
+ for to_counter, to_node in enumerate(data['locations']):
+ if from_counter == to_counter:
+ distances[from_counter][to_counter] = 0
+ else:
+ # Euclidean distance
+ distances[from_counter][to_counter] = (int(
+ math.hypot((from_node[0] - to_node[0]),
+ (from_node[1] - to_node[1]))))
+ return distances
+ # [END distance_callback]
+
+
+# [START solution_printer]
+def print_solution(manager, routing, assignment):
+ """Prints assignment on console."""
+ print('Objective: {}'.format(assignment.ObjectiveValue()))
+ index = routing.Start(0)
+ plan_output = 'Route:\n'
+ route_distance = 0
+ while not routing.IsEnd(index):
+ plan_output += ' {} ->'.format(manager.IndexToNode(index))
+ previous_index = index
+ index = assignment.Value(routing.NextVar(index))
+ route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
+ plan_output += ' {}\n'.format(manager.IndexToNode(index))
+ print(plan_output)
+ plan_output += 'Objective: {}m\n'.format(route_distance)
+ # [END solution_printer]
+
+
+def main():
+ """Entry point of the program."""
+ # Instantiate the data problem.
+ # [START data]
+ data = create_data_model()
+ # [END data]
+
+ # Create the routing index manager.
+ # [START index_manager]
+ manager = pywrapcp.RoutingIndexManager(
+ len(data['locations']), data['num_vehicles'], data['depot'])
+ # [END index_manager]
+
+ # Create Routing Model.
+ # [START routing_model]
+ routing = pywrapcp.RoutingModel(manager)
+ # [END routing_model]
+
+ # [START transit_callback]
+ distance_matrix = compute_euclidean_distance_matrix(data)
+
+ def distance_callback(from_index, to_index):
+ """Returns the distance between the two nodes."""
+ # Convert from routing variable Index to distance matrix NodeIndex.
+ from_node = manager.IndexToNode(from_index)
+ to_node = manager.IndexToNode(to_index)
+ return distance_matrix[from_node][to_node]
+
+ transit_callback_index = routing.RegisterTransitCallback(distance_callback)
+ # [END transit_callback]
+
+ # Define cost of each arc.
+ # [START arc_cost]
+ routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
+ # [END arc_cost]
+
+ # Setting first solution heuristic.
+ # [START parameters]
+ search_parameters = pywrapcp.DefaultRoutingSearchParameters()
+ search_parameters.first_solution_strategy = (
+ routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
+ # [END parameters]
+
+ # Solve the problem.
+ # [START solve]
+ assignment = routing.SolveWithParameters(search_parameters)
+ # [END solve]
+
+ # Print solution on console.
+ # [START print_solution]
+ if assignment:
+ print_solution(manager, routing, assignment)
+ # [END print_solution]
+
+
+if __name__ == '__main__':
+ main()
+# [END program]
diff --git a/ortools/constraint_solver/samples/tsp_cities.cc b/ortools/constraint_solver/samples/tsp_cities.cc
new file mode 100644
index 0000000000..a43a7e18ee
--- /dev/null
+++ b/ortools/constraint_solver/samples/tsp_cities.cc
@@ -0,0 +1,124 @@
+// 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]
+#include
+#include
+#include "ortools/constraint_solver/routing.h"
+#include "ortools/constraint_solver/routing_enums.pb.h"
+#include "ortools/constraint_solver/routing_index_manager.h"
+#include "ortools/constraint_solver/routing_parameters.h"
+// [END import]
+
+namespace operations_research {
+// [START solution_printer]
+//! @brief Print the solution.
+//! @param[in] manager Index manager used.
+//! @param[in] routing Routing solver used.
+//! @param[in] solution Solution found by the solver.
+void PrintSolution(const RoutingIndexManager& manager,
+ const RoutingModel& routing, const Assignment& solution) {
+ // Inspect solution.
+ LOG(INFO) << "Objective: " << solution.ObjectiveValue() << " miles";
+ int64 index = routing.Start(0);
+ LOG(INFO) << "Route:";
+ int64 distance{0};
+ std::stringstream route;
+ while (routing.IsEnd(index) == false) {
+ route << manager.IndexToNode(index).value() << " -> ";
+ int64 previous_index = index;
+ index = solution.Value(routing.NextVar(index));
+ distance += const_cast(routing).GetArcCostForVehicle(
+ previous_index, index, 0LL);
+ }
+ LOG(INFO) << route.str() << manager.IndexToNode(index).value();
+ LOG(INFO) << "Route distance: " << distance << "miles";
+ LOG(INFO) << "";
+ LOG(INFO) << "Advanced usage:";
+ LOG(INFO) << "Problem solved in " << routing.solver()->wall_time() << "ms";
+}
+// [END solution_printer]
+
+void Tsp() {
+ // Instantiate the data problem.
+ // [START data]
+ const std::vector> distance_matrix = {
+ {0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972},
+ {2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579},
+ {713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260},
+ {1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987},
+ {1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371},
+ {1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999},
+ {2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701},
+ {213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099},
+ {2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600},
+ {875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162},
+ {1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200},
+ {2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504},
+ {1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0},
+ };
+ const int num_vehicles(1);
+ const RoutingIndexManager::NodeIndex depot(0);
+ // [END data]
+
+ // Create Routing Index Manager
+ // [START index_manager]
+ RoutingIndexManager manager(distance_matrix.size(), num_vehicles, depot);
+ // [END index_manager]
+
+ // Create Routing Model.
+ // [START routing_model]
+ RoutingModel routing(manager);
+ // [END routing_model]
+
+ // [START transit_callback]
+ const int transit_callback_index = routing.RegisterTransitCallback(
+ [&distance_matrix, &manager](int64 from_index, int64 to_index) -> int64 {
+ // Convert from routing variable Index to distance matrix NodeIndex.
+ auto from_node = manager.IndexToNode(from_index).value();
+ auto to_node = manager.IndexToNode(to_index).value();
+ return distance_matrix[from_node][to_node];
+ });
+ // [END transit_callback]
+
+ // Define cost of each arc.
+ // [START arc_cost]
+ routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index);
+ // [END arc_cost]
+
+ // Setting first solution heuristic.
+ // [START parameters]
+ RoutingSearchParameters searchParameters = DefaultRoutingSearchParameters();
+ searchParameters.set_first_solution_strategy(
+ FirstSolutionStrategy::PATH_CHEAPEST_ARC);
+ // [END parameters]
+
+ // Solve the problem.
+ // [START solve]
+ const Assignment* solution = routing.SolveWithParameters(searchParameters);
+ // [END solve]
+
+ // Print solution on console.
+ // [START print_solution]
+ PrintSolution(manager, routing, *solution);
+ // [END print_solution]
+}
+
+} // namespace operations_research
+
+int main(int argc, char** argv) {
+ operations_research::Tsp();
+ return EXIT_SUCCESS;
+}
+// [END program]
diff --git a/ortools/constraint_solver/samples/tsp_cities.py b/ortools/constraint_solver/samples/tsp_cities.py
new file mode 100644
index 0000000000..33c8a145c0
--- /dev/null
+++ b/ortools/constraint_solver/samples/tsp_cities.py
@@ -0,0 +1,131 @@
+# 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]
+"""Simple travelling salesman problem between cities."""
+
+# [START import]
+from __future__ import print_function
+from ortools.constraint_solver import routing_enums_pb2
+from ortools.constraint_solver import pywrapcp
+# [END import]
+
+
+# [START data_model]
+def create_data_model():
+ """Stores the data for the problem."""
+ data = {}
+ data['distance_matrix'] = [
+ [
+ 0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145,
+ 1972
+ ],
+ [2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579],
+ [713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260],
+ [1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987],
+ [1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371],
+ [1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999],
+ [
+ 2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114,
+ 701
+ ],
+ [
+ 213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300,
+ 2099
+ ],
+ [2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600],
+ [875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162],
+ [1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200],
+ [2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504],
+ [1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0]
+ ]
+ data['num_vehicles'] = 1
+ data['depot'] = 0
+ return data
+ # [END data_model]
+
+
+# [START solution_printer]
+def print_solution(manager, routing, assignment):
+ """Prints assignment on console."""
+ print('Objective: {} miles'.format(assignment.ObjectiveValue()))
+ index = routing.Start(0)
+ plan_output = 'Route for vehicle 0:\n'
+ route_distance = 0
+ while not routing.IsEnd(index):
+ plan_output += ' {} ->'.format(manager.IndexToNode(index))
+ previous_index = index
+ index = assignment.Value(routing.NextVar(index))
+ route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)
+ plan_output += ' {}\n'.format(manager.IndexToNode(index))
+ print(plan_output)
+ plan_output += 'Route distance: {}miles\n'.format(route_distance)
+ # [END solution_printer]
+
+
+def main():
+ """Entry point of the program."""
+ # Instantiate the data problem.
+ # [START data]
+ data = create_data_model()
+ # [END data]
+
+ # Create the routing index manager.
+ # [START index_manager]
+ manager = pywrapcp.RoutingIndexManager(
+ len(data['distance_matrix']), data['num_vehicles'], data['depot'])
+ # [END index_manager]
+
+ # Create Routing Model.
+ # [START routing_model]
+ routing = pywrapcp.RoutingModel(manager)
+
+ # [END routing_model]
+
+ # [START transit_callback]
+ def distance_callback(from_index, to_index):
+ """Returns the distance between the two nodes."""
+ # Convert from routing variable Index to distance matrix NodeIndex.
+ from_node = manager.IndexToNode(from_index)
+ to_node = manager.IndexToNode(to_index)
+ return data['distance_matrix'][from_node][to_node]
+
+ transit_callback_index = routing.RegisterTransitCallback(distance_callback)
+ # [END transit_callback]
+
+ # Define cost of each arc.
+ # [START arc_cost]
+ routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
+ # [END arc_cost]
+
+ # Setting first solution heuristic.
+ # [START parameters]
+ search_parameters = pywrapcp.DefaultRoutingSearchParameters()
+ search_parameters.first_solution_strategy = (
+ routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
+ # [END parameters]
+
+ # Solve the problem.
+ # [START solve]
+ assignment = routing.SolveWithParameters(search_parameters)
+ # [END solve]
+
+ # Print solution on console.
+ # [START print_solution]
+ if assignment:
+ print_solution(manager, routing, assignment)
+ # [END print_solution]
+
+
+if __name__ == '__main__':
+ main()
+# [END program]