diff --git a/examples/dotnet/GateSchedulingSat.cs b/examples/dotnet/GateSchedulingSat.cs index 532facc6bd..63370e8866 100644 --- a/examples/dotnet/GateSchedulingSat.cs +++ b/examples/dotnet/GateSchedulingSat.cs @@ -89,11 +89,7 @@ public class GateSchedulingSat } // Max Length constraint (modeled as a cumulative) - CumulativeConstraint cumul = model.AddCumulative(max_length); - foreach (var p in intervals.Zip(demands, (i, d) => new { Interval = i, Demand = d })) - { - cumul.AddDemand(p.Interval, p.Demand); - } + model.AddCumulative(max_length).AddDemands(intervals, demands); // Choose which machine to perform the jobs on. model.AddNoOverlap(intervals0); diff --git a/examples/tests/SatSolverTests.cs b/examples/tests/SatSolverTests.cs index 5355b6ebd7..235eb21d39 100644 --- a/examples/tests/SatSolverTests.cs +++ b/examples/tests/SatSolverTests.cs @@ -233,10 +233,7 @@ public class SatSolverTest model.Add(delta == x - 5); long[,] tuples = { { -5, 25 }, { -4, 16 }, { -3, 9 }, { -2, 4 }, { -1, 1 }, { 0, 0 }, { 1, 1 }, { 2, 4 }, { 3, 9 }, { 4, 16 }, { 5, 25 } }; - TableConstraint ct = model.AddAllowedAssignments(new IntVar[] { delta, squaredDelta }); - for (int i = 0; i < tuples.GetLength(0); ++i) { - ct.AddTuple(new long[] { tuples[i, 0], tuples[i, 1]}); - } + model.AddAllowedAssignments(new IntVar[] { delta, squaredDelta }).AddTuples(tuples); model.Minimize(squaredDelta); CpSolver solver = new CpSolver(); diff --git a/ortools/sat/csharp/Constraints.cs b/ortools/sat/csharp/Constraints.cs index 7fc43dd0d4..719199fcc6 100644 --- a/ortools/sat/csharp/Constraints.cs +++ b/ortools/sat/csharp/Constraints.cs @@ -15,6 +15,7 @@ namespace Google.OrTools.Sat { using System; using System.Collections.Generic; +using System.Linq; public class Constraint { @@ -170,6 +171,56 @@ public class TableConstraint : Constraint throw new ArgumentException("addTuple", "tuple does not have the same length as the variables"); } } + + /** + * Adds a set of tuple of possible/forbidden values to the constraint. + * + * @param tuples the set of tuples to add to the constraint. + * @throws CpModel.WrongLength if tuples do not have the same length as the array of + * variables of the constraint. + */ + public void AddTuples(int[,] tuples) + { + TableConstraintProto table = Proto.Table; + + if (tuples.GetLength(1) != table.Vars.Count) + { + throw new ArgumentException("addTuples", "tuples does not have the same length as the variables"); + } + + for (int i = 0; i < tuples.GetLength(0); ++i) + { + for (int j = 0; j < tuples.GetLength(1); ++j) + { + table.Values.Add(tuples[i, j]); + } + } + } + + /** + * Adds a set of tuple of possible/forbidden values to the constraint. + * + * @param tuples the set of tuples to add to the constraint. + * @throws CpModel.WrongLength if tuples do not have the same length as the array of + * variables of the constraint. + */ + public void AddTuples(long[,] tuples) + { + TableConstraintProto table = Proto.Table; + + if (tuples.GetLength(1) != table.Vars.Count) + { + throw new ArgumentException("addTuples", "tuples does not have the same length as the variables"); + } + + for (int i = 0; i < tuples.GetLength(0); ++i) + { + for (int j = 0; j < tuples.GetLength(1); ++j) + { + table.Values.Add(tuples[i, j]); + } + } + } } /** @@ -259,6 +310,18 @@ public class CumulativeConstraint : Constraint cumul.Demands.Add(cp_model_.GetLinearExpressionProto(demandExpr)); } + /// Adds all pairs (interval, demand) to the constraint. + public void AddDemands(IEnumerable intervals, IEnumerable demands) + { + CumulativeConstraintProto cumul = Proto.Cumulative; + foreach (var p in intervals.Zip(demands, (i, d) => new { Interval = i, Demand = d })) + { + cumul.Intervals.Add(p.Interval.GetIndex()); + LinearExpr demandExpr = cp_model_.GetLinearExpr(p.Demand); + cumul.Demands.Add(cp_model_.GetLinearExpressionProto(demandExpr)); + } + } + private CpModel cp_model_; } diff --git a/ortools/sat/samples/AssignmentGroupsSat.cs b/ortools/sat/samples/AssignmentGroupsSat.cs index 0e7dc16ccb..eaa69ab8f5 100644 --- a/ortools/sat/samples/AssignmentGroupsSat.cs +++ b/ortools/sat/samples/AssignmentGroupsSat.cs @@ -40,28 +40,28 @@ public class AssignmentGroupsSat // Allowed groups of workers: // [START allowed_groups] - long[][] group1 = { - new long[] { 0, 0, 1, 1 }, // Workers 2, 3 - new long[] { 0, 1, 0, 1 }, // Workers 1, 3 - new long[] { 0, 1, 1, 0 }, // Workers 1, 2 - new long[] { 1, 1, 0, 0 }, // Workers 0, 1 - new long[] { 1, 0, 1, 0 }, // Workers 0, 2 + long[,] group1 = { + { 0, 0, 1, 1 }, // Workers 2, 3 + { 0, 1, 0, 1 }, // Workers 1, 3 + { 0, 1, 1, 0 }, // Workers 1, 2 + { 1, 1, 0, 0 }, // Workers 0, 1 + { 1, 0, 1, 0 }, // Workers 0, 2 }; - long[][] group2 = { - new long[] { 0, 0, 1, 1 }, // Workers 6, 7 - new long[] { 0, 1, 0, 1 }, // Workers 5, 7 - new long[] { 0, 1, 1, 0 }, // Workers 5, 6 - new long[] { 1, 1, 0, 0 }, // Workers 4, 5 - new long[] { 1, 0, 0, 1 }, // Workers 4, 7 + long[,] group2 = { + { 0, 0, 1, 1 }, // Workers 6, 7 + { 0, 1, 0, 1 }, // Workers 5, 7 + { 0, 1, 1, 0 }, // Workers 5, 6 + { 1, 1, 0, 0 }, // Workers 4, 5 + { 1, 0, 0, 1 }, // Workers 4, 7 }; - long[][] group3 = { - new long[] { 0, 0, 1, 1 }, // Workers 10, 11 - new long[] { 0, 1, 0, 1 }, // Workers 9, 11 - new long[] { 0, 1, 1, 0 }, // Workers 9, 10 - new long[] { 1, 0, 1, 0 }, // Workers 8, 10 - new long[] { 1, 0, 0, 1 }, // Workers 8, 11 + long[,] group3 = { + { 0, 0, 1, 1 }, // Workers 10, 11 + { 0, 1, 0, 1 }, // Workers 9, 11 + { 0, 1, 1, 0 }, // Workers 9, 10 + { 1, 0, 1, 0 }, // Workers 8, 10 + { 1, 0, 0, 1 }, // Workers 8, 11 }; // [END allowed_groups] @@ -127,21 +127,9 @@ public class AssignmentGroupsSat } // Define the allowed groups of worders - TableConstraint group1_ct = model.AddAllowedAssignments(new IntVar[] { work[0], work[1], work[2], work[3] }); - foreach (long[] tuple in group1) - { - group1_ct.AddTuple(tuple); - } - TableConstraint group2_ct = model.AddAllowedAssignments(new IntVar[] { work[4], work[5], work[6], work[7] }); - foreach (long[] tuple in group2) - { - group2_ct.AddTuple(tuple); - } - TableConstraint group3_ct = model.AddAllowedAssignments(new IntVar[] { work[8], work[9], work[10], work[11] }); - foreach (long[] tuple in group3) - { - group3_ct.AddTuple(tuple); - } + model.AddAllowedAssignments(new IntVar[] { work[0], work[1], work[2], work[3] }).AddTuples(group1); + model.AddAllowedAssignments(new IntVar[] { work[4], work[5], work[6], work[7] }).AddTuples(group2); + model.AddAllowedAssignments(new IntVar[] { work[8], work[9], work[10], work[11] }).AddTuples(group3); // [END assignments] // Objective