Add VrpCapacity.java
This commit is contained in:
@@ -376,6 +376,7 @@ test_java_constraint_solver_samples: \
|
||||
rjava_SimpleRoutingProgram \
|
||||
rjava_Tsp \
|
||||
rjava_Vrp \
|
||||
rjava_VrpCapacity \
|
||||
|
||||
.PHONY: test_java_graph_samples # Build and Run all Java Graph Samples (located in ortools/graph/samples)
|
||||
test_java_graph_samples: \
|
||||
|
||||
198
ortools/constraint_solver/samples/VrpCapacity.java
Normal file
198
ortools/constraint_solver/samples/VrpCapacity.java
Normal file
@@ -0,0 +1,198 @@
|
||||
// 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]
|
||||
import com.google.ortools.constraintsolver.Assignment;
|
||||
import com.google.ortools.constraintsolver.FirstSolutionStrategy;
|
||||
import com.google.ortools.constraintsolver.LongLongToLong;
|
||||
import com.google.ortools.constraintsolver.LongToLong;
|
||||
import com.google.ortools.constraintsolver.RoutingDimension;
|
||||
import com.google.ortools.constraintsolver.RoutingIndexManager;
|
||||
import com.google.ortools.constraintsolver.RoutingModel;
|
||||
import com.google.ortools.constraintsolver.RoutingDimension;
|
||||
import com.google.ortools.constraintsolver.RoutingSearchParameters;
|
||||
import com.google.ortools.constraintsolver.main;
|
||||
import java.util.logging.Logger;
|
||||
// [END import]
|
||||
|
||||
/** Minimal VRP.*/
|
||||
public class VrpCapacity {
|
||||
static { System.loadLibrary("jniortools"); }
|
||||
|
||||
private static final Logger logger = Logger.getLogger(VrpCapacity.class.getName());
|
||||
|
||||
// [START data_model]
|
||||
static class DataModel {
|
||||
public DataModel() {
|
||||
distanceMatrix = 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};
|
||||
vehicleNumber = 4;
|
||||
vehicleCapacities = new long[] {15, 15, 15, 15};
|
||||
depot = 0;
|
||||
}
|
||||
public final long[][] distanceMatrix;
|
||||
public final long[] demands;
|
||||
public final int vehicleNumber;
|
||||
public final long[] vehicleCapacities;
|
||||
public final int depot;
|
||||
}
|
||||
// [END data_model]
|
||||
|
||||
// [START manhattan_distance]
|
||||
/// @brief Manhattan distance implemented as a transit callback.
|
||||
/// @details It uses an array of positions and computes
|
||||
/// the Manhattan distance between the two positions of
|
||||
/// two different indices.
|
||||
static class ManhattanDistance extends LongLongToLong {
|
||||
public ManhattanDistance(DataModel data, RoutingIndexManager manager) {
|
||||
// precompute distance between location to have distance callback in O(1)
|
||||
distanceMatrix_ = data.distanceMatrix;
|
||||
indexManager_ = manager;
|
||||
}
|
||||
@Override
|
||||
public long run(long fromIndex, long toIndex) {
|
||||
int fromNode = indexManager_.indexToNode(fromIndex);
|
||||
int toNode = indexManager_.indexToNode(toIndex);
|
||||
return distanceMatrix_[fromNode][toNode];
|
||||
}
|
||||
private long[][] distanceMatrix_;
|
||||
private RoutingIndexManager indexManager_;
|
||||
}
|
||||
// [END manhattan_distance]
|
||||
|
||||
|
||||
// [START demands]
|
||||
static class DemandCallback extends LongToLong {
|
||||
public DemandCallback(DataModel data, RoutingIndexManager manager) {
|
||||
// precompute distance between location to have distance callback in O(1)
|
||||
demands_ = data.demands;
|
||||
indexManager_ = manager;
|
||||
}
|
||||
@Override
|
||||
public long run(long fromIndex) {
|
||||
int fromNode = indexManager_.indexToNode(fromIndex);
|
||||
return demands_[fromNode];
|
||||
}
|
||||
private long[] demands_;
|
||||
private RoutingIndexManager indexManager_;
|
||||
}
|
||||
// [END demands]
|
||||
|
||||
// [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.
|
||||
long totalDistance = 0;
|
||||
long totalLoad = 0;
|
||||
for (int i = 0; i < data.vehicleNumber; ++i) {
|
||||
long index = routing.start(i);
|
||||
logger.info("Route for Vehicle " + i + ":");
|
||||
long routeDistance = 0;
|
||||
long routeLoad = 0;
|
||||
String route = "";
|
||||
while (!routing.isEnd(index)) {
|
||||
long nodeIndex = manager.indexToNode(index);
|
||||
routeLoad += data.demands[(int) nodeIndex];
|
||||
route += nodeIndex + " Load(" + routeLoad + ") -> ";
|
||||
long previousIndex = index;
|
||||
index = solution.value(routing.nextVar(index));
|
||||
routeDistance += routing.getArcCostForVehicle(previousIndex, index, i);
|
||||
}
|
||||
route += manager.indexToNode(routing.end(i));
|
||||
logger.info(route);
|
||||
logger.info("Distance of the route: " + routeDistance + "m");
|
||||
totalDistance += routeDistance;
|
||||
totalLoad += routeLoad;
|
||||
}
|
||||
logger.info("Total Distance of all routes: " + totalDistance + "m");
|
||||
logger.info("Total Load of all routes: " + totalLoad);
|
||||
}
|
||||
// [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]
|
||||
|
||||
// Define cost of each arc.
|
||||
// [START arc_cost]
|
||||
LongLongToLong distanceEvaluator = new ManhattanDistance(data, manager);
|
||||
int transitCostIndex = routing.registerTransitCallback(distanceEvaluator);
|
||||
routing.setArcCostEvaluatorOfAllVehicles(transitCostIndex);
|
||||
// [END arc_cost]
|
||||
|
||||
// Add Capacity constraint.
|
||||
// [START capacity_constraint]
|
||||
LongToLong demandEvaluator = new DemandCallback(data, manager);
|
||||
int demandCostIndex = routing.registerUnaryTransitCallback(demandEvaluator);
|
||||
routing.addDimensionWithVehicleCapacity(
|
||||
demandCostIndex, 0, // null capacity slack
|
||||
data.vehicleCapacities, // vehicle maximum capacities
|
||||
true, // start cumul to zero
|
||||
"Capacity");
|
||||
// [END capacity_constraint]
|
||||
|
||||
// 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]
|
||||
Reference in New Issue
Block a user