diff --git a/ortools/java/com/google/ortools/sat/AffineExpression.java b/ortools/java/com/google/ortools/sat/AffineExpression.java index c81de860a7..b86d5a4b9f 100644 --- a/ortools/java/com/google/ortools/sat/AffineExpression.java +++ b/ortools/java/com/google/ortools/sat/AffineExpression.java @@ -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 diff --git a/ortools/java/com/google/ortools/sat/BoolVar.java b/ortools/java/com/google/ortools/sat/BoolVar.java index 3f45b1f00f..38024efef5 100644 --- a/ortools/java/com/google/ortools/sat/BoolVar.java +++ b/ortools/java/com/google/ortools/sat/BoolVar.java @@ -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; } diff --git a/ortools/java/com/google/ortools/sat/ConstantExpression.java b/ortools/java/com/google/ortools/sat/ConstantExpression.java index 05c70d15b0..fef6b10108 100644 --- a/ortools/java/com/google/ortools/sat/ConstantExpression.java +++ b/ortools/java/com/google/ortools/sat/ConstantExpression.java @@ -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); + } } diff --git a/ortools/java/com/google/ortools/sat/CpModel.java b/ortools/java/com/google/ortools/sat/CpModel.java index a4aa8e42ad..1e4b7b5ac5 100644 --- a/ortools/java/com/google/ortools/sat/CpModel.java +++ b/ortools/java/com/google/ortools/sat/CpModel.java @@ -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 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)}. - * - *

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 expressions) { + public Constraint addAllDifferent(Iterable 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 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 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 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 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); diff --git a/ortools/java/com/google/ortools/sat/CpSolver.java b/ortools/java/com/google/ortools/sat/CpSolver.java index b31b89a47e..35fcf7829e 100644 --- a/ortools/java/com/google/ortools/sat/CpSolver.java +++ b/ortools/java/com/google/ortools/sat/CpSolver.java @@ -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; } diff --git a/ortools/java/com/google/ortools/sat/CpSolverSolutionCallback.java b/ortools/java/com/google/ortools/sat/CpSolverSolutionCallback.java index 2e5e5a0bd7..7a5828d41d 100644 --- a/ortools/java/com/google/ortools/sat/CpSolverSolutionCallback.java +++ b/ortools/java/com/google/ortools/sat/CpSolverSolutionCallback.java @@ -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; } diff --git a/ortools/java/com/google/ortools/sat/CumulativeConstraint.java b/ortools/java/com/google/ortools/sat/CumulativeConstraint.java index 0c34b6e040..2ebb7dceec 100644 --- a/ortools/java/com/google/ortools/sat/CumulativeConstraint.java +++ b/ortools/java/com/google/ortools/sat/CumulativeConstraint.java @@ -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. diff --git a/ortools/java/com/google/ortools/sat/IntVar.java b/ortools/java/com/google/ortools/sat/IntVar.java index a41c1581b0..7736d98a45 100644 --- a/ortools/java/com/google/ortools/sat/IntVar.java +++ b/ortools/java/com/google/ortools/sat/IntVar.java @@ -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)); diff --git a/ortools/java/com/google/ortools/sat/IntervalVar.java b/ortools/java/com/google/ortools/sat/IntervalVar.java index 2fbaea2351..bb0689ac7c 100644 --- a/ortools/java/com/google/ortools/sat/IntervalVar.java +++ b/ortools/java/com/google/ortools/sat/IntervalVar.java @@ -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; diff --git a/ortools/java/com/google/ortools/sat/LinearArgument.java b/ortools/java/com/google/ortools/sat/LinearArgument.java new file mode 100644 index 0000000000..0004178391 --- /dev/null +++ b/ortools/java/com/google/ortools/sat/LinearArgument.java @@ -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(); +} diff --git a/ortools/java/com/google/ortools/sat/LinearExpr.java b/ortools/java/com/google/ortools/sat/LinearExpr.java index b92e914f03..be6e61ea2f 100644 --- a/ortools/java/com/google/ortools/sat/LinearExpr.java +++ b/ortools/java/com/google/ortools/sat/LinearExpr.java @@ -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); } } } diff --git a/ortools/java/com/google/ortools/sat/LinearExprBuilder.java b/ortools/java/com/google/ortools/sat/LinearExprBuilder.java index 85fcb9772b..64bbbbd5d3 100644 --- a/ortools/java/com/google/ortools/sat/LinearExprBuilder.java +++ b/ortools/java/com/google/ortools/sat/LinearExprBuilder.java @@ -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 coefficients; +public final class LinearExprBuilder implements LinearArgument { + private final TreeMap 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 entry : coefficients.entrySet()) { + for (Map.Entry 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 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 entry : coefficients.entrySet()) { + for (Map.Entry 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); } } } diff --git a/ortools/java/com/google/ortools/sat/Literal.java b/ortools/java/com/google/ortools/sat/Literal.java index 10a50d9c5f..8674c1c823 100644 --- a/ortools/java/com/google/ortools/sat/Literal.java +++ b/ortools/java/com/google/ortools/sat/Literal.java @@ -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(); } diff --git a/ortools/java/com/google/ortools/sat/NotBooleanVariable.java b/ortools/java/com/google/ortools/sat/NotBoolVar.java similarity index 53% rename from ortools/java/com/google/ortools/sat/NotBooleanVariable.java rename to ortools/java/com/google/ortools/sat/NotBoolVar.java index 2ddcfe345f..de5d8c46d6 100644 --- a/ortools/java/com/google/ortools/sat/NotBooleanVariable.java +++ b/ortools/java/com/google/ortools/sat/NotBoolVar.java @@ -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; diff --git a/ortools/java/com/google/ortools/sat/ReservoirConstraint.java b/ortools/java/com/google/ortools/sat/ReservoirConstraint.java index 25ce611b6f..6b34afa01b 100644 --- a/ortools/java/com/google/ortools/sat/ReservoirConstraint.java +++ b/ortools/java/com/google/ortools/sat/ReservoirConstraint.java @@ -33,10 +33,10 @@ public class ReservoirConstraint extends Constraint { *

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()); } diff --git a/ortools/java/com/google/ortools/sat/SumExpression.java b/ortools/java/com/google/ortools/sat/SumExpression.java deleted file mode 100644 index 99065bd983..0000000000 --- a/ortools/java/com/google/ortools/sat/SumExpression.java +++ /dev/null @@ -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; - } -} diff --git a/ortools/java/com/google/ortools/sat/WeightedSumExpression.java b/ortools/java/com/google/ortools/sat/WeightedSumExpression.java index d3d194033c..6bc8d72392 100644 --- a/ortools/java/com/google/ortools/sat/WeightedSumExpression.java +++ b/ortools/java/com/google/ortools/sat/WeightedSumExpression.java @@ -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]; diff --git a/ortools/sat/doc/boolean_logic.md b/ortools/sat/doc/boolean_logic.md index fc975ab3cf..6e47e077ca 100644 --- a/ortools/sat/doc/boolean_logic.md +++ b/ortools/sat/doc/boolean_logic.md @@ -107,7 +107,7 @@ public class LiteralSampleSat { CpModel model = new CpModel(); BoolVar x = model.newBoolVar("x"); Literal notX = x.not(); - System.out.println(notX.getShortString()); + System.out.println(notX); } } ``` diff --git a/ortools/sat/doc/channeling.md b/ortools/sat/doc/channeling.md index d5d2906c94..9214242290 100644 --- a/ortools/sat/doc/channeling.md +++ b/ortools/sat/doc/channeling.md @@ -561,7 +561,7 @@ public class BinPackingProblemSat { for (int i = 0; i < numItems; ++i) { expr.addTerm(x[i][b], items[i][0]); } - model.addEquality(expr.build(), load[b]); + model.addEquality(expr, load[b]); } // Place all items. @@ -570,7 +570,7 @@ public class BinPackingProblemSat { for (int b = 0; b < numBins; ++b) { expr.add(x[i][b]); } - model.addEquality(expr.build(), items[i][1]); + model.addEquality(expr, items[i][1]); } // Links load and slack. diff --git a/ortools/sat/doc/integer_arithmetic.md b/ortools/sat/doc/integer_arithmetic.md index 04d40a5c6b..2aaf78ea14 100644 --- a/ortools/sat/doc/integer_arithmetic.md +++ b/ortools/sat/doc/integer_arithmetic.md @@ -238,9 +238,9 @@ public class RabbitsAndPheasantsSat { IntVar r = model.newIntVar(0, 100, "r"); IntVar p = model.newIntVar(0, 100, "p"); // 20 heads. - model.addEquality(LinearExpr.newBuilder().add(r).add(p).build(), 20); + model.addEquality(LinearExpr.newBuilder().add(r).add(p), 20); // 56 legs. - model.addEquality(LinearExpr.newBuilder().addTerm(r, 4).addTerm(p, 2).build(), 56); + model.addEquality(LinearExpr.newBuilder().addTerm(r, 4).addTerm(p, 2), 56); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); diff --git a/ortools/sat/doc/scheduling.md b/ortools/sat/doc/scheduling.md index 1eca60bedf..a51f7221c7 100644 --- a/ortools/sat/doc/scheduling.md +++ b/ortools/sat/doc/scheduling.md @@ -177,7 +177,7 @@ public class IntervalSampleSat { model.newIntervalVar( startVar, LinearExpr.constant(10), - LinearExpr.newBuilder().add(endVar).add(2).build(), + LinearExpr.newBuilder().add(endVar).add(2), "interval"); System.out.println(intervalVar); @@ -347,7 +347,7 @@ public class OptionalIntervalSampleSat { model.newOptionalIntervalVar( startVar, LinearExpr.constant(10), - LinearExpr.newBuilder().add(endVar).add(2).build(), + LinearExpr.newBuilder().add(endVar).add(2), presence, "interval"); System.out.println(intervalVar); @@ -1067,7 +1067,7 @@ public class RankingSampleSat { expr.add(precedences[j][i]); } expr.add(-1); - model.addEquality(ranks[i], expr.build()); + model.addEquality(ranks[i], expr); } } @@ -1132,7 +1132,7 @@ public class RankingSampleSat { obj.addTerm(presences[t], -7); } obj.addTerm(makespan, 2); - model.minimize(obj.build()); + model.minimize(obj); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); diff --git a/ortools/sat/samples/AssignmentGroupsSat.java b/ortools/sat/samples/AssignmentGroupsSat.java index 000a91cb6f..2be81925c3 100644 --- a/ortools/sat/samples/AssignmentGroupsSat.java +++ b/ortools/sat/samples/AssignmentGroupsSat.java @@ -131,7 +131,7 @@ public class AssignmentGroupsSat { for (int task : allTasks) { expr.add(x[worker][task]); } - model.addEquality(work[worker], expr.build()); + model.addEquality(work[worker], expr); } // Define the allowed groups of worders @@ -160,7 +160,7 @@ public class AssignmentGroupsSat { obj.addTerm(x[worker][task], costs[worker][task]); } } - model.minimize(obj.build()); + model.minimize(obj); // [END objective] // Solve diff --git a/ortools/sat/samples/AssignmentSat.java b/ortools/sat/samples/AssignmentSat.java index 385bbed436..3f490784a4 100644 --- a/ortools/sat/samples/AssignmentSat.java +++ b/ortools/sat/samples/AssignmentSat.java @@ -91,7 +91,7 @@ public class AssignmentSat { obj.addTerm(x[worker][task], costs[worker][task]); } } - model.minimize(obj.build()); + model.minimize(obj); // [END objective] // Solve diff --git a/ortools/sat/samples/AssignmentTaskSizesSat.java b/ortools/sat/samples/AssignmentTaskSizesSat.java index 4860c018c6..8596223d78 100644 --- a/ortools/sat/samples/AssignmentTaskSizesSat.java +++ b/ortools/sat/samples/AssignmentTaskSizesSat.java @@ -79,7 +79,7 @@ public class AssignmentTaskSizesSat { for (int task : allTasks) { expr.addTerm(x[worker][task], taskSizes[task]); } - model.addLessOrEqual(expr.build(), totalSizeMax); + model.addLessOrEqual(expr, totalSizeMax); } // Each task is assigned to exactly one worker. @@ -100,7 +100,7 @@ public class AssignmentTaskSizesSat { obj.addTerm(x[worker][task], costs[worker][task]); } } - model.minimize(obj.build()); + model.minimize(obj); // [END objective] // Solve diff --git a/ortools/sat/samples/AssignmentTeamsSat.java b/ortools/sat/samples/AssignmentTeamsSat.java index dc006a3ecd..6058a8fe9a 100644 --- a/ortools/sat/samples/AssignmentTeamsSat.java +++ b/ortools/sat/samples/AssignmentTeamsSat.java @@ -96,7 +96,7 @@ public class AssignmentTeamsSat { team1Tasks.add(x[worker][task]); } } - model.addLessOrEqual(team1Tasks.build(), teamMax); + model.addLessOrEqual(team1Tasks, teamMax); LinearExprBuilder team2Tasks = LinearExpr.newBuilder(); for (int worker : team2) { @@ -104,7 +104,7 @@ public class AssignmentTeamsSat { team2Tasks.add(x[worker][task]); } } - model.addLessOrEqual(team2Tasks.build(), teamMax); + model.addLessOrEqual(team2Tasks, teamMax); // [END constraints] // Objective @@ -115,7 +115,7 @@ public class AssignmentTeamsSat { obj.addTerm(x[worker][task], costs[worker][task]); } } - model.minimize(obj.build()); + model.minimize(obj); // [END objective] // Solve diff --git a/ortools/sat/samples/BinPackingProblemSat.java b/ortools/sat/samples/BinPackingProblemSat.java index 975143dbea..7d6df08cfa 100644 --- a/ortools/sat/samples/BinPackingProblemSat.java +++ b/ortools/sat/samples/BinPackingProblemSat.java @@ -64,7 +64,7 @@ public class BinPackingProblemSat { for (int i = 0; i < numItems; ++i) { expr.addTerm(x[i][b], items[i][0]); } - model.addEquality(expr.build(), load[b]); + model.addEquality(expr, load[b]); } // Place all items. @@ -73,7 +73,7 @@ public class BinPackingProblemSat { for (int b = 0; b < numBins; ++b) { expr.add(x[i][b]); } - model.addEquality(expr.build(), items[i][1]); + model.addEquality(expr, items[i][1]); } // Links load and slack. diff --git a/ortools/sat/samples/IntervalSampleSat.java b/ortools/sat/samples/IntervalSampleSat.java index 19881c417c..00eaeaec70 100644 --- a/ortools/sat/samples/IntervalSampleSat.java +++ b/ortools/sat/samples/IntervalSampleSat.java @@ -29,8 +29,8 @@ public class IntervalSampleSat { // An interval can be created from three affine expressions. IntVar startVar = model.newIntVar(0, horizon, "start"); IntVar endVar = model.newIntVar(0, horizon, "end"); - IntervalVar intervalVar = model.newIntervalVar(startVar, LinearExpr.constant(10), - LinearExpr.newBuilder().add(endVar).add(2).build(), "interval"); + IntervalVar intervalVar = model.newIntervalVar( + startVar, LinearExpr.constant(10), LinearExpr.newBuilder().add(endVar).add(2), "interval"); System.out.println(intervalVar); // If the size is fixed, a simpler version uses the start expression and the size. diff --git a/ortools/sat/samples/LiteralSampleSat.java b/ortools/sat/samples/LiteralSampleSat.java index 0d5e3d07c8..ec2db0722c 100644 --- a/ortools/sat/samples/LiteralSampleSat.java +++ b/ortools/sat/samples/LiteralSampleSat.java @@ -25,6 +25,6 @@ public class LiteralSampleSat { CpModel model = new CpModel(); BoolVar x = model.newBoolVar("x"); Literal notX = x.not(); - System.out.println(notX.getShortString()); + System.out.println(notX); } } diff --git a/ortools/sat/samples/MinimalJobshopSat.java b/ortools/sat/samples/MinimalJobshopSat.java index 84d0f1471c..905fb5d185 100644 --- a/ortools/sat/samples/MinimalJobshopSat.java +++ b/ortools/sat/samples/MinimalJobshopSat.java @@ -125,7 +125,7 @@ public class MinimalJobshopSat { // [START objective] // Makespan objective. IntVar objVar = model.newIntVar(0, horizon, "makespan"); - List ends = new ArrayList<>(); + List ends = new ArrayList<>(); for (int jobID = 0; jobID < allJobs.size(); ++jobID) { List job = allJobs.get(jobID); List key = Arrays.asList(jobID, job.size() - 1); diff --git a/ortools/sat/samples/MultipleKnapsackSat.java b/ortools/sat/samples/MultipleKnapsackSat.java index c8de6cbb86..4963b877b1 100644 --- a/ortools/sat/samples/MultipleKnapsackSat.java +++ b/ortools/sat/samples/MultipleKnapsackSat.java @@ -74,7 +74,7 @@ public class MultipleKnapsackSat { for (int i : allItems) { load.addTerm(x[i][b], weights[i]); } - model.addLessOrEqual(load.build(), binCapacities[b]); + model.addLessOrEqual(load, binCapacities[b]); } // [END constraints] @@ -87,7 +87,7 @@ public class MultipleKnapsackSat { obj.addTerm(x[i][b], values[i]); } } - model.maximize(obj.build()); + model.maximize(obj); // [END objective] // [START solve] diff --git a/ortools/sat/samples/NursesSat.java b/ortools/sat/samples/NursesSat.java index cd44d76c38..ae05941921 100644 --- a/ortools/sat/samples/NursesSat.java +++ b/ortools/sat/samples/NursesSat.java @@ -104,7 +104,7 @@ public class NursesSat { numShiftsWorked.add(shifts[n][d][s]); } } - model.addLinearConstraint(numShiftsWorked.build(), minShiftsPerNurse, maxShiftsPerNurse); + model.addLinearConstraint(numShiftsWorked, minShiftsPerNurse, maxShiftsPerNurse); } // [END assign_nurses_evenly] diff --git a/ortools/sat/samples/OptionalIntervalSampleSat.java b/ortools/sat/samples/OptionalIntervalSampleSat.java index e9f91dad13..0cbfb7a951 100644 --- a/ortools/sat/samples/OptionalIntervalSampleSat.java +++ b/ortools/sat/samples/OptionalIntervalSampleSat.java @@ -32,7 +32,7 @@ public class OptionalIntervalSampleSat { IntVar endVar = model.newIntVar(0, horizon, "end"); Literal presence = model.newBoolVar("presence"); IntervalVar intervalVar = model.newOptionalIntervalVar(startVar, LinearExpr.constant(10), - LinearExpr.newBuilder().add(endVar).add(2).build(), presence, "interval"); + LinearExpr.newBuilder().add(endVar).add(2), presence, "interval"); System.out.println(intervalVar); // If the size is fixed, a simpler version uses the start expression, the size and the literal. diff --git a/ortools/sat/samples/RabbitsAndPheasantsSat.java b/ortools/sat/samples/RabbitsAndPheasantsSat.java index 1c69c05a4a..94fcf91419 100644 --- a/ortools/sat/samples/RabbitsAndPheasantsSat.java +++ b/ortools/sat/samples/RabbitsAndPheasantsSat.java @@ -33,9 +33,9 @@ public class RabbitsAndPheasantsSat { IntVar r = model.newIntVar(0, 100, "r"); IntVar p = model.newIntVar(0, 100, "p"); // 20 heads. - model.addEquality(LinearExpr.newBuilder().add(r).add(p).build(), 20); + model.addEquality(LinearExpr.newBuilder().add(r).add(p), 20); // 56 legs. - model.addEquality(LinearExpr.newBuilder().addTerm(r, 4).addTerm(p, 2).build(), 56); + model.addEquality(LinearExpr.newBuilder().addTerm(r, 4).addTerm(p, 2), 56); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); diff --git a/ortools/sat/samples/RankingSampleSat.java b/ortools/sat/samples/RankingSampleSat.java index 47076d56d8..55c2d126f3 100644 --- a/ortools/sat/samples/RankingSampleSat.java +++ b/ortools/sat/samples/RankingSampleSat.java @@ -89,7 +89,7 @@ public class RankingSampleSat { expr.add(precedences[j][i]); } expr.add(-1); - model.addEquality(ranks[i], expr.build()); + model.addEquality(ranks[i], expr); } } @@ -152,7 +152,7 @@ public class RankingSampleSat { obj.addTerm(presences[t], -7); } obj.addTerm(makespan, 2); - model.minimize(obj.build()); + model.minimize(obj); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); diff --git a/ortools/sat/samples/ScheduleRequestsSat.java b/ortools/sat/samples/ScheduleRequestsSat.java index f8d3ed76ac..212f4c32f5 100644 --- a/ortools/sat/samples/ScheduleRequestsSat.java +++ b/ortools/sat/samples/ScheduleRequestsSat.java @@ -151,7 +151,7 @@ public class ScheduleRequestsSat { numShiftsWorked.add(shifts[n][d][s]); } } - model.addLinearConstraint(numShiftsWorked.build(), minShiftsPerNurse, maxShiftsPerNurse); + model.addLinearConstraint(numShiftsWorked, minShiftsPerNurse, maxShiftsPerNurse); } // [END assign_nurses_evenly] @@ -164,7 +164,7 @@ public class ScheduleRequestsSat { } } } - model.maximize(obj.build()); + model.maximize(obj); // [END objective] // Creates a solver and solves the model.