mimic C++ linear API in java for CP-SAT

This commit is contained in:
Laurent Perron
2019-05-06 16:47:58 +02:00
parent 70574490ba
commit 2594fa858d
14 changed files with 270 additions and 274 deletions

View File

@@ -129,29 +129,15 @@ public class CpModel {
// Linear constraints.
/** Add {@code lb <= sum(vars) <= ub}. */
public Constraint addSumConstraint(IntVar[] vars, long lb, long ub) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
for (IntVar var : vars) {
lin.addVars(var.getIndex());
lin.addCoeffs(1);
}
lin.addDomain(lb);
lin.addDomain(ub);
return ct;
}
/**
* Add {@code sum(vars) in domain}, where domain is a flattened list of intervals similar to the
* one for enumerated integer variables.
* Adds {@code expr in domain}.
*/
public Constraint addSumInDomain(IntVar[] vars, Domain domain) {
public Constraint addLinearExpressionInDomain(LinearExpr expr, Domain domain) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
for (IntVar var : vars) {
lin.addVars(var.getIndex());
lin.addCoeffs(1);
for (int i = 0; i < expr.numElements(); ++i) {
lin.addVars(expr.getVariable(i).getIndex());
lin.addCoeffs(expr.getCoefficient(i));
}
for (long b : domain.flattenedIntervals()) {
lin.addDomain(b);
@@ -159,201 +145,75 @@ public class CpModel {
return ct;
}
/** Add {@code sum(vars) == value}. */
public Constraint addSumEqual(IntVar[] vars, long value) {
return addSumConstraint(vars, value, value);
/** Adds {@code lb <= expr <= ub}. */
public Constraint addLinearConstraint(LinearExpr expr, long lb, long ub) {
return addLinearExpressionInDomain(expr, new Domain(lb, ub));
}
/** Add {@code sum(vars) == target}. */
public Constraint addSumEqual(IntVar[] vars, IntVar target) {
int size = vars.length;
IntVar[] newVars = new IntVar[size + 1];
long[] coeffs = new long[size + 1];
for (int i = 0; i < size; ++i) {
newVars[i] = vars[i];
coeffs[i] = 1;
}
newVars[size] = target;
coeffs[size] = -1;
return addLinearConstraint(newVars, coeffs, 0, 0);
/** Adds {@code expr == value}. */
public Constraint addEquality(LinearExpr expr, long value) {
return addLinearExpressionInDomain(expr, new Domain(value));
}
/** Add {@code lb <= sum(vars[i] * coeffs[i]) <= ub}. */
public Constraint addLinearConstraint(IntVar[] vars, long[] coeffs, long lb, long ub) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
for (IntVar var : vars) {
lin.addVars(var.getIndex());
}
for (long c : coeffs) {
lin.addCoeffs(c);
}
lin.addDomain(lb);
lin.addDomain(ub);
return ct;
/** Adds {@code left == right}. */
public Constraint addEquality(LinearExpr left, LinearExpr right) {
return addLinearExpressionInDomain(new Difference(left, right), new Domain(0));
}
/** Add {@code lb <= sum(vars[i] * coeffs[i]) <= ub}. */
public Constraint addLinearConstraint(IntVar[] vars, int[] coeffs, long lb, long ub) {
return addLinearConstraint(vars, toLongArray(coeffs), lb, ub);
/** Adds {@code left + offset == right}. */
public Constraint addEqualityWithOffset(LinearExpr left, LinearExpr right, long offset) {
return addLinearExpressionInDomain(new Difference(left, right), new Domain(-offset));
}
/**
* Add {@code sum(vars[i] * coeffs[i]) in domain}, where domain is a flattened list of intervals
* similar to the one for enumerated integer variables.
*/
public Constraint addLinearExpressionInDomain(IntVar[] vars, long[] coeffs, Domain domain) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
for (IntVar var : vars) {
lin.addVars(var.getIndex());
}
for (long c : coeffs) {
lin.addCoeffs(c);
}
for (long b : domain.flattenedIntervals()) {
lin.addDomain(b);
}
return ct;
/** Adds {@code expr <= value}. */
public Constraint addLessOrEqual(LinearExpr expr, long value) {
return addLinearExpressionInDomain(expr, new Domain(Long.MIN_VALUE, value));
}
/** Add {@code sum(vars[i] * coeffs[i]) == value}. */
public Constraint addLinearExpressionEqual(IntVar[] vars, long[] coeffs, long value) {
return addLinearConstraint(vars, coeffs, value, value);
/** Adds {@code left <= right}. */
public Constraint addLessOrEqual(LinearExpr left, LinearExpr right) {
return addLinearExpressionInDomain(new Difference(left, right),
new Domain(Long.MIN_VALUE, 0));
}
/** Add {@code sum(vars[i] * coeffs[i]) == value}. */
public Constraint addLinearExpressionEqual(IntVar[] vars, int[] coeffs, long value) {
return addLinearConstraint(vars, toLongArray(coeffs), value, value);
/** Adds {@code left + offset <= right}. */
public Constraint addLessOrEqualWithOffset(LinearExpr left, LinearExpr right, long offset) {
return addLinearExpressionInDomain(new Difference(left, right),
new Domain(Long.MIN_VALUE, -offset));
}
/** Add {@code sum(vars[i] * coeffs[i]) == target}. */
public Constraint addLinearExpressionEqual(IntVar[] vars, long[] coeffs, IntVar target) {
int size = vars.length;
IntVar[] newVars = new IntVar[size + 1];
long[] newCoeffs = new long[size + 1];
for (int i = 0; i < size; ++i) {
newVars[i] = vars[i];
newCoeffs[i] = coeffs[i];
}
newVars[size] = target;
newCoeffs[size] = -1;
return addLinearConstraint(newVars, newCoeffs, 0, 0);
/** Adds {@code expr >= value}. */
public Constraint addGreaterOrEqual(LinearExpr expr, long value) {
return addLinearExpressionInDomain(expr, new Domain(value, Long.MAX_VALUE));
}
/** Add {@code sum(vars[i] * coeffs[i]) == target}. */
public Constraint addLinearExpressionEqual(IntVar[] vars, int[] coeffs, IntVar target) {
return addLinearExpressionEqual(vars, toLongArray(coeffs), target);
/** Adds {@code left >= right}. */
public Constraint addGreaterOrEqual(LinearExpr left, LinearExpr right) {
return addLinearExpressionInDomain(new Difference(left, right), new Domain(0, Long.MAX_VALUE));
}
/** Adds {@code left + offset >= right}. */
public Constraint addGreaterOrEqualWithOffset(LinearExpr left, LinearExpr right, long offset) {
return addLinearExpressionInDomain(new Difference(left, right),
new Domain(-offset, Long.MAX_VALUE));
}
/** Adds {@code expr != value}. */
public Constraint addDifferent(LinearExpr expr, long value) {
return addLinearExpressionInDomain(expr, Domain.fromFlatIntervals(
new long[] {Long.MIN_VALUE, value - 1, value + 1, Long.MAX_VALUE}));
}
/** Adds {@code var <= value}. */
public Constraint addLessOrEqual(IntVar var, long value) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(var.getIndex());
lin.addCoeffs(1);
lin.addDomain(java.lang.Long.MIN_VALUE);
lin.addDomain(value);
return ct;
/** Adds {@code left != right}. */
public Constraint addDifferent(IntVar left, IntVar right) {
return addLinearExpressionInDomain(new Difference(left, right), Domain.fromFlatIntervals(
new long[] {Long.MIN_VALUE, -1, 1, Long.MAX_VALUE}));
}
/** Adds {@code before <= after}. */
public Constraint addLessOrEqual(IntVar before, IntVar after) {
return addLessOrEqualWithOffset(before, after, 0);
}
/** Adds {@code var >= value}. */
public Constraint addGreaterOrEqual(IntVar var, long value) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(var.getIndex());
lin.addCoeffs(1);
lin.addDomain(value);
lin.addDomain(java.lang.Long.MAX_VALUE);
return ct;
}
/** Adds {@code var == value}. */
public Constraint addEquality(IntVar var, long value) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(var.getIndex());
lin.addCoeffs(1);
lin.addDomain(value);
lin.addDomain(value);
return ct;
}
/** Adds {@code a == b}. */
public Constraint addEquality(IntVar a, IntVar b) {
return addEqualityWithOffset(a, b, 0);
}
/** Adds {@code a + offset == b}. */
public Constraint addEqualityWithOffset(IntVar a, IntVar b, long offset) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(a.getIndex());
lin.addCoeffs(-1);
lin.addVars(b.getIndex());
lin.addCoeffs(1);
lin.addDomain(offset);
lin.addDomain(offset);
return ct;
}
/** Adds {@code var != value}. */
public Constraint addDifferent(IntVar var, long value) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(var.getIndex());
lin.addCoeffs(1);
if (value > java.lang.Long.MIN_VALUE) {
lin.addDomain(java.lang.Long.MIN_VALUE);
lin.addDomain(value - 1);
}
if (value < java.lang.Long.MAX_VALUE) {
lin.addDomain(value + 1);
lin.addDomain(java.lang.Long.MAX_VALUE);
}
return ct;
}
/** Adds {@code a != b}. */
public Constraint addDifferent(IntVar a, IntVar b) {
return addDifferentWithOffset(a, b, 0);
}
/** Adds {@code a + offset != b} */
public Constraint addDifferentWithOffset(IntVar a, IntVar b, long offset) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(a.getIndex());
lin.addCoeffs(-1);
lin.addVars(b.getIndex());
lin.addCoeffs(1);
if (offset > java.lang.Long.MIN_VALUE) {
lin.addDomain(java.lang.Long.MIN_VALUE);
lin.addDomain(offset - 1);
}
if (offset < java.lang.Long.MAX_VALUE) {
lin.addDomain(offset + 1);
lin.addDomain(java.lang.Long.MAX_VALUE);
}
return ct;
}
/** Adds {@code before + offset <= after}. */
public Constraint addLessOrEqualWithOffset(IntVar before, IntVar after, long offset) {
Constraint ct = new Constraint(modelBuilder);
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
lin.addVars(before.getIndex());
lin.addCoeffs(-1);
lin.addVars(after.getIndex());
lin.addCoeffs(1);
lin.addDomain(offset);
lin.addDomain(java.lang.Long.MAX_VALUE);
return ct;
/** Adds {@code left + offset != right}. */
public Constraint addDifferentWithOffset(IntVar left, IntVar right, long offset) {
return addLinearExpressionInDomain(new Difference(left, right), Domain.fromFlatIntervals(
new long[] {Long.MIN_VALUE, -offset - 1, -offset + 1, Long.MAX_VALUE}));
}
// Integer constraints.
@@ -1074,73 +934,25 @@ public class CpModel {
// Objective.
/** Adds a minimization objective of a single variable. */
public void minimize(IntVar var) {
/** Adds a minimization objective of a linear expression. */
public void minimize(LinearExpr expr) {
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
obj.addVars(var.getIndex());
obj.addCoeffs(1);
}
/** Adds a minimization objective of a sum of variables. */
public void minimizeSum(IntVar[] vars) {
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
for (IntVar var : vars) {
obj.addVars(var.getIndex());
obj.addCoeffs(1);
for (int i = 0; i < expr.numElements(); ++i) {
obj.addVars(expr.getVariable(i).getIndex());
obj.addCoeffs(expr.getCoefficient(i));
}
}
/** Adds a minimization objective of a scalar product of variables. */
public void minimizeLinearExpression(IntVar[] vars, long[] coeffs) {
/** Adds a maximization objective of a linear expression. */
public void maximize(LinearExpr expr) {
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
for (IntVar var : vars) {
obj.addVars(var.getIndex());
}
for (long c : coeffs) {
obj.addCoeffs(c);
}
}
/** Adds a minimization objective of a scalar product of variables. */
public void minimizeLinearExpression(IntVar[] vars, int[] coeffs) {
minimizeLinearExpression(vars, toLongArray(coeffs));
}
/** Adds a maximization objective of a single variable. */
public void maximize(IntVar var) {
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
obj.addVars(negated(var.getIndex()));
obj.addCoeffs(1);
obj.setScalingFactor(-1.0);
}
/** Adds a maximization objective of a sum of variables. */
public void maximizeSum(IntVar[] vars) {
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
for (IntVar var : vars) {
obj.addVars(negated(var.getIndex()));
obj.addCoeffs(1);
for (int i = 0; i < expr.numElements(); ++i) {
obj.addVars(expr.getVariable(i).getIndex());
obj.addCoeffs(-expr.getCoefficient(i));
}
obj.setScalingFactor(-1.0);
}
/** Adds a maximization objective of a scalar product of variables. */
public void maximizeLinearExpression(IntVar[] vars, long[] coeffs) {
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
for (IntVar var : vars) {
obj.addVars(negated(var.getIndex()));
}
for (long c : coeffs) {
obj.addCoeffs(c);
}
obj.setScalingFactor(-1.0);
}
/** Adds a maximization objective of a scalar product of variables. */
public void maximizeLinearExpression(IntVar[] vars, int[] coeffs) {
maximizeLinearExpression(vars, toLongArray(coeffs));
}
// DecisionStrategy
/** Adds {@code DecisionStrategy(variables, varStr, domStr)}. */

View File

@@ -0,0 +1,45 @@
// Copyright 2010-2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.ortools.sat;
/** the substraction of two linear expressions. Used internally. */
class Difference implements LinearExpr {
private LinearExpr left;
private LinearExpr right;
public Difference(LinearExpr left, LinearExpr right) {
this.left = left;
this.right = right;
}
public int numElements() {
return left.numElements() + right.numElements();
}
public IntVar getVariable(int index) {
if (index < left.numElements()) {
return left.getVariable(index);
} else {
return right.getVariable(index - left.numElements());
}
}
public long getCoefficient(int index) {
if (index < left.numElements()) {
return left.getCoefficient(index);
} else {
return -right.getCoefficient(index - left.numElements());
}
}
}

View File

@@ -17,7 +17,7 @@ import com.google.ortools.sat.CpModelProto;
import com.google.ortools.sat.IntegerVariableProto;
/** An integer variable. */
public class IntVar implements Literal {
public class IntVar implements Literal, LinearExpr {
IntVar(CpModelProto.Builder builder, Domain domain, String name) {
this.modelBuilder = builder;
this.variableIndex = modelBuilder.getVariablesCount();
@@ -50,6 +50,21 @@ public class IntVar implements Literal {
return varBuilder;
}
// LinearExpr interface.
public int numElements() {
return 1;
}
public IntVar getVariable(int index) {
assert(index == 0);
return this;
}
public long getCoefficient(int index) {
assert(index == 0);
return 1;
}
/** Returns a short string describing the variable. */
@Override
public String getShortString() {

View File

@@ -0,0 +1,46 @@
// Copyright 2010-2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.ortools.sat;
/** A linear expression interface that can be parsed. */
public interface LinearExpr {
/** Returns the number of elements in the interface. */
int numElements();
/** Returns the ith variable. */
IntVar getVariable(int index);
/** Returns the ith coefficient. */
long getCoefficient(int index);
/** Creates a sum expression. */
static LinearExpr Sum(IntVar[] variables) {
return new SumOfVariables(variables);
}
/** Creates a scalar product. */
static LinearExpr ScalProd(IntVar[] variables, long[] coefficients) {
return new ScalProd(variables, coefficients);
}
/** Creates a scalar product. */
static LinearExpr ScalProd(IntVar[] variables, int[] coefficients) {
long[] tmp = new long[coefficients.length];
for (int i = 0; i < coefficients.length; ++i) {
tmp[i] = coefficients[i];
}
return new ScalProd(variables, tmp);
}
}

View File

@@ -0,0 +1,37 @@
// Copyright 2010-2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.ortools.sat;
/** A linear expression interface that can be parsed. */
public class ScalProd implements LinearExpr {
private IntVar[] variables;
private long[] coefficients;
public ScalProd(IntVar[] variables, long[] coefficients) {
this.variables = variables;
this.coefficients = coefficients;
}
public int numElements() {
return variables.length;
}
public IntVar getVariable(int index) {
return variables[index];
}
public long getCoefficient(int index) {
return coefficients[index];
}
}

View File

@@ -0,0 +1,35 @@
// Copyright 2010-2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.ortools.sat;
/** A linear expression interface that can be parsed. */
public class SumOfVariables implements LinearExpr {
private IntVar[] variables;
public SumOfVariables(IntVar[] variables) {
this.variables = variables;
}
public int numElements() {
return variables.length;
}
public IntVar getVariable(int index) {
return variables[index];
}
public long getCoefficient(int index) {
return 1;
}
}

View File

@@ -15,6 +15,7 @@ import com.google.ortools.sat.CpModel;
import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverStatus;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.LinearExpr;
/** Solves a bin packing problem with the CP-SAT solver. */
public class BinPackingProblemSat {
@@ -65,7 +66,7 @@ public class BinPackingProblemSat {
for (int i = 0; i < numItems; ++i) {
vars[i] = x[i][b];
}
model.addLinearExpressionEqual(vars, sizes, load[b]);
model.addEquality(LinearExpr.ScalProd(vars, sizes), load[b]);
}
// Place all items.
@@ -74,7 +75,7 @@ public class BinPackingProblemSat {
for (int b = 0; b < numBins; ++b) {
vars[b] = x[i][b];
}
model.addSumEqual(vars, items[i][1]);
model.addEquality(LinearExpr.Sum(vars), items[i][1]);
}
// Links load and slack.
@@ -87,7 +88,7 @@ public class BinPackingProblemSat {
}
// Maximize sum of slacks.
model.maximizeSum(slacks);
model.maximize(LinearExpr.Sum(slacks));
// Solves and prints out the solution.
CpSolver solver = new CpSolver();

View File

@@ -16,6 +16,7 @@ import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverSolutionCallback;
import com.google.ortools.sat.DecisionStrategyProto;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.LinearExpr;
import com.google.ortools.sat.SatParameters;
/** Link integer constraints together. */
@@ -41,7 +42,7 @@ public class ChannelingSampleSat {
// Create our two half-reified constraints.
// First, b implies (y == 10 - x).
model.addSumEqual(new IntVar[] {x, y}, 10).onlyEnforceIf(b);
model.addEquality(LinearExpr.Sum(new IntVar[] {x, y}), 10).onlyEnforceIf(b);
// Second, not(b) implies y == 0.
model.addEquality(y, 0).onlyEnforceIf(b.not());

View File

@@ -16,6 +16,7 @@ import com.google.ortools.sat.CpModel;
import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverSolutionCallback;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.LinearExpr;
/** Cryptarithmetic puzzle. */
public class CpIsFunSat {
@@ -73,9 +74,9 @@ public class CpIsFunSat {
model.addAllDifferent(letters);
// CP + IS + FUN = TRUE
model.addLinearExpressionEqual(new IntVar[] {c, p, i, s, f, u, n, t, r, u, e},
model.addEquality(LinearExpr.ScalProd(new IntVar[] {c, p, i, s, f, u, n, t, r, u, e},
new long[] {
base, 1, base, 1, base * base, base, 1, -base * base * base, -base * base, -base, -1},
base, 1, base, 1, base * base, base, 1, -base * base * base, -base * base, -base, -1}),
0);
// [END constraints]

View File

@@ -16,6 +16,7 @@ import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverSolutionCallback;
import com.google.ortools.sat.DecisionStrategyProto;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.LinearExpr;
import com.google.ortools.sat.SatParameters;
/** Encode the piecewise linear expression. */
@@ -47,16 +48,18 @@ public class EarlinessTardinessCostSampleSat {
// First segment: s1 == earlinessCost * (earlinessDate - x).
IntVar s1 = model.newIntVar(-largeConstant, largeConstant, "s1");
model.addLinearExpressionEqual(
new IntVar[] {s1, x}, new long[] {1, earlinessCost}, earlinessCost* earlinessDate);
model.addEquality(
LinearExpr.ScalProd(new IntVar[] {s1, x}, new long[] {1, earlinessCost}),
earlinessCost* earlinessDate);
// Second segment.
IntVar s2 = model.newConstant(0);
// Third segment: s3 == latenessCost * (x - latenessDate).
IntVar s3 = model.newIntVar(-largeConstant, largeConstant, "s3");
model.addLinearExpressionEqual(
new IntVar[] {s3, x}, new long[] {1, -latenessCost}, -latenessCost* latenessDate);
model.addEquality(
LinearExpr.ScalProd(new IntVar[] {s3, x}, new long[] {1, -latenessCost}),
-latenessCost* latenessDate);
// Link together expr and x through s1, s2, and s3.
model.addMaxEquality(expr, new IntVar[] {s1, s2, s3});

View File

@@ -15,6 +15,7 @@ import com.google.ortools.sat.CpModel;
import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverStatus;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.LinearExpr;
/**
* In a field of rabbits and pheasants, there are 20 heads and 56 legs. How many rabbits and
@@ -32,9 +33,9 @@ public class RabbitsAndPheasantsSat {
IntVar r = model.newIntVar(0, 100, "r");
IntVar p = model.newIntVar(0, 100, "p");
// 20 heads.
model.addSumEqual(new IntVar[] {r, p}, 20);
model.addEquality(LinearExpr.Sum(new IntVar[] {r, p}), 20);
// 56 legs.
model.addLinearExpressionEqual(new IntVar[] {r, p}, new long[] {4, 2}, 56);
model.addEquality(LinearExpr.ScalProd(new IntVar[] {r, p}, new long[] {4, 2}), 56);
// Creates a solver and solves the model.
CpSolver solver = new CpSolver();

View File

@@ -15,6 +15,7 @@ import com.google.ortools.sat.CpModel;
import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverStatus;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.LinearExpr;
import com.google.ortools.sat.IntervalVar;
import com.google.ortools.sat.Literal;
import java.util.ArrayList;
@@ -89,7 +90,7 @@ public class RankingSampleSat {
vars[numTasks] = ranks[i];
coefs[numTasks] = -1;
// ranks == sum(precedences) - 1;
model.addLinearExpressionEqual(vars, coefs, 1);
model.addEquality(LinearExpr.ScalProd(vars, coefs), 1);
}
}
@@ -153,7 +154,7 @@ public class RankingSampleSat {
}
objectiveVars[numTasks] = makespan;
objectiveCoefs[numTasks] = 2;
model.minimizeLinearExpression(objectiveVars, objectiveCoefs);
model.minimize(LinearExpr.ScalProd(objectiveVars, objectiveCoefs));
// Creates a solver and solves the model.
CpSolver solver = new CpSolver();

View File

@@ -70,7 +70,7 @@ public class SolveAndPrintIntermediateSolutionsSampleSat {
// Maximize a linear combination of variables.
// [START objective]
model.maximizeLinearExpression(new IntVar[] {x, y, z}, new int[] {1, 2, 3});
model.maximize(LinearExpr.ScalProd(new IntVar[] {x, y, z}, new int[] {1, 2, 3}));
// [END objective]
// Create a solver and solve the model.

View File

@@ -46,16 +46,14 @@ public class StepFunctionSampleSat {
// expr == 0 on [5, 6] U [8, 10]
Literal b0 = model.newBoolVar("b0");
model.addSumInDomain(new IntVar[] {x}, Domain.fromValues(new long[] {5, 6, 8, 9, 10}))
.onlyEnforceIf(b0);
model.addLinearExpressionInDomain(
x, Domain.fromValues(new long[] {5, 6, 8, 9, 10})).onlyEnforceIf(b0);
model.addEquality(expr, 0).onlyEnforceIf(b0);
// expr == 2 on [0, 1] U [3, 4] U [11, 20]
Literal b2 = model.newBoolVar("b2");
model
.addSumInDomain(
new IntVar[] {x}, Domain.fromIntervals(new long[][] {{0, 1}, {3, 4}, {11, 20}}))
.onlyEnforceIf(b2);
model.addLinearExpressionInDomain(
x, Domain.fromIntervals(new long[][] {{0, 1}, {3, 4}, {11, 20}})).onlyEnforceIf(b2);
model.addEquality(expr, 2).onlyEnforceIf(b2);
// expr == 3 when x = 7