[CP-SAT] ScalProd -> WeightedSum

This commit is contained in:
Laurent Perron
2022-01-04 19:35:22 +01:00
parent a022daa56a
commit ceabca677c
29 changed files with 142 additions and 153 deletions

View File

@@ -304,7 +304,7 @@ void AddAlternativeTaskDurationRelaxation(
cp_model.AddEquality(
tasks[t].end,
tasks[t].start +
LinearExpr::ScalProd(presence_literals, shifted_durations) +
LinearExpr::WeightedSum(presence_literals, shifted_durations) +
min_duration);
}
}
@@ -452,9 +452,9 @@ void CreateMachines(
// Add a linear equation to define the size of the tail interval.
if (absl::GetFlag(FLAGS_use_variable_duration_to_encode_transition)) {
cp_model.AddEquality(
tail.interval.SizeExpr(),
LinearExpr::ScalProd(literals, transitions) + tail.fixed_duration);
cp_model.AddEquality(tail.interval.SizeExpr(),
LinearExpr::WeightedSum(literals, transitions) +
tail.fixed_duration);
}
}
LOG(INFO) << "Machine " << m
@@ -540,11 +540,12 @@ void CreateObjective(
problem.scaling_factor().value());
}
cp_model.Minimize(
DoubleLinearExpr::ScalProd(objective_vars, double_objective_coeffs) +
DoubleLinearExpr::WeightedSum(objective_vars, double_objective_coeffs) +
static_cast<double>(objective_offset));
} else {
cp_model.Minimize(LinearExpr::ScalProd(objective_vars, objective_coeffs) +
objective_offset);
cp_model.Minimize(
LinearExpr::WeightedSum(objective_vars, objective_coeffs) +
objective_offset);
}
}

View File

@@ -60,7 +60,7 @@ void MagicSequence(int size) {
for (int i = 0; i < size; ++i) {
vars_equal_to_j.push_back(var_domains[i][j]);
}
cp_model.AddEquality(LinearExpr::ScalProd(var_domains[j], values),
cp_model.AddEquality(LinearExpr::WeightedSum(var_domains[j], values),
LinearExpr::Sum(vars_equal_to_j));
}

View File

@@ -80,10 +80,11 @@ void MultiKnapsackSat(int scaling, const std::string& params) {
for (int b = 0; b < num_bins; ++b) {
IntVar bin_weight = builder.NewIntVar({kWeightMin, kWeightMax});
bin_weights.push_back(bin_weight);
builder.AddEquality(LinearExpr::ScalProd(items_in_bins[b], weights),
builder.AddEquality(LinearExpr::WeightedSum(items_in_bins[b], weights),
bin_weight);
builder.AddLinearConstraint(LinearExpr::ScalProd(items_in_bins[b], volumes),
{kVolumeMin, kVolumeMax});
builder.AddLinearConstraint(
LinearExpr::WeightedSum(items_in_bins[b], volumes),
{kVolumeMin, kVolumeMax});
}
// Each item is selected at most one time.

View File

@@ -91,7 +91,7 @@ public class BalanceGroupSat
{
var itemValues = allItems.Select(x => itemInGroup[x, @group]).ToArray();
var sum = LinearExpr.ScalProd(itemValues, values);
var sum = LinearExpr.WeightedSum(itemValues, values);
model.Add(sum <= averageSumPerGroup + e);
model.Add(sum >= averageSumPerGroup - e);
}

View File

@@ -735,7 +735,7 @@ public class NetworkRoutingSat
traffics.Add(_demands[i].Traffic);
}
var sum = LinearExpr.ScalProd(vars, traffics);
var sum = LinearExpr.WeightedSum(vars, traffics);
var trafficVar = cpModel.NewIntVar(0, sumOfTraffic, $"trafficVar{arcIndex}");
trafficVars.Add(trafficVar);
cpModel.Add(sum == trafficVar);

View File

@@ -253,8 +253,8 @@ public class ShiftSchedulingSat
}
// Objective
var objBoolSum = LinearExpr.ScalProd(objBoolVars, objBoolCoeffs);
var objIntSum = LinearExpr.ScalProd(objIntVars, objIntCoeffs);
var objBoolSum = LinearExpr.WeightedSum(objBoolVars, objBoolCoeffs);
var objIntSum = LinearExpr.WeightedSum(objIntVars, objIntCoeffs);
model.Minimize(objBoolSum + objIntSum);

View File

@@ -1922,7 +1922,7 @@ def bus_driver_scheduling(minimize_drivers, max_num_drivers):
model.Add(
cp_model.LinearExpr.Sum(working_times) == total_driving_time +
num_drivers * (setup_time + cleanup_time) +
cp_model.LinearExpr.ScalProd(delay_literals, delay_weights))
cp_model.LinearExpr.WeightedSum(delay_literals, delay_weights))
if minimize_drivers:
# Minimize the number of working drivers
@@ -1931,7 +1931,7 @@ def bus_driver_scheduling(minimize_drivers, max_num_drivers):
# Minimize the sum of delays between tasks, which in turns minimize the
# sum of working times as the total driving time is fixed
model.Minimize(
cp_model.LinearExpr.ScalProd(delay_literals, delay_weights))
cp_model.LinearExpr.WeightedSum(delay_literals, delay_weights))
if not minimize_drivers and FLAGS.output_proto:
print('Writing proto to %s' % FLAGS.output_proto)

View File

@@ -127,7 +127,7 @@ def solve_with_duplicate_items(data, max_height, max_width):
model.AddNoOverlap2D(x_intervals, y_intervals)
## Objective.
model.Maximize(cp_model.LinearExpr.ScalProd(is_used, item_values))
model.Maximize(cp_model.LinearExpr.WeightedSum(is_used, item_values))
# Output proto to file.
if FLAGS.output_proto:
@@ -217,7 +217,7 @@ def solve_with_duplicate_optional_items(data, max_height, max_width):
model.AddNoOverlap2D(x_intervals, y_intervals)
## Objective.
model.Maximize(cp_model.LinearExpr.ScalProd(is_used, item_values))
model.Maximize(cp_model.LinearExpr.WeightedSum(is_used, item_values))
# Output proto to file.
if FLAGS.output_proto:
@@ -330,7 +330,7 @@ def solve_with_rotations(data, max_height, max_width):
model.AddNoOverlap2D(x_intervals, y_intervals)
# Objective.
model.Maximize(cp_model.LinearExpr.ScalProd(is_used, item_values))
model.Maximize(cp_model.LinearExpr.WeightedSum(is_used, item_values))
# Output proto to file.
if FLAGS.output_proto:

View File

@@ -288,7 +288,7 @@ def solve_shift_scheduling(params, output_proto):
# Exactly one shift per day.
for e in range(num_employees):
for d in range(num_days):
model.Add(sum(work[e, s, d] for s in range(num_shifts)) == 1)
model.AddExactlyOne([work[e, s, d] for s in range(num_shifts)])
# Fixed assignments.
for e, s, d in fixed_assignments:

View File

@@ -156,7 +156,7 @@ public final class LinearExprTest {
}
@Test
public void testLinearExpr_scalProd() {
public void testLinearExpr_weightedSum() {
final CpModel model = new CpModel();
assertNotNull(model);
final Domain domain = new Domain(0, 10);
@@ -193,7 +193,7 @@ public final class LinearExprTest {
}
@Test
public void testLinearExpr_booleanScalProd() {
public void testLinearExpr_booleanWeightedSum() {
final CpModel model = new CpModel();
assertNotNull(model);
final Literal x = model.newBoolVar("x");

View File

@@ -291,7 +291,7 @@ namespace Google.OrTools.Tests
}
[Fact]
public void LargeScalProdLong()
public void LargeWeightedSumLong()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
@@ -304,14 +304,14 @@ namespace Google.OrTools.Tests
}
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.ScalProd(vars, coeffs));
model.Minimize(LinearExpr.WeightedSum(vars, coeffs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Long: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeScalProdInt()
public void LargeWeightedSumInt()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
@@ -324,14 +324,14 @@ namespace Google.OrTools.Tests
}
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.ScalProd(vars, coeffs));
model.Minimize(LinearExpr.WeightedSum(vars, coeffs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Int: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeScalProdExpr()
public void LargeWeightedSumExpr()
{
CpModel model = new CpModel();
List<LinearExpr> exprs = new List<LinearExpr>();
@@ -349,7 +349,7 @@ namespace Google.OrTools.Tests
}
[Fact]
public void LargeScalProdProto()
public void LargeWeightedSumProto()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
@@ -388,7 +388,7 @@ namespace Google.OrTools.Tests
public void SolveFromString()
{
string model_str = @"
{
{
""variables"": [
{ ""name"": ""C"", ""domain"": [ ""1"", ""9"" ] },
{ ""name"": ""P"", ""domain"": [ ""0"", ""9"" ] },

View File

@@ -923,7 +923,7 @@ public final class CpModel {
public void minimize(DoubleLinearExpr expr) {
FloatObjectiveProto.Builder obj = modelBuilder.getFloatingPointObjectiveBuilder();
for (int i = 0; i < expr.numElements(); ++i) {
obj.addVars(expr.getVariable(i).getIndex()).addCoeffs(expr.getCoefficient(i));
obj.addVars(expr.getVariableIndex(i)).addCoeffs(expr.getCoefficient(i));
}
obj.setOffset(expr.getOffset()).setMaximize(false);
}
@@ -942,7 +942,7 @@ public final class CpModel {
public void maximize(DoubleLinearExpr expr) {
FloatObjectiveProto.Builder obj = modelBuilder.getFloatingPointObjectiveBuilder();
for (int i = 0; i < expr.numElements(); ++i) {
obj.addVars(expr.getVariable(i).getIndex()).addCoeffs(expr.getCoefficient(i));
obj.addVars(expr.getVariableIndex(i)).addCoeffs(expr.getCoefficient(i));
}
obj.setOffset(expr.getOffset()).setMaximize(true);
}

View File

@@ -15,7 +15,7 @@ package com.google.ortools.sat;
/** A linear expression interface that can be parsed. */
public class DoubleLinearExpr {
private final IntVar[] variables;
private final int[] variableIndices;
private final double[] coefficients;
private double offset;
@@ -24,49 +24,49 @@ public class DoubleLinearExpr {
return sumWithOffset(variables, 0.0);
}
/** Creates a sum expression. */
static DoubleLinearExpr sum(Literal[] literals) {
// We need the scalar product for the negative coefficient of negated Boolean variables.
return sumWithOffset(literals, 0.0);
}
/** Creates a sum expression with a double offset. */
static DoubleLinearExpr sumWithOffset(IntVar[] variables, double offset) {
return new DoubleLinearExpr(variables, offset);
}
/** Creates a sum expression. */
static DoubleLinearExpr booleanSum(Literal[] literals) {
// We need the scalar product for the negative coefficient of negated Boolean variables.
return booleanSumWithOffset(literals, 0.0);
}
/** Creates a sum expression with a double offset. */
static DoubleLinearExpr booleanSumWithOffset(Literal[] literals, double offset) {
static DoubleLinearExpr sumWithOffset(Literal[] literals, double offset) {
// We need the scalar product for the negative coefficient of negated Boolean variables.
return new DoubleLinearExpr(literals, offset);
}
/** Creates a scalar product. */
static DoubleLinearExpr scalProd(IntVar[] variables, double[] coefficients) {
return scalProdWithOffset(variables, coefficients, 0.0);
static DoubleLinearExpr weightedSum(IntVar[] variables, double[] coefficients) {
return weightedSumWithOffset(variables, coefficients, 0.0);
}
/** Creates a scalar product. */
static DoubleLinearExpr scalProdWithOffset(
static DoubleLinearExpr weightedSum(Literal[] literals, double[] coefficients) {
return weightedSumWithOffset(literals, coefficients, 0.0);
}
/** Creates a scalar product. */
static DoubleLinearExpr weightedSumWithOffset(
IntVar[] variables, double[] coefficients, double offset) {
if (variables.length != coefficients.length) {
throw new CpModel.MismatchedArrayLengths(
"DoubleLinearExpr.scalProd", "variables", "coefficients");
"DoubleLinearExpr.weightedSum", "variables", "coefficients");
}
return new DoubleLinearExpr(variables, coefficients, offset);
}
/** Creates a scalar product. */
static DoubleLinearExpr booleanScalProd(Literal[] literals, double[] coefficients) {
return booleanScalProdWithOffset(literals, coefficients, 0.0);
}
/** Creates a scalar product with a double offset. */
static DoubleLinearExpr booleanScalProdWithOffset(
static DoubleLinearExpr weightedSumWithOffset(
Literal[] literals, double[] coefficients, double offset) {
if (literals.length != coefficients.length) {
throw new CpModel.MismatchedArrayLengths(
"DoubleLinearExpr.scalProd", "literals", "coefficients");
"DoubleLinearExpr.weightedSum", "literals", "coefficients");
}
return new DoubleLinearExpr(literals, coefficients, offset);
}
@@ -98,20 +98,20 @@ public class DoubleLinearExpr {
/** Returns the number of elements in the interface. */
public int numElements() {
return variables.length;
return variableIndices.length;
}
/** Returns the ith variable. */
public IntVar getVariable(int index) {
if (index < 0 || index >= variables.length) {
public int getVariableIndex(int index) {
if (index < 0 || index >= variableIndices.length) {
throw new IllegalArgumentException("wrong index in LinearExpr.getVariable(): " + index);
}
return variables[index];
return variableIndices[index];
}
/** Returns the ith coefficient. */
public double getCoefficient(int index) {
if (index < 0 || index >= variables.length) {
if (index < 0 || index >= variableIndices.length) {
throw new IllegalArgumentException("wrong index in LinearExpr.getCoefficient(): " + index);
}
return coefficients[index];
@@ -123,14 +123,17 @@ public class DoubleLinearExpr {
}
public DoubleLinearExpr(IntVar[] variables, double[] coefficients, double offset) {
this.variables = variables;
this.variableIndices = new int[variables.length];
for (int i = 0; i < variables.length; ++i) {
this.variableIndices[i] = variables[i].getIndex();
}
this.coefficients = coefficients;
this.offset = offset;
}
public DoubleLinearExpr(Literal[] literals, double[] coefficients, double offset) {
int size = literals.length;
this.variables = new IntVar[size];
this.variableIndices = new int[size];
this.coefficients = new double[size];
this.offset = offset;
@@ -138,10 +141,10 @@ public class DoubleLinearExpr {
Literal lit = literals[i];
double coeff = coefficients[i];
if (lit.getIndex() >= 0) {
this.variables[i] = (IntVar) lit;
this.variableIndices[i] = lit.getIndex();
this.coefficients[i] = coeff;
} else {
this.variables[i] = (IntVar) lit.not();
this.variableIndices[i] = lit.not().getIndex();
this.coefficients[i] = -coeff;
this.offset -= coeff;
}
@@ -149,18 +152,18 @@ public class DoubleLinearExpr {
}
public DoubleLinearExpr(IntVar var, double coefficient, double offset) {
this.variables = new IntVar[] {var};
this.variableIndices = new int[] {var.getIndex()};
this.coefficients = new double[] {coefficient};
this.offset = offset;
}
public DoubleLinearExpr(Literal lit, double coefficient, double offset) {
if (lit.getIndex() >= 0) {
this.variables = new IntVar[] {(IntVar) lit};
this.variableIndices = new int[] {lit.getIndex()};
this.coefficients = new double[] {coefficient};
this.offset = offset;
} else {
this.variables = new IntVar[] {(IntVar) lit.not()};
this.variableIndices = new int[] {lit.not().getIndex()};
this.coefficients = new double[] {-coefficient};
this.offset = offset + coefficient;
}
@@ -168,29 +171,29 @@ public class DoubleLinearExpr {
public DoubleLinearExpr(IntVar[] vars, double offset) {
int size = vars.length;
this.variables = new IntVar[size];
this.variableIndices = new int[size];
this.coefficients = new double[size];
this.offset = offset;
for (int i = 0; i < size; ++i) {
this.variables[i] = vars[i];
this.variableIndices[i] = vars[i].getIndex();
this.coefficients[i] = 1;
}
}
public DoubleLinearExpr(Literal[] literals, double offset) {
int size = literals.length;
this.variables = new IntVar[size];
this.variableIndices = new int[size];
this.coefficients = new double[size];
this.offset = offset;
for (int i = 0; i < size; ++i) {
Literal lit = literals[i];
if (lit.getIndex() >= 0) {
this.variables[i] = (IntVar) lit;
this.variableIndices[i] = lit.getIndex();
this.coefficients[i] = 1;
} else { // NotBooleanVar.
this.variables[i] = (IntVar) lit.not();
} else { // NotBoolVar.
this.variableIndices[i] = lit.not().getIndex();
this.coefficients[i] = -1.0;
this.offset -= 1.0;
}

View File

@@ -13,7 +13,11 @@
package com.google.ortools.sat;
/** A object that can build a LinearExpr object. */
/**
* A object that can build a LinearExpr object.
*
* <p>This class is used in all modeling methods of the CpModel class.
*/
public interface LinearArgument {
/** Builds a linear expression. */
LinearExpr build();

View File

@@ -202,8 +202,8 @@ LinearExpr LinearExpr::Sum(absl::Span<const BoolVar> vars) {
return result;
}
LinearExpr LinearExpr::ScalProd(absl::Span<const IntVar> vars,
absl::Span<const int64_t> coeffs) {
LinearExpr LinearExpr::WeightedSum(absl::Span<const IntVar> vars,
absl::Span<const int64_t> coeffs) {
CHECK_EQ(vars.size(), coeffs.size());
LinearExpr result;
for (int i = 0; i < vars.size(); ++i) {
@@ -212,8 +212,8 @@ LinearExpr LinearExpr::ScalProd(absl::Span<const IntVar> vars,
return result;
}
LinearExpr LinearExpr::ScalProd(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs) {
LinearExpr LinearExpr::WeightedSum(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs) {
CHECK_EQ(vars.size(), coeffs.size());
LinearExpr result;
for (int i = 0; i < vars.size(); ++i) {
@@ -222,8 +222,8 @@ LinearExpr LinearExpr::ScalProd(absl::Span<const BoolVar> vars,
return result;
}
LinearExpr LinearExpr::ScalProd(std::initializer_list<IntVar> vars,
absl::Span<const int64_t> coeffs) {
LinearExpr LinearExpr::WeightedSum(std::initializer_list<IntVar> vars,
absl::Span<const int64_t> coeffs) {
CHECK_EQ(vars.size(), coeffs.size());
LinearExpr result;
int count = 0;
@@ -253,8 +253,8 @@ LinearExpr LinearExpr::BooleanSum(absl::Span<const BoolVar> vars) {
return result;
}
LinearExpr LinearExpr::BooleanScalProd(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs) {
LinearExpr LinearExpr::BooleanWeightedSum(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs) {
CHECK_EQ(vars.size(), coeffs.size());
LinearExpr result;
for (int i = 0; i < vars.size(); ++i) {
@@ -386,8 +386,8 @@ DoubleLinearExpr DoubleLinearExpr::Sum(absl::Span<const BoolVar> vars) {
return result;
}
DoubleLinearExpr DoubleLinearExpr::ScalProd(absl::Span<const IntVar> vars,
absl::Span<const double> coeffs) {
DoubleLinearExpr DoubleLinearExpr::WeightedSum(
absl::Span<const IntVar> vars, absl::Span<const double> coeffs) {
CHECK_EQ(vars.size(), coeffs.size());
DoubleLinearExpr result;
for (int i = 0; i < vars.size(); ++i) {
@@ -396,8 +396,8 @@ DoubleLinearExpr DoubleLinearExpr::ScalProd(absl::Span<const IntVar> vars,
return result;
}
DoubleLinearExpr DoubleLinearExpr::ScalProd(absl::Span<const BoolVar> vars,
absl::Span<const double> coeffs) {
DoubleLinearExpr DoubleLinearExpr::WeightedSum(
absl::Span<const BoolVar> vars, absl::Span<const double> coeffs) {
CHECK_EQ(vars.size(), coeffs.size());
DoubleLinearExpr result;
for (int i = 0; i < vars.size(); ++i) {

View File

@@ -24,7 +24,8 @@
IntVar pheasants = cp_model.NewIntVar(all_animals).WithName("pheasants");
cp_model.AddEquality(LinearExpr::Sum({rabbits, pheasants}), 20);
cp_model.AddEquality(LinearExpr::ScalProd({rabbits, pheasants}, {4, 2}), 56);
cp_model.AddEquality(LinearExpr::WeightedSum({rabbits, pheasants}, {4, 2}),
56);
const CpSolverResponse response = Solve(cp_model.Build());
if (response.status() == CpSolverStatus::FEASIBLE) {
@@ -260,17 +261,17 @@ class LinearExpr {
static LinearExpr Sum(absl::Span<const BoolVar> vars);
/// Constructs the scalar product of variables and coefficients.
static LinearExpr ScalProd(absl::Span<const IntVar> vars,
absl::Span<const int64_t> coeffs);
static LinearExpr WeightedSum(absl::Span<const IntVar> vars,
absl::Span<const int64_t> coeffs);
/// Constructs the scalar product of Boolean variables and coefficients.
static LinearExpr ScalProd(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs);
static LinearExpr WeightedSum(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs);
/// Constructs the scalar product of variables and coefficients.
// TODO(user): Remove when the operators + and * are implemented.
static LinearExpr ScalProd(std::initializer_list<IntVar> vars,
absl::Span<const int64_t> coeffs);
static LinearExpr WeightedSum(std::initializer_list<IntVar> vars,
absl::Span<const int64_t> coeffs);
/// Constructs var * coefficient.
static LinearExpr Term(IntVar var, int64_t coefficient);
@@ -281,9 +282,9 @@ class LinearExpr {
/// Deprecated. Use Sum() instead.
static LinearExpr BooleanSum(absl::Span<const BoolVar> vars);
/// Deprecated. Use ScalProd() instead.
static LinearExpr BooleanScalProd(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs);
/// Deprecated. Use WeightedSum() instead.
static LinearExpr BooleanWeightedSum(absl::Span<const BoolVar> vars,
absl::Span<const int64_t> coeffs);
/// Constructs a linear expr from its proto representation.
static LinearExpr FromProto(const LinearExpressionProto& proto);
@@ -348,14 +349,14 @@ std::ostream& operator<<(std::ostream& os, const LinearExpr& e);
// e2 = x + y + 5
DoubleLinearExpr e2 = DoubleLinearExpr::Sum({x, y}).AddConstant(5.0);
// e3 = 2 * x - y
DoubleLinearExpr e3 = DoubleLinearExpr::ScalProd({x, y}, {2, -1});
DoubleLinearExpr e3 = DoubleLinearExpr::WeightedSum({x, y}, {2, -1});
DoubleLinearExpr e4(b); // e4 = b.
DoubleLinearExpr e5(b.Not()); // e5 = 1 - b.
// If passing a std::vector<BoolVar>, a specialized method must be called.
std::vector<BoolVar> bools = {b, Not(c)};
DoubleLinearExpr e6 = DoubleLinearExpr::Sum(bools); // e6 = b + 1 - c;
// e7 = -3.0 * b + 1.5 - 1.5 * c;
DoubleLinearExpr e7 = DoubleLinearExpr::ScalProd(bools, {-3.0, 1.5});
DoubleLinearExpr e7 = DoubleLinearExpr::WeightedSum(bools, {-3.0, 1.5});
\endcode
* This can be used in the objective definition.
* \code
@@ -410,12 +411,12 @@ class DoubleLinearExpr {
static DoubleLinearExpr Sum(absl::Span<const BoolVar> vars);
/// Constructs the scalar product of variables and coefficients.
static DoubleLinearExpr ScalProd(absl::Span<const IntVar> vars,
absl::Span<const double> coeffs);
static DoubleLinearExpr WeightedSum(absl::Span<const IntVar> vars,
absl::Span<const double> coeffs);
/// Constructs the scalar product of Boolean variables and coefficients.
static DoubleLinearExpr ScalProd(absl::Span<const BoolVar> vars,
absl::Span<const double> coeffs);
static DoubleLinearExpr WeightedSum(absl::Span<const BoolVar> vars,
absl::Span<const double> coeffs);
/// Returns the vector of variable indices.
const std::vector<int>& variables() const { return variables_; }

View File

@@ -17,28 +17,6 @@ using System;
using System.Collections.Generic;
using Google.OrTools.Util;
// Helpers.
// IntVar[] helper class.
public static class IntVarArrayHelper
{
[Obsolete("This Sum method is deprecated, please use LinearExpr.Sum() instead.")]
public static LinearExpr Sum(this IntVar[] vars)
{
return LinearExpr.Sum(vars);
}
[Obsolete("This ScalProd method is deprecated, please use LinearExpr.ScalProd() instead.")]
public static LinearExpr ScalProd(this IntVar[] vars, int[] coeffs)
{
return LinearExpr.ScalProd(vars, coeffs);
}
[Obsolete("This ScalProd method is deprecated, please use LinearExpr.ScalProd() instead.")]
public static LinearExpr ScalProd(this IntVar[] vars, long[] coeffs)
{
return LinearExpr.ScalProd(vars, coeffs);
}
}
public interface ILiteral
{
ILiteral Not();
@@ -58,12 +36,12 @@ public class LinearExpr
return new SumArray(exprs);
}
public static LinearExpr ScalProd(IEnumerable<IntVar> vars, IEnumerable<int> coeffs)
public static LinearExpr WeightedSum(IEnumerable<IntVar> vars, IEnumerable<int> coeffs)
{
return new SumArray(vars, coeffs);
}
public static LinearExpr ScalProd(IEnumerable<IntVar> vars, IEnumerable<long> coeffs)
public static LinearExpr WeightedSum(IEnumerable<IntVar> vars, IEnumerable<long> coeffs)
{
return new SumArray(vars, coeffs);
}

View File

@@ -665,7 +665,7 @@ public class BinPackingProblemSat
{
tmp[i] = x[i, b];
}
model.Add(load[b] == LinearExpr.ScalProd(tmp, sizes));
model.Add(load[b] == LinearExpr.WeightedSum(tmp, sizes));
}
// Place all items.

View File

@@ -96,7 +96,8 @@ type is not uniform across languages.
### Other methods
To exclude a single value, use ranges combined with int64min and int64max
values, e.g., `[[int64min, -3], [-1, int64max]]`, or use the `Complement` method.
values, e.g., `[[int64min, -3], [-1, int64max]]`, or use the `Complement`
method.
To create a variable with a single value domain, use the `NewConstant()` API (or
`newConstant()` in Java).
@@ -106,13 +107,13 @@ To create a variable with a single value domain, use the `NewConstant()` API (or
### C++ and Java linear constraints and linear expressions
**C++** and **Java** APIs do not use arithmetic operators (+, \*, -, <=...).
Linear constraints are created using a method of the model factory, such as
Linear constraints are created using a method of the model factory, such as
`cp_model.AddEquality(x, 3)` in C++, or `cp_model.addGreaterOrEqual(x, 10)` in
Java.
Furthermore, helper methods can be used to create sums and scalar products like
`LinearExpr::Sum({x, y, z})` in C++, and `LinearExpr.scalProd(new IntVar[] {x,
y, z}, new long[] {1, 2, 3})` in Java.
`LinearExpr::Sum({x, y, z})` in C++, and `LinearExpr.weightedSum(new IntVar[]
{x, y, z}, new long[] {1, 2, 3})` in Java.
### Python and C\# linear constraints and linear expressions
@@ -122,9 +123,9 @@ y, z}, new long[] {1, 2, 3})` in Java.
### Generic linear constraint
in **all languages**, the cp_model factory offers a generic method to constrain a
linear expression to be in a domain. This is used in the step function examples
below.
in **all languages**, the cp_model factory offers a generic method to constrain
a linear expression to be in a domain. This is used in the step function
examples below.
### Limitations

View File

@@ -295,7 +295,7 @@ public class SolutionHintingSampleSat
model.AddHint(x, 1);
model.AddHint(y, 2);
model.Maximize(LinearExpr.ScalProd(new IntVar[] { x, y, z }, new int[] { 1, 2, 3 }));
model.Maximize(LinearExpr.WeightedSum(new IntVar[] { x, y, z }, new int[] { 1, 2, 3 }));
// Creates a solver and solves the model.
CpSolver solver = new CpSolver();

View File

@@ -172,7 +172,7 @@ class LinearExpr(object):
```
model.Minimize(cp_model.LinearExpr.Sum(expressions))
model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0)
```
"""
@@ -184,14 +184,14 @@ class LinearExpr(object):
return _SumArray(expressions)
@classmethod
def ScalProd(cls, expressions, coefficients):
def WeightedSum(cls, expressions, coefficients):
"""Creates the expression sum(expressions[i] * coefficients[i])."""
if LinearExpr.IsEmptyOrAllNull(coefficients):
return 0
elif len(expressions) == 1:
return expressions[0] * coefficients[0]
else:
return _ScalProd(expressions, coefficients)
return _WeightedSum(expressions, coefficients)
@classmethod
def Term(cls, expression, coefficient):
@@ -229,7 +229,7 @@ class LinearExpr(object):
if all_ones:
return _SumArray(variables, offset)
else:
return _ScalProd(variables, coeffs, offset)
return _WeightedSum(variables, coeffs, offset)
def GetIntegerVarValueMap(self):
"""Scans the expression, and returns (var_coef_map, constant)."""
@@ -250,7 +250,7 @@ class LinearExpr(object):
for e in expr.Expressions():
to_process.append((e, coeff))
constant += expr.Constant() * coeff
elif isinstance(expr, _ScalProd):
elif isinstance(expr, _WeightedSum):
for e, c in zip(expr.Expressions(), expr.Coefficients()):
to_process.append((e, coeff * c))
constant += expr.Constant() * coeff
@@ -285,7 +285,7 @@ class LinearExpr(object):
for e in expr.Expressions():
to_process.append((e, coeff))
constant += expr.Constant() * coeff
elif isinstance(expr, _ScalProd):
elif isinstance(expr, _WeightedSum):
for e, c in zip(expr.Expressions(), expr.Coefficients()):
to_process.append((e, coeff * c))
constant += expr.Constant() * coeff
@@ -547,8 +547,8 @@ class _SumArray(LinearExpr):
return self.__constant
class _ScalProd(LinearExpr):
"""Represents the scalar product of expressions with constants and a constant."""
class _WeightedSum(LinearExpr):
"""Represents sum(ai * xi) + b."""
def __init__(self, expressions, coefficients, constant=0):
self.__expressions = []
@@ -556,7 +556,7 @@ class _ScalProd(LinearExpr):
self.__constant = constant
if len(expressions) != len(coefficients):
raise TypeError(
'In the LinearExpr.ScalProd method, the expression array and the '
'In the LinearExpr.WeightedSum method, the expression array and the '
' coefficient array must have the same length.')
for e, c in zip(expressions, coefficients):
c = cmh.assert_is_a_number(c)
@@ -597,7 +597,7 @@ class _ScalProd(LinearExpr):
return output
def __repr__(self):
return 'ScalProd([{}], [{}], {})'.format(
return 'WeightedSum([{}], [{}], {})'.format(
', '.join(map(repr, self.__expressions)),
', '.join(map(repr, self.__coefficients)), self.__constant)
@@ -2090,7 +2090,7 @@ def EvaluateLinearExpr(expression, solution):
for e in expr.Expressions():
to_process.append((e, coeff))
value += expr.Constant() * coeff
elif isinstance(expr, _ScalProd):
elif isinstance(expr, _WeightedSum):
for e, c in zip(expr.Expressions(), expr.Coefficients()):
to_process.append((e, coeff * c))
value += expr.Constant() * coeff
@@ -2362,7 +2362,7 @@ class CpSolverSolutionCallback(pywrapsat.SolutionCallback):
for e in expr.Expressions():
to_process.append((e, coeff))
value += expr.Constant() * coeff
elif isinstance(expr, _ScalProd):
elif isinstance(expr, _WeightedSum):
for e, c in zip(expr.Expressions(), expr.Coefficients()):
to_process.append((e, coeff * c))
value += expr.Constant() * coeff

View File

@@ -139,7 +139,7 @@ public class AssignmentGroupsSat
// Objective
// [START objective]
model.Minimize(LinearExpr.ScalProd(xFlat, costsFlat));
model.Minimize(LinearExpr.WeightedSum(xFlat, costsFlat));
// [END objective]
// Solve

View File

@@ -80,7 +80,7 @@ public class AssignmentSat
// Objective
// [START objective]
model.Minimize(LinearExpr.ScalProd(xFlat, costsFlat));
model.Minimize(LinearExpr.WeightedSum(xFlat, costsFlat));
// [END objective]
// Solve

View File

@@ -76,7 +76,7 @@ public class AssignmentTaskSizesSat
{
vars[task] = x[worker, task];
}
model.Add(LinearExpr.ScalProd(vars, taskSizes) <= totalSizeMax);
model.Add(LinearExpr.WeightedSum(vars, taskSizes) <= totalSizeMax);
}
// Each task is assigned to exactly one worker.
@@ -93,7 +93,7 @@ public class AssignmentTaskSizesSat
// Objective
// [START objective]
model.Minimize(LinearExpr.ScalProd(xFlat, costsFlat));
model.Minimize(LinearExpr.WeightedSum(xFlat, costsFlat));
// [END objective]
// Solve

View File

@@ -112,7 +112,7 @@ public class AssignmentTeamsSat
// Objective
// [START objective]
model.Minimize(LinearExpr.ScalProd(xFlat, costsFlat));
model.Minimize(LinearExpr.WeightedSum(xFlat, costsFlat));
// [END objective]
// Solve

View File

@@ -67,7 +67,7 @@ public class BinPackingProblemSat
{
tmp[i] = x[i, b];
}
model.Add(load[b] == LinearExpr.ScalProd(tmp, sizes));
model.Add(load[b] == LinearExpr.WeightedSum(tmp, sizes));
}
// Place all items.

View File

@@ -74,7 +74,7 @@ public class MultipleKnapsackSat
{
vars[i] = x[i, b];
}
model.Add(LinearExpr.ScalProd(vars, Weights) <= BinCapacities[b]);
model.Add(LinearExpr.WeightedSum(vars, Weights) <= BinCapacities[b]);
}
// [END constraints]
@@ -91,7 +91,7 @@ public class MultipleKnapsackSat
objectiveValues[k] = Values[i];
}
}
model.Maximize(LinearExpr.ScalProd(objectiveVars, objectiveValues));
model.Maximize(LinearExpr.WeightedSum(objectiveVars, objectiveValues));
// [END objective]
// Solve

View File

@@ -181,7 +181,7 @@ public class ScheduleRequestsSat
}
}
}
model.Maximize(LinearExpr.ScalProd(flatShifts, flatShiftRequests));
model.Maximize(LinearExpr.WeightedSum(flatShifts, flatShiftRequests));
// [END objective]
// Solve

View File

@@ -73,7 +73,7 @@ public class SolutionHintingSampleSat
model.AddHint(y, 2);
// [START objective]
model.Maximize(LinearExpr.ScalProd(new IntVar[] { x, y, z }, new int[] { 1, 2, 3 }));
model.Maximize(LinearExpr.WeightedSum(new IntVar[] { x, y, z }, new int[] { 1, 2, 3 }));
// [END objective]
// Creates a solver and solves the model.