From ceabca677cdd8ec97594c3896ff57d664ba10bab Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Tue, 4 Jan 2022 19:35:22 +0100 Subject: [PATCH] [CP-SAT] ScalProd -> WeightedSum --- examples/cpp/jobshop_sat.cc | 15 ++-- examples/cpp/magic_sequence_sat.cc | 2 +- examples/cpp/multi_knapsack_sat.cc | 7 +- examples/dotnet/BalanceGroupSat.cs | 2 +- examples/dotnet/NetworkRoutingSat.cs | 2 +- examples/dotnet/ShiftSchedulingSat.cs | 4 +- examples/python/bus_driver_scheduling_sat.py | 4 +- examples/python/knapsack_2d_sat.py | 6 +- examples/python/shift_scheduling_sat.py | 2 +- examples/tests/LinearExprTest.java | 4 +- examples/tests/SatSolverTests.cs | 14 ++-- .../java/com/google/ortools/sat/CpModel.java | 4 +- .../google/ortools/sat/DoubleLinearExpr.java | 77 ++++++++++--------- .../google/ortools/sat/LinearArgument.java | 6 +- ortools/sat/cp_model.cc | 24 +++--- ortools/sat/cp_model.h | 33 ++++---- ortools/sat/csharp/IntegerExpressions.cs | 26 +------ ortools/sat/doc/channeling.md | 2 +- ortools/sat/doc/integer_arithmetic.md | 15 ++-- ortools/sat/doc/model.md | 2 +- ortools/sat/python/cp_model.py | 24 +++--- ortools/sat/samples/AssignmentGroupsSat.cs | 2 +- ortools/sat/samples/AssignmentSat.cs | 2 +- ortools/sat/samples/AssignmentTaskSizesSat.cs | 4 +- ortools/sat/samples/AssignmentTeamsSat.cs | 2 +- ortools/sat/samples/BinPackingProblemSat.cs | 2 +- ortools/sat/samples/MultipleKnapsackSat.cs | 4 +- ortools/sat/samples/ScheduleRequestsSat.cs | 2 +- .../sat/samples/SolutionHintingSampleSat.cs | 2 +- 29 files changed, 142 insertions(+), 153 deletions(-) diff --git a/examples/cpp/jobshop_sat.cc b/examples/cpp/jobshop_sat.cc index bf866ddee6..baa2b3b1d2 100644 --- a/examples/cpp/jobshop_sat.cc +++ b/examples/cpp/jobshop_sat.cc @@ -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(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); } } diff --git a/examples/cpp/magic_sequence_sat.cc b/examples/cpp/magic_sequence_sat.cc index 7f53564a86..4afefde14f 100644 --- a/examples/cpp/magic_sequence_sat.cc +++ b/examples/cpp/magic_sequence_sat.cc @@ -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)); } diff --git a/examples/cpp/multi_knapsack_sat.cc b/examples/cpp/multi_knapsack_sat.cc index 79f2a7253c..ea9d5fa33e 100644 --- a/examples/cpp/multi_knapsack_sat.cc +++ b/examples/cpp/multi_knapsack_sat.cc @@ -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. diff --git a/examples/dotnet/BalanceGroupSat.cs b/examples/dotnet/BalanceGroupSat.cs index 3f63d6b86a..afec922857 100644 --- a/examples/dotnet/BalanceGroupSat.cs +++ b/examples/dotnet/BalanceGroupSat.cs @@ -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); } diff --git a/examples/dotnet/NetworkRoutingSat.cs b/examples/dotnet/NetworkRoutingSat.cs index cfe3716ab2..4a8dea7976 100644 --- a/examples/dotnet/NetworkRoutingSat.cs +++ b/examples/dotnet/NetworkRoutingSat.cs @@ -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); diff --git a/examples/dotnet/ShiftSchedulingSat.cs b/examples/dotnet/ShiftSchedulingSat.cs index 987095384a..7624842512 100644 --- a/examples/dotnet/ShiftSchedulingSat.cs +++ b/examples/dotnet/ShiftSchedulingSat.cs @@ -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); diff --git a/examples/python/bus_driver_scheduling_sat.py b/examples/python/bus_driver_scheduling_sat.py index 2aa69d154b..1361e1791d 100644 --- a/examples/python/bus_driver_scheduling_sat.py +++ b/examples/python/bus_driver_scheduling_sat.py @@ -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) diff --git a/examples/python/knapsack_2d_sat.py b/examples/python/knapsack_2d_sat.py index cfc21dc531..ec0c5e5499 100644 --- a/examples/python/knapsack_2d_sat.py +++ b/examples/python/knapsack_2d_sat.py @@ -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: diff --git a/examples/python/shift_scheduling_sat.py b/examples/python/shift_scheduling_sat.py index b1fa81ccd4..55384d5334 100644 --- a/examples/python/shift_scheduling_sat.py +++ b/examples/python/shift_scheduling_sat.py @@ -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: diff --git a/examples/tests/LinearExprTest.java b/examples/tests/LinearExprTest.java index 0d2af900e2..b8200a9807 100644 --- a/examples/tests/LinearExprTest.java +++ b/examples/tests/LinearExprTest.java @@ -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"); diff --git a/examples/tests/SatSolverTests.cs b/examples/tests/SatSolverTests.cs index 2658fbfe54..c9f092d4b8 100644 --- a/examples/tests/SatSolverTests.cs +++ b/examples/tests/SatSolverTests.cs @@ -291,7 +291,7 @@ namespace Google.OrTools.Tests } [Fact] - public void LargeScalProdLong() + public void LargeWeightedSumLong() { CpModel model = new CpModel(); List vars = new List(); @@ -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 vars = new List(); @@ -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 exprs = new List(); @@ -349,7 +349,7 @@ namespace Google.OrTools.Tests } [Fact] - public void LargeScalProdProto() + public void LargeWeightedSumProto() { CpModel model = new CpModel(); List vars = new List(); @@ -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"" ] }, diff --git a/ortools/java/com/google/ortools/sat/CpModel.java b/ortools/java/com/google/ortools/sat/CpModel.java index 1e4b7b5ac5..385231d7d4 100644 --- a/ortools/java/com/google/ortools/sat/CpModel.java +++ b/ortools/java/com/google/ortools/sat/CpModel.java @@ -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); } diff --git a/ortools/java/com/google/ortools/sat/DoubleLinearExpr.java b/ortools/java/com/google/ortools/sat/DoubleLinearExpr.java index 7ac7672ba1..b7519b5134 100644 --- a/ortools/java/com/google/ortools/sat/DoubleLinearExpr.java +++ b/ortools/java/com/google/ortools/sat/DoubleLinearExpr.java @@ -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; } diff --git a/ortools/java/com/google/ortools/sat/LinearArgument.java b/ortools/java/com/google/ortools/sat/LinearArgument.java index 0004178391..5c8cf77e29 100644 --- a/ortools/java/com/google/ortools/sat/LinearArgument.java +++ b/ortools/java/com/google/ortools/sat/LinearArgument.java @@ -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. + * + *

This class is used in all modeling methods of the CpModel class. + */ public interface LinearArgument { /** Builds a linear expression. */ LinearExpr build(); diff --git a/ortools/sat/cp_model.cc b/ortools/sat/cp_model.cc index 542b74745c..ee054f8775 100644 --- a/ortools/sat/cp_model.cc +++ b/ortools/sat/cp_model.cc @@ -202,8 +202,8 @@ LinearExpr LinearExpr::Sum(absl::Span vars) { return result; } -LinearExpr LinearExpr::ScalProd(absl::Span vars, - absl::Span coeffs) { +LinearExpr LinearExpr::WeightedSum(absl::Span vars, + absl::Span 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 vars, return result; } -LinearExpr LinearExpr::ScalProd(absl::Span vars, - absl::Span coeffs) { +LinearExpr LinearExpr::WeightedSum(absl::Span vars, + absl::Span 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 vars, return result; } -LinearExpr LinearExpr::ScalProd(std::initializer_list vars, - absl::Span coeffs) { +LinearExpr LinearExpr::WeightedSum(std::initializer_list vars, + absl::Span coeffs) { CHECK_EQ(vars.size(), coeffs.size()); LinearExpr result; int count = 0; @@ -253,8 +253,8 @@ LinearExpr LinearExpr::BooleanSum(absl::Span vars) { return result; } -LinearExpr LinearExpr::BooleanScalProd(absl::Span vars, - absl::Span coeffs) { +LinearExpr LinearExpr::BooleanWeightedSum(absl::Span vars, + absl::Span 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 vars) { return result; } -DoubleLinearExpr DoubleLinearExpr::ScalProd(absl::Span vars, - absl::Span coeffs) { +DoubleLinearExpr DoubleLinearExpr::WeightedSum( + absl::Span vars, absl::Span 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 vars, return result; } -DoubleLinearExpr DoubleLinearExpr::ScalProd(absl::Span vars, - absl::Span coeffs) { +DoubleLinearExpr DoubleLinearExpr::WeightedSum( + absl::Span vars, absl::Span coeffs) { CHECK_EQ(vars.size(), coeffs.size()); DoubleLinearExpr result; for (int i = 0; i < vars.size(); ++i) { diff --git a/ortools/sat/cp_model.h b/ortools/sat/cp_model.h index 54f8be57d1..6ad7684be7 100644 --- a/ortools/sat/cp_model.h +++ b/ortools/sat/cp_model.h @@ -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 vars); /// Constructs the scalar product of variables and coefficients. - static LinearExpr ScalProd(absl::Span vars, - absl::Span coeffs); + static LinearExpr WeightedSum(absl::Span vars, + absl::Span coeffs); /// Constructs the scalar product of Boolean variables and coefficients. - static LinearExpr ScalProd(absl::Span vars, - absl::Span coeffs); + static LinearExpr WeightedSum(absl::Span vars, + absl::Span coeffs); /// Constructs the scalar product of variables and coefficients. // TODO(user): Remove when the operators + and * are implemented. - static LinearExpr ScalProd(std::initializer_list vars, - absl::Span coeffs); + static LinearExpr WeightedSum(std::initializer_list vars, + absl::Span 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 vars); - /// Deprecated. Use ScalProd() instead. - static LinearExpr BooleanScalProd(absl::Span vars, - absl::Span coeffs); + /// Deprecated. Use WeightedSum() instead. + static LinearExpr BooleanWeightedSum(absl::Span vars, + absl::Span 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, a specialized method must be called. std::vector 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 vars); /// Constructs the scalar product of variables and coefficients. - static DoubleLinearExpr ScalProd(absl::Span vars, - absl::Span coeffs); + static DoubleLinearExpr WeightedSum(absl::Span vars, + absl::Span coeffs); /// Constructs the scalar product of Boolean variables and coefficients. - static DoubleLinearExpr ScalProd(absl::Span vars, - absl::Span coeffs); + static DoubleLinearExpr WeightedSum(absl::Span vars, + absl::Span coeffs); /// Returns the vector of variable indices. const std::vector& variables() const { return variables_; } diff --git a/ortools/sat/csharp/IntegerExpressions.cs b/ortools/sat/csharp/IntegerExpressions.cs index d31c16cf15..ae8b08e4ff 100644 --- a/ortools/sat/csharp/IntegerExpressions.cs +++ b/ortools/sat/csharp/IntegerExpressions.cs @@ -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 vars, IEnumerable coeffs) + public static LinearExpr WeightedSum(IEnumerable vars, IEnumerable coeffs) { return new SumArray(vars, coeffs); } - public static LinearExpr ScalProd(IEnumerable vars, IEnumerable coeffs) + public static LinearExpr WeightedSum(IEnumerable vars, IEnumerable coeffs) { return new SumArray(vars, coeffs); } diff --git a/ortools/sat/doc/channeling.md b/ortools/sat/doc/channeling.md index 9214242290..c39bfcd72f 100644 --- a/ortools/sat/doc/channeling.md +++ b/ortools/sat/doc/channeling.md @@ -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. diff --git a/ortools/sat/doc/integer_arithmetic.md b/ortools/sat/doc/integer_arithmetic.md index 2aaf78ea14..b649d31600 100644 --- a/ortools/sat/doc/integer_arithmetic.md +++ b/ortools/sat/doc/integer_arithmetic.md @@ -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 diff --git a/ortools/sat/doc/model.md b/ortools/sat/doc/model.md index a9d5a4d7d9..a4309ac012 100644 --- a/ortools/sat/doc/model.md +++ b/ortools/sat/doc/model.md @@ -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(); diff --git a/ortools/sat/python/cp_model.py b/ortools/sat/python/cp_model.py index 7b3193ced6..3c74a5dde2 100644 --- a/ortools/sat/python/cp_model.py +++ b/ortools/sat/python/cp_model.py @@ -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 diff --git a/ortools/sat/samples/AssignmentGroupsSat.cs b/ortools/sat/samples/AssignmentGroupsSat.cs index 6ad693ddc9..1861e338e0 100644 --- a/ortools/sat/samples/AssignmentGroupsSat.cs +++ b/ortools/sat/samples/AssignmentGroupsSat.cs @@ -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 diff --git a/ortools/sat/samples/AssignmentSat.cs b/ortools/sat/samples/AssignmentSat.cs index c5e4a5fd15..c5f0cbeaf8 100644 --- a/ortools/sat/samples/AssignmentSat.cs +++ b/ortools/sat/samples/AssignmentSat.cs @@ -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 diff --git a/ortools/sat/samples/AssignmentTaskSizesSat.cs b/ortools/sat/samples/AssignmentTaskSizesSat.cs index 0ad73ba59d..5486a9ad4c 100644 --- a/ortools/sat/samples/AssignmentTaskSizesSat.cs +++ b/ortools/sat/samples/AssignmentTaskSizesSat.cs @@ -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 diff --git a/ortools/sat/samples/AssignmentTeamsSat.cs b/ortools/sat/samples/AssignmentTeamsSat.cs index 4c9a1f7fd9..08a73197b0 100644 --- a/ortools/sat/samples/AssignmentTeamsSat.cs +++ b/ortools/sat/samples/AssignmentTeamsSat.cs @@ -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 diff --git a/ortools/sat/samples/BinPackingProblemSat.cs b/ortools/sat/samples/BinPackingProblemSat.cs index 49aa28279a..811f0a0735 100644 --- a/ortools/sat/samples/BinPackingProblemSat.cs +++ b/ortools/sat/samples/BinPackingProblemSat.cs @@ -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. diff --git a/ortools/sat/samples/MultipleKnapsackSat.cs b/ortools/sat/samples/MultipleKnapsackSat.cs index c54b5f35ab..50a503f2c3 100644 --- a/ortools/sat/samples/MultipleKnapsackSat.cs +++ b/ortools/sat/samples/MultipleKnapsackSat.cs @@ -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 diff --git a/ortools/sat/samples/ScheduleRequestsSat.cs b/ortools/sat/samples/ScheduleRequestsSat.cs index e2e8329c9f..b359f175a4 100644 --- a/ortools/sat/samples/ScheduleRequestsSat.cs +++ b/ortools/sat/samples/ScheduleRequestsSat.cs @@ -181,7 +181,7 @@ public class ScheduleRequestsSat } } } - model.Maximize(LinearExpr.ScalProd(flatShifts, flatShiftRequests)); + model.Maximize(LinearExpr.WeightedSum(flatShifts, flatShiftRequests)); // [END objective] // Solve diff --git a/ortools/sat/samples/SolutionHintingSampleSat.cs b/ortools/sat/samples/SolutionHintingSampleSat.cs index 8e04187700..6ca6f3ba26 100644 --- a/ortools/sat/samples/SolutionHintingSampleSat.cs +++ b/ortools/sat/samples/SolutionHintingSampleSat.cs @@ -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.