Move java examples

This commit is contained in:
Corentin Le Molgat
2018-07-06 21:03:33 +02:00
parent 6485017458
commit 13a566bed4
58 changed files with 340 additions and 693 deletions

View File

@@ -0,0 +1,118 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class AllDifferentExcept0 {
static {
System.loadLibrary("jniortools");
}
//
// alldifferent_except_0(solver, x)
//
// A decomposition of the global constraint
// alldifferent_except_0, i.e. all values
// must be either distinct, or 0.
//
public static void alldifferent_except_0(Solver solver, IntVar[] a) {
int n = a.length;
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) {
IntVar bi = solver.makeIsDifferentCstVar(a[i], 0);
IntVar bj = solver.makeIsDifferentCstVar(a[j], 0);
IntVar bij = solver.makeIsDifferentCstVar(a[i], a[j]);
solver.addConstraint(
solver.makeLessOrEqual(
solver.makeProd(bi, bj).var(), bij));
}
}
}
/**
*
* Implements a (decomposition) of global constraint
* alldifferent_except_0.
* See http://www.hakank.org/google_or_tools/circuit.py
*
*/
private static void solve() {
Solver solver = new Solver("AllDifferentExcept0");
//
// data
//
int n = 5;
//
// variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, n - 1, "x");
//
// constraints
//
alldifferent_except_0(solver, x);
// we also require at least 2 0's
IntVar[] z_tmp = solver.makeBoolVarArray(n, "z_tmp");
for(int i = 0; i < n; i++) {
solver.addConstraint(
solver.makeIsEqualCstCt(x[i], 0, z_tmp[i]));
}
IntVar z = solver.makeSum(z_tmp).var();
solver.addConstraint(solver.makeEquality(z, 2));
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("x: ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println(" z: " + z.value());
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
AllDifferentExcept0.solve();
}
}

View File

@@ -0,0 +1,108 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class AllInterval {
static {
System.loadLibrary("jniortools");
}
/**
*
* Implements the all interval problem.
* See http://www.hakank.org/google_or_tools/all_interval.py
*
*/
private static void solve(int n) {
Solver solver = new Solver("AllInterval");
//
// variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, n - 1, "x");
IntVar[] diffs = solver.makeIntVarArray(n - 1, 1, n - 1, "diffs");
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(x));
solver.addConstraint(solver.makeAllDifferent(diffs));
for(int k = 0; k < n - 1; k++) {
solver.addConstraint(
solver.makeEquality(diffs[k],
solver.makeAbs(solver.makeDifference(x[k + 1], x[k])).var()));
}
// symmetry breaking
solver.addConstraint(solver.makeLess(x[0], x[n - 1]));
solver.addConstraint(solver.makeLess(diffs[0], diffs[1]));
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("x : ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.print("\ndiffs: ");
for(int i = 0; i < n-1; i++) {
System.out.print(diffs[i].value() + " ");
}
System.out.println("\n");
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 12;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
AllInterval.solve(n);
}
}

View File

@@ -0,0 +1,341 @@
//
// Copyright 2012 Google
//
// 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.
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.RoutingSearchParameters;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;
// A pair class
class Pair<K, V> {
final K first;
final V second;
public static <K, V> Pair<K, V> of(K element0, V element1) {
return new Pair<K, V>(element0, element1);
}
public Pair(K element0, V element1) {
this.first = element0;
this.second = element1;
}
}
/**
* 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");
}
private static Logger logger =
Logger.getLogger(CapacitatedVehicleRoutingProblemWithTimeWindows.class.getName());
// Locations representing either an order location or a vehicle route
// start/end.
private List<Pair<Integer, Integer>> locations = new ArrayList();
// 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.
private List<Integer> orderPenalties = new ArrayList();
// 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.
private List<Integer> vehicleCostCoefficients = new ArrayList();
// Vehicle start and end indices. They have to be implemented as int[] due
// to the available SWIG-ed interface.
private int vehicleStarts[];
private int vehicleEnds[];
// Random number generator to produce data.
private final Random randomGenerator = new Random(0xBEEF);
/**
* Constructs a capacitated vehicle routing problem with time windows.
*/
private CapacitatedVehicleRoutingProblemWithTimeWindows() {}
/**
* 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) {
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;
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.
*
* @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),
*/
private void buildFleet(int numberOfVehicles,
int xMax, int yMax,
int startTime,
int endTime,
int capacity,
int costCoefficientMax) {
logger.info("Building fleet.");
vehicleCapacity = capacity;
vehicleStarts = new int[numberOfVehicles];
vehicleEnds = new int[numberOfVehicles];
for (int vehicle = 0; vehicle < numberOfVehicles; ++vehicle) {
vehicleStarts[vehicle] = locations.size();
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.
*/
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);
// 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);
}
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");
// Setting up vehicles
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));
}
// Setting up orders
for (int order = 0; order < numberOfOrders; ++order) {
model.cumulVar(model.nodeToIndex(order), "time").setRange(
orderTimeWindows.get(order).first,
orderTimeWindows.get(order).second);
int[] orders = {order};
model.addDisjunction(orders, orderPenalties.get(order));
}
// Solving
RoutingSearchParameters parameters =
RoutingSearchParameters.newBuilder()
.mergeFrom(RoutingModel.defaultSearchParameters())
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
.build();
logger.info("Search");
Assignment solution = model.solveWithParameters(parameters);
if (solution != null) {
String output = "Total cost: " + solution.objectiveValue() + "\n";
// Dropped orders
String dropped = "";
for (int order = 0; order < numberOfOrders; ++order) {
if (solution.value(model.nextVar(order)) == order) {
dropped += " " + order;
}
}
if (dropped.length() > 0) {
output += "Dropped orders:" + dropped + "\n";
}
// Routes
for (int vehicle = 0; vehicle < numberOfVehicles; ++vehicle) {
String route = "Vehicle " + vehicle + ": ";
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/!\\ ";
}
{
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 = model.cumulVar(order, "capacity");
IntVar time = model.cumulVar(order, "time");
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 !");
}
}
public static void main(String[] args) throws Exception {
CapacitatedVehicleRoutingProblemWithTimeWindows problem =
new 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 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 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.solve(orders, vehicles);
}
}

120
examples/java/Circuit.java Normal file
View File

@@ -0,0 +1,120 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class Circuit {
static {
System.loadLibrary("jniortools");
}
/**
* circuit(solver, x)
*
* A decomposition of the global constraint circuit, based
* on some observation of the orbits in an array.
*
* Note: The domain of x must be 0..n-1 (not 1..n)
* since Java is 0-based.
*/
public static void circuit(Solver solver, IntVar[] x) {
int n = x.length;
IntVar[] z = solver.makeIntVarArray(n, 0, n - 1, "z");
solver.addConstraint(solver.makeAllDifferent(x));
solver.addConstraint(solver.makeAllDifferent(z));
// put the orbit of x[0] in z[0..n-1]
solver.addConstraint(solver.makeEquality(z[0], x[0]));
for(int i = 1; i < n-1; i++) {
solver.addConstraint(
solver.makeEquality(z[i],
solver.makeElement(x, z[i-1]).var()));
}
// z may not be 0 for i < n-1
for(int i = 1; i < n - 1; i++) {
solver.addConstraint(solver.makeNonEquality(z[i], 0));
}
// when i = n-1 it must be 0
solver.addConstraint(solver.makeEquality(z[n - 1], 0));
}
/**
*
* Implements a (decomposition) of the global constraint circuit.
* See http://www.hakank.org/google_or_tools/circuit.py
*
*/
private static void solve(int n) {
Solver solver = new Solver("Circuit");
//
// variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, n - 1, "x");
//
// constraints
//
circuit(solver, x);
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 5;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
Circuit.solve(n);
}
}

View File

@@ -0,0 +1,123 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class CoinsGrid {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the Coins Grid problem.
* See http://www.hakank.org/google_or_tools/coins_grid.py
*
*/
private static void solve() {
Solver solver = new Solver("CoinsGrid");
//
// data
//
int n = 31;
int c = 14;
//
// variables
//
IntVar[][] x = new IntVar[n][n];
IntVar[] x_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
x[i][j] = solver.makeIntVar(0, 1, "x[" + i + "," + j + "]");
x_flat[i * n + j] = x[i][j];
}
}
//
// constraints
//
// sum row/columns == c
for(int i = 0; i < n; i++) {
IntVar[] row = new IntVar[n];
IntVar[] col = new IntVar[n];
for(int j = 0; j < n; j++) {
row[j] = x[i][j];
col[j] = x[j][i];
}
solver.addConstraint(solver.makeSumEquality(row, c));
solver.addConstraint(solver.makeSumEquality(col, c));
}
// quadratic horizonal distance
IntVar[] obj_tmp = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
obj_tmp[i * n + j] =
solver.makeProd(x[i][j],(i - j) * (i - j)).var();
}
}
IntVar obj_var = solver.makeSum(obj_tmp).var();
//
// objective
//
OptimizeVar obj = solver.makeMinimize(obj_var, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MAX_VALUE);
solver.newSearch(db, obj);
//
// output
//
while (solver.nextSolution()) {
System.out.println("obj_var: " + obj_var.value());
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(x[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
CoinsGrid.solve();
}
}

116
examples/java/CoinsGridMIP.java Executable file
View File

@@ -0,0 +1,116 @@
/*
* Copyright 2017 Darian Sastre darian.sastre@minimaxlabs.com
* 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.
*
* ************************************************************************
*
* Coins grid problem in Google CP Solver.
*
* Problem from
* Tony Hurlimann: "A coin puzzle - SVOR-contest 2007"
* http://www.svor.ch/competitions/competition2007/AsroContestSolution.pdf
* "
* In a quadratic grid (or a larger chessboard) with 31x31 cells, one should
* place coins in such a way that the following conditions are fulfilled:
* 1. In each row exactly 14 coins must be placed.
* 2. In each column exactly 14 coins must be placed.
* 3. The sum of the quadratic horizontal distance from the main diagonal
* of all cells containing a coin must be as small as possible.
* 4. In each cell at most one coin can be placed.
* The description says to place 14x31 = 434 coins on the chessboard each row
* containing 14 coins and each column also containing 14 coins.
* "
*
* This is a Java MIP version of
* http://www.hakank.org/google_or_tools/coins_grid_mip.py
*
* which is the MIP version of
* http://www.hakank.org/google_or_tools/coins_grid.py
*
* by Hakan Kjellerstrand (hakank@gmail.com).
*
* Java version by Darian Sastre (darian.sastre@minimaxlabs.com)
*/
import com.google.ortools.linearsolver.*;
public class CoinsGridMIP {
static {
System.loadLibrary("jniortools");
}
private static MPSolver createSolver (String solverType) {
return new MPSolver("MIPDiet",
MPSolver.OptimizationProblemType.valueOf(solverType));
}
private static void solve(String solverType) {
MPSolver solver = createSolver(solverType);
/** invariants */
int n = 31;
int c = 14;
/** variables */
MPVariable[][] x = new MPVariable[n][n];
for (int i = 0; i < n; i ++) {
x[i] = solver.makeBoolVarArray(n);
}
/** constraints & objective */
MPConstraint[] constraints = new MPConstraint[2 * n];
MPObjective obj = solver.objective();
for (int i = 0; i < n; i ++) {
constraints[2*i] = solver.makeConstraint(c, c);
constraints[2*i + 1] = solver.makeConstraint(c, c);
for (int j = 0; j < n; j ++) {
constraints[2*i].setCoefficient(x[i][j], 1);
constraints[2*i + 1].setCoefficient(x[j][i], 1);
obj.setCoefficient(x[i][j], (i-j) * (j-i));
}
}
solver.solve();
for (int i = 0; i < n; i ++) {
for (int j = 0; j < n; j ++) {
System.out.print((int) x[i][j].solutionValue() + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
try {
System.out.println("---- Integer programming example with SCIP (recommended) ----");
solve("SCIP_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
try {
System.out.println("---- Integer programming example with CBC ----");
solve("CBC_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
try {
System.out.println("---- Integer programming example with GLPK ----");
solve("GLPK_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
}
}

154
examples/java/ColoringMIP.java Executable file
View File

@@ -0,0 +1,154 @@
/*
* Copyright 2017 Darian Sastre darian.sastre@minimaxlabs.com
* 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.
*
* ************************************************************************
*
* This model was created by Hakan Kjellerstrand (hakank@gmail.com)
*
* Java version by Darian Sastre (darian.sastre@minimaxlabs.com)
*/
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
public class ColoringMIP {
public static class Edge {
public int a, b;
public Edge(int a, int b) {
this.a = a;
this.b = b;
}
}
static {
System.loadLibrary("jniortools");
}
private static MPSolver createSolver (String solverType) {
return new MPSolver("MIPDiet",
MPSolver.OptimizationProblemType.valueOf(solverType));
}
private static void solve(String solverType) {
MPSolver solver = createSolver(solverType);
double infinity = MPSolver.infinity();
/** invariants */
int noCols = 5; // variables number
int noNodes = 11; // constraints number
Edge[] edges = {
new Edge(1,2),
new Edge(1,4),
new Edge(1,7),
new Edge(1,9),
new Edge(2,3),
new Edge(2,6),
new Edge(2,8),
new Edge(3,5),
new Edge(3,7),
new Edge(3,10),
new Edge(4,5),
new Edge(4,6),
new Edge(4,10),
new Edge(5,8),
new Edge(5,9),
new Edge(6,11),
new Edge(7,11),
new Edge(8,11),
new Edge(9,11),
new Edge(10,11)
};
/** variables */
MPVariable[][] x = new MPVariable[noNodes][noCols];
for (Integer i = 0; i < noNodes; i ++) {
x[i] = solver.makeBoolVarArray(noCols);
}
MPVariable[] colUsed = solver.makeBoolVarArray(noCols);
MPObjective obj = solver.objective();
for (MPVariable objVar : colUsed) {
obj.setCoefficient(objVar, 1);
}
/** Bound each vertex to only one color */
MPConstraint[] constraints = new MPConstraint[noNodes];
for (int i = 0; i < noNodes; i ++) {
constraints[i] = solver.makeConstraint(1,1);
for (int j = 0; j < noCols; j ++) {
constraints[i].setCoefficient(x[i][j], 1);
}
}
/** Set adjacent nodes to have different colors */
MPConstraint[][] adjacencies = new MPConstraint[edges.length][noCols];
for (int i = 0; i < edges.length; i ++) {
for (int j = 0; j < noCols; j ++) {
adjacencies[i][j] = solver.makeConstraint(-infinity, 0);
adjacencies[i][j].setCoefficient(x[edges[i].a - 1][j], 1);
adjacencies[i][j].setCoefficient(x[edges[i].b - 1][j], 1);
adjacencies[i][j].setCoefficient(colUsed[j], -1);
}
}
/** Minimize by default */
final MPSolver.ResultStatus resultStatus = solver.solve();
/** printing */
if (resultStatus != MPSolver.ResultStatus.OPTIMAL) {
System.err.println("The problem does not have an optimal solution!");
return;
} else {
System.out.print("Colors used: ");
for (MPVariable var : colUsed) {
System.out.print((int) var.solutionValue() + " ");
}
System.out.println("\n");
for (int i = 0; i < noNodes; i ++) {
System.out.print("Col of vertex " + i + " : ");
for (int j = 0; j < noCols; j ++) {
if (x[i][j].solutionValue() > 0) {
System.out.println(j);
}
}
}
}
}
public static void main(String[] args) {
try {
System.out.println("---- Integer programming example with SCIP (recommended) ----");
solve("SCIP_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
try {
System.out.println("---- Integer programming example with CBC ----");
solve("CBC_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
try {
System.out.println("---- Integer programming example with GLPK ----");
solve("GLPK_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
}
}

View File

@@ -0,0 +1,132 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class CoveringOpl {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a set covering problem.
* See http://www.hakank.org/google_or_tools/covering_opl.py
*
*/
private static void solve() {
Solver solver = new Solver("CoveringOpl");
//
// data
//
int num_workers = 32;
int num_tasks = 15;
// Which worker is qualified for each task.
// Note: This is 1-based and will be made 0-base below.
int[][] qualified = {{ 1, 9, 19, 22, 25, 28, 31 },
{ 2, 12, 15, 19, 21, 23, 27, 29, 30, 31, 32 },
{ 3, 10, 19, 24, 26, 30, 32 },
{ 4, 21, 25, 28, 32 },
{ 5, 11, 16, 22, 23, 27, 31 },
{ 6, 20, 24, 26, 30, 32 },
{ 7, 12, 17, 25, 30, 31 } ,
{ 8, 17, 20, 22, 23 },
{ 9, 13, 14, 26, 29, 30, 31 },
{ 10, 21, 25, 31, 32 },
{ 14, 15, 18, 23, 24, 27, 30, 32 },
{ 18, 19, 22, 24, 26, 29, 31 },
{ 11, 20, 25, 28, 30, 32 },
{ 16, 19, 23, 31 },
{ 9, 18, 26, 28, 31, 32 }};
int[] cost = {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3,
3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9};
//
// variables
//
IntVar[] hire = solver.makeIntVarArray(num_workers, 0, 1, "workers");
IntVar total_cost = solver.makeScalProd(hire, cost).var();
//
// constraints
//
for(int j = 0; j < num_tasks; j++) {
// Sum the cost for hiring the qualified workers
// (also, make 0-base).
int len = qualified[j].length;
IntVar[] tmp = new IntVar[len];
for(int c = 0; c < len; c++) {
tmp[c] = hire[qualified[j][c] - 1];
}
IntVar b = solver.makeSum(tmp).var();
solver.addConstraint(solver.makeGreaterOrEqual(b, 1));
}
// Objective: Minimize total cost
OptimizeVar objective = solver.makeMinimize(total_cost, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(hire,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db, objective);
//
// output
//
while (solver.nextSolution()) {
System.out.println("Cost: " + total_cost.value());
System.out.print("Hire: ");
for(int i = 0; i < num_workers; i++) {
if (hire[i].value() == 1) {
System.out.print(i + " ");
}
}
System.out.println("\n");
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
CoveringOpl.solve();
}
}

View File

@@ -0,0 +1,182 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class Crossword {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solving a simple crossword.
* See http://www.hakank.org/google_or_tools/crossword2.py
*
*/
private static void solve() {
Solver solver = new Solver("Crossword");
//
// data
//
String[] alpha = {"_","a","b","c","d","e","f",
"g","h","i","j","k","l","m",
"n","o","p","q","r","s","t",
"u","v","w","x","y","z"};
int a=1; int b=2; int c=3; int d=4; int e=5; int f=6;
int g=7; int h=8; int i=9; int j=10; int k=11; int l=12;
int m=13; int n=14; int o=15; int p=16; int q=17; int r=18;
int s=19; int t=20; int u=21; int v=22; int w=23; int x=24;
int y=25; int z=26;
int num_words = 15;
int word_len = 5;
int[][] AA = {{h, o, s, e, s}, // HOSES
{l, a, s, e, r}, // LASER
{s, a, i, l, s}, // SAILS
{s, h, e, e, t}, // SHEET
{s, t, e, e, r}, // STEER
{h, e, e, l, 0}, // HEEL
{h, i, k, e, 0}, // HIKE
{k, e, e, l, 0}, // KEEL
{k, n, o, t, 0}, // KNOT
{l, i, n, e, 0}, // LINE
{a, f, t, 0, 0}, // AFT
{a, l, e, 0, 0}, // ALE
{e, e, l, 0, 0}, // EEL
{l, e, e, 0, 0}, // LEE
{t, i, e, 0, 0}}; // TIE
int num_overlapping = 12;
int[][] overlapping = {{0, 2, 1, 0}, // s
{0, 4, 2, 0}, // s
{3, 1, 1, 2}, // i
{3, 2, 4, 0}, // k
{3, 3, 2, 2}, // e
{6, 0, 1, 3}, // l
{6, 1, 4, 1}, // e
{6, 2, 2, 3}, // e
{7, 0, 5, 1}, // l
{7, 2, 1, 4}, // s
{7, 3, 4, 2}, // e
{7, 4, 2, 4}}; // r
int N = 8;
//
// variables
//
IntVar[][] A = new IntVar[num_words][word_len];
IntVar[] A_flat = new IntVar[num_words * word_len];
// for labeling on A and E
IntVar[] all = new IntVar[(num_words * word_len) + N];
for(int I = 0; I < num_words; I++) {
for(int J = 0; J < word_len; J++) {
A[I][J] = solver.makeIntVar(0, 26, "A[" + I + "," + J + "]");
A_flat[I * word_len + J] = A[I][J];
all[I * word_len + J] = A[I][J];
}
}
IntVar[] E = solver.makeIntVarArray(N, 0, num_words, "E");
for(int I = 0; I < N; I++) {
all[num_words * word_len + I] = E[I];
}
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(E));
for(int I = 0; I < num_words; I++) {
for(int J = 0; J < word_len; J++) {
solver.addConstraint(solver.makeEquality(A[I][J], AA[I][J]));
}
}
for(int I = 0; I < num_overlapping; I++) {
solver.addConstraint(
solver.makeEquality(
solver.makeElement(A_flat,
solver.makeSum(
solver.makeProd(
E[overlapping[I][0]], word_len).var(),
overlapping[I][1]).var()).var(),
solver.makeElement(A_flat,
solver.makeSum(
solver.makeProd(
E[overlapping[I][2]], word_len).var(),
overlapping[I][3]).var()).var() ));
}
//
// search
//
DecisionBuilder db = solver.makePhase(all,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.println("E:");
for(int ee = 0; ee < N; ee++) {
int e_val = (int)E[ee].value();
System.out.print(ee + ": (" + e_val + ") ");
for(int ii = 0; ii < word_len; ii++) {
System.out.print(alpha[(int)A[ee][ii].value()]);
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Crossword.solve();
}
}

228
examples/java/DeBruijn.java Normal file
View File

@@ -0,0 +1,228 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class DeBruijn {
static {
System.loadLibrary("jniortools");
}
/**
*
* toNum(solver, a, num, base)
*
* channelling between the array a and the number num
*
*/
private static void toNum(Solver solver, IntVar[] a, IntVar num, int base) {
int len = a.length;
IntVar[] tmp = new IntVar[len];
for(int i = 0; i < len; i++) {
tmp[i] = solver.makeProd(a[i], (int)Math.pow(base,(len-i-1))).var();
}
solver.addConstraint(
solver.makeEquality(solver.makeSum(tmp).var(), num));
}
/**
*
* Implements "arbitrary" de Bruijn sequences.
* See http://www.hakank.org/google_or_tools/debruijn_binary.py
*
*/
private static void solve(int base, int n, int m) {
Solver solver = new Solver("DeBruijn");
System.out.println("base: " + base + " n: " + n + " m: " + m);
// Ensure that the number of each digit in bin_code is
// the same. Nice feature, but it can slow things down...
boolean check_same_gcc = false; // true;
//
// variables
//
IntVar[] x =
solver.makeIntVarArray(m, 0, (int)Math.pow(base, n) - 1, "x");
IntVar[][] binary = new IntVar[m][n];
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
binary[i][j] =
solver.makeIntVar(0, base - 1, "binary[" + i + "," + j + "]");
}
}
// this is the de Bruijn sequence
IntVar[] bin_code =
solver.makeIntVarArray(m, 0, base - 1, "bin_code");
// occurences of each number in bin_code
IntVar[] gcc = solver.makeIntVarArray(base, 0, m, "gcc");
// for the branching
IntVar[] all = new IntVar[2 * m + base];
for(int i = 0; i < m; i++) {
all[i] = x[i];
all[m + i] = bin_code[i];
}
for(int i = 0; i < base; i++) {
all[2 * m + i] = gcc[i];
}
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(x));
// converts x <-> binary
for(int i = 0; i < m; i++) {
IntVar[] t = new IntVar[n];
for(int j = 0; j < n; j++) {
t[j] = binary[i][j];
}
toNum(solver, t, x[i], base);
}
// the de Bruijn condition:
// the first elements in binary[i] is the same as the last
// elements in binary[i-1]
for(int i = 1; i < m; i++) {
for(int j = 1; j < n; j++) {
solver.addConstraint(
solver.makeEquality(binary[i - 1][j], binary[i][j - 1]));
}
}
// ... and around the corner
for(int j = 1; j < n; j++) {
solver.addConstraint(
solver.makeEquality(binary[m - 1][j], binary[0][j - 1]));
}
// converts binary -> bin_code (de Bruijn sequence)
for(int i = 0; i < m; i++) {
solver.addConstraint(solver.makeEquality(bin_code[i], binary[i][0]));
}
// extra: ensure that all the numbers in the de Bruijn sequence
// (bin_code) has the same occurrences (if check_same_gcc is True
// and mathematically possible)
solver.addConstraint(solver.makeDistribute(bin_code, gcc));
if (check_same_gcc && m % base == 0) {
for(int i = 1; i < base; i++) {
solver.addConstraint(solver.makeEquality(gcc[i], gcc[i - 1]));
}
}
// symmetry breaking:
// the minimum value of x should be first
solver.addConstraint(solver.makeEquality(x[0], solver.makeMin(x).var()));
//
// search
//
DecisionBuilder db = solver.makePhase(all,
solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("x: ");
for(int i = 0; i < m; i++) {
System.out.print(x[i].value() + " ");
}
System.out.print("\nde Bruijn sequence:");
for(int i = 0; i < m; i++) {
System.out.print(bin_code[i].value() + " ");
}
System.out.print("\ngcc: ");
for(int i = 0; i < base; i++) {
System.out.print(gcc[i].value() + " ");
}
System.out.println("\n");
// for debugging etc: show the full binary table
/*
System.out.println("binary:");
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
System.out.print(binary[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
*/
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int base = 2;
int n = 3;
int m = 8;
if (args.length > 0) {
base = Integer.parseInt(args[0]);
}
if (args.length > 1) {
n = Integer.parseInt(args[1]);
m = (int)Math.pow(base, n);
}
if (args.length > 2) {
int m_max = (int) Math.pow(base, n);
m = Integer.parseInt(args[2]);
if (m > m_max) {
System.out.println("m(" + m + ") is too large. Set m to " +
m_max + ".");
m = m_max;
}
}
DeBruijn.solve(base, n, m);
}
}

110
examples/java/Diet.java Normal file
View File

@@ -0,0 +1,110 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class Diet {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the Diet problem.
* See http://www.hakank.org/google_or_tools/diet1.py
*
*/
private static void solve() {
Solver solver = new Solver("Diet");
int n = 4;
int[] price = { 50, 20, 30, 80}; // in cents
// requirements for each nutrition type
int[] limits = {500, 6, 10, 8};
// nutritions for each product
int[] calories = {400, 200, 150, 500};
int[] chocolate = {3, 2, 0, 0};
int[] sugar = {2, 2, 4, 4};
int[] fat = {2, 4, 1, 5};
//
// Variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, 100, "x");
IntVar cost = solver.makeScalProd(x, price).var();
//
// Constraints
//
solver.addConstraint(
solver.makeScalProdGreaterOrEqual(x, calories, limits[0]));
solver.addConstraint(
solver.makeScalProdGreaterOrEqual(x,chocolate, limits[1]));
solver.addConstraint(
solver.makeScalProdGreaterOrEqual(x, sugar, limits[2]));
solver.addConstraint(
solver.makeScalProdGreaterOrEqual(x, fat, limits[3]));
//
// Objective
//
OptimizeVar obj = solver.makeMinimize(cost, 1);
//
// Search
//
DecisionBuilder db = solver.makePhase(x,
solver.CHOOSE_PATH,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db, obj);
while (solver.nextSolution()) {
System.out.println("cost: " + cost.value());
System.out.print("x: ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Diet.solve();
}
}

92
examples/java/DietMIP.java Executable file
View File

@@ -0,0 +1,92 @@
/*
* Copyright 2017 Darian Sastre darian.sastre@minimaxlabs.com
* 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.
*
* ************************************************************************
*
* This model was created by Hakan Kjellerstrand (hakank@gmail.com)
*/
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
public class DietMIP {
static {
System.loadLibrary("jniortools");
}
private static MPSolver createSolver(String solverType) {
try {
return new MPSolver("MIPDiet", MPSolver.OptimizationProblemType.valueOf(solverType));
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
return null;
}
}
private static void solve(String solverType) {
MPSolver solver = createSolver(solverType);
double infinity = MPSolver.infinity();
int n = 4; // variables number
int m = 4; // constraints number
int[] price = { 50, 20, 30, 80 };
int[] limits = { 500, 6, 10, 8 };
int[] calories = { 400, 200, 150, 500 };
int[] chocolate = { 3, 2, 0, 0 };
int[] sugar = { 2, 2, 4, 4 };
int[] fat = { 2, 4, 1, 5 };
int[][] values = { calories, chocolate, sugar, fat };
MPVariable[] x = solver.makeIntVarArray(n, 0, 100, "x");
MPObjective objective = solver.objective();
MPConstraint[] targets = new MPConstraint[4];
for (int i = 0; i < n; i++) {
objective.setCoefficient(x[i], price[i]);
// constraints
targets[i] = solver.makeConstraint(limits[i], infinity);
for (int j = 0; j < m; j++) {
targets[i].setCoefficient(x[j], values[i][j]);
}
}
final MPSolver.ResultStatus resultStatus = solver.solve();
/** printing */
if (resultStatus != MPSolver.ResultStatus.OPTIMAL) {
System.err.println("The problem does not have an optimal solution!");
return;
} else {
System.out.println("Optimal objective value = " + solver.objective().value());
System.out.print("Item quantities: ");
System.out.print((int) x[0].solutionValue() + " ");
System.out.print((int) x[1].solutionValue() + " ");
System.out.print((int) x[2].solutionValue() + " ");
System.out.print((int) x[3].solutionValue() + " ");
}
}
public static void main(String[] args) throws Exception {
solve("CBC_MIXED_INTEGER_PROGRAMMING");
}
}

View File

@@ -0,0 +1,216 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class DivisibleBy9Through1 {
static {
System.loadLibrary("jniortools");
}
/**
*
* A simple propagator for modulo constraint.
*
* This implementation is based on the ECLiPSe version
* mentioned in "A Modulo propagator for ECLiPSE"
* http://www.hakank.org/constraint_programming_blog/2010/05/a_modulo_propagator_for_eclips.html
* The ECLiPSe Prolog source code:
* http://www.hakank.org/eclipse/modulo_propagator.ecl
*
*/
public static void my_mod(Solver solver, IntVar x, IntVar y, IntVar r) {
long lbx = x.min();
long ubx = x.max();
long ubx_neg = -ubx;
long lbx_neg = -lbx;
int min_x = (int)Math.min(lbx, ubx_neg);
int max_x = (int)Math.max(ubx, lbx_neg);
IntVar d = solver.makeIntVar(min_x, max_x, "d");
// r >= 0
solver.addConstraint(solver.makeGreaterOrEqual(r,0));
// x*r >= 0
solver.addConstraint(
solver.makeGreaterOrEqual(
solver.makeProd(x,r).var(), 0));
// -abs(y) < r
solver.addConstraint(
solver.makeLess(
solver.makeOpposite(solver.makeAbs(y).var()).var(), r));
// r < abs(y)
solver.addConstraint(
solver.makeLess(r,
solver.makeAbs(y).var().var()));
// min_x <= d, i.e. d > min_x
solver.addConstraint(solver.makeGreater(d, min_x));
// d <= max_x
solver.addConstraint(solver.makeLessOrEqual(d, max_x));
// x == y*d+r
solver.addConstraint(solver.makeEquality(x,
solver.makeSum(
solver.makeProd(y,d).var(),r).var()));
}
/**
*
* toNum(solver, a, num, base)
*
* channelling between the array a and the number num
*
*/
private static void toNum(Solver solver, IntVar[] a, IntVar num, int base) {
int len = a.length;
IntVar[] tmp = new IntVar[len];
for(int i = 0; i < len; i++) {
tmp[i] = solver.makeProd(a[i], (int)Math.pow(base,(len-i-1))).var();
}
solver.addConstraint(
solver.makeEquality(solver.makeSum(tmp).var(), num));
}
/**
*
* Solves the divisible by 9 through 1 problem.
* See http://www.hakank.org/google_or_tools/divisible_by_9_through_1.py
*
*/
private static void solve(int base) {
Solver solver = new Solver("DivisibleBy9Through1");
//
// data
//
int m = (int)Math.pow(base,(base-1)) - 1;
int n = base - 1;
String[] digits_str = {"_","0","1","2","3","4","5","6","7","8","9"};
System.out.println("base: " + base);
//
// variables
//
// digits
IntVar[] x = solver.makeIntVarArray(n, 1, base - 1, "x");
// the numbers. t[0] contains the answe
IntVar[] t = solver.makeIntVarArray(n, 0, m, "t");
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(x));
// Ensure the divisibility of base .. 1
IntVar zero = solver.makeIntConst(0);
for(int i = 0; i < n; i++) {
int mm = base - i - 1;
IntVar[] tt = new IntVar[mm];
for(int j = 0; j < mm; j++) {
tt[j] = x[j];
}
toNum(solver, tt, t[i], base);
IntVar mm_const = solver.makeIntConst(mm);
my_mod(solver, t[i], mm_const, zero);
}
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("x: ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println("\nt: ");
for(int i = 0; i < n; i++) {
System.out.print(t[i].value() + " ");
}
System.out.println();
if (base != 10) {
System.out.print("Number base 10: " + t[0].value());
System.out.print(" Base " + base + ": ");
for(int i = 0; i < n; i++) {
System.out.print(digits_str[(int)x[i].value() + 1]);
}
System.out.println("\n");
}
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int base = 10;
if (args.length > 0) {
int new_base = Integer.parseInt(args[0]);
if (new_base > 10) {
// Note: The next valid base after 10 is 14 and
// the number 559922224824157, which is too large in this model.
System.out.println("Sorry, max allowed base is 10. Setting base to 10.");
} else if (new_base < 2) {
System.out.println("Sorry, min allowed base is 2. Setting base to 2.");
base = 2;
} else {
base = new_base;
}
}
DivisibleBy9Through1.solve(base);
}
}

View File

@@ -0,0 +1,94 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.graph.MaxFlow;
import com.google.ortools.graph.MinCostFlow;
/**
* Sample showing how to model using the flow solver.
*
*/
public class FlowExample {
static {
System.loadLibrary("jniortools");
}
private static void solveMinCostFlow() {
System.out.println("Min Cost Flow Problem - Simple interface");
final int numSources = 4;
final int numTargets = 4;
final int[][] costs = {{90, 75, 75, 80},
{35, 85, 55, 65},
{125, 95, 90, 105},
{45, 110, 95, 115}};
final int expectedCost = 275;
MinCostFlow minCostFlow = new MinCostFlow();
for (int source = 0; source < numSources; ++source) {
for (int target = 0; target < numTargets; ++target) {
minCostFlow.addArcWithCapacityAndUnitCost(
source, numSources + target, 1, costs[source][target]);
}
}
for (int node = 0; node < numSources; ++node) {
minCostFlow.setNodeSupply(node, 1);
minCostFlow.setNodeSupply(numSources + node, -1);
}
if (minCostFlow.solve() == MinCostFlow.Status.OPTIMAL) {
final long totalFlowCost = minCostFlow.getOptimalCost();
System.out.println("total flow = " + totalFlowCost + "/" + expectedCost);
for (int i = 0; i < minCostFlow.getNumArcs(); ++i) {
if (minCostFlow.getFlow(i) > 0) {
System.out.println("From source " + minCostFlow.getTail(i)
+ " to target " + minCostFlow.getHead(i) + ": cost "
+ minCostFlow.getUnitCost(i));
}
}
} else {
System.out.println("No solution found");
}
}
private static void solveMaxFlow() {
System.out.println("Max Flow Problem - Simple interface");
final int[] tails = {0, 0, 0, 0, 1, 2, 3, 3, 4};
final int[] heads = {1, 2, 3, 4, 3, 4, 4, 5, 5};
final int[] capacities = {5, 8, 5, 3, 4, 5, 6, 6, 4};
final int expectedTotalFlow = 10;
MaxFlow maxFlow = new MaxFlow();
for (int i = 0; i < tails.length; ++i) {
maxFlow.addArcWithCapacity(tails[i], heads[i], capacities[i]);
}
if (maxFlow.solve(0, 5) == MaxFlow.Status.OPTIMAL) {
System.out.println("Total flow " + maxFlow.getOptimalFlow() + "/" + expectedTotalFlow);
for (int i = 0; i < maxFlow.getNumArcs(); ++i) {
System.out.println("From source " + maxFlow.getTail(i)
+ " to target " + maxFlow.getHead(i) + ": "
+ maxFlow.getFlow(i) + " / " + maxFlow.getCapacity(i));
}
// TODO(user): Our SWIG configuration does not currently handle these
// functions correctly in Java:
// maxFlow.getSourceSideMinCut(...);
// maxFlow.getSinkSideMinCut(...);
} else {
System.out.println("There was an issue with the input.");
}
}
public static void main(String[] args) throws Exception {
FlowExample.solveMinCostFlow();
FlowExample.solveMaxFlow();
}
}

View File

@@ -0,0 +1,102 @@
/**
* Copyright (c) 1999-2011, Ecole des Mines de Nantes
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Ecole des Mines de Nantes nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntExpr;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.OptimizeVar;
import com.google.ortools.constraintsolver.SearchMonitor;
import com.google.ortools.constraintsolver.SolutionCollector;
import com.google.ortools.constraintsolver.Solver;
/**
* Golomb ruler problem
* <br/>
*
* @author Charles Prud'homme
* @since 17/03/11
*/
public class GolombRuler {
static {
System.loadLibrary("jniortools");
}
/**
* Golomb Ruler Problem.
*/
private static void solve(int m) {
Solver solver = new Solver("GR " + m);
IntVar[] ticks =
solver.makeIntVarArray(m,
0,
((m < 31) ? (1 << (m + 1)) - 1 : 9999),
"ticks");
solver.addConstraint(solver.makeEquality(ticks[0], 0));
for (int i = 0; i < ticks.length - 1; i++) {
solver.addConstraint(solver.makeLess(ticks[i], ticks[i + 1]));
}
IntVar[] diff = new IntVar[(m * m - m) / 2];
for (int k = 0, i = 0; i < m - 1; i++) {
for (int j = i + 1; j < m; j++, k++) {
diff[k] = solver.makeDifference(ticks[j], ticks[i]).var();
solver.addConstraint(
solver.makeGreaterOrEqual(diff[k], (j - i) * (j - i + 1) / 2));
}
}
solver.addConstraint(solver.makeAllDifferent(diff));
// break symetries
if (m > 2) {
solver.addConstraint(solver.makeLess(diff[0], diff[diff.length - 1]));
}
OptimizeVar opt = solver.makeMinimize(ticks[m - 1], 1);
DecisionBuilder db = solver.makePhase(ticks,
solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
solver.ASSIGN_MIN_VALUE);
SolutionCollector collector = solver.makeLastSolutionCollector();
collector.add(ticks);
collector.addObjective(ticks[m - 1]);
SearchMonitor log = solver.makeSearchLog(10000, opt);
solver.solve(db, opt, log, collector);
System.out.println("Optimal solution = " + collector.objectiveValue(0));
for (int i = 0; i < m; ++i) {
System.out.print("[" + collector.value(0, ticks[i]) + "] ");
}
System.out.println();
}
public static void main(String[] args) throws Exception {
GolombRuler.solve(8);
}
}

View File

@@ -0,0 +1,96 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
/**
* Integer programming example that shows how to use the API.
*
*/
public class IntegerProgramming {
static { System.loadLibrary("jniortools"); }
private static MPSolver createSolver (String solverType) {
try {
return new MPSolver("IntegerProgrammingExample",
MPSolver.OptimizationProblemType.valueOf(solverType));
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
return null;
}
}
private static void runIntegerProgrammingExample(String solverType) {
MPSolver solver = createSolver(solverType);
if (solver == null) {
System.out.println("Could not create solver " + solverType);
return;
}
double infinity = MPSolver.infinity();
// x1 and x2 are integer non-negative variables.
MPVariable x1 = solver.makeIntVar(0.0, infinity, "x1");
MPVariable x2 = solver.makeIntVar(0.0, infinity, "x2");
// Minimize x1 + 2 * x2.
MPObjective objective = solver.objective();
objective.setCoefficient(x1, 1);
objective.setCoefficient(x2, 2);
// 2 * x2 + 3 * x1 >= 17.
MPConstraint ct = solver.makeConstraint(17, infinity);
ct.setCoefficient(x1, 3);
ct.setCoefficient(x2, 2);
final MPSolver.ResultStatus resultStatus = solver.solve();
// Check that the problem has an optimal solution.
if (resultStatus != MPSolver.ResultStatus.OPTIMAL) {
System.err.println("The problem does not have an optimal solution!");
return;
}
// Verify that the solution satisfies all constraints (when using solvers
// others than GLOP_LINEAR_PROGRAMMING, this is highly recommended!).
if (!solver.verifySolution(/*tolerance=*/1e-7, /*logErrors=*/true)) {
System.err.println("The solution returned by the solver violated the"
+ " problem constraints by at least 1e-7");
return;
}
System.out.println("Problem solved in " + solver.wallTime() + " milliseconds");
// The objective value of the solution.
System.out.println("Optimal objective value = " + solver.objective().value());
// The value of each variable in the solution.
System.out.println("x1 = " + x1.solutionValue());
System.out.println("x2 = " + x2.solutionValue());
System.out.println("Advanced usage:");
System.out.println("Problem solved in " + solver.nodes() + " branch-and-bound nodes");
}
public static void main(String[] args) throws Exception {
System.out.println("---- Integer programming example with SCIP (recommended) ----");
runIntegerProgrammingExample("SCIP_MIXED_INTEGER_PROGRAMMING");
System.out.println("---- Integer programming example with CBC ----");
runIntegerProgrammingExample("CBC_MIXED_INTEGER_PROGRAMMING");
System.out.println("---- Integer programming example with GLPK ----");
runIntegerProgrammingExample("GLPK_MIXED_INTEGER_PROGRAMMING");
}
}

View File

@@ -0,0 +1,39 @@
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
public class Issue173 {
static {
System.loadLibrary("jniortools");
}
public static void breakit() {
for (int i = 0; i < 50000; i++) {
solveLP();
}
}
private static void solveLP() {
MPSolver solver = new MPSolver(
"test",
MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING);
MPVariable x = solver.makeNumVar(Double.NEGATIVE_INFINITY,
Double.POSITIVE_INFINITY, "x");
final MPObjective objective = solver.objective();
objective.setMaximization();
objective.setCoefficient(x, 1);
MPConstraint constraint = solver.makeConstraint(0, 5);
constraint.setCoefficient(x, 1);
solver.solve();
}
public static void main(String[] args) throws Exception {
breakit();
}
}

View File

@@ -0,0 +1,57 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.algorithms.KnapsackSolver;
/**
* Sample showing how to model using the knapsack solver.
*
*/
public class Knapsack {
static { System.loadLibrary("jniortools"); }
private static void solve() {
KnapsackSolver solver = new KnapsackSolver(
KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "test");
final long[] profits = {360, 83, 59, 130, 431, 67, 230, 52, 93,
125, 670, 892, 600, 38, 48, 147, 78, 256,
63, 17, 120, 164, 432, 35, 92, 110, 22,
42, 50, 323, 514, 28, 87, 73, 78, 15,
26, 78, 210, 36, 85, 189, 274, 43, 33,
10, 19, 389, 276, 312};
final long[][] weights = {{7, 0, 30, 22, 80, 94, 11, 81, 70,
64, 59, 18, 0, 36, 3, 8, 15, 42,
9, 0, 42, 47, 52, 32, 26, 48, 55,
6, 29, 84, 2, 4, 18, 56, 7, 29,
93, 44, 71, 3, 86, 66, 31, 65, 0,
79, 20, 65, 52, 13}};
final long[] capacities = {850};
final long optimalProfit = 7534;
System.out.println("Solving knapsack with " + profits.length + " items");
solver.init(profits, weights, capacities);
final long computedProfit = solver.solve();
System.out.println("Optimal_Profit = " + computedProfit + "/" +
optimalProfit);
}
public static void main(String[] args) throws Exception {
Knapsack.solve();
}
}

98
examples/java/KnapsackMIP.java Executable file
View File

@@ -0,0 +1,98 @@
/*
* Copyright 2017 Darian Sastre darian.sastre@minimaxlabs.com
* 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.
*
* ************************************************************************
*
* Each knapsack perceives a different weight for each item. Item values are
* the same across knapsacks. Optimizing constrains the count of each item such
* that all knapsack capacities are respected, and their values are maximized.
*
* This model was created by Hakan Kjellerstrand (hakank@gmail.com)
*/
import com.google.ortools.linearsolver.*;
public class KnapsackMIP {
static {
System.loadLibrary("jniortools");
}
private static MPSolver createSolver (String solverType) {
try {
return new MPSolver("MIPDiet",
MPSolver.OptimizationProblemType.valueOf(solverType));
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
return null;
}
}
private static void solve(String solverType) {
MPSolver solver = createSolver(solverType);
/** variables */
int itemCount = 12;
int capacityCount = 7;
int[] capacity = {18209, 7692, 1333, 924, 26638, 61188, 13360};
int[] value = {96, 76, 56, 11, 86, 10, 66, 86, 83, 12, 9, 81};
int[][] weights = {
{19, 1, 10, 1, 1, 14, 152, 11, 1, 1, 1, 1},
{0, 4, 53, 0, 0, 80, 0, 4, 5, 0, 0, 0},
{4, 660, 3, 0, 30, 0, 3, 0, 4, 90, 0, 0},
{7, 0, 18, 6, 770, 330, 7, 0, 0, 6, 0, 0},
{0, 20, 0, 4, 52, 3, 0, 0, 0, 5, 4, 0},
{0, 0, 40, 70, 4, 63, 0, 0, 60, 0, 4, 0},
{0, 32, 0, 0, 0, 5, 0, 3, 0, 660, 0, 9}
};
int maxCapacity = -1;
for (int c : capacity) {
if (c > maxCapacity) {
maxCapacity = c;
}
}
MPVariable[] taken = solver.makeIntVarArray(itemCount, 0, maxCapacity);
/** constraints */
MPConstraint constraints[] = new MPConstraint[capacityCount];
for (int i = 0; i < capacityCount; i ++) {
constraints[i] = solver.makeConstraint(0, capacity[i]);
for (int j = 0; j < itemCount; j ++) {
constraints[i].setCoefficient(taken[j], weights[i][j]);
}
}
/** objective */
MPObjective obj = solver.objective();
obj.setMaximization();
for (int i = 0; i < itemCount; i ++) {
obj.setCoefficient(taken[i], value[i]);
}
solver.solve();
/** printing */
System.out.println("Max cost: " + obj.value());
System.out.print("Item quantities: ");
for (MPVariable var : taken) {
System.out.print((int) var.solutionValue() + " ");
}
}
public static void main(String[] args) {
solve("CBC_MIXED_INTEGER_PROGRAMMING");
}
}

View File

@@ -0,0 +1,105 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.*;
public class LeastDiff {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the Least Diff problem.
* See http://www.hakank.org/google_or_tools/least_diff.py
*
*/
private static void solve() {
final int base = 10;
Solver solver = new Solver("LeastDiff");
//
// Variables
//
IntVar a = solver.makeIntVar(0, base - 1, "a");
IntVar b = solver.makeIntVar(0, base - 1, "b");
IntVar c = solver.makeIntVar(0, base - 1, "c");
IntVar d = solver.makeIntVar(0, base - 1, "d");
IntVar e = solver.makeIntVar(0, base - 1, "e");
IntVar f = solver.makeIntVar(0, base - 1, "f");
IntVar g = solver.makeIntVar(0, base - 1, "g");
IntVar h = solver.makeIntVar(0, base - 1, "h");
IntVar i = solver.makeIntVar(0, base - 1, "i");
IntVar j = solver.makeIntVar(0, base - 1, "j");
IntVar[] all = {a,b,c,d,e,f,g,h,i,j};
//
// Constraints
//
int[] coeffs = {10000, 1000, 100, 10, 1};
IntVar x = solver.makeScalProd(new IntVar[]{a,b,c,d,e}, coeffs).var();
x.setName("x");
IntVar y = solver.makeScalProd(new IntVar[]{f,g,h,i,j}, coeffs).var();
y.setName("y");
// a > 0
solver.addConstraint(solver.makeGreater(a, 0));
// f > 0
solver.addConstraint(solver.makeGreater(f, 0));
// diff = x - y
IntVar diff = solver.makeDifference(x, y).var();
diff.setName("diff");
solver.addConstraint(solver.makeAllDifferent(all));
//
// Objective
//
OptimizeVar obj = solver.makeMinimize(diff, 1);
//
// Search
//
DecisionBuilder db = solver.makePhase(all,
solver.CHOOSE_PATH,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db, obj);
while (solver.nextSolution()) {
System.out.println("" + x.value() + " - " +
y.value() + " = " + diff.value());
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
LeastDiff.solve();
}
}

View File

@@ -0,0 +1,61 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.graph.LinearSumAssignment;
/**
* Test assignment on a 4x4 matrix. Example taken from
* http://www.ee.oulu.fi/~mpa/matreng/eem1_2-1.htm with kCost[0][1]
* modified so the optimum solution is unique.
*
*/
public class LinearAssignmentAPI {
static {
System.loadLibrary("jniortools");
}
private static void runAssignmentOn4x4Matrix() {
final int numSources = 4;
final int numTargets = 4;
final int[][] cost = {{ 90, 76, 75, 80 },
{ 35, 85, 55, 65 },
{ 125, 95, 90, 105 },
{ 45, 110, 95, 115 }};
final int expectedCost = cost[0][3] + cost[1][2] + cost[2][1] + cost[3][0];
LinearSumAssignment assignment = new LinearSumAssignment();
for (int source = 0; source < numSources; ++source) {
for (int target = 0; target < numTargets; ++target) {
assignment.addArcWithCost(source, target, cost[source][target]);
}
}
if (assignment.solve() == LinearSumAssignment.Status.OPTIMAL) {
System.out.println("Total cost = " + assignment.getOptimalCost() + "/" + expectedCost);
for (int node = 0; node < assignment.getNumNodes(); ++node) {
System.out.println("Left node " + node
+ " assigned to right node " + assignment.getRightMate(node)
+ " with cost " + assignment.getAssignmentCost(node));
}
} else {
System.out.println("No solution found.");
}
}
public static void main(String[] args) throws Exception {
LinearAssignmentAPI.runAssignmentOn4x4Matrix();
}
}

View File

@@ -0,0 +1,131 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
/**
* Linear programming example that shows how to use the API.
*
*/
public class LinearProgramming {
static { System.loadLibrary("jniortools"); }
private static MPSolver createSolver (String solverType) {
try {
return new MPSolver("LinearProgrammingExample",
MPSolver.OptimizationProblemType.valueOf(solverType));
} catch (java.lang.IllegalArgumentException e) {
return null;
}
}
private static void runLinearProgrammingExample(String solverType,
boolean printModel) {
MPSolver solver = createSolver(solverType);
if (solver == null) {
System.out.println("Could not create solver " + solverType);
return;
}
double infinity = MPSolver.infinity();
// x1, x2 and x3 are continuous non-negative variables.
MPVariable x1 = solver.makeNumVar(0.0, infinity, "x1");
MPVariable x2 = solver.makeNumVar(0.0, infinity, "x2");
MPVariable x3 = solver.makeNumVar(0.0, infinity, "x3");
// Maximize 10 * x1 + 6 * x2 + 4 * x3.
MPObjective objective = solver.objective();
objective.setCoefficient(x1, 10);
objective.setCoefficient(x2, 6);
objective.setCoefficient(x3, 4);
objective.setMaximization();
// x1 + x2 + x3 <= 100.
MPConstraint c0 = solver.makeConstraint(-infinity, 100.0);
c0.setCoefficient(x1, 1);
c0.setCoefficient(x2, 1);
c0.setCoefficient(x3, 1);
// 10 * x1 + 4 * x2 + 5 * x3 <= 600.
MPConstraint c1 = solver.makeConstraint(-infinity, 600.0);
c1.setCoefficient(x1, 10);
c1.setCoefficient(x2, 4);
c1.setCoefficient(x3, 5);
// 2 * x1 + 2 * x2 + 6 * x3 <= 300.
MPConstraint c2 = solver.makeConstraint(-infinity, 300.0);
c2.setCoefficient(x1, 2);
c2.setCoefficient(x2, 2);
c2.setCoefficient(x3, 6);
System.out.println("Number of variables = " + solver.numVariables());
System.out.println("Number of constraints = " + solver.numConstraints());
if (printModel) {
String model = solver.exportModelAsLpFormat(false);
System.out.println(model);
}
final MPSolver.ResultStatus resultStatus = solver.solve();
// Check that the problem has an optimal solution.
if (resultStatus != MPSolver.ResultStatus.OPTIMAL) {
System.err.println("The problem does not have an optimal solution!");
return;
}
// Verify that the solution satisfies all constraints (when using solvers
// others than GLOP_LINEAR_PROGRAMMING, this is highly recommended!).
if (!solver.verifySolution(/*tolerance=*/1e-7, /*logErrors=*/true)) {
System.err.println("The solution returned by the solver violated the"
+ " problem constraints by at least 1e-7");
return;
}
System.out.println("Problem solved in " + solver.wallTime() + " milliseconds");
// The objective value of the solution.
System.out.println("Optimal objective value = " + solver.objective().value());
// The value of each variable in the solution.
System.out.println("x1 = " + x1.solutionValue());
System.out.println("x2 = " + x2.solutionValue());
System.out.println("x3 = " + x3.solutionValue());
final double[] activities = solver.computeConstraintActivities();
System.out.println("Advanced usage:");
System.out.println("Problem solved in " + solver.iterations() + " iterations");
System.out.println("x1: reduced cost = " + x1.reducedCost());
System.out.println("x2: reduced cost = " + x2.reducedCost());
System.out.println("x3: reduced cost = " + x3.reducedCost());
System.out.println("c0: dual value = " + c0.dualValue());
System.out.println(" activity = " + activities[c0.index()]);
System.out.println("c1: dual value = " + c1.dualValue());
System.out.println(" activity = " + activities[c1.index()]);
System.out.println("c2: dual value = " + c2.dualValue());
System.out.println(" activity = " + activities[c2.index()]);
}
public static void main(String[] args) throws Exception {
System.out.println("---- Linear programming example with GLOP (recommended) ----");
runLinearProgrammingExample("GLOP_LINEAR_PROGRAMMING", true);
System.out.println("---- Linear programming example with CLP ----");
runLinearProgrammingExample("CLP_LINEAR_PROGRAMMING", false);
System.out.println("---- Linear programming example with GLPK ----");
runLinearProgrammingExample("GLPK_LINEAR_PROGRAMMING", false);
}
}

193
examples/java/LsApi.java Normal file
View File

@@ -0,0 +1,193 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.constraintsolver.Assignment;
import com.google.ortools.constraintsolver.AssignmentIntContainer;
import com.google.ortools.constraintsolver.BaseLns;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.IntVarLocalSearchFilter;
import com.google.ortools.constraintsolver.IntVarLocalSearchOperator;
import com.google.ortools.constraintsolver.LocalSearchPhaseParameters;
import com.google.ortools.constraintsolver.OptimizeVar;
import com.google.ortools.constraintsolver.SearchMonitor;
import com.google.ortools.constraintsolver.SolutionCollector;
import com.google.ortools.constraintsolver.Solver;
/**
* Sample showing how to model using the constraint programming solver.
*
*/
public class LsApi {
static {
System.loadLibrary("jniortools");
}
static class OneVarLns extends BaseLns {
public OneVarLns(IntVar[] vars) {
super(vars);
}
@Override
public void initFragments() {
index_ = 0;
}
@Override
public boolean nextFragment() {
int size = size();
if (index_ < size) {
appendToFragment(index_);
++index_;
return true;
} else {
return false;
}
}
private int index_;
}
static class MoveOneVar extends IntVarLocalSearchOperator {
public MoveOneVar(IntVar[] variables) {
super(variables);
variableIndex = 0;
moveUp = false;
}
@Override
protected boolean oneNeighbor() {
long currentValue = oldValue(variableIndex);
if (moveUp) {
setValue(variableIndex, currentValue + 1);
variableIndex = (variableIndex + 1) % size();
} else {
setValue(variableIndex, currentValue - 1);
}
moveUp = !moveUp;
return true;
}
@Override
public void onStart() {}
// Index of the next variable to try to restore
private long variableIndex;
// Direction of the modification.
private boolean moveUp;
}
static class SumFilter extends IntVarLocalSearchFilter {
public SumFilter(IntVar[] vars) {
super(vars);
sum = 0;
}
@Override
protected void onSynchronize(Assignment unusedDelta) {
sum = 0;
for (int index = 0; index < size(); ++index) {
sum += value(index);
}
}
@Override
public boolean accept(Assignment delta, Assignment unusedDeltadelta) {
AssignmentIntContainer solutionDelta = delta.intVarContainer();
int solutionDeltaSize = solutionDelta.size();
for (int i = 0; i < solutionDeltaSize; ++i) {
if (!solutionDelta.element(i).activated()) {
return true;
}
}
long newSum = sum;
for (int index = 0; index < solutionDeltaSize; ++index) {
int touchedVar = index(solutionDelta.element(index).var());
long oldValue = value(touchedVar);
long newValue = solutionDelta.element(index).value();
newSum += newValue - oldValue;
}
return newSum < sum;
}
private long sum;
}
private static void basicLns() {
System.out.println("basicLns");
Solver solver = new Solver("basicLns");
IntVar[] vars = solver.makeIntVarArray(4, 0, 4, "vars");
IntVar sumVar = solver.makeSum(vars).var();
OptimizeVar obj = solver.makeMinimize(sumVar, 1);
DecisionBuilder db =
solver.makePhase(vars, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE);
OneVarLns oneVarLns = new OneVarLns(vars);
LocalSearchPhaseParameters lsParams = solver.makeLocalSearchPhaseParameters(oneVarLns, db);
DecisionBuilder ls = solver.makeLocalSearchPhase(vars, db, lsParams);
SolutionCollector collector = solver.makeLastSolutionCollector();
collector.addObjective(sumVar);
SearchMonitor log = solver.makeSearchLog(1000, obj);
solver.solve(ls, collector, obj, log);
System.out.println("Objective value = " + collector.objectiveValue(0));
}
private static void basicLs() {
System.out.println("basicLs");
Solver solver = new Solver("basicLs");
IntVar[] vars = solver.makeIntVarArray(4, 0, 4, "vars");
IntVar sumVar = solver.makeSum(vars).var();
OptimizeVar obj = solver.makeMinimize(sumVar, 1);
DecisionBuilder db =
solver.makePhase(vars, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE);
MoveOneVar moveOneVar = new MoveOneVar(vars);
LocalSearchPhaseParameters lsParams = solver.makeLocalSearchPhaseParameters(moveOneVar, db);
DecisionBuilder ls = solver.makeLocalSearchPhase(vars, db, lsParams);
SolutionCollector collector = solver.makeLastSolutionCollector();
collector.addObjective(sumVar);
SearchMonitor log = solver.makeSearchLog(1000, obj);
solver.solve(ls, collector, obj, log);
System.out.println("Objective value = " + collector.objectiveValue(0));
}
private static void basicLsWithFilter() {
System.out.println("basicLsWithFilter");
Solver solver = new Solver("basicLs");
IntVar[] vars = solver.makeIntVarArray(4, 0, 4, "vars");
IntVar sumVar = solver.makeSum(vars).var();
OptimizeVar obj = solver.makeMinimize(sumVar, 1);
DecisionBuilder db =
solver.makePhase(vars, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE);
MoveOneVar moveOneVar = new MoveOneVar(vars);
SumFilter filter = new SumFilter(vars);
IntVarLocalSearchFilter[] filters = new IntVarLocalSearchFilter[1];
filters[0] = filter;
LocalSearchPhaseParameters lsParams =
solver.makeLocalSearchPhaseParameters(moveOneVar, db, null, filters);
DecisionBuilder ls = solver.makeLocalSearchPhase(vars, db, lsParams);
SolutionCollector collector = solver.makeLastSolutionCollector();
collector.addObjective(sumVar);
SearchMonitor log = solver.makeSearchLog(1000, obj);
solver.solve(ls, collector, obj, log);
System.out.println("Objective value = " + collector.objectiveValue(0));
}
public static void main(String[] args) throws Exception {
LsApi.basicLns();
LsApi.basicLs();
LsApi.basicLsWithFilter();
}
}

View File

@@ -0,0 +1,137 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class MagicSquare {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the Magic Square problem.
* See http://www.hakank.org/google_or_tools/magic_square.py
*
*/
private static void solve(int n, int num) {
Solver solver = new Solver("MagicSquare");
System.out.println("n: " + n);
//
// variables
//
IntVar[][] x = new IntVar[n][n];
// for the branching
IntVar[] x_flat = new IntVar[n*n];
//
// constraints
//
final long s = (n * (n * n + 1)) / 2;
System.out.println("s: " + s);
// IntVar s = solver.makeIntVar(0, n*n*n, "s");
IntVar[] diag1 = new IntVar[n];
IntVar[] diag2 = new IntVar[n];
for(int i = 0; i < n; i++) {
IntVar[] row = new IntVar[n];
for(int j = 0; j < n; j++) {
x[i][j] = solver.makeIntVar(1, n * n, "x[" + i + "," + j + "]");
x_flat[i * n + j] = x[i][j];
row[j] = x[i][j];
}
// sum row to s
solver.addConstraint(solver.makeSumEquality(row, s));
diag1[i] = x[i][i];
diag2[i] = x[i][n - i - 1];
}
// sum diagonals to s
solver.addConstraint(solver.makeSumEquality(diag1, s));
solver.addConstraint(solver.makeSumEquality(diag2, s));
// sum columns to s
for(int j = 0; j < n; j++) {
IntVar[] col = new IntVar[n];
for(int i = 0; i < n; i++) {
col[i] = x[i][j];
}
solver.addConstraint(solver.makeSumEquality(col, s));
}
// all are different
solver.addConstraint(solver.makeAllDifferent(x_flat));
// symmetry breaking: upper left is 1
// solver.addConstraint(solver.makeEquality(x[0][0], 1));
//
// Solve
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_CENTER_VALUE);
solver.newSearch(db);
int c = 0;
while (solver.nextSolution()) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(x[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
c++;
if (num > 0 && c >= num) {
break;
}
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 4;
int num = 0;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
if (args.length > 1) {
num = Integer.parseInt(args[1]);
}
MagicSquare.solve(n, num);
}
}

112
examples/java/Map.java Normal file
View File

@@ -0,0 +1,112 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class Map {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a simple map coloring problem.
* See http://www.hakank.org/google_or_tools/map.py
*
*/
private static void solve() {
Solver solver = new Solver("Map");
//
// data
//
int Belgium = 0;
int Denmark = 1;
int France = 2;
int Germany = 3;
int Netherlands = 4;
int Luxembourg = 5;
int n = 6;
int max_num_colors = 4;
//
// Variables
//
IntVar[] color = solver.makeIntVarArray(n, 1, max_num_colors, "x");
//
// Constraints
//
solver.addConstraint(solver.makeNonEquality(color[France],
color[Belgium]));
solver.addConstraint(solver.makeNonEquality(color[France],
color[Luxembourg]));
solver.addConstraint(solver.makeNonEquality(color[France],
color[Germany]));
solver.addConstraint(solver.makeNonEquality(color[Luxembourg],
color[Germany]));
solver.addConstraint(solver.makeNonEquality(color[Luxembourg],
color[Belgium]));
solver.addConstraint(solver.makeNonEquality(color[Belgium],
color[Netherlands]));
solver.addConstraint(solver.makeNonEquality(color[Belgium],
color[Germany]));
solver.addConstraint(solver.makeNonEquality(color[Germany],
color[Netherlands]));
solver.addConstraint(solver.makeNonEquality(color[Germany],
color[Denmark]));
// Symmetry breaking
solver.addConstraint(solver.makeEquality(color[Belgium], 1));
//
// Search
//
DecisionBuilder db = solver.makePhase(color,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
while (solver.nextSolution()) {
System.out.print("Colors: ");
for(int i = 0; i < n; i++) {
System.out.print(color[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Map.solve();
}
}

111
examples/java/Map2.java Normal file
View File

@@ -0,0 +1,111 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class Map2 {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a simple map coloring problem, take II.
* See http://www.hakank.org/google_or_tools/map.py
*
*/
private static void solve() {
Solver solver = new Solver("Map2");
//
// data
//
int Belgium = 0;
int Denmark = 1;
int France = 2;
int Germany = 3;
int Netherlands = 4;
int Luxembourg = 5;
int n = 6;
int max_num_colors = 4;
int[][] neighbours = {{France, Belgium},
{France, Luxembourg},
{France, Germany},
{Luxembourg, Germany},
{Luxembourg, Belgium},
{Belgium, Netherlands},
{Belgium, Germany},
{Germany, Netherlands},
{Germany, Denmark}};
//
// Variables
//
IntVar[] color = solver.makeIntVarArray(n, 1, max_num_colors, "x");
//
// Constraints
//
for(int i = 0; i < neighbours.length; i++) {
solver.addConstraint(
solver.makeNonEquality(color[neighbours[i][0]],
color[neighbours[i][1]]));
}
// Symmetry breaking
solver.addConstraint(solver.makeEquality(color[Belgium], 1));
//
// Search
//
DecisionBuilder db = solver.makePhase(color,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
while (solver.nextSolution()) {
System.out.print("Colors: ");
for(int i = 0; i < n; i++) {
System.out.print(color[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Map2.solve();
}
}

View File

@@ -0,0 +1,252 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class Minesweeper {
static {
System.loadLibrary("jniortools");
}
static int X = -1;
//
// Default problem.
// It has 4 solutions.
//
static int default_r = 8;
static int default_c = 8;
static int[][] default_game = {{2, 3, X, 2, 2, X, 2, 1},
{X, X, 4, X, X, 4, X, 2},
{X, X, X, X, X, X, 4, X},
{X, 5, X, 6, X, X, X, 2},
{2, X, X, X, 5, 5, X, 2},
{1, 3, 4, X, X, X, 4, X},
{0, 1, X, 4, X, X, X, 3},
{0, 1, 2, X, 2, 3, X, 2}};
// for the actual problem
static int r;
static int c;
static int[][] game;
/**
*
* Solves the Minesweeper problems.
* See http://www.hakank.org/google_or_tools/minesweeper.py
*
*/
private static void solve() {
Solver solver = new Solver("Minesweeper");
int[] S = {-1, 0, 1};
//
// data
//
System.out.println("Problem:");
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
if (game[i][j] > X) {
System.out.print(game[i][j] + " ");
} else {
System.out.print("X ");
}
}
System.out.println();
}
System.out.println();
//
// Variables
//
IntVar[][] mines = new IntVar[r][c];
IntVar[] mines_flat = new IntVar[r * c]; // for branching
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
mines[i][j] = solver.makeIntVar(0, 1, "mines[" + i + ", " + j + "]");
mines_flat[i * c + j] = mines[i][j];
}
}
//
// Constraints
//
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
if (game[i][j] >= 0) {
solver.addConstraint(
solver.makeEquality(mines[i][j], 0));
// this cell is the sum of all its neighbours
ArrayList<IntVar> neighbours = new ArrayList<IntVar>();
for(int a: S) {
for(int b: S) {
if (i + a >= 0 &&
j + b >= 0 &&
i + a < r &&
j + b < c) {
neighbours.add(mines[i + a][j + b]);
}
}
}
solver.addConstraint(
solver.makeSumEquality(
neighbours.toArray(new IntVar[1]), game[i][j]));
}
if (game[i][j] > X) {
// This cell cannot be a mine since it
// has some value assigned to it
solver.addConstraint(
solver.makeEquality(mines[i][j], 0));
}
}
}
//
// Search
//
DecisionBuilder db = solver.makePhase(mines_flat,
solver.INT_VAR_SIMPLE,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
int sol = 0;
while (solver.nextSolution()) {
sol++;
System.out.println("Solution #" + sol + ":");
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
System.out.print(mines[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
/**
*
* Reads a minesweeper file.
* File format:
* # a comment which is ignored
* % a comment which also is ignored
* number of rows
* number of columns
* <
* row number of neighbours lines...
* >
*
* 0..8 means number of neighbours, "." mean unknown (may be a mine)
*
* Example (from minesweeper0.txt)
* # Problem from Gecode/examples/minesweeper.cc problem 0
* 6
* 6
* ..2.3.
* 2.....
* ..24.3
* 1.34..
* .....3
* .3.3..
*
*/
private static void readFile(String file) {
System.out.println("readFile(" + file + ")");
int lineCount = 0;
try {
BufferedReader inr = new BufferedReader(new FileReader(file));
String str;
while ((str = inr.readLine()) != null && str.length() > 0) {
str = str.trim();
// ignore comments
if(str.startsWith("#") || str.startsWith("%")) {
continue;
}
System.out.println(str);
if (lineCount == 0) {
r = Integer.parseInt(str); // number of rows
} else if (lineCount == 1) {
c = Integer.parseInt(str); // number of columns
game = new int[r][c];
} else {
// the problem matrix
String row[] = str.split("");
for(int j = 1; j <= c; j++) {
String s = row[j];
if (s.equals(".")) {
game[lineCount-2][j-1] = -1;
} else {
game[lineCount-2][j-1] = Integer.parseInt(s);
}
}
}
lineCount++;
} // end while
inr.close();
} catch (IOException e) {
System.out.println(e);
}
} // end readFile
public static void main(String[] args) throws Exception {
String file = "";
if (args.length > 0) {
file = args[0];
Minesweeper.readFile(file);
} else {
game = default_game;
r = default_r;
c = default_c;
}
Minesweeper.solve();
}
}

View File

@@ -0,0 +1,126 @@
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Arrays;
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPSolver.OptimizationProblemType;
import com.google.ortools.linearsolver.MPSolver.ResultStatus;
import com.google.ortools.linearsolver.MPVariable;
public class MultiThreadTest {
static { System.loadLibrary("jniortools"); }
private final static boolean verboseOutput = false; // To enable Cbc logging
public static void main(String[] args) throws Exception {
launchProtocol(10, 8, true);
System.out.println("Cbc multi thread test successful");
return;
}
public static void launchProtocol(int wholeLoopAttmpts, int threadPoolSize, boolean runInParallel) throws Exception {
for (int noAttmpt = 0; noAttmpt < wholeLoopAttmpts; noAttmpt++) {
System.out.println(String.format("Attempt %d", noAttmpt));
int maxThreads = threadPoolSize;
List<SolverThread> threadList = new ArrayList<SolverThread>();
for (int i = 0; i < maxThreads; i++) {
SolverThread thread = new SolverThread();
threadList.add(thread);
}
ExecutorService executor = Executors.newFixedThreadPool(maxThreads);
if (runInParallel) {
System.out.println("Launching thread pool");
executor.invokeAll(threadList);
for( SolverThread thread : threadList ) {
System.out.println(thread.getStatusSolver().toString());
}
} else {
for (SolverThread thread : threadList) {
System.out.println("Launching single thread");
executor.invokeAll( Arrays.asList(thread) );
System.out.println(thread.getStatusSolver().toString());
}
}
System.out.println("Attempt finalized!");
executor.shutdown();
}
System.out.println("Now exiting multi thread execution");
}
private static MPSolver makeProblem() {
MPSolver solver = new MPSolver(UUID.randomUUID().toString(), OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING);
double infinity = MPSolver.infinity();
// x1 and x2 are integer non-negative variables.
MPVariable x1 = solver.makeIntVar(0.0, infinity, "x1");
MPVariable x2 = solver.makeIntVar(0.0, infinity, "x2");
// Minimize x1 + 2 * x2.
MPObjective objective = solver.objective();
objective.setCoefficient(x1, 1);
objective.setCoefficient(x2, 2);
// 2 * x2 + 3 * x1 >= 17.
MPConstraint ct = solver.makeConstraint(17, infinity);
ct.setCoefficient(x1, 3);
ct.setCoefficient(x2, 2);
if (verboseOutput) {
solver.enableOutput();
}
return solver;
}
private final static class SolverThread implements Callable<MPSolver.ResultStatus> {
private MPSolver.ResultStatus statusSolver;
public SolverThread() {
}
@Override
public ResultStatus call() throws Exception {
MPSolver solver = makeProblem();
statusSolver = solver.solve();
// Check that the problem has an optimal solution.
if ( MPSolver.ResultStatus.OPTIMAL.equals(statusSolver) ) {
throw new RuntimeException("Non OPTIMAL status after solve.");
}
return statusSolver;
}
public MPSolver.ResultStatus getStatusSolver() {
return statusSolver;
}
}
}

120
examples/java/NQueens.java Normal file
View File

@@ -0,0 +1,120 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class NQueens {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the N Queens problem.
* See http://www.hakank.org/google_or_tools/nqueens2.py
*
*/
private static void solve(int n, int num, int print) {
Solver solver = new Solver("NQueens");
System.out.println("n: " + n);
//
// variables
//
IntVar[] q = solver.makeIntVarArray(n, 0, n-1, "q");
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(q));
IntVar b = solver.makeIntVar(1, 1, "b");
IntVar[] q1 = new IntVar[n];
IntVar[] q2 = new IntVar[n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) {
// // q[i]+i != q[j]+j
solver.addConstraint(
solver.makeNonEquality(
solver.makeSum(q[i],i).var(),
solver.makeSum(q[j],j).var()));
// q[i]-i != q[j]-j
solver.addConstraint(
solver.makeNonEquality(solver.makeSum(q[i],-i).var(),
solver.makeSum(q[j],-j).var()));
}
}
//
// Solve
//
DecisionBuilder db = solver.makePhase(q,
solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
solver.ASSIGN_CENTER_VALUE);
solver.newSearch(db);
int c = 0;
while (solver.nextSolution()) {
if (print != 0) {
for(int i = 0; i < n; i++) {
System.out.print(q[i].value() + " ");
}
System.out.println();
}
c++;
if (num > 0 && c >= num) {
break;
}
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 8;
int num = 0;
int print = 1;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
if (args.length > 1) {
num = Integer.parseInt(args[1]);
}
if (args.length > 2) {
print = Integer.parseInt(args[2]);
}
NQueens.solve(n, num, print);
}
}

110
examples/java/NQueens2.java Normal file
View File

@@ -0,0 +1,110 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class NQueens2 {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the N Queens problem.
* See http://www.hakank.org/google_or_tools/nqueens2.py
*
*/
private static void solve(int n, int num, int print) {
Solver solver = new Solver("NQueens");
System.out.println("n: " + n);
//
// variables
//
IntVar[] q = solver.makeIntVarArray(n, 0, n-1, "q");
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(q));
IntVar[] q1 = new IntVar[n];
IntVar[] q2 = new IntVar[n];
for(int i = 0; i < n; i++) {
q1[i] = solver.makeSum(q[i], i).var();
q2[i] = solver.makeSum(q[i], -i).var();
}
solver.addConstraint(solver.makeAllDifferent(q1));
solver.addConstraint(solver.makeAllDifferent(q2));
//
// Solve
//
DecisionBuilder db = solver.makePhase(q,
solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
solver.ASSIGN_CENTER_VALUE);
solver.newSearch(db);
int c = 0;
while (solver.nextSolution()) {
if (print != 0) {
for(int i = 0; i < n; i++) {
System.out.print(q[i].value() + " ");
}
System.out.println();
}
c++;
if (num > 0 && c >= num) {
break;
}
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 8;
int num = 0;
int print = 1;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
if (args.length > 1) {
num = Integer.parseInt(args[1]);
}
if (args.length > 2) {
print = Integer.parseInt(args[2]);
}
NQueens2.solve(n, num, print);
}
}

View File

@@ -0,0 +1,121 @@
/**
* Copyright (c) 1999-2011, Ecole des Mines de Nantes
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Ecole des Mines de Nantes nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import com.google.ortools.constraintsolver.*;
/**
* Partition n numbers into two groups, so that
* - the sum of the first group equals the sum of the second,
* - and the sum of the squares of the first group equals the sum of
* the squares of the second
* <br/>
*
* @author Charles Prud'homme
* @since 18/03/11
*/
public class Partition {
static {
System.loadLibrary("jniortools");
}
/**
* Partition Problem.
*/
private static void solve(int m) {
Solver solver = new Solver("Partition " + m);
IntVar[] x, y;
x = solver.makeIntVarArray(m, 1, 2 * m, "x");
y = solver.makeIntVarArray(m, 1, 2 * m, "y");
// break symmetries
for (int i = 0; i < m - 1; i++) {
solver.addConstraint(solver.makeLess(x[i], x[i + 1]));
solver.addConstraint(solver.makeLess(y[i], y[i + 1]));
}
solver.addConstraint(solver.makeLess(x[0], y[0]));
IntVar[] xy = new IntVar[2 * m];
for (int i = m - 1; i >= 0; i--) {
xy[i] = x[i];
xy[m + i] = y[i];
}
solver.addConstraint(solver.makeAllDifferent(xy));
int[] coeffs = new int[2 * m];
for (int i = m - 1; i >= 0; i--) {
coeffs[i] = 1;
coeffs[m + i] = -1;
}
solver.addConstraint(solver.makeScalProdEquality(xy, coeffs, 0));
IntVar[] sxy, sx, sy;
sxy = new IntVar[2 * m];
sx = new IntVar[m];
sy = new IntVar[m];
for (int i = m - 1; i >= 0; i--) {
sx[i] = solver.makeSquare(x[i]).var();
sxy[i] = sx[i];
sy[i] = solver.makeSquare(y[i]).var();
sxy[m + i] = sy[i];
}
solver.addConstraint(solver.makeScalProdEquality(sxy, coeffs, 0));
solver.addConstraint(
solver.makeSumEquality(x, 2 * m * (2 * m + 1) / 4));
solver.addConstraint(
solver.makeSumEquality(y, 2 * m * (2 * m + 1) / 4));
solver.addConstraint(
solver.makeSumEquality(sx, 2 * m * (2 * m + 1) * (4 * m + 1) / 12));
solver.addConstraint(
solver.makeSumEquality(sy, 2 * m * (2 * m + 1) * (4 * m + 1) / 12));
DecisionBuilder db = solver.makeDefaultPhase(xy);
SolutionCollector collector = solver.makeFirstSolutionCollector();
collector.add(xy);
SearchMonitor log = solver.makeSearchLog(10000);
solver.newSearch(db, log, collector);
solver.nextSolution();
System.out.println("Solution solution");
for (int i = 0; i < m; ++i) {
System.out.print("[" + collector.value(0, xy[i]) + "] ");
}
System.out.printf("\n");
for (int i = 0; i < m; ++i) {
System.out.print("[" + collector.value(0, xy[m+i]) + "] ");
}
System.out.println();
}
public static void main(String[] args) throws Exception {
Partition.solve(32);
}
}

View File

@@ -0,0 +1,241 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class QuasigroupCompletion {
static {
System.loadLibrary("jniortools");
}
static int X = 0;
/*
* default problem
*
* Example from Ruben Martins and Inès Lynce
* Breaking Local Symmetries in Quasigroup Completion Problems, page 3
* The solution is unique:
*
* 1 3 2 5 4
* 2 5 4 1 3
* 4 1 3 2 5
* 5 4 1 3 2
* 3 2 5 4 1
*/
static int default_n = 5;
static int[][] default_problem = {{1, X, X, X, 4},
{X, 5, X, X, X},
{4, X, X, 2, X},
{X, 4, X, X, X},
{X, X, 5, X, 1}};
// for the actual problem
static int n;
static int[][] problem;
/**
*
* Solves the Quasigroup Completion problem.
* See http://www.hakank.org/google_or_tools/quasigroup_completion.py
*/
private static void solve() {
Solver solver = new Solver("QuasigroupCompletion");
//
// data
//
System.out.println("Problem:");
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(problem[i][j] + " ");
}
System.out.println();
}
System.out.println();
//
// Variables
//
IntVar[][] x = new IntVar[n][n];
IntVar[] x_flat = new IntVar[n * n]; // for branching
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
x[i][j] = solver.makeIntVar(1, n, "x[" + i + "," + j + "]");
x_flat[i * n + j] = x[i][j];
}
}
//
// Constraints
//
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if (problem[i][j] > X) {
solver.addConstraint(solver.makeEquality(x[i][j], problem[i][j]));
}
}
}
//
// rows and columns must be different
//
// rows
for(int i = 0; i < n; i++) {
IntVar[] row = new IntVar[n];
for(int j = 0; j < n; j++) {
row[j] = x[i][j];
}
solver.addConstraint(
solver.makeAllDifferent(row));
}
// columns
for(int j = 0; j < n; j++) {
IntVar[] col = new IntVar[n];
for(int i = 0; i < n; i++) {
col[i] = x[i][j];
}
solver.addConstraint(solver.makeAllDifferent(col));
}
//
// Search
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.INT_VAR_SIMPLE,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
int sol = 0;
while (solver.nextSolution()) {
sol++;
System.out.println("Solution #" + sol + ":");
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(x[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
/**
*
* Reads a Quasigroup completion file.
* File format:
* # a comment which is ignored
* % a comment which also is ignored
* number of rows (n)
* <
* row number of space separated entries
* >
*
* "." or "0" means unknown, integer 1..n means known value
*
* Example
* 5
* 1 . . . 4
* . 5 . . .
* 4 . . 2 .
* . 4 . . .
* . . 5 . 1
*
*/
private static void readFile(String file) {
System.out.println("readFile(" + file + ")");
int lineCount = 0;
try {
BufferedReader inr = new BufferedReader(new FileReader(file));
String str;
while ((str = inr.readLine()) != null && str.length() > 0) {
str = str.trim();
// ignore comments
if(str.startsWith("#") || str.startsWith("%")) {
continue;
}
System.out.println(str);
if (lineCount == 0) {
n = Integer.parseInt(str); // number of rows
problem = new int[n][n];
} else {
// the problem matrix
String row[] = str.split(" ");
for(int i = 0; i < n; i++) {
String s = row[i];
if (s.equals(".")) {
problem[lineCount - 1][i] = 0;
} else {
problem[lineCount - 1][i] = Integer.parseInt(s);
}
}
}
lineCount++;
} // end while
inr.close();
} catch (IOException e) {
System.out.println(e);
}
} // end readFile
public static void main(String[] args) throws Exception {
if (args.length > 0) {
String file = "";
file = args[0];
QuasigroupCompletion.readFile(file);
} else {
problem = default_problem;
n = default_n;
}
QuasigroupCompletion.solve();
}
}

View File

@@ -0,0 +1,63 @@
// Copyright 2010-2017 Google
// 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.
import com.google.ortools.constraintsolver.ConstraintSolverParameters;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import java.util.logging.Logger;
/**
* Sample showing how to model using the constraint programming solver.
*
*/
public class RabbitsPheasants {
private static Logger logger = Logger.getLogger(RabbitsPheasants.class.getName());
static {
System.loadLibrary("jniortools");
}
/**
* Solves the rabbits + pheasants problem. We are seing 20 heads
* and 56 legs. How many rabbits and how many pheasants are we thus
* seeing?
*/
private static void solve(boolean traceSearch) {
ConstraintSolverParameters parameters =
ConstraintSolverParameters.newBuilder()
.mergeFrom(Solver.defaultSolverParameters())
.setTraceSearch(traceSearch)
.build();
Solver solver = new Solver("RabbitsPheasants", parameters);
IntVar rabbits = solver.makeIntVar(0, 100, "rabbits");
IntVar pheasants = solver.makeIntVar(0, 100, "pheasants");
solver.addConstraint(solver.makeEquality(solver.makeSum(rabbits, pheasants), 20));
solver.addConstraint(
solver.makeEquality(
solver.makeSum(solver.makeProd(rabbits, 4), solver.makeProd(pheasants, 2)), 56));
DecisionBuilder db =
solver.makePhase(rabbits, pheasants, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
solver.nextSolution();
logger.info(rabbits.toString());
logger.info(pheasants.toString());
solver.endSearch();
}
public static void main(String[] args) throws Exception {
boolean traceSearch = args.length > 0 && args[1].equals("--trace");
RabbitsPheasants.solve(traceSearch);
}
}

View File

@@ -0,0 +1,91 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class SendMoreMoney {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the SEND+MORE=MONEY problem.
*
*/
private static void solve() {
int base = 10;
Solver solver = new Solver("SendMoreMoney");
IntVar s = solver.makeIntVar(0, base - 1, "s");
IntVar e = solver.makeIntVar(0, base - 1, "e");
IntVar n = solver.makeIntVar(0, base - 1, "n");
IntVar d = solver.makeIntVar(0, base - 1, "d");
IntVar m = solver.makeIntVar(0, base - 1, "m");
IntVar o = solver.makeIntVar(0, base - 1, "o");
IntVar r = solver.makeIntVar(0, base - 1, "r");
IntVar y = solver.makeIntVar(0, base - 1, "y");
IntVar[] x = {s,e,n,d,m,o,r,y};
IntVar[] eq = {s,e,n,d, m,o,r,e, m,o,n,e,y};
int[] coeffs = {1000, 100, 10, 1, // S E N D +
1000, 100, 10, 1, // M O R E
-10000, -1000, -100, -10, -1 // == M O N E Y
};
solver.addConstraint(solver.makeScalProdEquality(eq, coeffs, 0));
// alternative:
solver.addConstraint(
solver.makeScalProdEquality(new IntVar[] {s,e,n,d, m,o,r,e, m,o,n,e,y},
coeffs, 0));
// s > 0
solver.addConstraint(solver.makeGreater(s, 0));
// m > 0
solver.addConstraint(solver.makeGreater(m, 0));
solver.addConstraint(solver.makeAllDifferent(x));
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
while (solver.nextSolution()) {
for(int i = 0; i < 8; i++) {
System.out.print(x[i].toString() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
SendMoreMoney.solve();
}
}

View File

@@ -0,0 +1,214 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.*;
public class SendMoreMoney2 {
static Solver sol;
static {
System.loadLibrary("jniortools");
}
//
// Some helper methods
//
static IntExpr p(IntExpr a, int b, IntExpr c) {
return sol.makeSum(sol.makeProd(a, b), c);
}
static IntExpr p(IntVar a, int b) {
return sol.makeProd(a, b);
}
// a slighly more intelligent scalar product
static IntExpr sp(IntVar[] a) {
int len = a.length;
int c = 1;
int[] t = new int[len];
for(int i = len-1; i >= 0; i--) {
t[i] = c;
c *= 10;
}
return sol.makeScalProd(a, t);
}
/**
*
* Solves the SEND+MORE=MONEY problem with different approaches.
*
*/
private static void solve(int alt) {
sol = new Solver("SendMoreMoney");
int base = 10;
//
// variables
//
IntVar s = sol.makeIntVar(0, base - 1, "s");
IntVar e = sol.makeIntVar(0, base - 1, "e");
IntVar n = sol.makeIntVar(0, base - 1, "n");
IntVar d = sol.makeIntVar(0, base - 1, "d");
IntVar m = sol.makeIntVar(0, base - 1, "m");
IntVar o = sol.makeIntVar(0, base - 1, "o");
IntVar r = sol.makeIntVar(0, base - 1, "r");
IntVar y = sol.makeIntVar(0, base - 1, "y");
IntVar[] x = {s, e, n, d, m, o, r, y};
//
// Constraints
//
/*
*
* Below are some alternatives encodings of the
* same idea:
*
* 1000*s + 100*e + 10*n + d +
* 1000*m + 100*o + 10*r + e ==
* 10000*m + 1000*o + 100*n + 10*e + y
*
*/
if (alt == 0) {
//
// First, a version approach which is just too noisy.
//
sol.addConstraint(
sol.makeEquality(
sol.makeSum(sol.makeSum(
sol.makeProd(s, 1000),
sol.makeSum(sol.makeProd(e, 100),
sol.makeSum(sol.makeProd(n, 10),
sol.makeProd(d, 1)))),
sol.makeSum(
sol.makeProd(m, 1000),
sol.makeSum(sol.makeProd(o, 100),
sol.makeSum(sol.makeProd(r, 10),
sol.makeProd(e, 1))))
).var(),
sol.makeSum(sol.makeProd(m, 10000),
sol.makeSum(
sol.makeProd(o, 1000),
sol.makeSum(
sol.makeProd(n, 100),
sol.makeSum(
sol.makeProd(e, 10),
sol.makeProd(y, 1))))).var()));
} else if (alt == 1) {
//
// Alternative 1, using the helper methods
//
// p(IntExpr, int, IntExpr) and
// p(IntVar, int)
//
sol.addConstraint(
sol.makeEquality(
sol.makeSum(p(s, 1000, p(e, 100, p(n, 10, p(d, 1)))),
p(m, 1000, p(o, 100, p(r, 10, p(e, 1))))).var(),
p(m, 10000, p(o, 1000, p(n, 100, p(e, 10, p(y, 1))))).var()));
} else if (alt == 2) {
//
// Alternative 2
//
sol.addConstraint(
sol.makeEquality(
sol.makeSum(
sol.makeScalProd(new IntVar[] {s, e, n, d},
new int[] {1000, 100, 10, 1}),
sol.makeScalProd(new IntVar[] {m, o, r, e},
new int[] {1000, 100, 10, 1})).var(),
sol.makeScalProd(new IntVar[] {m, o, n, e, y},
new int[] {10000, 1000, 100, 10, 1}).var()));
} else if (alt == 3) {
//
// alternative 3: same approach as 2, with some helper methods
//
sol.addConstraint(
sol.makeEquality(sol.makeSum(sp(new IntVar[] {s, e, n, d}),
sp(new IntVar[] {m, o, r, e})).var(),
sp(new IntVar[] {m, o, n, e, y}).var()));
} else if (alt == 4) {
//
// Alternative 4, using explicit variables
//
IntExpr send = sol.makeScalProd(new IntVar[] {s, e, n, d},
new int[] {1000, 100, 10, 1});
IntExpr more = sol.makeScalProd(new IntVar[] {m, o, r, e},
new int[] {1000, 100, 10, 1});
IntExpr money = sol.makeScalProd(new IntVar[] {m, o, n, e, y},
new int[] {10000, 1000, 100, 10, 1});
sol.addConstraint(
sol.makeEquality(sol.makeSum(send, more).var(), money.var()));
}
// s > 0
sol.addConstraint(sol.makeGreater(s, 0));
// m > 0
sol.addConstraint(sol.makeGreater(m, 0));
sol.addConstraint(sol.makeAllDifferent(x));
//
// Search
//
DecisionBuilder db = sol.makePhase(x,
sol.INT_VAR_DEFAULT,
sol.INT_VALUE_DEFAULT);
sol.newSearch(db);
while (sol.nextSolution()) {
for(int i = 0; i < 8; i++) {
System.out.print(x[i].toString() + " ");
}
System.out.println();
}
sol.endSearch();
//
// Statistics
//
System.out.println();
System.out.println("Solutions: " + sol.solutions());
System.out.println("Failures: " + sol.failures());
System.out.println("Branches: " + sol.branches());
System.out.println("Wall time: " + sol.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 5; i++) {
System.out.println("\nalternative #" + i);
SendMoreMoney2.solve(i);
}
}
}

View File

@@ -0,0 +1,130 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class SendMostMoney {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the SEND+MOST=MONEY problem, where
* we maximize MONEY.
* See http://www.hakank.org/google_or_tools/send_more_money.py
*
*/
private static long solve(long MONEY) {
Solver solver = new Solver("SendMostMoney");
//
// data
//
final int base = 10;
//
// variables
//
IntVar s = solver.makeIntVar(0, base - 1, "s");
IntVar e = solver.makeIntVar(0, base - 1, "e");
IntVar n = solver.makeIntVar(0, base - 1, "n");
IntVar d = solver.makeIntVar(0, base - 1, "d");
IntVar m = solver.makeIntVar(0, base - 1, "m");
IntVar o = solver.makeIntVar(0, base - 1, "o");
IntVar t = solver.makeIntVar(0, base - 1, "t");
IntVar y = solver.makeIntVar(0, base - 1, "y");
IntVar[] x = {s, e, n, d, m, o, t, y};
IntVar[] eq = {s,e,n,d, m,o,s,t, m,o,n,e,y};
int[] coeffs = {1000, 100, 10, 1, // S E N D +
1000, 100, 10, 1, // M O S T
-10000,-1000, -100,-10,-1 // == M O N E Y
};
solver.addConstraint(solver.makeScalProdEquality(eq, coeffs, 0));
IntVar money = solver.makeScalProd(new IntVar[] {m, o, n, e, y},
new int[] {10000, 1000, 100, 10, 1}).var();
//
// constraints
//
// s > 0
solver.addConstraint(solver.makeGreater(s, 0));
// m > 0
solver.addConstraint(solver.makeGreater(m, 0));
solver.addConstraint(solver.makeAllDifferent(x));
if (MONEY > 0) {
// Search for all solutions.
solver.addConstraint(solver.makeEquality(money, MONEY));
}
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MAX_VALUE);
if (MONEY == 0) {
// first round: get the optimal value
OptimizeVar obj = solver.makeMaximize(money, 1);
solver.newSearch(db, obj);
} else {
// search for all solutions
solver.newSearch(db);
}
long money_ret = 0;
while (solver.nextSolution()) {
System.out.println("money: " + money.value());
money_ret = money.value();
for(int i = 0; i < x.length; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
return money_ret;
}
public static void main(String[] args) throws Exception {
System.out.println("Get the max value of money:");
long this_money = SendMostMoney.solve(0);
System.out.println("\nThen find all solutions with this value:");
long tmp = SendMostMoney.solve(this_money);
}
}

139
examples/java/Seseman.java Normal file
View File

@@ -0,0 +1,139 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class Seseman {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the Seseman convent problem.
* See http://www.hakank.org/google_or_tools/seseman.py
*
*/
private static void solve(int n) {
Solver solver = new Solver("Seseman");
//
// data
//
final int border_sum = n * n;
//
// variables
//
IntVar[][] x = new IntVar[n][n];
IntVar[] x_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
x[i][j] = solver.makeIntVar(0, n * n);
x_flat[i * n + j] = x[i][j];
}
}
IntVar total_sum = solver.makeSum(x_flat).var();
//
// constraints
//
// zero in all middle cells
for(int i = 1; i < n-1; i++) {
for(int j = 1; j < n-1; j++) {
solver.addConstraint(solver.makeEquality(x[i][j], 0));
}
}
// all borders must be >= 1
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if (i == 0 || j == 0 || i == n - 1 || j == n - 1) {
solver.addConstraint(solver.makeGreaterOrEqual(x[i][j], 1));
}
}
}
// sum the four borders
IntVar[] border1 = new IntVar[n];
IntVar[] border2 = new IntVar[n];
IntVar[] border3 = new IntVar[n];
IntVar[] border4 = new IntVar[n];
for(int i = 0; i < n; i++) {
border1[i] = x[i][0];
border2[i] = x[i][n - 1];
border3[i] = x[0][i];
border4[i] = x[n - 1][i];
}
solver.addConstraint(
solver.makeSumEquality(border1, border_sum));
solver.addConstraint(
solver.makeSumEquality(border2, border_sum));
solver.addConstraint(
solver.makeSumEquality(border3, border_sum));
solver.addConstraint(
solver.makeSumEquality(border4, border_sum));
//
// search
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
while (solver.nextSolution()) {
System.out.println("total_sum: " + total_sum.value());
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(x[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 3;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
Seseman.solve(n);
}
}

View File

@@ -0,0 +1,118 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class SetCovering {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a set covering problem.
* See http://www.hakank.org/google_or_tools/set_covering.py
*
*/
private static void solve() {
Solver solver = new Solver("SetCovering");
//
// data
//
// Placing of firestations, from Winston 'Operations Research',
// page 486.
int min_distance = 15;
int num_cities = 6;
int[][] distance = {{ 0,10,20,30,30,20},
{10, 0,25,35,20,10},
{20,25, 0,15,30,20},
{30,35,15, 0,15,25},
{30,20,30,15, 0,14},
{20,10,20,25,14, 0}};
//
// variables
//
IntVar[] x = solver.makeIntVarArray(num_cities, 0, 1, "x");
IntVar z = solver.makeSum(x).var();
//
// constraints
//
// ensure that all cities are covered
for(int i = 0; i < num_cities; i++) {
ArrayList<IntVar> b = new ArrayList<IntVar>();
for(int j = 0; j < num_cities; j++) {
if (distance[i][j] <= min_distance) {
b.add(x[j]);
}
}
solver.addConstraint(
solver.makeSumGreaterOrEqual(b.toArray(new IntVar[1]), 1));
}
//
// objective
//
OptimizeVar objective = solver.makeMinimize(z, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db, objective);
//
// output
//
while (solver.nextSolution()) {
System.out.println("z: " + z.value());
System.out.print("x: ");
for(int i = 0; i < num_cities; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
SetCovering.solve();
}
}

View File

@@ -0,0 +1,126 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class SetCovering2 {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a set covering problem.
* See http://www.hakank.org/google_or_tools/set_covering2.py
*
*/
private static void solve() {
Solver solver = new Solver("SetCovering2");
//
// data
//
// Example 9.1-2 from
// Taha "Operations Research - An Introduction",
// page 354ff.
// Minimize the number of security telephones in street
// corners on a campus.
int n = 8; // maximum number of corners
int num_streets = 11; // number of connected streets
// corners of each street
// Note: 1-based (handled below)
int[][] corner = {{1,2},
{2,3},
{4,5},
{7,8},
{6,7},
{2,6},
{1,6},
{4,7},
{2,4},
{5,8},
{3,5}};
//
// variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, 1, "x");
// number of telephones, to be minimize
IntVar z = solver.makeSum(x).var();
//
// constraints
//
// ensure that all cities are covered
for(int i = 0; i < num_streets; i++) {
IntVar[] b = new IntVar[2];
b[0] = x[corner[i][0] - 1];
b[1] = x[corner[i][1] - 1];
solver.addConstraint(
solver.makeSumGreaterOrEqual(b, 1));
}
//
// objective
//
OptimizeVar objective = solver.makeMinimize(z, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db, objective);
//
// output
//
while (solver.nextSolution()) {
System.out.println("z: " + z.value());
System.out.print("x: ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
SetCovering2.solve();
}
}

View File

@@ -0,0 +1,137 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class SetCovering3 {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a set covering problem.
* See http://www.hakank.org/google_or_tools/set_covering3.py
*
*/
private static void solve() {
Solver solver = new Solver("SetCovering3");
//
// data
//
// Set covering problem from
// Katta G. Murty: 'Optimization Models for Decision Making',
// page 302f
// http://ioe.engin.umich.edu/people/fac/books/murty/opti_model/junior-7.pdf
int num_groups = 6;
int num_senators = 10;
// which group does a senator belong to?
int[][] belongs = {{1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 1 southern
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, // 2 northern
{0, 1, 1, 0, 0, 0, 0, 1, 1, 1}, // 3 liberals
{1, 0, 0, 0, 1, 1, 1, 0, 0, 0}, // 4 conservative
{0, 0, 1, 1, 1, 1, 1, 0, 1, 0}, // 5 democrats
{1, 1, 0, 0, 0, 0, 0, 1, 0, 1}}; // 6 republicans
//
// variables
//
IntVar[] x = solver.makeIntVarArray(num_senators, 0, 1, "x");
// number of assigned senators, to be minimize
IntVar z = solver.makeSum(x).var();
//
// constraints
//
// ensure that each group is covered by at least
// one senator
for(int i = 0; i < num_groups; i++) {
IntVar[] b = new IntVar[num_senators];
for(int j = 0; j < num_senators; j++) {
b[j] = solver.makeProd(x[j], belongs[i][j]).var();
}
solver.addConstraint(
solver.makeSumGreaterOrEqual(b, 1));
}
//
// objective
//
OptimizeVar objective = solver.makeMinimize(z, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db, objective);
//
// output
//
while (solver.nextSolution()) {
System.out.println("z: " + z.value());
System.out.print("x: ");
for(int j = 0; j < num_senators; j++) {
System.out.print(x[j].value() + " ");
}
System.out.println();
// More details
for(int j = 0; j < num_senators; j++) {
if (x[j].value() == 1) {
System.out.print("Senator " + (1 + j) +
" belongs to these groups: ");
for(int i = 0; i < num_groups; i++) {
if (belongs[i][j] == 1) {
System.out.print((1 + i) + " ");
}
}
System.out.println();
}
}
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
SetCovering3.solve();
}
}

View File

@@ -0,0 +1,141 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class SetCovering4 {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a set covering problem.
* See http://www.hakank.org/google_or_tools/set_covering4.py
*
*/
private static void solve(int set_partition) {
Solver solver = new Solver("SetCovering4");
//
// data
//
// Set partition and set covering problem from
// Example from the Swedish book
// Lundgren, Roennqvist, Vaebrand
// 'Optimeringslaera' (translation: 'Optimization theory'),
// page 408.
int num_alternatives = 10;
int num_objects = 8;
// costs for the alternatives
int[] costs = {19, 16, 18, 13, 15, 19, 15, 17, 16, 15};
// the alternatives, and their objects
int[][] a = {
// 1 2 3 4 5 6 7 8 the objects
{1,0,0,0,0,1,0,0}, // alternative 1
{0,1,0,0,0,1,0,1}, // alternative 2
{1,0,0,1,0,0,1,0}, // alternative 3
{0,1,1,0,1,0,0,0}, // alternative 4
{0,1,0,0,1,0,0,0}, // alternative 5
{0,1,1,0,0,0,0,0}, // alternative 6
{0,1,1,1,0,0,0,0}, // alternative 7
{0,0,0,1,1,0,0,1}, // alternative 8
{0,0,1,0,0,1,0,1}, // alternative 9
{1,0,0,0,0,1,1,0}}; // alternative 10
//
// variables
//
IntVar[] x = solver.makeIntVarArray(num_alternatives, 0, 1, "x");
// number of assigned senators, to be minimize
IntVar z = solver.makeScalProd(x, costs).var();
//
// constraints
//
for(int j = 0; j < num_objects; j++) {
IntVar[] b = new IntVar[num_alternatives];
for(int i = 0; i < num_alternatives; i++) {
b[i] = solver.makeProd(x[i], a[i][j]).var();
}
if (set_partition == 1) {
solver.addConstraint(
solver.makeSumGreaterOrEqual(b, 1));
} else {
solver.addConstraint(
solver.makeSumEquality(b, 1));
}
}
//
// objective
//
OptimizeVar objective = solver.makeMinimize(z, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db, objective);
//
// output
//
while (solver.nextSolution()) {
System.out.println("z: " + z.value());
System.out.print("Selected alternatives: ");
for(int i = 0; i < num_alternatives; i++) {
if (x[i].value() == 1) {
System.out.print((1 + i) + " ");
}
}
System.out.println("\n");
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
System.out.println("Set partition:");
SetCovering4.solve(1);
System.out.println("\nSet covering:");
SetCovering4.solve(0);
}
}

View File

@@ -0,0 +1,157 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.OptimizeVar;
public class SetCoveringDeployment {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a set covering deployment problem.
* See http://www.hakank.org/google_or_tools/set_covering_deployment.py
*
*/
private static void solve() {
Solver solver = new Solver("SetCoveringDeployment");
//
// data
//
// From http://mathworld.wolfram.com/SetCoveringDeployment.html
String[] countries = {"Alexandria",
"Asia Minor",
"Britain",
"Byzantium",
"Gaul",
"Iberia",
"Rome",
"Tunis"};
int n = countries.length;
// the incidence matrix (neighbours)
int[][] mat = {{0, 1, 0, 1, 0, 0, 1, 1},
{1, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 0, 0},
{1, 1, 0, 0, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 1, 1, 0},
{0, 0, 1, 0, 1, 0, 1, 1},
{1, 0, 0, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 1, 0}};
//
// variables
//
// First army
IntVar[] x = solver.makeIntVarArray(n, 0, 1, "x");
// Second (reserve) army
IntVar[] y = solver.makeIntVarArray(n, 0, 1, "y");
// total number of armies
IntVar num_armies = solver.makeSum(solver.makeSum(x),
solver.makeSum(y)).var();
//
// constraints
//
//
// Constraint 1: There is always an army in a city
// (+ maybe a backup)
// Or rather: Is there a backup, there
// must be an an army
//
for(int i = 0; i < n; i++) {
solver.addConstraint(solver.makeGreaterOrEqual(x[i], y[i]));
}
//
// Constraint 2: There should always be an backup
// army near every city
//
for(int i = 0; i < n; i++) {
ArrayList<IntVar> count_neighbours = new ArrayList<IntVar>();
for(int j = 0; j < n; j++) {
if (mat[i][j] == 1) {
count_neighbours.add(y[j]);
}
}
solver.addConstraint(
solver.makeGreaterOrEqual(
solver.makeSum(x[i],
solver.makeSum(
count_neighbours.toArray(new IntVar[1])).var()), 1));
}
//
// objective
//
OptimizeVar objective = solver.makeMinimize(num_armies, 1);
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db, objective);
//
// output
//
while (solver.nextSolution()) {
System.out.println("num_armies: " + num_armies.value());
for(int i = 0; i < n; i++) {
if (x[i].value() == 1) {
System.out.print("Army: " + countries[i] + " ");
}
if (y[i].value() == 1) {
System.out.println("Reserve army: " + countries[i]);
}
}
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
SetCoveringDeployment.solve();
}
}

View File

@@ -0,0 +1,89 @@
import java.util.ArrayList;
import com.google.ortools.constraintsolver.Assignment;
import com.google.ortools.constraintsolver.NodeEvaluator2;
import com.google.ortools.constraintsolver.RoutingModel;
import com.google.ortools.constraintsolver.FirstSolutionStrategy;
import com.google.ortools.constraintsolver.RoutingSearchParameters;
public class SimpleRoutingTest {
//Static Add Library
static { System.loadLibrary("jniortools"); }
private ArrayList<Integer> globalRes;
private long globalResCost;
private int[][] costMatrix;
public ArrayList<Integer> getGlobalRes() {return globalRes;}
public void setGlobalRes(ArrayList<Integer> globalRes) {this.globalRes = globalRes;}
public long getGlobalResCost() {return globalResCost;}
public void setGlobalResCost(int globalResCost) {this.globalResCost = globalResCost;}
public int[][] getCostMatrix() {return costMatrix;}
public void setCostMatrix(int[][] costMatrix) {this.costMatrix = costMatrix;}
public SimpleRoutingTest(int[][] costMatrix) {
super();
this.costMatrix = costMatrix;
globalRes = new ArrayList();
}
//Node Distance Evaluation
public static class NodeDistance extends NodeEvaluator2 {
private int[][] costMatrix;
public NodeDistance(int[][] costMatrix) {
this.costMatrix = costMatrix;
}
@Override
public long run(int firstIndex, int secondIndex) {
return costMatrix[firstIndex][secondIndex];
}
}
//Solve Method
public void solve() {
RoutingModel routing = new RoutingModel(costMatrix.length, 1, 0);
RoutingSearchParameters parameters =
RoutingSearchParameters.newBuilder()
.mergeFrom(RoutingModel.defaultSearchParameters())
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
.build();
NodeDistance distances = new NodeDistance(costMatrix);
routing.setArcCostEvaluatorOfAllVehicles(distances);
Assignment solution = routing.solve();
if (solution != null) {
int route_number = 0;
for (long node = routing.start(route_number); !routing.isEnd(node); node = solution.value(routing.nextVar(node))) {
globalRes.add((int) node);
}
}
globalResCost = solution.objectiveValue();
System.out.println("cost = " + globalResCost);
}
public static void main(String[] args) throws Exception {
int[][] values = new int[4][4];
values[0][0]=0;
values[0][1]=5;
values[0][2]=3;
values[0][3]=6;
values[1][0]=5;
values[1][1]=0;
values[1][2]=8;
values[1][3]=1;
values[2][0]=3;
values[2][1]=8;
values[2][2]=0;
values[2][3]=4;
values[3][0]=6;
values[3][1]=1;
values[3][2]=4;
values[3][3]=0;
SimpleRoutingTest model = new SimpleRoutingTest(values);
model.solve();
}
}

View File

@@ -0,0 +1,242 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class StableMarriage {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves some stable marriage problems.
* See http://www.hakank.org/google_or_tools/stable_marriage.py
*
*/
private static void solve(long[][][] ranks, String problem_name) {
Solver solver = new Solver("StableMarriage");
//
// data
//
System.out.println("\n#####################");
System.out.println("Problem: " + problem_name);
long[][] rankWomen = ranks[0];
long[][] rankMen = ranks[1];
int n = rankWomen.length;
//
// variables
//
IntVar[] wife = solver.makeIntVarArray(n, 0, n - 1, "wife");
IntVar[] husband = solver.makeIntVarArray(n, 0, n - 1, "husband");
//
// constraints
// (the comments are the Comet code)
// forall(m in Men)
// cp.post(husband[wife[m]] == m);
for(int m = 0; m < n; m++) {
solver.addConstraint(
solver.makeEquality(solver.makeElement(husband, wife[m]), m));
}
// forall(w in Women)
// cp.post(wife[husband[w]] == w);
for(int w = 0; w < n; w++) {
solver.addConstraint(
solver.makeEquality(solver.makeElement(wife, husband[w]), w));
}
// forall(m in Men, o in Women)
// cp.post(rankMen[m,o] < rankMen[m, wife[m]] =>
// rankWomen[o,husband[o]] < rankWomen[o,m]);
for(int m = 0; m < n; m++) {
for(int o = 0; o < n; o++) {
IntVar b1 = solver.makeIsGreaterCstVar(
solver.makeElement(rankMen[m], wife[m]).var(),
rankMen[m][o]);
IntVar b2 = solver.makeIsLessCstVar(
solver.makeElement(rankWomen[o], husband[o]).var(),
rankWomen[o][m]);
solver.addConstraint(
solver.makeLessOrEqual(
solver.makeDifference(b1, b2), 0));
}
}
// forall(w in Women, o in Men)
// cp.post(rankWomen[w,o] < rankWomen[w,husband[w]] =>
// rankMen[o,wife[o]] < rankMen[o,w]);
for(int w = 0; w < n; w++) {
for(int o = 0; o < n; o++) {
IntVar b1 = solver.makeIsGreaterCstVar(
solver.makeElement(rankWomen[w], husband[w]).var(),
rankWomen[w][o]);
IntVar b2 = solver.makeIsLessCstVar(
solver.makeElement(rankMen[o], wife[o]).var(),
rankMen[o][w]);
solver.addConstraint(
solver.makeLessOrEqual(
solver.makeDifference(b1, b2), 0));
}
}
//
// search
//
DecisionBuilder db = solver.makePhase(wife,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("wife : ");
for(int i = 0; i < n; i++) {
System.out.print(wife[i].value() + " ");
}
System.out.print("\nhusband: ");
for(int i = 0; i < n; i++) {
System.out.print(husband[i].value() + " ");
}
System.out.println("\n");
}
solver.endSearch();
// Statistics
// System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
//
// From Pascal Van Hentenryck's OPL book
//
long[][][] van_hentenryck = {
// rankWomen
{{1, 2, 4, 3, 5},
{3, 5, 1, 2, 4},
{5, 4, 2, 1, 3},
{1, 3, 5, 4, 2},
{4, 2, 3, 5, 1}},
// rankMen
{{5, 1, 2, 4, 3},
{4, 1, 3, 2, 5},
{5, 3, 2, 4, 1},
{1, 5, 4, 3, 2},
{4, 3, 2, 1, 5}}
};
//
// Data from MathWorld
// http://mathworld.wolfram.com/StableMarriageProblem.html
//
long[][][] mathworld = {
// rankWomen
{{3, 1, 5, 2, 8, 7, 6, 9, 4},
{9, 4, 8, 1, 7, 6, 3, 2, 5},
{3, 1, 8, 9, 5, 4, 2, 6, 7},
{8, 7, 5, 3, 2, 6, 4, 9, 1},
{6, 9, 2, 5, 1, 4, 7, 3, 8},
{2, 4, 5, 1, 6, 8, 3, 9, 7},
{9, 3, 8, 2, 7, 5, 4, 6, 1},
{6, 3, 2, 1, 8, 4, 5, 9, 7},
{8, 2, 6, 4, 9, 1, 3, 7, 5}},
// rankMen
{{7, 3, 8, 9, 6, 4, 2, 1, 5},
{5, 4, 8, 3, 1, 2, 6, 7, 9},
{4, 8, 3, 9, 7, 5, 6, 1, 2},
{9, 7, 4, 2, 5, 8, 3, 1, 6},
{2, 6, 4, 9, 8, 7, 5, 1, 3},
{2, 7, 8, 6, 5, 3, 4, 1, 9},
{1, 6, 2, 3, 8, 5, 4, 9, 7},
{5, 6, 9, 1, 2, 8, 4, 3, 7},
{6, 1, 4, 7, 5, 8, 3, 9, 2}}};
//
// Data from
// http://www.csee.wvu.edu/~ksmani/courses/fa01/random/lecnotes/lecture5.pdf
//
long[][][] problem3 = {
// rankWomen
{{1,2,3,4},
{4,3,2,1},
{1,2,3,4},
{3,4,1,2}},
// rankMen"
{{1,2,3,4},
{2,1,3,4},
{1,4,3,2},
{4,3,1,2}}};
//
// Data from
// http://www.comp.rgu.ac.uk/staff/ha/ZCSP/additional_problems/stable_marriage/stable_marriage.pdf
// page 4
//
long[][][] problem4 = {
// rankWomen
{{1,5,4,6,2,3},
{4,1,5,2,6,3},
{6,4,2,1,5,3},
{1,5,2,4,3,6},
{4,2,1,5,6,3},
{2,6,3,5,1,4}},
// rankMen
{{1,4,2,5,6,3},
{3,4,6,1,5,2},
{1,6,4,2,3,5},
{6,5,3,4,2,1},
{3,1,2,4,5,6},
{2,3,1,6,5,4}}};
StableMarriage.solve(van_hentenryck, "Van Hentenryck");
StableMarriage.solve(mathworld, "MathWorld");
StableMarriage.solve(problem3, "Problem 3");
StableMarriage.solve(problem4, "Problem 4");
}
}

300
examples/java/StiglerMIP.java Executable file
View File

@@ -0,0 +1,300 @@
/*
* Copyright 2017 Darian Sastre darian.sastre@minimaxlabs.com
* 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.
*
* ************************************************************************
*
* This model was created by Hakan Kjellerstrand (hakank@gmail.com)
*
* Java version by Darian Sastre (darian.sastre@minimaxlabs.com)
*/
import java.math.RoundingMode;
import java.text.DecimalFormat;
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
public class StiglerMIP {
static {
System.loadLibrary("jniortools");
}
private static MPSolver createSolver (String solverType) {
return new MPSolver("MIPDiet",
MPSolver.OptimizationProblemType.valueOf(solverType));
}
private static void solve(String solverType) {
MPSolver solver = createSolver(solverType);
double infinity = MPSolver.infinity();
/** invariants */
double days = 365.25;
int nutrientsCount = 9;
int commoditiesCount = 77;
String[] nutrients = {
"calories", // Calories, unit = 1000
"protein", // Protein, unit = grams
"calcium", // Calcium, unit = grams
"iron", // Iron, unit = milligrams
"vitaminA", // Vitamin A, unit = 1000 International Units
"thiamine", // Thiamine, Vit. B1, unit = milligrams
"riboflavin", // Riboflavin, Vit. B2, unit = milligrams
"niacin", // Niacin (Nicotinic Acid), unit = milligrams
"ascorbicAcid" // Ascorbic Acid, Vit. C, unit = milligrams
};
String[] commodities = {
"Wheat Flour (Enriched), 10 lb.",
"Macaroni, 1 lb.",
"Wheat Cereal (Enriched), 28 oz.",
"Corn Flakes, 8 oz.",
"Corn Meal, 1 lb.",
"Hominy Grits, 24 oz.",
"Rice, 1 lb.",
"Rolled Oats, 1 lb.",
"White Bread (Enriched), 1 lb.",
"Whole Wheat Bread, 1 lb.",
"Rye Bread, 1 lb.",
"Pound Cake, 1 lb.",
"Soda Crackers, 1 lb.",
"Milk, 1 qt.",
"Evaporated Milk (can), 14.5 oz.",
"Butter, 1 lb.",
"Oleomargarine, 1 lb.",
"Eggs, 1 doz.",
"Cheese (Cheddar), 1 lb.",
"Cream, 1/2 pt.",
"Peanut Butter, 1 lb.",
"Mayonnaise, 1/2 pt.",
"Crisco, 1 lb.",
"Lard, 1 lb.",
"Sirloin Steak, 1 lb.",
"Round Steak, 1 lb.",
"Rib Roast, 1 lb.",
"Chuck Roast, 1 lb.",
"Plate, 1 lb.",
"Liver (Beef), 1 lb.",
"Leg of Lamb, 1 lb.",
"Lamb Chops (Rib), 1 lb.",
"Pork Chops, 1 lb.",
"Pork Loin Roast, 1 lb.",
"Bacon, 1 lb.",
"Ham - smoked, 1 lb.",
"Salt Pork, 1 lb.",
"Roasting Chicken, 1 lb.",
"Veal Cutlets, 1 lb.",
"Salmon, Pink (can), 16 oz.",
"Apples, 1 lb.",
"Bananas, 1 lb.",
"Lemons, 1 doz.",
"Oranges, 1 doz.",
"Green Beans, 1 lb.",
"Cabbage, 1 lb.",
"Carrots, 1 bunch",
"Celery, 1 stalk",
"Lettuce, 1 head",
"Onions, 1 lb.",
"Potatoes, 15 lb.",
"Spinach, 1 lb.",
"Sweet Potatoes, 1 lb.",
"Peaches (can), No. 2 1/2",
"Pears (can), No. 2 1/2,",
"Pineapple (can), No. 2 1/2",
"Asparagus (can), No. 2",
"Grean Beans (can), No. 2",
"Pork and Beans (can), 16 oz.",
"Corn (can), No. 2",
"Peas (can), No. 2",
"Tomatoes (can), No. 2",
"Tomato Soup (can), 10 1/2 oz.",
"Peaches, Dried, 1 lb.",
"Prunes, Dried, 1 lb.",
"Raisins, Dried, 15 oz.",
"Peas, Dried, 1 lb.",
"Lima Beans, Dried, 1 lb.",
"Navy Beans, Dried, 1 lb.",
"Coffee, 1 lb.",
"Tea, 1/4 lb.",
"Cocoa, 8 oz.",
"Chocolate, 8 oz.",
"Sugar, 10 lb.",
"Corn Sirup, 24 oz.",
"Molasses, 18 oz.",
"Strawberry Preserve, 1 lb."
};
// price and weight per unit correspond to the two first columns
double[][] data = {
{36.0, 12600.0, 44.7, 1411.0, 2.0, 365.0, 0.0, 55.4, 33.3, 441.0, 0.0},
{14.1, 3217.0, 11.6, 418.0, 0.7, 54.0, 0.0, 3.2, 1.9, 68.0, 0.0},
{24.2, 3280.0, 11.8, 377.0, 14.4, 175.0, 0.0, 14.4, 8.8, 114.0, 0.0},
{7.1, 3194.0, 11.4, 252.0, 0.1, 56.0, 0.0, 13.5, 2.3, 68.0, 0.0},
{4.6, 9861.0, 36.0, 897.0, 1.7, 99.0, 30.9, 17.4, 7.9, 106.0, 0.0},
{8.5, 8005.0, 28.6, 680.0, 0.8, 80.0, 0.0, 10.6, 1.6, 110.0, 0.0},
{7.5, 6048.0, 21.2, 460.0, 0.6, 41.0, 0.0, 2.0, 4.8, 60.0, 0.0},
{7.1, 6389.0, 25.3, 907.0, 5.1, 341.0, 0.0, 37.1, 8.9, 64.0, 0.0},
{7.9, 5742.0, 15.6, 488.0, 2.5, 115.0, 0.0, 13.8, 8.5, 126.0, 0.0},
{9.1, 4985.0, 12.2, 484.0, 2.7, 125.0, 0.0, 13.9, 6.4, 160.0, 0.0},
{9.2, 4930.0, 12.4, 439.0, 1.1, 82.0, 0.0, 9.9, 3.0, 66.0, 0.0},
{24.8, 1829.0, 8.0, 130.0, 0.4, 31.0, 18.9, 2.8, 3.0, 17.0, 0.0},
{15.1, 3004.0, 12.5, 288.0, 0.5, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{11.0, 8867.0, 6.1, 310.0, 10.5, 18.0, 16.8, 4.0, 16.0, 7.0, 177.0},
{6.7, 6035.0, 8.4, 422.0, 15.1, 9.0, 26.0, 3.0, 23.5, 11.0, 60.0},
{20.8, 1473.0, 10.8, 9.0, 0.2, 3.0, 44.2, 0.0, 0.2, 2.0, 0.0},
{16.1, 2817.0, 20.6, 17.0, 0.6, 6.0, 55.8, 0.2, 0.0, 0.0, 0.0},
{32.6, 1857.0, 2.9, 238.0, 1.0, 52.0, 18.6, 2.8, 6.5, 1.0, 0.0},
{24.2, 1874.0, 7.4, 448.0, 16.4, 19.0, 28.1, 0.8, 10.3, 4.0, 0.0},
{14.1, 1689.0, 3.5, 49.0, 1.7, 3.0, 16.9, 0.6, 2.5, 0.0, 17.0},
{17.9, 2534.0, 15.7, 661.0, 1.0, 48.0, 0.0, 9.6, 8.1, 471.0, 0.0},
{16.7, 1198.0, 8.6, 18.0, 0.2, 8.0, 2.7, 0.4, 0.5, 0.0, 0.0},
{20.3, 2234.0, 20.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{9.8, 4628.0, 41.7, 0.0, 0.0, 0.0, 0.2, 0.0, 0.5, 5.0, 0.0},
{39.6, 1145.0, 2.9, 166.0, 0.1, 34.0, 0.2, 2.1, 2.9, 69.0, 0.0},
{36.4, 1246.0, 2.2, 214.0, 0.1, 32.0, 0.4, 2.5, 2.4, 87.0, 0.0},
{29.2, 1553.0, 3.4, 213.0, 0.1, 33.0, 0.0, 0.0, 2.0, 0.0, 0.0},
{22.6, 2007.0, 3.6, 309.0, 0.2, 46.0, 0.4, 1.0, 4.0, 120.0, 0.0},
{14.6, 3107.0, 8.5, 404.0, 0.2, 62.0, 0.0, 0.9, 0.0, 0.0, 0.0},
{26.8, 1692.0, 2.2, 333.0, 0.2, 139.0, 169.2, 6.4, 50.8, 316.0, 525.0},
{27.6, 1643.0, 3.1, 245.0, 0.1, 20.0, 0.0, 2.8, 3.0, 86.0, 0.0},
{36.6, 1239.0, 3.3, 140.0, 0.1, 15.0, 0.0, 1.7, 2.7, 54.0, 0.0},
{30.7, 1477.0, 3.5, 196.0, 0.2, 80.0, 0.0, 17.4, 2.7, 60.0, 0.0},
{24.2, 1874.0, 4.4, 249.0, 0.3, 37.0, 0.0, 18.2, 3.6, 79.0, 0.0},
{25.6, 1772.0, 10.4, 152.0, 0.2, 23.0, 0.0, 1.8, 1.8, 71.0, 0.0},
{27.4, 1655.0, 6.7, 212.0, 0.2, 31.0, 0.0, 9.9, 3.3, 50.0, 0.0},
{16.0, 2835.0, 18.8, 164.0, 0.1, 26.0, 0.0, 1.4, 1.8, 0.0, 0.0},
{30.3, 1497.0, 1.8, 184.0, 0.1, 30.0, 0.1, 0.9, 1.8, 68.0, 46.0},
{42.3, 1072.0, 1.7, 156.0, 0.1, 24.0, 0.0, 1.4, 2.4, 57.0, 0.0},
{13.0, 3489.0, 5.8, 705.0, 6.8, 45.0, 3.5, 1.0, 4.9, 209.0, 0.0},
{4.4, 9072.0, 5.8, 27.0, 0.5, 36.0, 7.3, 3.6, 2.7, 5.0, 544.0},
{6.1, 4982.0, 4.9, 60.0, 0.4, 30.0, 17.4, 2.5, 3.5, 28.0, 498.0},
{26.0, 2380.0, 1.0, 21.0, 0.5, 14.0, 0.0, 0.5, 0.0, 4.0, 952.0},
{30.9, 4439.0, 2.2, 40.0, 1.1, 18.0, 11.1, 3.6, 1.3, 10.0, 1993.0},
{7.1, 5750.0, 2.4, 138.0, 3.7, 80.0, 69.0, 4.3, 5.8, 37.0, 862.0},
{3.7, 8949.0, 2.6, 125.0, 4.0, 36.0, 7.2, 9.0, 4.5, 26.0, 5369.0},
{4.7, 6080.0, 2.7, 73.0, 2.8, 43.0, 188.5, 6.1, 4.3, 89.0, 608.0},
{7.3, 3915.0, 0.9, 51.0, 3.0, 23.0, 0.9, 1.4, 1.4, 9.0, 313.0},
{8.2, 2247.0, 0.4, 27.0, 1.1, 22.0, 112.4, 1.8, 3.4, 11.0, 449.0},
{3.6, 11844.0, 5.8, 166.0, 3.8, 59.0, 16.6, 4.7, 5.9, 21.0, 1184.0},
{34.0, 16810.0, 14.3, 336.0, 1.8, 118.0, 6.7, 29.4, 7.1, 198.0, 2522.0},
{8.1, 4592.0, 1.1, 106.0, 0.0, 138.0, 918.4, 5.7, 13.8, 33.0, 2755.0},
{5.1, 7649.0, 9.6, 138.0, 2.7, 54.0, 290.7, 8.4, 5.4, 83.0, 1912.0},
{16.8, 4894.0, 3.7, 20.0, 0.4, 10.0, 21.5, 0.5, 1.0, 31.0, 196.0},
{20.4, 4030.0, 3.0, 8.0, 0.3, 8.0, 0.8, 0.8, 0.8, 5.0, 81.0},
{21.3, 3993.0, 2.4, 16.0, 0.4, 8.0, 2.0, 2.8, 0.8, 7.0, 399.0},
{27.7, 1945.0, 0.4, 33.0, 0.3, 12.0, 16.3, 1.4, 2.1, 17.0, 272.0},
{10.0, 5386.0, 1.0, 54.0, 2.0, 65.0, 53.9, 1.6, 4.3, 32.0, 431.0},
{7.1, 6389.0, 7.5, 364.0, 4.0, 134.0, 3.5, 8.3, 7.7, 56.0, 0.0},
{10.4, 5452.0, 5.2, 136.0, 0.2, 16.0, 12.0, 1.6, 2.7, 42.0, 218.0},
{13.8, 4109.0, 2.3, 136.0, 0.6, 45.0, 34.9, 4.9, 2.5, 37.0, 370.0},
{8.6, 6263.0, 1.3, 63.0, 0.7, 38.0, 53.2, 3.4, 2.5, 36.0, 1253.0},
{7.6, 3917.0, 1.6, 71.0, 0.6, 43.0, 57.9, 3.5, 2.4, 67.0, 862.0},
{15.7, 2889.0, 8.5, 87.0, 1.7, 173.0, 86.8, 1.2, 4.3, 55.0, 57.0},
{9.0, 4284.0, 12.8, 99.0, 2.5, 154.0, 85.7, 3.9, 4.3, 65.0, 257.0},
{9.4, 4524.0, 13.5, 104.0, 2.5, 136.0, 4.5, 6.3, 1.4, 24.0, 136.0},
{7.9, 5742.0, 20.0, 1367.0, 4.2, 345.0, 2.9, 28.7, 18.4, 162.0, 0.0},
{8.9, 5097.0, 17.4, 1055.0, 3.7, 459.0, 5.1, 26.9, 38.2, 93.0, 0.0},
{5.9, 7688.0, 26.9, 1691.0, 11.4, 792.0, 0.0, 38.4, 24.6, 217.0, 0.0},
{22.4, 2025.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 5.1, 50.0, 0.0},
{17.4, 652.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.3, 42.0, 0.0},
{8.6, 2637.0, 8.7, 237.0, 3.0, 72.0, 0.0, 2.0, 11.9, 40.0, 0.0},
{16.2, 1400.0, 8.0, 77.0, 1.3, 39.0, 0.0, 0.9, 3.4, 14.0, 0.0},
{51.7, 8773.0, 34.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{13.7, 4996.0, 14.7, 0.0, 0.5, 74.0, 0.0, 0.0, 0.0, 5.0, 0.0},
{13.6, 3752.0, 9.0, 0.0, 10.3, 244.0, 0.0, 1.9, 7.5, 146.0, 0.0},
{20.5, 2213.0, 6.4, 11.0, 0.4, 7.0, 0.2, 0.2, 0.4, 3.0, 0.0}
};
// recommended daily nutritional allowance
double[] allowance = {3.0, 70.0, 0.8, 12.0, 5.0, 1.8, 2.7, 18.0, 75.0};
/** variables */
MPVariable[] x = solver.makeNumVarArray(commoditiesCount, 0, 1000);
MPVariable[] xCost = solver.makeNumVarArray(commoditiesCount, 0, 1000);
MPVariable[] quant = solver.makeNumVarArray(commoditiesCount, 0, 1000);
MPVariable totalCost = solver.makeNumVar(0, 1000, "total_cost");
/** constraints & objective */
MPObjective obj = solver.objective();
MPConstraint[] costConstraint = new MPConstraint[2 * commoditiesCount];
MPConstraint[] quantConstraint = new MPConstraint[2 * commoditiesCount];
MPConstraint totalCostConstraint = solver.makeConstraint(0, 0);
for (int i = 0; i < commoditiesCount; i ++) {
totalCostConstraint.setCoefficient(x[i], days);
costConstraint[i] = solver.makeConstraint(0, 0);
costConstraint[i].setCoefficient(x[i], days);
costConstraint[i].setCoefficient(xCost[i], -1);
quantConstraint[i] = solver.makeConstraint(0, 0);
quantConstraint[i].setCoefficient(x[i], days * 100 / data[i][0]);
quantConstraint[i].setCoefficient(quant[i], -1);
obj.setCoefficient(x[i], 1);
}
totalCostConstraint.setCoefficient(totalCost, -1);
MPConstraint[] nutrientConstraint = new MPConstraint[nutrientsCount];
for (int i = 0; i < nutrientsCount; i ++) {
nutrientConstraint[i] = solver.makeConstraint(allowance[i], infinity);
for (int j = 0; j < commoditiesCount; j ++) {
nutrientConstraint[i].setCoefficient(x[j], data[j][i+2]);
}
}
solver.solve();
/** printing */
DecimalFormat df = new DecimalFormat("#.##");
df.setRoundingMode(RoundingMode.CEILING);
System.out.println("Min cost: " + df.format(obj.value()));
System.out.println("Total cost: " + df.format(totalCost.solutionValue()));
for (int i = 0; i < commoditiesCount; i ++) {
if (x[i].solutionValue() > 0) {
System.out.println(commodities[i] + ": " + df.format(xCost[i].solutionValue()) + " " + df.format(quant[i].solutionValue()));
}
}
}
public static void main(String[] args) {
try {
System.out.println("---- Integer programming example with SCIP (recommended) ----");
solve("SCIP_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
try {
System.out.println("---- Integer programming example with CBC ----");
solve("CBC_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
try {
System.out.println("---- Integer programming example with GLPK ----");
solve("GLPK_MIXED_INTEGER_PROGRAMMING");
} catch (java.lang.IllegalArgumentException e) {
System.err.println("Bad solver type: " + e);
}
}
}

158
examples/java/Strimko2.java Normal file
View File

@@ -0,0 +1,158 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class Strimko2 {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a Strimko problem.
* See http://www.hakank.org/google_or_tools/strimko2.py
*
*/
private static void solve() {
Solver solver = new Solver("Strimko2");
//
// data
//
int[][] streams = {{1,1,2,2,2,2,2},
{1,1,2,3,3,3,2},
{1,4,1,3,3,5,5},
{4,4,3,1,3,5,5},
{4,6,6,6,7,7,5},
{6,4,6,4,5,5,7},
{6,6,4,7,7,7,7}};
// Note: This is 1-based
int[][] placed = {{2,1,1},
{2,3,7},
{2,5,6},
{2,7,4},
{3,2,7},
{3,6,1},
{4,1,4},
{4,7,5},
{5,2,2},
{5,6,6}};
int n = streams.length;
int num_placed = placed.length;
//
// variables
//
IntVar[][] x = new IntVar[n][n];
IntVar[] x_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
x[i][j] = solver.makeIntVar(1, n, "x[" + i + "," + j + "]");
x_flat[i * n + j] = x[i][j];
}
}
//
// constraints
//
// all rows and columns must be unique, i.e. a Latin Square
for(int i = 0; i < n; i++) {
IntVar[] row = new IntVar[n];
IntVar[] col = new IntVar[n];
for(int j = 0; j < n; j++) {
row[j] = x[i][j];
col[j] = x[j][i];
}
solver.addConstraint(solver.makeAllDifferent(row));
solver.addConstraint(solver.makeAllDifferent(col));
}
// streams
for(int s = 1; s <= n; s++) {
ArrayList<IntVar> tmp = new ArrayList<IntVar>();
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if (streams[i][j] == s) {
tmp.add(x[i][j]);
}
}
}
solver.addConstraint(
solver.makeAllDifferent(tmp.toArray(new IntVar[1])));
}
// placed
for(int i = 0; i < num_placed; i++) {
// note: also adjust to 0-based
solver.addConstraint(
solver.makeEquality(x[placed[i][0] - 1][placed[i][1] - 1],
placed[i][2]));
}
//
// search
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.INT_VAR_DEFAULT,
solver.INT_VALUE_DEFAULT);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(x[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Strimko2.solve();
}
}

136
examples/java/Sudoku.java Normal file
View File

@@ -0,0 +1,136 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class Sudoku {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves a Sudoku problem.
*
*/
private static void solve() {
Solver solver = new Solver("Sudoku");
int cell_size = 3;
int n = cell_size * cell_size;
// 0 marks an unknown value
int[][] initial_grid = new int[][] {{0, 6, 0, 0, 5, 0, 0, 2, 0},
{0, 0, 0, 3, 0, 0, 0, 9, 0},
{7, 0, 0, 6, 0, 0, 0, 1, 0},
{0, 0, 6, 0, 3, 0, 4, 0, 0},
{0, 0, 4, 0, 7, 0, 1, 0, 0},
{0, 0, 5, 0, 9, 0, 8, 0, 0},
{0, 4, 0, 0, 0, 1, 0, 0, 6},
{0, 3, 0, 0, 0, 8, 0, 0, 0},
{0, 2, 0, 0, 4, 0, 0, 5, 0}};
//
// variables
//
IntVar[][] grid = new IntVar[n][n];
IntVar[] grid_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
grid[i][j] = solver.makeIntVar(1, 9, "grid[" + i +"," + j + "]");
grid_flat[i * n + j] = grid[i][j];
}
}
//
// constraints
//
// init and rows
for(int i = 0; i < n; i++) {
IntVar[] row = new IntVar[n];
for(int j = 0; j < n; j++) {
if (initial_grid[i][j] > 0) {
solver.addConstraint(
solver.makeEquality(grid[i][j], initial_grid[i][j]));
}
row[j] = grid[i][j];
}
solver.addConstraint(solver.makeAllDifferent(row));
}
// columns
for(int j = 0; j < n; j++) {
IntVar[] col = new IntVar[n];
for(int i = 0; i < n; i++) {
col[i] = grid[i][j];
}
solver.addConstraint(solver.makeAllDifferent(col));
}
// cells
for(int i = 0; i < cell_size; i++) {
for(int j = 0; j < cell_size; j++) {
IntVar[] cell = new IntVar[n];
for(int di = 0; di < cell_size; di++) {
for(int dj = 0; dj < cell_size; dj++) {
cell[di * cell_size + dj] =
grid[i * cell_size + di][j * cell_size + dj];
}
}
solver.addConstraint(solver.makeAllDifferent(cell));
}
}
//
// Search
//
DecisionBuilder db = solver.makePhase(grid_flat,
solver.INT_VAR_SIMPLE,
solver.INT_VALUE_SIMPLE);
solver.newSearch(db);
while (solver.nextSolution()) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.print(grid[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Sudoku.solve();
}
}

View File

@@ -0,0 +1,248 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class SurvoPuzzle {
static {
System.loadLibrary("jniortools");
}
/*
* default problem
*/
static int default_r = 3;
static int default_c = 4;
static int[] default_rowsums = {30, 18, 30};
static int[] default_colsums = {27, 16, 10, 25};
static int[][] default_game = {{0, 6, 0, 0},
{8, 0, 0, 0},
{0, 0, 3, 0}};
// for the actual problem
static int r;
static int c;
static int[] rowsums;
static int[] colsums;
static int[][] game;
/**
*
* Solves the Survo puzzle problem.
* See http://www.hakank.org/google_or_tools/survo_puzzle.py
*
*/
private static void solve() {
Solver solver = new Solver("Survopuzzle");
//
// data
//
System.out.println("Problem:");
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
System.out.print(game[i][j] + " ");
}
System.out.println();
}
System.out.println();
//
// Variables
//
IntVar[][] x = new IntVar[r][c];
IntVar[] x_flat = new IntVar[r * c]; // for branching
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
x[i][j] = solver.makeIntVar(1, r * c, "x[" + i + "," + j + "]");
x_flat[i * c + j] = x[i][j];
}
}
//
// Constraints
//
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
if (game[i][j] > 0) {
solver.addConstraint(
solver.makeEquality(x[i][j], game[i][j]));
}
}
}
solver.addConstraint(solver.makeAllDifferent(x_flat));
//
// calculate rowsums and colsums
//
for(int i = 0; i < r; i++) {
IntVar[] row = new IntVar[c];
for(int j = 0; j < c; j++) {
row[j] = x[i][j];
}
solver.addConstraint(
solver.makeEquality(solver.makeSum(row).var(), rowsums[i]));
}
for(int j = 0; j < c; j++) {
IntVar[] col = new IntVar[r];
for(int i = 0; i < r; i++) {
col[i] = x[i][j];
}
solver.addConstraint(
solver.makeEquality(solver.makeSum(col).var(), colsums[j]));
}
//
// Search
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.INT_VAR_SIMPLE,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
int sol = 0;
while (solver.nextSolution()) {
sol++;
System.out.println("Solution #" + sol + ":");
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
System.out.print(x[i][j].value() + " ");
}
System.out.println();
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
/**
*
* readFile()
*
* Reads a Survo puzzle in the following format
* r
* c
* rowsums
* olsums
* data
* ...
*
* Example:
* 3
* 4
* 30,18,30
* 27,16,10,25
* 0,6,0,0
* 8,0,0,0
* 0,0,3,0
*
*/
private static void readFile(String file) {
System.out.println("readFile(" + file + ")");
try {
BufferedReader inr = new BufferedReader(new FileReader(file));
r = Integer.parseInt(inr.readLine());
c = Integer.parseInt(inr.readLine());
rowsums = new int[r];
colsums = new int[c];
System.out.println("r: " + r + " c: " + c);
String[] rowsums_str = inr.readLine().split(",\\s*");
String[] colsums_str = inr.readLine().split(",\\s*");
System.out.println("rowsums:");
for(int i = 0; i < r; i++) {
System.out.print(rowsums_str[i] + " ");
rowsums[i] = Integer.parseInt(rowsums_str[i]);
}
System.out.println("\ncolsums:");
for(int j = 0; j < c; j++) {
System.out.print(colsums_str[j] + " ");
colsums[j] = Integer.parseInt(colsums_str[j]);
}
System.out.println();
// init the game matrix and read data from file
game = new int[r][c];
String str;
int line_count = 0;
while ((str = inr.readLine()) != null && str.length() > 0) {
str = str.trim();
// ignore comments
// starting with either # or %
if(str.startsWith("#") || str.startsWith("%")) {
continue;
}
String this_row[] = str.split(",\\s*");
for(int j = 0; j < this_row.length; j++) {
game[line_count][j] = Integer.parseInt(this_row[j]);
}
line_count++;
} // end while
inr.close();
} catch (IOException e) {
System.out.println(e);
}
} // end readFile
public static void main(String[] args) throws Exception {
if (args.length > 0) {
String file = args[0];
SurvoPuzzle.readFile(file);
} else {
r = default_r;
c = default_c;
game = default_game;
rowsums = default_rowsums;
colsums = default_colsums;
}
SurvoPuzzle.solve();
}
}

115
examples/java/ToNum.java Normal file
View File

@@ -0,0 +1,115 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class ToNum {
static {
System.loadLibrary("jniortools");
}
/**
*
* toNum(solver, a, num, base)
*
* channelling between the array a and the number num
*
*/
private static void toNum(Solver solver, IntVar[] a, IntVar num, int base) {
int len = a.length;
IntVar[] tmp = new IntVar[len];
for(int i = 0; i < len; i++) {
tmp[i] = solver.makeProd(a[i], (int)Math.pow(base,(len-i-1))).var();
}
solver.addConstraint(
solver.makeEquality(solver.makeSum(tmp).var(), num));
}
/**
*
* Implements toNum: channeling between a number and an array.
* See http://www.hakank.org/google_or_tools/toNum.py
*
*/
private static void solve() {
Solver solver = new Solver("ToNum");
int n = 5;
int base = 10;
//
// variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, base - 1, "x");
IntVar num = solver.makeIntVar(0, (int)Math.pow(base, n) - 1 , "num");
//
// constraints
//
solver.addConstraint(solver.makeAllDifferent(x));
toNum(solver, x, num, base);
// extra constraint (just for fun):
// second digit should be 7
// solver.addConstraint(solver.makeEquality(x[1], 7));
//
// search
//
DecisionBuilder db = solver.makePhase(x,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("num: " + num.value() + ": ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
ToNum.solve();
}
}

131
examples/java/Tsp.java Normal file
View File

@@ -0,0 +1,131 @@
//
// Copyright 2012 Google
//
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.Assignment;
import com.google.ortools.constraintsolver.NodeEvaluator2;
import com.google.ortools.constraintsolver.RoutingModel;
import com.google.ortools.constraintsolver.FirstSolutionStrategy;
import com.google.ortools.constraintsolver.RoutingSearchParameters;
class Tsp {
static {
System.loadLibrary("jniortools");
}
static class RandomManhattan extends NodeEvaluator2 {
public RandomManhattan(int size, int seed) {
this.xs = new int[size];
this.ys = new int[size];
Random generator = new Random(seed);
for (int i = 0; i < size; ++i) {
xs[i] = generator.nextInt(1000);
ys[i] = generator.nextInt(1000);
}
}
@Override
public long run(int firstIndex, int secondIndex) {
return Math.abs(xs[firstIndex] - xs[secondIndex]) +
Math.abs(ys[firstIndex] - ys[secondIndex]);
}
private int[] xs;
private int[] ys;
}
static class ConstantCallback extends NodeEvaluator2 {
@Override
public long run(int firstIndex, int secondIndex) {
return 1;
}
}
static void solve(int size, int forbidden, int seed)
{
RoutingModel routing = new RoutingModel(size, 1, 0);
// Setting the cost function.
// Put a permanent callback to the distance accessor here. The callback
// has the following signature: ResultCallback2<int64, int64, int64>.
// The two arguments are the from and to node inidices.
NodeEvaluator2 distances = new RandomManhattan(size, seed);
routing.setArcCostEvaluatorOfAllVehicles(distances);
// Forbid node connections (randomly).
Random randomizer = new Random();
long forbidden_connections = 0;
while (forbidden_connections < forbidden) {
long from = randomizer.nextInt(size - 1);
long to = randomizer.nextInt(size - 1) + 1;
if (routing.nextVar(from).contains(to)) {
System.out.println("Forbidding connection " + from + " -> " + to);
routing.nextVar(from).removeValue(to);
++forbidden_connections;
}
}
// Add dummy dimension to test API.
routing.addDimension(
new ConstantCallback(),
size + 1,
size + 1,
true,
"dummy");
// Solve, returns a solution if any (owned by RoutingModel).
RoutingSearchParameters search_parameters =
RoutingSearchParameters.newBuilder()
.mergeFrom(RoutingModel.defaultSearchParameters())
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
.build();
Assignment solution = routing.solveWithParameters(search_parameters);
if (solution != null) {
// Solution cost.
System.out.println("Cost = " + solution.objectiveValue());
// Inspect solution.
// Only one route here; otherwise iterate from 0 to routing.vehicles() - 1
int route_number = 0;
for (long node = routing.start(route_number);
!routing.isEnd(node);
node = solution.value(routing.nextVar(node))) {
System.out.print("" + node + " -> ");
}
System.out.println("0");
}
}
public static void main(String[] args) throws Exception {
int size = 10;
if (args.length > 0) {
size = Integer.parseInt(args[0]);
}
int forbidden = 0;
if (args.length > 1) {
forbidden = Integer.parseInt(args[1]);
}
int seed = 0;
if (args.length > 2) {
seed = Integer.parseInt(args[2]);
}
solve(size, forbidden, seed);
}
}

View File

@@ -0,0 +1,205 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class WhoKilledAgatha {
static {
System.loadLibrary("jniortools");
}
/**
*
* Implements the Who killed Agatha problem.
* See http://www.hakank.org/google_or_tools/who_killed_agatha.py
*
*/
private static void solve() {
Solver solver = new Solver("WhoKilledAgatha");
//
// data
//
final int n = 3;
final int agatha = 0;
final int butler = 1;
final int charles = 2;
String[] names = {"Agatha", "Butler", "Charles"};
//
// variables
//
IntVar the_killer = solver.makeIntVar(0, 2, "the_killer");
IntVar the_victim = solver.makeIntVar(0, 2, "the_victim");
IntVar[] all = new IntVar[2 * n * n]; // for branching
IntVar[][] hates = new IntVar[n][n];
IntVar[] hates_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
hates[i][j] = solver.makeIntVar(0, 1, "hates[" + i + "," + j + "]");
hates_flat[i * n + j] = hates[i][j];
all[i * n + j] = hates[i][j];
}
}
IntVar[][] richer = new IntVar[n][n];
IntVar[] richer_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
richer[i][j] = solver.makeIntVar(0, 1, "richer[" + i + "," + j + "]");
richer_flat[i * n + j] = richer[i][j];
all[(n * n) + (i * n + j)] = richer[i][j];
}
}
//
// constraints
//
// Agatha, the butler, and Charles live in Dreadsbury Mansion, and
// are the only ones to live there.
// A killer always hates, and is no richer than his victim.
// hates[the_killer, the_victim] == 1
// hates_flat[the_killer * n + the_victim] == 1
solver.addConstraint(
solver.makeEquality(
solver.makeElement(
hates_flat,
solver.makeSum(
solver.makeProd(the_killer, n).var(),
the_victim).var()).var(), 1));
// richer[the_killer, the_victim] == 0
solver.addConstraint(
solver.makeEquality(
solver.makeElement(
richer_flat,
solver.makeSum(
solver.makeProd(the_killer, n).var(),
the_victim).var()).var(), 0));
// define the concept of richer:
// no one is richer than him-/herself...
for(int i = 0; i < n; i++) {
solver.addConstraint(solver.makeEquality(richer[i][i], 0));
}
// (contd...) if i is richer than j then j is not richer than i
// if (i != j) =>
// ((richer[i,j] = 1) <=> (richer[j,i] = 0))
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if (i != j) {
IntVar bi = solver.makeIsEqualCstVar(richer[i][j], 1);
IntVar bj = solver.makeIsEqualCstVar(richer[j][i], 0);
solver.addConstraint(solver.makeEquality(bi, bj));
}
}
}
// Charles hates no one that Agatha hates.
// forall i in 0..2:
// (hates[agatha, i] = 1) => (hates[charles, i] = 0)
for(int i = 0; i < n; i++) {
IntVar b1a = solver.makeIsEqualCstVar(hates[agatha][i], 1);
IntVar b1b = solver.makeIsEqualCstVar(hates[charles][i], 0);
solver.addConstraint(
solver.makeLessOrEqual(
solver.makeDifference(b1a, b1b).var(), 0));
}
// Agatha hates everybody except the butler.
solver.addConstraint(solver.makeEquality(hates[agatha][charles], 1));
solver.addConstraint(solver.makeEquality(hates[agatha][agatha], 1));
solver.addConstraint(solver.makeEquality(hates[agatha][butler], 0));
// The butler hates everyone not richer than Aunt Agatha.
// forall i in 0..2:
// (richer[i, agatha] = 0) => (hates[butler, i] = 1)
for(int i = 0; i < n; i++) {
IntVar b2a = solver.makeIsEqualCstVar(richer[i][agatha], 0);
IntVar b2b = solver.makeIsEqualCstVar(hates[butler][i], 1);
solver.addConstraint(
solver.makeLessOrEqual(
solver.makeDifference(b2a, b2b).var(), 0));
}
// The butler hates everyone whom Agatha hates.
// forall i : 0..2:
// (hates[agatha, i] = 1) => (hates[butler, i] = 1)
for(int i = 0; i < n; i++) {
IntVar b3a = solver.makeIsEqualCstVar(hates[agatha][i], 1);
IntVar b3b = solver.makeIsEqualCstVar(hates[butler][i], 1);
solver.addConstraint(
solver.makeLessOrEqual(
solver.makeDifference(b3a, b3b).var(), 0));
}
// Noone hates everyone.
// forall i in 0..2:
// (sum j in 0..2: hates[i,j]) <= 2
for(int i = 0; i < n; i++) {
IntVar[] tmp = new IntVar[n];
for(int j = 0; j < n; j++) {
tmp[j] = hates[i][j];
}
solver.addConstraint(
solver.makeLessOrEqual(solver.makeSum(tmp).var(), 2));
}
// Who killed Agatha?
solver.addConstraint(solver.makeEquality(the_victim, agatha));
//
// search
//
DecisionBuilder db = solver.makePhase(all,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.println("the_killer: " + names[(int)the_killer.value()]);
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
WhoKilledAgatha.solve();
}
}

84
examples/java/Xkcd.java Normal file
View File

@@ -0,0 +1,84 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
import com.google.ortools.constraintsolver.*;
public class Xkcd {
static {
System.loadLibrary("jniortools");
}
/**
*
* Solves the xkcd problem.
* See http://www.hakank.org/google_or_tools/xkcd.py
*
*/
private static void solve() {
Solver solver = new Solver("Xkcd");
int n = 6;
// for price and total: multiplied by 100 to be able to use integers
int[]price = {215, 275, 335, 355, 420, 580};
int total = 1505;
//
// Variables
//
IntVar[] x = solver.makeIntVarArray(n, 0, 10, "x");
//
// Constraints
//
solver.addConstraint(
solver.makeEquality(solver.makeScalProd(x, price).var(), total));
//
// Search
//
DecisionBuilder db = solver.makePhase(x,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
while (solver.nextSolution()) {
System.out.print("x: ");
for(int i = 0; i < n; i++) {
System.out.print(x[i].value() + " ");
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
Xkcd.solve();
}
}

View File

@@ -0,0 +1,155 @@
// Copyright 2011 Hakan Kjellerstrand hakank@gmail.com
// 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.
import java.io.*;
import java.util.*;
import java.text.*;
import com.google.ortools.constraintsolver.DecisionBuilder;
import com.google.ortools.constraintsolver.IntVar;
import com.google.ortools.constraintsolver.Solver;
public class YoungTableaux {
static {
System.loadLibrary("jniortools");
}
/**
*
* Implements Young tableaux and partitions.
* See http://www.hakank.org/google_or_tools/young_tableuax.py
*
*/
private static void solve(int n) {
Solver solver = new Solver("YoungTableaux");
System.out.println("n: " + n);
//
// variables
//
IntVar[][] x = new IntVar[n][n];
IntVar[] x_flat = new IntVar[n * n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
x[i][j] = solver.makeIntVar(1, n + 1, "x[" + i + "," + j + "]");
x_flat[i * n + j] = x[i][j];
}
}
// partition structure
IntVar[] p = solver.makeIntVarArray(n, 0, n + 1, "p");
//
// constraints
//
// 1..n is used exactly once
for(int i = 1; i <= n; i++) {
solver.addConstraint(solver.makeCount(x_flat, i, 1));
}
solver.addConstraint(solver.makeEquality(x[0][0], 1));
// row wise
for(int i = 0; i < n; i++) {
for(int j = 1; j < n; j++) {
solver.addConstraint(
solver.makeGreaterOrEqual(x[i][j], x[i][j - 1]));
}
}
// column wise
for(int j = 0; j < n; j++) {
for(int i = 1; i < n; i++) {
solver.addConstraint(
solver.makeGreaterOrEqual(x[i][j], x[i - 1][j]));
}
}
// calculate the structure (i.e. the partition)
for(int i = 0; i < n; i++) {
IntVar[] b = new IntVar[n];
for(int j = 0; j < n; j++) {
b[j] = solver.makeIsLessOrEqualCstVar(x[i][j], n);
}
solver.addConstraint(
solver.makeEquality(p[i], solver.makeSum(b).var()));
}
solver.addConstraint(
solver.makeEquality(solver.makeSum(p).var(), n));
for(int i = 1; i < n; i++) {
solver.addConstraint(solver.makeGreaterOrEqual(p[i - 1], p[i]));
}
//
// search
//
DecisionBuilder db = solver.makePhase(x_flat,
solver.CHOOSE_FIRST_UNBOUND,
solver.ASSIGN_MIN_VALUE);
solver.newSearch(db);
//
// output
//
while (solver.nextSolution()) {
System.out.print("p: ");
for(int i = 0; i < n; i++) {
System.out.print(p[i].value() + " ");
}
System.out.println("\nx:");
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
long val = x[i][j].value();
if (val <= n) {
System.out.print(val + " ");
}
}
if (p[i].value() > 0) {
System.out.println();
}
}
System.out.println();
}
solver.endSearch();
// Statistics
System.out.println();
System.out.println("Solutions: " + solver.solutions());
System.out.println("Failures: " + solver.failures());
System.out.println("Branches: " + solver.branches());
System.out.println("Wall time: " + solver.wallTime() + "ms");
}
public static void main(String[] args) throws Exception {
int n = 5;
if (args.length > 0) {
n = Integer.parseInt(args[0]);
}
YoungTableaux.solve(n);
}
}