add incremental constraint creation in CP-SAT C#

This commit is contained in:
Laurent Perron
2022-01-11 15:25:23 +01:00
parent 577f5aef77
commit 43532a8d49
4 changed files with 86 additions and 42 deletions

View File

@@ -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);

View File

@@ -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();

View File

@@ -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<D>(IEnumerable<IntervalVar> intervals, IEnumerable<D> 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_;
}

View File

@@ -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