OR-Tools  7.1
VrpDropNodes.java
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 // [START program]
15 // [START import]
22 import java.util.logging.Logger;
23 // [END import]
24 
26 public class VrpDropNodes {
27  static {
28  System.loadLibrary("jniortools");
29  }
30 
31  private static final Logger logger = Logger.getLogger(VrpDropNodes.class.getName());
32 
33  // [START data_model]
34  static class DataModel {
35  public final long[][] distanceMatrix = {
36  {0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
37  {548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
38  {776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
39  {696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
40  {582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
41  {274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
42  {502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
43  {194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
44  {308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
45  {194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
46  {536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
47  {502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
48  {388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
49  {354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
50  {468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
51  {776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
52  {662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0},
53  };
54  // [START demands_capacities]
55  public final long[] demands = {0, 1, 1, 3, 6, 3, 6, 8, 8, 1, 2, 1, 2, 6, 6, 8, 8};
56  public final long[] vehicleCapacities = {15, 15, 15, 15};
57  // [END demands_capacities]
58  public final int vehicleNumber = 4;
59  public final int depot = 0;
60  }
61  // [END data_model]
62 
63  // [START solution_printer]
65  static void printSolution(
66  DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
67  // Display dropped nodes.
68  String droppedNodes = "Dropped nodes:";
69  for (int node = 0; node < routing.size(); ++node) {
70  if (routing.isStart(node) || routing.isEnd(node)) {
71  continue;
72  }
73  if (solution.value(routing.nextVar(node)) == node) {
74  droppedNodes += " " + manager.indexToNode(node);
75  }
76  }
77  logger.info(droppedNodes);
78  // Display routes
79  long totalDistance = 0;
80  long totalLoad = 0;
81  for (int i = 0; i < data.vehicleNumber; ++i) {
82  long index = routing.start(i);
83  logger.info("Route for Vehicle " + i + ":");
84  long routeDistance = 0;
85  long routeLoad = 0;
86  String route = "";
87  while (!routing.isEnd(index)) {
88  long nodeIndex = manager.indexToNode(index);
89  routeLoad += data.demands[(int) nodeIndex];
90  route += nodeIndex + " Load(" + routeLoad + ") -> ";
91  long previousIndex = index;
92  index = solution.value(routing.nextVar(index));
93  routeDistance += routing.getArcCostForVehicle(previousIndex, index, i);
94  }
95  route += manager.indexToNode(routing.end(i));
96  logger.info(route);
97  logger.info("Distance of the route: " + routeDistance + "m");
98  totalDistance += routeDistance;
99  totalLoad += routeLoad;
100  }
101  logger.info("Total Distance of all routes: " + totalDistance + "m");
102  logger.info("Total Load of all routes: " + totalLoad);
103  }
104  // [END solution_printer]
105 
106  public static void main(String[] args) throws Exception {
107  // Instantiate the data problem.
108  // [START data]
109  final DataModel data = new DataModel();
110  // [END data]
111 
112  // Create Routing Index Manager
113  // [START index_manager]
114  RoutingIndexManager manager =
115  new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
116  // [END index_manager]
117 
118  // Create Routing Model.
119  // [START routing_model]
120  RoutingModel routing = new RoutingModel(manager);
121  // [END routing_model]
122 
123  // Create and register a transit callback.
124  // [START transit_callback]
125  final int transitCallbackIndex =
126  routing.registerTransitCallback((long fromIndex, long toIndex) -> {
127  // Convert from routing variable Index to user NodeIndex.
128  int fromNode = manager.indexToNode(fromIndex);
129  int toNode = manager.indexToNode(toIndex);
130  return data.distanceMatrix[fromNode][toNode];
131  });
132  // [END transit_callback]
133 
134  // Define cost of each arc.
135  // [START arc_cost]
136  routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
137  // [END arc_cost]
138 
139  // Add Capacity constraint.
140  // [START capacity_constraint]
141  final int demandCallbackIndex = routing.registerUnaryTransitCallback((long fromIndex) -> {
142  // Convert from routing variable Index to user NodeIndex.
143  int fromNode = manager.indexToNode(fromIndex);
144  return data.demands[fromNode];
145  });
146  routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, // null capacity slack
147  data.vehicleCapacities, // vehicle maximum capacities
148  true, // start cumul to zero
149  "Capacity");
150  // Allow to drop nodes.
151  long penalty = 1000;
152  for (int i = 1; i < data.distanceMatrix.length; ++i) {
153  routing.addDisjunction(new long[] {manager.nodeToIndex(i)}, penalty);
154  }
155  // [END capacity_constraint]
156 
157  // Setting first solution heuristic.
158  // [START parameters]
159  RoutingSearchParameters searchParameters =
161  .toBuilder()
163  .build();
164  // [END parameters]
165 
166  // Solve the problem.
167  // [START solve]
168  Assignment solution = routing.solveWithParameters(searchParameters);
169  // [END solve]
170 
171  // Print solution on console.
172  // [START print_solution]
173  printSolution(data, routing, manager, solution);
174  // [END print_solution]
175  }
176 }
177 // [END program]
static com.google.ortools.constraintsolver.RoutingSearchParameters defaultRoutingSearchParameters()
int addDisjunction(long[] indices, long penalty, long max_cardinality)
int registerTransitCallback(LongBinaryOperator callback)
boolean addDimensionWithVehicleCapacity(int evaluator_index, long slack_max, long[] vehicle_capacities, boolean fix_start_cumul_to_zero, String name)
long getArcCostForVehicle(long from_index, long to_index, long vehicle)
static void main(String[] args)
int registerUnaryTransitCallback(LongUnaryOperator callback)
.lang.Override com.google.ortools.constraintsolver.RoutingSearchParameters build()
Builder setFirstSolutionStrategy(com.google.ortools.constraintsolver.FirstSolutionStrategy.Value value)
Minimal VRP.
Assignment solveWithParameters(com.google.ortools.constraintsolver.RoutingSearchParameters search_parameters)
void setArcCostEvaluatorOfAllVehicles(int evaluator_index)