dotnet: Remove reference to dotnet release command

- Currently not implemented...

Add abseil patch

- Add patches/absl-config.cmake

Makefile: Add abseil-cpp on unix

- Force abseil-cpp SHA1 to 45221cc
  note: Just before the PR #136 which break all CMake

Makefile: Add abseil-cpp on windows

- Force abseil-cpp SHA1 to 45221cc
  note: Just before the PR #136 which break all CMake

CMake: Add abseil-cpp

- Force abseil-cpp SHA1 to 45221cc
  note: Just before the PR #136 which break all CMake

port to absl: C++ Part

- Fix warning with the use of ABSL_MUST_USE_RESULT
  > The macro must appear as the very first part of a function
    declaration or definition:
    ...
    Note: past advice was to place the macro after the argument list.
  src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418
- Rename enum after windows clash
- Remove non compact table constraints
- Change index type from int64 to int in routing library
- Fix file_nonport compilation on windows
- Fix another naming conflict with windows (NO_ERROR is a macro)
- Cleanup hash containers; work on sat internals
- Add optional_boolean sub-proto

Sync cpp examples with internal code
- reenable issue173 after reducing number of loops

port to absl: Python Part

- Add back cp_model.INT32_MIN|MAX for examples

Update Python examples

- Add random_tsp.py
- Run words_square example
- Run magic_square in python tests

port to absl: Java Part

- Fix compilation of the new routing parameters in java
- Protect some code from SWIG parsing

Update Java Examples

port to absl: .Net Part

Update .Net examples

work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code

Remove VS 2015 in Appveyor-CI

- abseil-cpp does not support VS 2015...

improve tables

upgrade C++ sat examples to use the new API; work on sat internals

update license dates

rewrite jobshop_ft06_distance.py to use the CP-SAT solver

rename last example

revert last commit

more work on SAT internals

fix
This commit is contained in:
Corentin Le Molgat
2018-10-31 16:18:18 +01:00
parent 745906cb7c
commit b027e57e95
490 changed files with 92044 additions and 24779 deletions

View File

@@ -13,12 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import com.google.ortools.constraintsolver.Assignment;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.NodeEvaluator2;
import com.google.ortools.constraintsolver.RoutingModel;
import com.google.ortools.constraintsolver.FirstSolutionStrategy;
import com.google.ortools.constraintsolver.IntIntToLong;
import com.google.ortools.constraintsolver.IntToLong;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.RoutingDimension;
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.ArrayList;
import java.util.List;
import java.util.Random;
@@ -41,12 +44,11 @@ class Pair<K, V> {
}
/**
* Sample showing how to model and solve a capacitated vehicle routing problem
* with time windows using the swig-wrapped version of the vehicle routing
* library in src/constraint_solver.
* Sample showing how to model and solve a capacitated vehicle routing problem with time windows
* using the swig-wrapped version of the vehicle routing library in src/constraint_solver.
*/
public class CapacitatedVehicleRoutingProblemWithTimeWindows {
static {
System.loadLibrary("jniortools");
}
@@ -60,8 +62,6 @@ public class CapacitatedVehicleRoutingProblemWithTimeWindows {
// Quantity to be picked up for each order.
private List<Integer> orderDemands = new ArrayList();
// Time duration spent to deliver each order.
private List<Integer> orderDurations = new ArrayList();
// Time window in which each order must be performed.
private List<Pair<Integer, Integer>> orderTimeWindows = new ArrayList();
// Penalty cost "paid" for dropping an order.
@@ -69,8 +69,6 @@ public class CapacitatedVehicleRoutingProblemWithTimeWindows {
// Capacity of the vehicles.
private int vehicleCapacity = 0;
// Earliest time at which each vehicle must start its tour.
private List<Integer> vehicleStartTime = new ArrayList();
// Latest time at which each vehicle must end its tour.
private List<Integer> vehicleEndTime = new ArrayList();
// Cost per unit of distance of each vehicle.
@@ -84,53 +82,76 @@ public class CapacitatedVehicleRoutingProblemWithTimeWindows {
private final Random randomGenerator = new Random(0xBEEF);
/**
* Constructs a capacitated vehicle routing problem with time windows.
* Creates a Manhattan Distance evaluator with 'costCoefficient'.
*
* @param manager Node Index Manager.
* @param costCoefficient The coefficient to apply to the evaluator.
*/
private CapacitatedVehicleRoutingProblemWithTimeWindows() {}
private IntIntToLong buildManhattanCallback(RoutingIndexManager manager, int costCoefficient) {
return new IntIntToLong() {
@Override
public long run(int firstIndex, int secondIndex) {
try {
int firstNode = manager.indexToNode(firstIndex);
int secondNode = manager.indexToNode(secondIndex);
Pair<Integer, Integer> firstLocation = locations.get(firstNode);
Pair<Integer, Integer> secondLocation = locations.get(secondNode);
return (long) costCoefficient
* (Math.abs(firstLocation.first - secondLocation.first)
+ Math.abs(firstLocation.second - secondLocation.second));
} catch (Throwable throwed) {
logger.warning(throwed.getMessage());
return 0;
}
}
};
}
/**
* Creates order data. Location of the order is random, as well as its
* demand (quantity), time window and penalty.
* Creates order data. Location of the order is random, as well as its demand (quantity), time
* window and penalty.
*
* @param numberOfOrders number of orders to build.
* @param xMax maximum x coordinate in which orders are located.
* @param yMax maximum y coordinate in which orders are located.
* @param demandMax maximum quantity of a demand.
* @param timeWindowMin minimum starting time of the order time window.
* @param timeWindowMax maximum starting time of the order time window.
* @param timeWindowWidth duration of the order time window.
* @param penaltyMin minimum pernalty cost if order is dropped.
* @param penaltyMax maximum pernalty cost if order is dropped.
*/
private void buildOrders(int numberOfOrders, int xMax, int yMax, int demandMax, int timeWindowMin,
int timeWindowMax, int timeWindowWidth, int penaltyMin, int penaltyMax) {
private void buildOrders(
int numberOfOrders,
int xMax,
int yMax,
int demandMax,
int timeWindowMax,
int timeWindowWidth,
int penaltyMin,
int penaltyMax) {
logger.info("Building orders.");
for (int order = 0; order < numberOfOrders; ++order) {
locations.add(Pair.of(randomGenerator.nextInt(xMax + 1), randomGenerator.nextInt(yMax + 1)));
orderDemands.add(randomGenerator.nextInt(demandMax + 1));
/** @todo 1) Specify deliver duration for each shipment*/
orderDurations.add(2); // in minutes
int timeWindowStart = randomGenerator.nextInt(timeWindowMax - timeWindowMin) + timeWindowMin;
int timeWindowStart = randomGenerator.nextInt(timeWindowMax + 1);
orderTimeWindows.add(Pair.of(timeWindowStart, timeWindowStart + timeWindowWidth));
orderPenalties.add(randomGenerator.nextInt(penaltyMax - penaltyMin + 1) + penaltyMin);
}
}
/**
* Creates fleet data. Vehicle starting and ending locations are random, as
* well as vehicle costs per distance unit.
* Creates fleet data. Vehicle starting and ending locations are random, as well as vehicle costs
* per distance unit.
*
* @param numberOfVehicles
* @param xMax maximum x coordinate in which orders are located.
* @param yMax maximum y coordinate in which orders are located.
* @param startTime earliest start time of a tour of a vehicle.
* @param endTime latest end time of a tour of a vehicle.
* @param capacity capacity of a vehicle.
* @param costCoefficientMax maximum cost per distance unit of a vehicle
* (mimimum is 1),
* @param costCoefficientMax maximum cost per distance unit of a vehicle (mimimum is 1),
*/
private void buildFleet(int numberOfVehicles, int xMax, int yMax, int startTime, int endTime,
int capacity, int costCoefficientMax) {
private void buildFleet(
int numberOfVehicles, int xMax, int yMax, int endTime, int capacity, int costCoefficientMax) {
logger.info("Building fleet.");
vehicleCapacity = capacity;
vehicleStarts = new int[numberOfVehicles];
@@ -140,101 +161,75 @@ public class CapacitatedVehicleRoutingProblemWithTimeWindows {
locations.add(Pair.of(randomGenerator.nextInt(xMax + 1), randomGenerator.nextInt(yMax + 1)));
vehicleEnds[vehicle] = locations.size();
locations.add(Pair.of(randomGenerator.nextInt(xMax + 1), randomGenerator.nextInt(yMax + 1)));
vehicleStartTime.add(startTime);
vehicleEndTime.add(endTime);
vehicleCostCoefficients.add(randomGenerator.nextInt(costCoefficientMax) + 1);
}
}
/**
* Solves the current routing problem.
*/
/** Solves the current routing problem. */
private void solve(final int numberOfOrders, final int numberOfVehicles) {
logger.info(
"Creating model with " + numberOfOrders + " orders and " + numberOfVehicles + " vehicles.");
// Finalizing model
final int numberOfLocations = locations.size();
RoutingModel model =
new RoutingModel(numberOfLocations, numberOfVehicles, vehicleStarts, vehicleEnds);
RoutingIndexManager manager =
new RoutingIndexManager(numberOfLocations, numberOfVehicles, vehicleStarts, vehicleEnds);
RoutingModel model = new RoutingModel(manager);
// Setting up dimensions
final int bigNumber = 100000;
NodeEvaluator2 timeCallback = new NodeEvaluator2() {
@Override
public long run(int firstIndex, int secondIndex) {
try {
Pair<Integer, Integer> firstLocation = locations.get(firstIndex);
Pair<Integer, Integer> secondLocation = locations.get(secondIndex);
Integer distance = 0;
Integer duration = 0;
distance = Math.abs(firstLocation.first - secondLocation.first)
+ Math.abs(firstLocation.second - secondLocation.second);
// Deal with Order duration shipment
if (firstIndex < numberOfOrders) {
// shipment duration
duration += orderDurations.get(firstIndex);
final IntIntToLong callback = buildManhattanCallback(manager, 1);
final String timeStr = "time";
model.addDimension(
model.registerTransitCallback(callback), bigNumber, bigNumber, false, timeStr);
RoutingDimension timeDimension = model.getMutableDimension(timeStr);
IntToLong demandCallback =
new IntToLong() {
@Override
public long run(int index) {
try {
int node = manager.indexToNode(index);
if (node < numberOfOrders) {
return orderDemands.get(node);
}
return 0;
} catch (Throwable throwed) {
logger.warning(throwed.getMessage());
return 0;
}
}
return distance + duration;
} catch (Throwable throwed) {
logger.warning(throwed.getMessage());
return 0;
}
}
};
model.addDimension(timeCallback, bigNumber, bigNumber, false, "time");
NodeEvaluator2 demandCallback = new NodeEvaluator2() {
@Override
public long run(int firstIndex, int secondIndex) {
try {
if (firstIndex < numberOfOrders) {
return orderDemands.get(firstIndex);
}
return 0;
} catch (Throwable throwed) {
logger.warning(throwed.getMessage());
return 0;
}
}
};
model.addDimension(demandCallback, 0, vehicleCapacity, true, "capacity");
};
final String capacityStr = "capacity";
model.addDimension(
model.registerUnaryTransitCallback(demandCallback), 0, vehicleCapacity, true, capacityStr);
RoutingDimension capacityDimension = model.getMutableDimension(capacityStr);
// Setting up vehicles
IntIntToLong[] callbacks = new IntIntToLong[numberOfVehicles];
for (int vehicle = 0; vehicle < numberOfVehicles; ++vehicle) {
final int costCoefficient = vehicleCostCoefficients.get(vehicle);
NodeEvaluator2 manhattanCostCallback = new NodeEvaluator2() {
@Override
public long run(int firstIndex, int secondIndex) {
try {
Pair<Integer, Integer> firstLocation = locations.get(firstIndex);
Pair<Integer, Integer> secondLocation = locations.get(secondIndex);
return costCoefficient
* (Math.abs(firstLocation.first - secondLocation.first)
+ Math.abs(firstLocation.second - secondLocation.second));
} catch (Throwable throwed) {
logger.warning(throwed.getMessage());
return 0;
}
}
};
model.setArcCostEvaluatorOfVehicle(manhattanCostCallback, vehicle);
model.cumulVar(model.start(vehicle), "time").setMin(vehicleStartTime.get(vehicle));
model.cumulVar(model.end(vehicle), "time").setMax(vehicleEndTime.get(vehicle));
callbacks[vehicle] = buildManhattanCallback(manager, costCoefficient);
final int vehicleCost = model.registerTransitCallback(callbacks[vehicle]);
model.setArcCostEvaluatorOfVehicle(vehicleCost, vehicle);
timeDimension.cumulVar(model.end(vehicle)).setMax(vehicleEndTime.get(vehicle));
}
// Setting up orders
for (int order = 0; order < numberOfOrders; ++order) {
model.cumulVar(model.nodeToIndex(order), "time")
timeDimension
.cumulVar(order)
.setRange(orderTimeWindows.get(order).first, orderTimeWindows.get(order).second);
int[] orders = {order};
model.addDisjunction(orders, orderPenalties.get(order));
long[] orderIndices = {manager.nodeToIndex(order)};
model.addDisjunction(orderIndices, orderPenalties.get(order));
}
// Solving
RoutingSearchParameters parameters =
RoutingSearchParameters.newBuilder()
.mergeFrom(RoutingModel.defaultSearchParameters())
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
main.defaultRoutingSearchParameters()
.toBuilder()
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.ALL_UNPERFORMED)
.build();
logger.info("Search");
@@ -258,25 +253,38 @@ public class CapacitatedVehicleRoutingProblemWithTimeWindows {
long order = model.start(vehicle);
// Empty route has a minimum of two nodes: Start => End
if (model.isEnd(solution.value(model.nextVar(order)))) {
route += "/!\\Empty Route/!\\ ";
}
{
route += "Empty";
} else {
for (; !model.isEnd(order); order = solution.value(model.nextVar(order))) {
IntVar load = model.cumulVar(order, "capacity");
IntVar time = model.cumulVar(order, "time");
route += order + " Load(" + solution.value(load) + ") "
+ "Time(" + solution.min(time) + ", " + solution.max(time) + ") -> ";
IntVar load = capacityDimension.cumulVar(order);
IntVar time = timeDimension.cumulVar(order);
route +=
order
+ " Load("
+ solution.value(load)
+ ") "
+ "Time("
+ solution.min(time)
+ ", "
+ solution.max(time)
+ ") -> ";
}
IntVar load = model.cumulVar(order, "capacity");
IntVar time = model.cumulVar(order, "time");
route += order + " Load(" + solution.value(load) + ") "
+ "Time(" + solution.min(time) + ", " + solution.max(time) + ")";
IntVar load = capacityDimension.cumulVar(order);
IntVar time = timeDimension.cumulVar(order);
route +=
order
+ " Load("
+ solution.value(load)
+ ") "
+ "Time("
+ solution.min(time)
+ ", "
+ solution.max(time)
+ ")";
}
output += route + "\n";
}
logger.info(output);
} else {
logger.info("No solution Found !");
}
}
@@ -286,24 +294,20 @@ public class CapacitatedVehicleRoutingProblemWithTimeWindows {
final int xMax = 20;
final int yMax = 20;
final int demandMax = 3;
final int timeWindowMin = 8 * 60;
final int timeWindowMax = 17 * 60;
final int timeWindowMax = 24 * 60;
final int timeWindowWidth = 4 * 60;
final int penaltyMin = 50;
final int penaltyMax = 100;
/** @todo Specify vehicle start time*/
final int startTime = 8 * 60;
/** @todo Specify vehicle end time*/
final int endTime = 17 * 60;
final int endTime = 24 * 60;
final int costCoefficientMax = 3;
final int orders = 100;
final int vehicles = 20;
final int capacity = 50;
problem.buildOrders(orders, xMax, yMax, demandMax, timeWindowMin, timeWindowMax,
timeWindowWidth, penaltyMin, penaltyMax);
problem.buildFleet(vehicles, xMax, yMax, startTime, endTime, capacity, costCoefficientMax);
problem.buildOrders(
orders, xMax, yMax, demandMax, timeWindowMax, timeWindowWidth, penaltyMin, penaltyMax);
problem.buildFleet(vehicles, xMax, yMax, endTime, capacity, costCoefficientMax);
problem.solve(orders, vehicles);
}
}