[CP-SAT] Next iteration in java modelling layer
This commit is contained in:
@@ -15,27 +15,34 @@ package com.google.ortools.sat;
|
||||
|
||||
/** A specialized linear expression: a * x + b */
|
||||
public final class AffineExpression implements LinearExpr {
|
||||
private final IntVar var;
|
||||
private final int varIndex;
|
||||
private final long coefficient;
|
||||
private final long offset;
|
||||
|
||||
public AffineExpression(IntVar var, long coefficient, long offset) {
|
||||
this.var = var;
|
||||
public AffineExpression(int varIndex, long coefficient, long offset) {
|
||||
this.varIndex = varIndex;
|
||||
this.coefficient = coefficient;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
// LinearArgument interface.
|
||||
@Override
|
||||
public LinearExpr build() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// LinearExpr interface.
|
||||
@Override
|
||||
public int numElements() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntVar getVariable(int index) {
|
||||
public int getVariableIndex(int index) {
|
||||
if (index != 0) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getIndex(): " + index);
|
||||
}
|
||||
return var;
|
||||
return varIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,32 +20,47 @@ import com.google.ortools.util.Domain;
|
||||
public final class BoolVar extends IntVar implements Literal {
|
||||
BoolVar(CpModelProto.Builder builder, Domain domain, String name) {
|
||||
super(builder, domain, name);
|
||||
this.negation_ = null;
|
||||
this.negation = null;
|
||||
}
|
||||
|
||||
BoolVar(CpModelProto.Builder builder, int index) {
|
||||
super(builder, index);
|
||||
this.negation_ = null;
|
||||
this.negation = null;
|
||||
}
|
||||
|
||||
/** Returns the negation of a boolean variable. */
|
||||
@Override
|
||||
public Literal not() {
|
||||
if (negation_ == null) {
|
||||
negation_ = new NotBooleanVariable(this);
|
||||
if (negation == null) {
|
||||
negation = new NotBoolVar(this);
|
||||
}
|
||||
return negation_;
|
||||
return negation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoolVar getBoolVar() {
|
||||
return this;
|
||||
public String toString() {
|
||||
if (varBuilder.getName().isEmpty()) {
|
||||
if (varBuilder.getDomainCount() == 2 && varBuilder.getDomain(0) == varBuilder.getDomain(1)) {
|
||||
if (varBuilder.getDomain(0) == 0) {
|
||||
return "false";
|
||||
} else {
|
||||
return "true";
|
||||
}
|
||||
} else {
|
||||
return String.format("boolvar_%d(%s)", getIndex(), displayBounds());
|
||||
}
|
||||
} else {
|
||||
if (varBuilder.getDomainCount() == 2 && varBuilder.getDomain(0) == varBuilder.getDomain(1)) {
|
||||
if (varBuilder.getDomain(0) == 0) {
|
||||
return String.format("%s(false)", varBuilder.getName());
|
||||
} else {
|
||||
return String.format("%s(true)", varBuilder.getName());
|
||||
}
|
||||
} else {
|
||||
return String.format("%s(%s)", getName(), displayBounds());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean negated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private NotBooleanVariable negation_ = null;
|
||||
private NotBoolVar negation = null;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,20 @@ public final class ConstantExpression implements LinearExpr {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
// LinearArgument interface.
|
||||
@Override
|
||||
public LinearExpr build() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// LinearExpr interface.
|
||||
@Override
|
||||
public int numElements() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntVar getVariable(int index) {
|
||||
public int getVariableIndex(int index) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
|
||||
}
|
||||
|
||||
@@ -40,4 +47,9 @@ public final class ConstantExpression implements LinearExpr {
|
||||
public long getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%d", offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.google.ortools.sat.NoOverlapConstraintProto;
|
||||
import com.google.ortools.sat.ReservoirConstraintProto;
|
||||
import com.google.ortools.sat.TableConstraintProto;
|
||||
import com.google.ortools.util.Domain;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -123,12 +124,7 @@ public final class CpModel {
|
||||
|
||||
/** Adds {@code Or(literals) == true}. */
|
||||
public Constraint addBoolOr(Literal[] literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder boolOr = ct.getBuilder().getBoolOrBuilder();
|
||||
for (Literal lit : literals) {
|
||||
boolOr.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addBoolOr(Arrays.asList(literals));
|
||||
}
|
||||
|
||||
/** Adds {@code Or(literals) == true}. */
|
||||
@@ -143,32 +139,17 @@ public final class CpModel {
|
||||
|
||||
/** Same as addBoolOr. {@code Sum(literals) >= 1}. */
|
||||
public Constraint addAtLeastOne(Literal[] literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder boolOr = ct.getBuilder().getBoolOrBuilder();
|
||||
for (Literal lit : literals) {
|
||||
boolOr.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addBoolOr(Arrays.asList(literals));
|
||||
}
|
||||
|
||||
/** Same as addBoolOr. {@code Sum(literals) >= 1}. */
|
||||
public Constraint addAtLeastOne(Iterable<Literal> literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder boolOr = ct.getBuilder().getBoolOrBuilder();
|
||||
for (Literal lit : literals) {
|
||||
boolOr.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addBoolOr(literals);
|
||||
}
|
||||
|
||||
/** Adds {@code AtMostOne(literals): Sum(literals) <= 1}. */
|
||||
public Constraint addAtMostOne(Literal[] literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder atMostOne = ct.getBuilder().getAtMostOneBuilder();
|
||||
for (Literal lit : literals) {
|
||||
atMostOne.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addAtMostOne(Arrays.asList(literals));
|
||||
}
|
||||
|
||||
/** Adds {@code AtMostOne(literals): Sum(literals) <= 1}. */
|
||||
@@ -183,12 +164,7 @@ public final class CpModel {
|
||||
|
||||
/** Adds {@code ExactlyOne(literals): Sum(literals) == 1}. */
|
||||
public Constraint addExactlyOne(Literal[] literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder exactlyOne = ct.getBuilder().getExactlyOneBuilder();
|
||||
for (Literal lit : literals) {
|
||||
exactlyOne.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addExactlyOne(Arrays.asList(literals));
|
||||
}
|
||||
|
||||
/** Adds {@code ExactlyOne(literals): Sum(literals) == 1}. */
|
||||
@@ -203,12 +179,7 @@ public final class CpModel {
|
||||
|
||||
/** Adds {@code And(literals) == true}. */
|
||||
public Constraint addBoolAnd(Literal[] literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder boolAnd = ct.getBuilder().getBoolAndBuilder();
|
||||
for (Literal lit : literals) {
|
||||
boolAnd.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addBoolAnd(Arrays.asList(literals));
|
||||
}
|
||||
|
||||
/** Adds {@code And(literals) == true}. */
|
||||
@@ -223,12 +194,7 @@ public final class CpModel {
|
||||
|
||||
/** Adds {@code XOr(literals) == true}. */
|
||||
public Constraint addBoolXor(Literal[] literals) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
BoolArgumentProto.Builder boolXOr = ct.getBuilder().getBoolXorBuilder();
|
||||
for (Literal lit : literals) {
|
||||
boolXOr.addLiterals(lit.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addBoolXor(Arrays.asList(literals));
|
||||
}
|
||||
|
||||
/** Adds {@code XOr(literals) == true}. */
|
||||
@@ -249,127 +215,112 @@ public final class CpModel {
|
||||
// Linear constraints.
|
||||
|
||||
/** Adds {@code expr in domain}. */
|
||||
public Constraint addLinearExpressionInDomain(LinearExpr expr, Domain domain) {
|
||||
public Constraint addLinearExpressionInDomain(LinearArgument expr, Domain domain) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearConstraintProto.Builder lin = ct.getBuilder().getLinearBuilder();
|
||||
for (int i = 0; i < expr.numElements(); ++i) {
|
||||
lin.addVars(expr.getVariable(i).getIndex()).addCoeffs(expr.getCoefficient(i));
|
||||
}
|
||||
long offset = expr.getOffset();
|
||||
if (offset != 0) {
|
||||
lin.addVars(newConstant(1).getIndex()).addCoeffs(offset);
|
||||
final LinearExpr e = expr.build();
|
||||
for (int i = 0; i < e.numElements(); ++i) {
|
||||
lin.addVars(e.getVariableIndex(i)).addCoeffs(e.getCoefficient(i));
|
||||
}
|
||||
long offset = e.getOffset();
|
||||
for (long b : domain.flattenedIntervals()) {
|
||||
lin.addDomain(b);
|
||||
if (b == Long.MIN_VALUE || b == Long.MAX_VALUE) {
|
||||
lin.addDomain(b);
|
||||
} else {
|
||||
lin.addDomain(b - offset);
|
||||
}
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code lb <= expr <= ub}. */
|
||||
public Constraint addLinearConstraint(LinearExpr expr, long lb, long ub) {
|
||||
public Constraint addLinearConstraint(LinearArgument expr, long lb, long ub) {
|
||||
return addLinearExpressionInDomain(expr, new Domain(lb, ub));
|
||||
}
|
||||
|
||||
/** Adds {@code expr == value}. */
|
||||
public Constraint addEquality(LinearExpr expr, long value) {
|
||||
public Constraint addEquality(LinearArgument expr, long value) {
|
||||
return addLinearExpressionInDomain(expr, new Domain(value));
|
||||
}
|
||||
|
||||
/** Adds {@code left == right}. */
|
||||
public Constraint addEquality(LinearExpr left, LinearExpr right) {
|
||||
public Constraint addEquality(LinearArgument left, LinearArgument right) {
|
||||
LinearExprBuilder difference = LinearExpr.newBuilder();
|
||||
difference.addTerm(left, 1);
|
||||
difference.addTerm(right, -1);
|
||||
return addLinearExpressionInDomain(difference.build(), new Domain(0));
|
||||
return addLinearExpressionInDomain(difference, new Domain(0));
|
||||
}
|
||||
|
||||
/** Adds {@code expr <= value}. */
|
||||
public Constraint addLessOrEqual(LinearExpr expr, long value) {
|
||||
public Constraint addLessOrEqual(LinearArgument expr, long value) {
|
||||
return addLinearExpressionInDomain(expr, new Domain(Long.MIN_VALUE, value));
|
||||
}
|
||||
|
||||
/** Adds {@code left <= right}. */
|
||||
public Constraint addLessOrEqual(LinearExpr left, LinearExpr right) {
|
||||
public Constraint addLessOrEqual(LinearArgument left, LinearArgument right) {
|
||||
LinearExprBuilder difference = LinearExpr.newBuilder();
|
||||
difference.addTerm(left, 1);
|
||||
difference.addTerm(right, -1);
|
||||
return addLinearExpressionInDomain(difference.build(), new Domain(Long.MIN_VALUE, 0));
|
||||
return addLinearExpressionInDomain(difference, new Domain(Long.MIN_VALUE, 0));
|
||||
}
|
||||
|
||||
/** Adds {@code expr < value}. */
|
||||
public Constraint addLessThan(LinearExpr expr, long value) {
|
||||
public Constraint addLessThan(LinearArgument expr, long value) {
|
||||
return addLinearExpressionInDomain(expr, new Domain(Long.MIN_VALUE, value - 1));
|
||||
}
|
||||
|
||||
/** Adds {@code left < right}. */
|
||||
public Constraint addLessThan(LinearExpr left, LinearExpr right) {
|
||||
public Constraint addLessThan(LinearArgument left, LinearArgument right) {
|
||||
LinearExprBuilder difference = LinearExpr.newBuilder();
|
||||
difference.addTerm(left, 1);
|
||||
difference.addTerm(right, -1);
|
||||
return addLinearExpressionInDomain(difference.build(), new Domain(Long.MIN_VALUE, -1));
|
||||
return addLinearExpressionInDomain(difference, new Domain(Long.MIN_VALUE, -1));
|
||||
}
|
||||
|
||||
/** Adds {@code expr >= value}. */
|
||||
public Constraint addGreaterOrEqual(LinearExpr expr, long value) {
|
||||
public Constraint addGreaterOrEqual(LinearArgument expr, long value) {
|
||||
return addLinearExpressionInDomain(expr, new Domain(value, Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
/** Adds {@code left >= right}. */
|
||||
public Constraint addGreaterOrEqual(LinearExpr left, LinearExpr right) {
|
||||
public Constraint addGreaterOrEqual(LinearArgument left, LinearArgument right) {
|
||||
LinearExprBuilder difference = LinearExpr.newBuilder();
|
||||
difference.addTerm(left, 1);
|
||||
difference.addTerm(right, -1);
|
||||
return addLinearExpressionInDomain(difference.build(), new Domain(0, Long.MAX_VALUE));
|
||||
return addLinearExpressionInDomain(difference, new Domain(0, Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
/** Adds {@code expr > value}. */
|
||||
public Constraint addGreaterThan(LinearExpr expr, long value) {
|
||||
public Constraint addGreaterThan(LinearArgument expr, long value) {
|
||||
return addLinearExpressionInDomain(expr, new Domain(value + 1, Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
/** Adds {@code left > right}. */
|
||||
public Constraint addGreaterThan(LinearExpr left, LinearExpr right) {
|
||||
public Constraint addGreaterThan(LinearArgument left, LinearArgument right) {
|
||||
LinearExprBuilder difference = LinearExpr.newBuilder();
|
||||
difference.addTerm(left, 1);
|
||||
difference.addTerm(right, -1);
|
||||
return addLinearExpressionInDomain(difference.build(), new Domain(1, Long.MAX_VALUE));
|
||||
return addLinearExpressionInDomain(difference, new Domain(1, Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
/** Adds {@code expr != value}. */
|
||||
public Constraint addDifferent(LinearExpr expr, long value) {
|
||||
public Constraint addDifferent(LinearArgument expr, long value) {
|
||||
return addLinearExpressionInDomain(expr,
|
||||
Domain.fromFlatIntervals(
|
||||
new long[] {Long.MIN_VALUE, value - 1, value + 1, Long.MAX_VALUE}));
|
||||
}
|
||||
|
||||
/** Adds {@code left != right}. */
|
||||
public Constraint addDifferent(LinearExpr left, LinearExpr right) {
|
||||
public Constraint addDifferent(LinearArgument left, LinearArgument right) {
|
||||
LinearExprBuilder difference = LinearExpr.newBuilder();
|
||||
difference.addTerm(left, 1);
|
||||
difference.addTerm(right, -1);
|
||||
return addLinearExpressionInDomain(difference.build(),
|
||||
Domain.fromFlatIntervals(new long[] {Long.MIN_VALUE, -1, 1, Long.MAX_VALUE}));
|
||||
return addLinearExpressionInDomain(
|
||||
difference, Domain.fromFlatIntervals(new long[] {Long.MIN_VALUE, -1, 1, Long.MAX_VALUE}));
|
||||
}
|
||||
|
||||
// Integer constraints.
|
||||
|
||||
/**
|
||||
* Adds {@code AllDifferent(variables)}.
|
||||
*
|
||||
* <p>This constraint forces all variables to have different values.
|
||||
*
|
||||
* @param variables a list of integer variables
|
||||
* @return an instance of the Constraint class
|
||||
*/
|
||||
public Constraint addAllDifferent(IntVar[] variables) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
AllDifferentConstraintProto.Builder allDiff = ct.getBuilder().getAllDiffBuilder();
|
||||
for (IntVar var : variables) {
|
||||
allDiff.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(var, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code AllDifferent(expressions)}.
|
||||
*
|
||||
@@ -378,25 +329,20 @@ public final class CpModel {
|
||||
* @param expressions a list of affine integer expressions
|
||||
* @return an instance of the Constraint class
|
||||
*/
|
||||
public Constraint addAllDifferent(LinearExpr[] expressions) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
AllDifferentConstraintProto.Builder allDiff = ct.getBuilder().getAllDiffBuilder();
|
||||
for (LinearExpr expr : expressions) {
|
||||
allDiff.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
public Constraint addAllDifferent(LinearArgument[] expressions) {
|
||||
return addAllDifferent(Arrays.asList(expressions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code AllDifferent(expressions)}.
|
||||
*
|
||||
* @see addAllDifferent(LinearExpr[]).
|
||||
* @see addAllDifferent(LinearArgument[]).
|
||||
*/
|
||||
public Constraint addAllDifferent(Iterable<LinearExpr> expressions) {
|
||||
public Constraint addAllDifferent(Iterable<? extends LinearArgument> expressions) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
AllDifferentConstraintProto.Builder allDiff = ct.getBuilder().getAllDiffBuilder();
|
||||
for (LinearExpr expr : expressions) {
|
||||
allDiff.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/false));
|
||||
for (LinearArgument expr : expressions) {
|
||||
allDiff.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
@@ -419,7 +365,7 @@ public final class CpModel {
|
||||
ElementConstraintProto.Builder element =
|
||||
ct.getBuilder().getElementBuilder().setIndex(index.getIndex());
|
||||
for (long v : values) {
|
||||
element.addVars(indexFromConstant(v));
|
||||
element.addVars(newConstant(v).getIndex());
|
||||
}
|
||||
element.setTarget(target.getIndex());
|
||||
return ct;
|
||||
@@ -431,7 +377,7 @@ public final class CpModel {
|
||||
ElementConstraintProto.Builder element =
|
||||
ct.getBuilder().getElementBuilder().setIndex(index.getIndex());
|
||||
for (long v : values) {
|
||||
element.addVars(indexFromConstant(v));
|
||||
element.addVars(newConstant(v).getIndex());
|
||||
}
|
||||
element.setTarget(target.getIndex());
|
||||
return ct;
|
||||
@@ -476,13 +422,7 @@ public final class CpModel {
|
||||
* directly to the table constraint.
|
||||
*/
|
||||
public TableConstraint addAllowedAssignments(IntVar[] variables) {
|
||||
TableConstraint ct = new TableConstraint(modelBuilder);
|
||||
TableConstraintProto.Builder table = ct.getBuilder().getTableBuilder();
|
||||
for (IntVar var : variables) {
|
||||
table.addVars(var.getIndex());
|
||||
}
|
||||
table.setNegated(false);
|
||||
return ct;
|
||||
return addAllowedAssignments(Arrays.asList(variables));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,13 +451,7 @@ public final class CpModel {
|
||||
* directly to the table constraint.
|
||||
*/
|
||||
public TableConstraint addForbiddenAssignments(IntVar[] variables) {
|
||||
TableConstraint ct = new TableConstraint(modelBuilder);
|
||||
TableConstraintProto.Builder table = ct.getBuilder().getTableBuilder();
|
||||
for (IntVar var : variables) {
|
||||
table.addVars(var.getIndex());
|
||||
}
|
||||
table.setNegated(true);
|
||||
return ct;
|
||||
return addForbiddenAssignments(Arrays.asList(variables));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -649,144 +583,115 @@ public final class CpModel {
|
||||
}
|
||||
|
||||
/** Adds {@code target == Min(vars)}. */
|
||||
public Constraint addMinEquality(LinearExpr target, IntVar[] vars) {
|
||||
public Constraint addMinEquality(LinearArgument target, LinearArgument[] exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/true));
|
||||
for (IntVar var : vars) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(var, /*negate=*/true));
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/true));
|
||||
for (LinearArgument expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/true));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Min(exprs)}. */
|
||||
public Constraint addMinEquality(LinearExpr target, LinearExpr[] exprs) {
|
||||
public Constraint addMinEquality(
|
||||
LinearArgument target, Iterable<? extends LinearArgument> exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/true));
|
||||
for (LinearExpr expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/true));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Min(exprs)}. */
|
||||
public Constraint addMinEquality(LinearExpr target, Iterable<LinearExpr> exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/true));
|
||||
for (LinearExpr expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/true));
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/true));
|
||||
for (LinearArgument expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/true));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Max(vars)}. */
|
||||
public Constraint addMaxEquality(LinearExpr target, IntVar[] vars) {
|
||||
public Constraint addMaxEquality(LinearArgument target, LinearArgument[] exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
for (IntVar var : vars) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(var, /*negate=*/false));
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false));
|
||||
for (LinearArgument expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Max(exprs)}. */
|
||||
public Constraint addMaxEquality(LinearExpr target, LinearExpr[] exprs) {
|
||||
public Constraint addMaxEquality(
|
||||
LinearArgument target, Iterable<? extends LinearArgument> exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
for (LinearExpr expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Max(exprs)}. */
|
||||
public Constraint addMaxEquality(LinearExpr target, Iterable<LinearExpr> exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
for (LinearExpr expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/false));
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false));
|
||||
for (LinearArgument expr : exprs) {
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == num / denom}, rounded towards 0. */
|
||||
public Constraint addDivisionEquality(LinearExpr target, LinearExpr num, LinearExpr denom) {
|
||||
public Constraint addDivisionEquality(
|
||||
LinearArgument target, LinearArgument num, LinearArgument denom) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
ct.getBuilder()
|
||||
.getIntDivBuilder()
|
||||
.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(num, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(denom, /*negate=*/false));
|
||||
.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(num, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(denom, /*negate=*/false));
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Abs(expr)}. */
|
||||
public Constraint addAbsEquality(LinearExpr target, LinearExpr expr) {
|
||||
public Constraint addAbsEquality(LinearArgument target, LinearArgument expr) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder linMax = ct.getBuilder().getLinMaxBuilder();
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/false));
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/true));
|
||||
linMax.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false));
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/false));
|
||||
linMax.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/true));
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == var % mod}. */
|
||||
public Constraint addModuloEquality(LinearExpr target, LinearExpr var, LinearExpr mod) {
|
||||
public Constraint addModuloEquality(
|
||||
LinearArgument target, LinearArgument var, LinearArgument mod) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
ct.getBuilder()
|
||||
.getIntModBuilder()
|
||||
.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(var, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(mod, /*negate=*/false));
|
||||
.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(var, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(mod, /*negate=*/false));
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == var % mod}. */
|
||||
public Constraint addModuloEquality(LinearExpr target, LinearExpr var, long mod) {
|
||||
public Constraint addModuloEquality(LinearArgument target, LinearArgument var, long mod) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
ct.getBuilder()
|
||||
.getIntModBuilder()
|
||||
.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(var, /*negate=*/false))
|
||||
.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(var, /*negate=*/false))
|
||||
.addExprs(getLinearExpressionProtoBuilderFromLong(mod));
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Product(vars)}. */
|
||||
public Constraint addMultiplicationEquality(LinearExpr target, IntVar[] vars) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder intProd = ct.getBuilder().getIntProdBuilder();
|
||||
intProd.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
for (IntVar var : vars) {
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(var, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == Product(exprs)}. */
|
||||
public Constraint addMultiplicationEquality(LinearExpr target, LinearExpr[] exprs) {
|
||||
public Constraint addMultiplicationEquality(LinearArgument target, LinearArgument[] exprs) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder intProd = ct.getBuilder().getIntProdBuilder();
|
||||
intProd.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
for (LinearExpr expr : exprs) {
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(expr, /*negate=*/false));
|
||||
intProd.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false));
|
||||
for (LinearArgument expr : exprs) {
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(expr, /*negate=*/false));
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/** Adds {@code target == left * right}. */
|
||||
public Constraint addMultiplicationEquality(
|
||||
LinearExpr target, LinearExpr left, LinearExpr right) {
|
||||
LinearArgument target, LinearArgument left, LinearArgument right) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
LinearArgumentProto.Builder intProd = ct.getBuilder().getIntProdBuilder();
|
||||
intProd.setTarget(getLinearExpressionProtoBuilderFromLinearExpr(target, /*negate=*/false));
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(left, /*negate=*/false));
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearExpr(right, /*negate=*/false));
|
||||
intProd.setTarget(getLinearExpressionProtoBuilderFromLinearArgument(target, /*negate=*/false));
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(left, /*negate=*/false));
|
||||
intProd.addExprs(getLinearExpressionProtoBuilderFromLinearArgument(right, /*negate=*/false));
|
||||
return ct;
|
||||
}
|
||||
|
||||
@@ -807,12 +712,12 @@ public final class CpModel {
|
||||
* @return An IntervalVar object
|
||||
*/
|
||||
public IntervalVar newIntervalVar(
|
||||
LinearExpr start, LinearExpr size, LinearExpr end, String name) {
|
||||
addEquality(LinearExpr.newBuilder().add(start).add(size).build(), end);
|
||||
LinearArgument start, LinearArgument size, LinearArgument end, String name) {
|
||||
addEquality(LinearExpr.newBuilder().add(start).add(size), end);
|
||||
return new IntervalVar(modelBuilder,
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(size, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(end, /*negate=*/false), name);
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(size, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(end, /*negate=*/false), name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -826,12 +731,12 @@ public final class CpModel {
|
||||
* @param name the name of the interval variable.
|
||||
* @return An IntervalVar object
|
||||
*/
|
||||
public IntervalVar newFixedSizeIntervalVar(LinearExpr start, long size, String name) {
|
||||
public IntervalVar newFixedSizeIntervalVar(LinearArgument start, long size, String name) {
|
||||
return new IntervalVar(modelBuilder,
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLong(size),
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(
|
||||
LinearExpr.newBuilder().add(start).add(size).build(), /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(
|
||||
LinearExpr.newBuilder().add(start).add(size), /*negate=*/false),
|
||||
name);
|
||||
}
|
||||
|
||||
@@ -860,14 +765,14 @@ public final class CpModel {
|
||||
* @param name The name of the interval variable
|
||||
* @return an IntervalVar object
|
||||
*/
|
||||
public IntervalVar newOptionalIntervalVar(
|
||||
LinearExpr start, LinearExpr size, LinearExpr end, Literal isPresent, String name) {
|
||||
addEquality(LinearExpr.newBuilder().add(start).add(size).build(), end).onlyEnforceIf(isPresent);
|
||||
public IntervalVar newOptionalIntervalVar(LinearArgument start, LinearArgument size,
|
||||
LinearArgument end, Literal isPresent, String name) {
|
||||
addEquality(LinearExpr.newBuilder().add(start).add(size), end).onlyEnforceIf(isPresent);
|
||||
return new IntervalVar(modelBuilder,
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(size, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(end, /*negate=*/false), isPresent.getIndex(),
|
||||
name);
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(size, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(end, /*negate=*/false),
|
||||
isPresent.getIndex(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -884,12 +789,12 @@ public final class CpModel {
|
||||
* @return An IntervalVar object
|
||||
*/
|
||||
public IntervalVar newOptionalFixedSizeIntervalVar(
|
||||
LinearExpr start, long size, Literal isPresent, String name) {
|
||||
LinearArgument start, long size, Literal isPresent, String name) {
|
||||
return new IntervalVar(modelBuilder,
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(start, /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLong(size),
|
||||
getLinearExpressionProtoBuilderFromLinearExpr(
|
||||
LinearExpr.newBuilder().add(start).add(size).build(), /*negate=*/false),
|
||||
getLinearExpressionProtoBuilderFromLinearArgument(
|
||||
LinearExpr.newBuilder().add(start).add(size), /*negate=*/false),
|
||||
isPresent.getIndex(), name);
|
||||
}
|
||||
|
||||
@@ -910,12 +815,7 @@ public final class CpModel {
|
||||
* @return an instance of the Constraint class
|
||||
*/
|
||||
public Constraint addNoOverlap(IntervalVar[] intervalVars) {
|
||||
Constraint ct = new Constraint(modelBuilder);
|
||||
NoOverlapConstraintProto.Builder noOverlap = ct.getBuilder().getNoOverlapBuilder();
|
||||
for (IntervalVar var : intervalVars) {
|
||||
noOverlap.addIntervals(var.getIndex());
|
||||
}
|
||||
return ct;
|
||||
return addNoOverlap(Arrays.asList(intervalVars));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -961,17 +861,17 @@ public final class CpModel {
|
||||
* @return an instance of the CumulativeConstraint class. this class allows adding (interval,
|
||||
* demand) pairs incrementally.
|
||||
*/
|
||||
public CumulativeConstraint addCumulative(LinearExpr capacity) {
|
||||
public CumulativeConstraint addCumulative(LinearArgument capacity) {
|
||||
CumulativeConstraint ct = new CumulativeConstraint(this);
|
||||
CumulativeConstraintProto.Builder cumul = ct.getBuilder().getCumulativeBuilder();
|
||||
cumul.setCapacity(getLinearExpressionProtoBuilderFromLinearExpr(capacity, false));
|
||||
cumul.setCapacity(getLinearExpressionProtoBuilderFromLinearArgument(capacity, false));
|
||||
return ct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@code Cumulative(capacity)}.
|
||||
*
|
||||
* @see #addCumulative(LinearExpr capacity)
|
||||
* @see #addCumulative(LinearArgument capacity)
|
||||
*/
|
||||
public CumulativeConstraint addCumulative(long capacity) {
|
||||
CumulativeConstraint ct = new CumulativeConstraint(this);
|
||||
@@ -1011,12 +911,13 @@ public final class CpModel {
|
||||
// Objective.
|
||||
|
||||
/** Adds a minimization objective of a linear expression. */
|
||||
public void minimize(LinearExpr expr) {
|
||||
public void minimize(LinearArgument expr) {
|
||||
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
|
||||
for (int i = 0; i < expr.numElements(); ++i) {
|
||||
obj.addVars(expr.getVariable(i).getIndex()).addCoeffs(expr.getCoefficient(i));
|
||||
final LinearExpr e = expr.build();
|
||||
for (int i = 0; i < e.numElements(); ++i) {
|
||||
obj.addVars(e.getVariableIndex(i)).addCoeffs(e.getCoefficient(i));
|
||||
}
|
||||
obj.setOffset(expr.getOffset());
|
||||
obj.setOffset(e.getOffset());
|
||||
}
|
||||
|
||||
public void minimize(DoubleLinearExpr expr) {
|
||||
@@ -1028,12 +929,13 @@ public final class CpModel {
|
||||
}
|
||||
|
||||
/** Adds a maximization objective of a linear expression. */
|
||||
public void maximize(LinearExpr expr) {
|
||||
public void maximize(LinearArgument expr) {
|
||||
CpObjectiveProto.Builder obj = modelBuilder.getObjectiveBuilder();
|
||||
for (int i = 0; i < expr.numElements(); ++i) {
|
||||
obj.addVars(expr.getVariable(i).getIndex()).addCoeffs(-expr.getCoefficient(i));
|
||||
final LinearExpr e = expr.build();
|
||||
for (int i = 0; i < e.numElements(); ++i) {
|
||||
obj.addVars(e.getVariableIndex(i)).addCoeffs(-e.getCoefficient(i));
|
||||
}
|
||||
obj.setOffset(-expr.getOffset());
|
||||
obj.setOffset(-e.getOffset());
|
||||
obj.setScalingFactor(-1.0);
|
||||
}
|
||||
|
||||
@@ -1081,27 +983,14 @@ public final class CpModel {
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
long[] toLongArray(int[] values) {
|
||||
long[] result = new long[values.length];
|
||||
for (int i = 0; i < values.length; ++i) {
|
||||
result[i] = values[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int indexFromConstant(long constant) {
|
||||
IntVar constVar = newConstant(constant);
|
||||
return constVar.getIndex();
|
||||
}
|
||||
|
||||
LinearExpressionProto.Builder getLinearExpressionProtoBuilderFromLinearExpr(
|
||||
LinearExpr expr, boolean negate) {
|
||||
LinearExpressionProto.Builder getLinearExpressionProtoBuilderFromLinearArgument(
|
||||
LinearArgument arg, boolean negate) {
|
||||
LinearExpressionProto.Builder builder = LinearExpressionProto.newBuilder();
|
||||
final LinearExpr expr = arg.build();
|
||||
final int numVariables = expr.numElements();
|
||||
final long mult = negate ? -1 : 1;
|
||||
for (int i = 0; i < numVariables; ++i) {
|
||||
builder.addVars(expr.getVariable(i).getIndex());
|
||||
builder.addVars(expr.getVariableIndex(i));
|
||||
builder.addCoeffs(expr.getCoefficient(i) * mult);
|
||||
}
|
||||
builder.setOffset(expr.getOffset() * mult);
|
||||
|
||||
@@ -127,10 +127,11 @@ public final class CpSolver {
|
||||
}
|
||||
|
||||
/** Returns the value of a linear expression in the last solution found. */
|
||||
public long value(LinearExpr expr) {
|
||||
long result = expr.getOffset();
|
||||
for (int i = 0; i < expr.numElements(); ++i) {
|
||||
result += solveResponse.getSolution(expr.getVariable(i).getIndex()) * expr.getCoefficient(i);
|
||||
public long value(LinearArgument expr) {
|
||||
final LinearExpr e = expr.build();
|
||||
long result = e.getOffset();
|
||||
for (int i = 0; i < e.numElements(); ++i) {
|
||||
result += solveResponse.getSolution(e.getVariableIndex(i)) * e.getCoefficient(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ package com.google.ortools.sat;
|
||||
*/
|
||||
public class CpSolverSolutionCallback extends SolutionCallback {
|
||||
/** Returns the value of the linear expression in the current solution. */
|
||||
public long value(LinearExpr expr) {
|
||||
long result = expr.getOffset();
|
||||
for (int i = 0; i < expr.numElements(); ++i) {
|
||||
result += solutionIntegerValue(expr.getVariable(i).getIndex()) * expr.getCoefficient(i);
|
||||
public long value(LinearArgument expr) {
|
||||
final LinearExpr e = expr.build();
|
||||
long result = e.getOffset();
|
||||
for (int i = 0; i < e.numElements(); ++i) {
|
||||
result += solutionIntegerValue(e.getVariableIndex(i)) * e.getCoefficient(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ public class CumulativeConstraint extends Constraint {
|
||||
}
|
||||
|
||||
/// Adds a pair (interval, demand) to the constraint.
|
||||
void addDemand(IntervalVar interval, LinearExpr demand) {
|
||||
void addDemand(IntervalVar interval, LinearArgument demand) {
|
||||
CumulativeConstraintProto.Builder cumul = getBuilder().getCumulativeBuilder();
|
||||
cumul.addIntervals(interval.getIndex());
|
||||
cumul.addDemands(model.getLinearExpressionProtoBuilderFromLinearExpr(demand, false));
|
||||
cumul.addDemands(model.getLinearExpressionProtoBuilderFromLinearArgument(demand, false));
|
||||
}
|
||||
|
||||
/// Adds a pair (interval, demand) to the constraint.
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.google.ortools.sat.IntegerVariableProto;
|
||||
import com.google.ortools.util.Domain;
|
||||
|
||||
/** An integer variable. */
|
||||
public class IntVar implements LinearExpr {
|
||||
public class IntVar implements LinearArgument {
|
||||
IntVar(CpModelProto.Builder builder, Domain domain, String name) {
|
||||
this.modelBuilder = builder;
|
||||
this.variableIndex = modelBuilder.getVariablesCount();
|
||||
@@ -35,17 +35,12 @@ public class IntVar implements LinearExpr {
|
||||
this.varBuilder = modelBuilder.getVariablesBuilder(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return varBuilder.toString();
|
||||
}
|
||||
|
||||
/** Returns the name of the variable given upon creation. */
|
||||
public String getName() {
|
||||
return varBuilder.getName();
|
||||
}
|
||||
|
||||
/** Internal, returns the index of the variable in the underlying CpModelProto. */
|
||||
/** Returns the index of the variable in the underlying CpModelProto. */
|
||||
public int getIndex() {
|
||||
return variableIndex;
|
||||
}
|
||||
@@ -55,31 +50,10 @@ public class IntVar implements LinearExpr {
|
||||
return varBuilder;
|
||||
}
|
||||
|
||||
// LinearExpr interface.
|
||||
// LinearArgument interface
|
||||
@Override
|
||||
public int numElements() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntVar getVariable(int index) {
|
||||
if (index != 0) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCoefficient(int index) {
|
||||
if (index != 0) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getCoefficient(): " + index);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOffset() {
|
||||
return 0;
|
||||
public LinearExpr build() {
|
||||
return new AffineExpression(variableIndex, 1, 0);
|
||||
}
|
||||
|
||||
/** Returns the domain as a string without the enclosing []. */
|
||||
@@ -103,8 +77,8 @@ public class IntVar implements LinearExpr {
|
||||
return CpSatHelper.variableDomain(varBuilder.build());
|
||||
}
|
||||
|
||||
/** Returns a short string describing the variable. */
|
||||
public String getShortString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
if (varBuilder.getName().isEmpty()) {
|
||||
if (varBuilder.getDomainCount() == 2 && varBuilder.getDomain(0) == varBuilder.getDomain(1)) {
|
||||
return String.format("%d", varBuilder.getDomain(0));
|
||||
|
||||
@@ -69,17 +69,17 @@ public final class IntervalVar {
|
||||
|
||||
/** Returns the start expression. */
|
||||
public LinearExpr getStartExpr() {
|
||||
return LinearExpr.rebuildFromLinearExpressionProto(intervalBuilder.getStart(), modelBuilder);
|
||||
return LinearExpr.rebuildFromLinearExpressionProto(intervalBuilder.getStart());
|
||||
}
|
||||
|
||||
/** Returns the size expression. */
|
||||
public LinearExpr getSizeExpr() {
|
||||
return LinearExpr.rebuildFromLinearExpressionProto(intervalBuilder.getSize(), modelBuilder);
|
||||
return LinearExpr.rebuildFromLinearExpressionProto(intervalBuilder.getSize());
|
||||
}
|
||||
|
||||
/** Returns the end expression. */
|
||||
public LinearExpr getEndExpr() {
|
||||
return LinearExpr.rebuildFromLinearExpressionProto(intervalBuilder.getEnd(), modelBuilder);
|
||||
return LinearExpr.rebuildFromLinearExpressionProto(intervalBuilder.getEnd());
|
||||
}
|
||||
|
||||
private final CpModelProto.Builder modelBuilder;
|
||||
|
||||
20
ortools/java/com/google/ortools/sat/LinearArgument.java
Normal file
20
ortools/java/com/google/ortools/sat/LinearArgument.java
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2010-2021 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 object that can build a LinearExpr object. */
|
||||
public interface LinearArgument {
|
||||
/** Builds a linear expression. */
|
||||
LinearExpr build();
|
||||
}
|
||||
@@ -13,16 +13,15 @@
|
||||
|
||||
package com.google.ortools.sat;
|
||||
|
||||
import com.google.ortools.sat.CpModelProto;
|
||||
import com.google.ortools.sat.LinearExpressionProto;
|
||||
|
||||
/** A linear expression interface that can be parsed. */
|
||||
public interface LinearExpr {
|
||||
/** Returns the number of elements in the interface. */
|
||||
/** A linear expression (sum (ai * xi) + b). It specifies methods to help parsing the expression. */
|
||||
public interface LinearExpr extends LinearArgument {
|
||||
/** Returns the number of terms (excluding the constant one) in this expression. */
|
||||
int numElements();
|
||||
|
||||
/** Returns the ith variable. */
|
||||
IntVar getVariable(int index);
|
||||
/** Returns the index of the ith variable. */
|
||||
int getVariableIndex(int index);
|
||||
|
||||
/** Returns the ith coefficient. */
|
||||
long getCoefficient(int index);
|
||||
@@ -40,76 +39,36 @@ public interface LinearExpr {
|
||||
return newBuilder().add(value).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addTerm(var, coeff).build() */
|
||||
static LinearExpr term(IntVar var, long coeff) {
|
||||
return newBuilder().addTerm(var, coeff).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addTerm(expr, coeff).build() */
|
||||
static LinearExpr term(LinearExpr expr, long coeff) {
|
||||
static LinearExpr term(LinearArgument expr, long coeff) {
|
||||
return newBuilder().addTerm(expr, coeff).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addTerm(literal, coeff).build() */
|
||||
static LinearExpr term(Literal literal, long coeff) {
|
||||
return newBuilder().addTerm(literal, coeff).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addSum(vars).build() */
|
||||
static LinearExpr sum(IntVar[] vars) {
|
||||
return newBuilder().addSum(vars).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addSum(exprs).build() */
|
||||
static LinearExpr sum(LinearExpr[] exprs) {
|
||||
static LinearExpr sum(LinearArgument[] exprs) {
|
||||
return newBuilder().addSum(exprs).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addSum(literals).build() */
|
||||
static LinearExpr sum(Literal[] literals) {
|
||||
return newBuilder().addSum(literals).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addWeightedSum(vars, coeffs).build() */
|
||||
static LinearExpr weightedSum(IntVar[] vars, long[] coeffs) {
|
||||
return newBuilder().addWeightedSum(vars, coeffs).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addWeightedSum(literals, coeffs).build() */
|
||||
static LinearExpr weightedSum(Literal[] literals, long[] coeffs) {
|
||||
return newBuilder().addWeightedSum(literals, coeffs).build();
|
||||
}
|
||||
|
||||
/** Shortcut for newBuilder().addWeightedSum(exprs, coeffs).build() */
|
||||
static LinearExpr weightedSum(LinearExpr[] exprs, long[] coeffs) {
|
||||
static LinearExpr weightedSum(LinearArgument[] exprs, long[] coeffs) {
|
||||
return newBuilder().addWeightedSum(exprs, coeffs).build();
|
||||
}
|
||||
|
||||
static LinearExpr rebuildFromLinearExpressionProto(
|
||||
LinearExpressionProto proto, CpModelProto.Builder builder) {
|
||||
static LinearExpr rebuildFromLinearExpressionProto(LinearExpressionProto proto) {
|
||||
int numElements = proto.getVarsCount();
|
||||
if (numElements == 0) {
|
||||
return new ConstantExpression(proto.getOffset());
|
||||
} else if (numElements == 1) {
|
||||
return new AffineExpression(
|
||||
new IntVar(builder, proto.getVars(0)), proto.getCoeffs(0), proto.getOffset());
|
||||
return new AffineExpression(proto.getVars(0), proto.getCoeffs(0), proto.getOffset());
|
||||
} else {
|
||||
IntVar[] vars = new IntVar[numElements];
|
||||
int[] varsIndices = new int[numElements];
|
||||
long[] coeffs = new long[numElements];
|
||||
long offset = proto.getOffset();
|
||||
boolean allOnes = true;
|
||||
for (int i = 0; i < numElements; ++i) {
|
||||
vars[i] = new IntVar(builder, proto.getVars(i));
|
||||
varsIndices[i] = proto.getVars(i);
|
||||
coeffs[i] = proto.getCoeffs(i);
|
||||
if (coeffs[i] != 1) {
|
||||
allOnes = false;
|
||||
}
|
||||
}
|
||||
if (allOnes) {
|
||||
return new SumExpression(vars, offset);
|
||||
} else {
|
||||
return new WeightedSumExpression(vars, coeffs, offset);
|
||||
}
|
||||
return new WeightedSumExpression(varsIndices, coeffs, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,160 +13,88 @@
|
||||
|
||||
package com.google.ortools.sat;
|
||||
|
||||
import static java.util.Comparator.comparingInt;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/** Builder class for the LinearExpr container. */
|
||||
public final class LinearExprBuilder {
|
||||
private final TreeMap<IntVar, Long> coefficients;
|
||||
public final class LinearExprBuilder implements LinearArgument {
|
||||
private final TreeMap<Integer, Long> coefficients;
|
||||
private long offset;
|
||||
|
||||
LinearExprBuilder() {
|
||||
this.coefficients = new TreeMap<>(comparingInt(IntVar::getIndex));
|
||||
this.coefficients = new TreeMap<>();
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
public LinearExprBuilder add(LinearExpr expr) {
|
||||
public LinearExprBuilder add(LinearArgument expr) {
|
||||
addTerm(expr, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder add(Literal literal) {
|
||||
addTerm(literal, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder add(long constant) {
|
||||
offset = offset + constant;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addTerm(LinearExpr expr, long coeff) {
|
||||
final int numElements = expr.numElements();
|
||||
public LinearExprBuilder addTerm(LinearArgument expr, long coeff) {
|
||||
final LinearExpr e = expr.build();
|
||||
final int numElements = e.numElements();
|
||||
for (int i = 0; i < numElements; ++i) {
|
||||
coefficients.merge(expr.getVariable(i), expr.getCoefficient(i) * coeff, Long::sum);
|
||||
coefficients.merge(e.getVariableIndex(i), e.getCoefficient(i) * coeff, Long::sum);
|
||||
}
|
||||
offset = offset + expr.getOffset() * coeff;
|
||||
offset = offset + e.getOffset() * coeff;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addTerm(Literal literal, long coeff) {
|
||||
final BoolVar boolVar = literal.getBoolVar();
|
||||
if (literal.negated()) {
|
||||
coefficients.merge(boolVar, -coeff, Long::sum);
|
||||
offset = offset + coeff;
|
||||
} else {
|
||||
coefficients.merge(boolVar, coeff, Long::sum);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addSum(IntVar[] vars) {
|
||||
for (final IntVar var : vars) {
|
||||
addTerm(var, 1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addSum(Literal[] literals) {
|
||||
for (final Literal literal : literals) {
|
||||
addTerm(literal, 1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addSum(LinearExpr[] exprs) {
|
||||
for (final LinearExpr expr : exprs) {
|
||||
public LinearExprBuilder addSum(LinearArgument[] exprs) {
|
||||
for (final LinearArgument expr : exprs) {
|
||||
addTerm(expr, 1);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addWeightedSum(IntVar[] vars, long[] coeffs) {
|
||||
for (int i = 0; i < vars.length; ++i) {
|
||||
addTerm(vars[i], coeffs[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addWeightedSum(IntVar[] vars, int[] coeffs) {
|
||||
for (int i = 0; i < vars.length; ++i) {
|
||||
addTerm(vars[i], coeffs[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addWeightedSum(Literal[] literals, long[] coeffs) {
|
||||
for (int i = 0; i < literals.length; ++i) {
|
||||
addTerm(literals[i], coeffs[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addWeightedSum(Literal[] literals, int[] coeffs) {
|
||||
for (int i = 0; i < literals.length; ++i) {
|
||||
addTerm(literals[i], coeffs[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addWeightedSum(LinearExpr[] exprs, long[] coeffs) {
|
||||
public LinearExprBuilder addWeightedSum(LinearArgument[] exprs, long[] coeffs) {
|
||||
for (int i = 0; i < exprs.length; ++i) {
|
||||
addTerm(exprs[i], coeffs[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearExprBuilder addWeightedSum(LinearExpr[] exprs, int[] coeffs) {
|
||||
public LinearExprBuilder addWeightedSum(LinearArgument[] exprs, int[] coeffs) {
|
||||
for (int i = 0; i < exprs.length; ++i) {
|
||||
addTerm(exprs[i], coeffs[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinearExpr build() {
|
||||
boolean allOnes = true;
|
||||
int numElements = 0;
|
||||
IntVar lastVar = null;
|
||||
int lastVarIndex = -1;
|
||||
long lastCoeff = 0;
|
||||
for (Map.Entry<IntVar, Long> entry : coefficients.entrySet()) {
|
||||
for (Map.Entry<Integer, Long> entry : coefficients.entrySet()) {
|
||||
if (entry.getValue() != 0) {
|
||||
numElements++;
|
||||
lastVar = entry.getKey();
|
||||
lastVarIndex = entry.getKey();
|
||||
lastCoeff = entry.getValue();
|
||||
if (lastCoeff != 1) {
|
||||
allOnes = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numElements == 0) {
|
||||
return new ConstantExpression(offset);
|
||||
} else if (numElements == 1) {
|
||||
return new AffineExpression(lastVar, lastCoeff, offset);
|
||||
} else if (allOnes) {
|
||||
IntVar[] vars = new IntVar[numElements];
|
||||
int index = 0;
|
||||
for (Map.Entry<IntVar, Long> entry : coefficients.entrySet()) {
|
||||
if (entry.getValue() != 0) {
|
||||
vars[index] = entry.getKey();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return new SumExpression(vars, offset);
|
||||
return new AffineExpression(lastVarIndex, lastCoeff, offset);
|
||||
} else {
|
||||
IntVar[] vars = new IntVar[numElements];
|
||||
int[] varIndices = new int[numElements];
|
||||
long[] coeffs = new long[numElements];
|
||||
int index = 0;
|
||||
for (Map.Entry<IntVar, Long> entry : coefficients.entrySet()) {
|
||||
for (Map.Entry<Integer, Long> entry : coefficients.entrySet()) {
|
||||
if (entry.getValue() != 0) {
|
||||
vars[index] = entry.getKey();
|
||||
varIndices[index] = entry.getKey();
|
||||
coeffs[index] = entry.getValue();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return new WeightedSumExpression(vars, coeffs, offset);
|
||||
return new WeightedSumExpression(varIndices, coeffs, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,18 +14,9 @@
|
||||
package com.google.ortools.sat;
|
||||
|
||||
/** Interface to describe a boolean variable or its negation. */
|
||||
public interface Literal extends LinearExpr {
|
||||
public interface Literal extends LinearArgument {
|
||||
public int getIndex();
|
||||
|
||||
/** Returns the Boolean negation of the current literal. */
|
||||
public Literal not();
|
||||
|
||||
/** Returns a short string to describe the literal. */
|
||||
public String getShortString();
|
||||
|
||||
/** Returns the underlying BoolVar */
|
||||
public BoolVar getBoolVar();
|
||||
|
||||
/** Returns true if the literal is the negation of a Boolean variable */
|
||||
public boolean negated();
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ package com.google.ortools.sat;
|
||||
* The negation of a boolean variable. This class should not be used directly, Literal must be used
|
||||
* instead.
|
||||
*/
|
||||
public final class NotBooleanVariable implements Literal {
|
||||
public NotBooleanVariable(BoolVar boolVar) {
|
||||
public final class NotBoolVar implements Literal {
|
||||
public NotBoolVar(BoolVar boolVar) {
|
||||
this.boolVar = boolVar;
|
||||
}
|
||||
|
||||
/** Internal: returns the index in the literal in the underlying CpModelProto. */
|
||||
/** returns the index in the literal in the underlying CpModelProto. */
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return -boolVar.getIndex() - 1;
|
||||
@@ -34,47 +34,16 @@ public final class NotBooleanVariable implements Literal {
|
||||
return boolVar;
|
||||
}
|
||||
|
||||
// LinearArgument interface.
|
||||
@Override
|
||||
public BoolVar getBoolVar() {
|
||||
return boolVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean negated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// LinearExpr interface.
|
||||
@Override
|
||||
public int numElements() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntVar getVariable(int index) {
|
||||
if (index != 0) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
|
||||
}
|
||||
return boolVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCoefficient(int index) {
|
||||
if (index != 0) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getCoefficient(): " + index);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOffset() {
|
||||
return 1;
|
||||
public LinearExpr build() {
|
||||
return new AffineExpression(boolVar.getIndex(), -1, 1);
|
||||
}
|
||||
|
||||
/** Returns a short string describing this literal. */
|
||||
@Override
|
||||
public String getShortString() {
|
||||
return "not(" + boolVar.getShortString() + ")";
|
||||
public String toString() {
|
||||
return "not(" + boolVar + ")";
|
||||
}
|
||||
|
||||
private final BoolVar boolVar;
|
||||
@@ -33,10 +33,10 @@ public class ReservoirConstraint extends Constraint {
|
||||
* <p>It will increase the used capacity by `levelChange` at time `time`. `time` must be an affine
|
||||
* expression.
|
||||
*/
|
||||
void addEvent(LinearExpr time, long levelChange) {
|
||||
void addEvent(LinearArgument time, long levelChange) {
|
||||
ReservoirConstraintProto.Builder reservoir = getBuilder().getReservoirBuilder();
|
||||
reservoir.addTimeExprs(
|
||||
model.getLinearExpressionProtoBuilderFromLinearExpr(time, /*negate=*/false));
|
||||
model.getLinearExpressionProtoBuilderFromLinearArgument(time, /*negate=*/false));
|
||||
reservoir.addLevelChanges(levelChange);
|
||||
reservoir.addActiveLiterals(model.trueLiteral().getIndex());
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class ReservoirConstraint extends Constraint {
|
||||
void addOptionalEvent(LinearExpr time, long levelChange, Literal isActive) {
|
||||
ReservoirConstraintProto.Builder reservoir = getBuilder().getReservoirBuilder();
|
||||
reservoir.addTimeExprs(
|
||||
model.getLinearExpressionProtoBuilderFromLinearExpr(time, /*negate=*/false));
|
||||
model.getLinearExpressionProtoBuilderFromLinearArgument(time, /*negate=*/false));
|
||||
reservoir.addLevelChanges(levelChange);
|
||||
reservoir.addActiveLiterals(isActive.getIndex());
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2010-2021 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 specialized linear expression: sum(xi) + b. */
|
||||
public final class SumExpression implements LinearExpr {
|
||||
private final IntVar[] variables;
|
||||
private final long offset;
|
||||
|
||||
public SumExpression(IntVar[] variables, long offset) {
|
||||
this.variables = variables;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int numElements() {
|
||||
return variables.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntVar getVariable(int index) {
|
||||
if (index < 0 || index >= variables.length) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
|
||||
}
|
||||
return variables[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCoefficient(int index) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@@ -15,32 +15,37 @@ package com.google.ortools.sat;
|
||||
|
||||
/** A specialized linear expression: sum(ai * xi) + b. */
|
||||
public final class WeightedSumExpression implements LinearExpr {
|
||||
private final IntVar[] variables;
|
||||
private final int[] variablesIndices;
|
||||
private final long[] coefficients;
|
||||
private final long offset;
|
||||
|
||||
public WeightedSumExpression(IntVar[] variables, long[] coefficients, long offset) {
|
||||
this.variables = variables;
|
||||
public WeightedSumExpression(int[] variablesIndices, long[] coefficients, long offset) {
|
||||
this.variablesIndices = variablesIndices;
|
||||
this.coefficients = coefficients;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int numElements() {
|
||||
return variables.length;
|
||||
public LinearExpr build() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntVar getVariable(int index) {
|
||||
if (index < 0 || index >= variables.length) {
|
||||
public int numElements() {
|
||||
return variablesIndices.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVariableIndex(int index) {
|
||||
if (index < 0 || index >= variablesIndices.length) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
|
||||
}
|
||||
return variables[index];
|
||||
return variablesIndices[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCoefficient(int index) {
|
||||
if (index < 0 || index >= variables.length) {
|
||||
if (index < 0 || index >= variablesIndices.length) {
|
||||
throw new IllegalArgumentException("wrong index in LinearExpr.getCoefficient(): " + index);
|
||||
}
|
||||
return coefficients[index];
|
||||
|
||||
Reference in New Issue
Block a user