C# CP-SAT: test new expression; reformat examples/tests/*cs

This commit is contained in:
Laurent Perron
2022-01-10 18:44:12 +01:00
parent 2f34343c6d
commit 4036cde59e
9 changed files with 2619 additions and 2562 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -18,36 +18,36 @@ using static Google.OrTools.Init.operations_research_init;
namespace Google.OrTools.Tests
{
public class InitTest
public class InitTest
{
[Fact]
public void CheckLogging()
{
[Fact]
public void CheckLogging()
{
Init.CppBridge.InitLogging("init");
Init.CppBridge.ShutdownLogging();
}
[Fact]
public void CheckFlags()
{
Init.CppFlags cpp_flags = new Init.CppFlags();
cpp_flags.logtostderr = true;
cpp_flags.log_prefix = true;
cpp_flags.cp_model_dump_prefix = "init";
cpp_flags.cp_model_dump_models = true;
cpp_flags.cp_model_dump_lns = true;
cpp_flags.cp_model_dump_response = true;
Init.CppBridge.SetFlags(cpp_flags);
}
[Fact]
public void CheckOrToolsVersion()
{
int major = OrToolsVersion.MajorNumber();
int minor = OrToolsVersion.MinorNumber();
int patch = OrToolsVersion.PatchNumber();
string version = OrToolsVersion.VersionString();
Assert.Equal($"{major}.{minor}.{patch}", version);
}
Init.CppBridge.InitLogging("init");
Init.CppBridge.ShutdownLogging();
}
[Fact]
public void CheckFlags()
{
Init.CppFlags cpp_flags = new Init.CppFlags();
cpp_flags.logtostderr = true;
cpp_flags.log_prefix = true;
cpp_flags.cp_model_dump_prefix = "init";
cpp_flags.cp_model_dump_models = true;
cpp_flags.cp_model_dump_lns = true;
cpp_flags.cp_model_dump_response = true;
Init.CppBridge.SetFlags(cpp_flags);
}
[Fact]
public void CheckOrToolsVersion()
{
int major = OrToolsVersion.MajorNumber();
int minor = OrToolsVersion.MinorNumber();
int patch = OrToolsVersion.PatchNumber();
string version = OrToolsVersion.VersionString();
Assert.Equal($"{major}.{minor}.{patch}", version);
}
}
} // namespace Google.OrTools.Tests

View File

@@ -17,402 +17,402 @@ using Google.OrTools.LinearSolver;
namespace Google.OrTools.Tests
{
public class LinearSolverTest
public class LinearSolverTest
{
[Fact]
public void VarOperator()
{
[Fact]
public void VarOperator()
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Constraint ct1 = solver.Add(x >= 1);
Assert.Equal(1.0, ct1.GetCoefficient(x));
Assert.Equal(1.0, ct1.Lb());
Assert.Equal(double.PositiveInfinity, ct1.Ub());
Constraint ct2 = solver.Add(x <= 1);
Assert.Equal(1.0, ct2.GetCoefficient(x));
Assert.Equal(double.NegativeInfinity, ct2.Lb());
Assert.Equal(1.0, ct2.Ub());
Constraint ct3 = solver.Add(x == 1);
Assert.Equal(1.0, ct3.GetCoefficient(x));
Assert.Equal(1.0, ct3.Lb());
Assert.Equal(1.0, ct3.Ub());
Constraint ct4 = solver.Add(1 >= x);
Assert.Equal(1.0, ct4.GetCoefficient(x));
Assert.Equal(double.NegativeInfinity, ct4.Lb());
Assert.Equal(1.0, ct4.Ub());
Constraint ct5 = solver.Add(1 <= x);
Assert.Equal(1.0, ct5.GetCoefficient(x));
Assert.Equal(1.0, ct5.Lb());
Assert.Equal(double.PositiveInfinity, ct5.Ub());
Constraint ct6 = solver.Add(1 == x);
Assert.Equal(1.0, ct6.GetCoefficient(x));
Assert.Equal(1.0, ct6.Lb());
Assert.Equal(1.0, ct6.Ub());
}
[Fact]
public void VarAddition()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(x + y == 1);
Assert.Equal(1.0, ct1.GetCoefficient(x));
Assert.Equal(1.0, ct1.GetCoefficient(y));
Constraint ct2 = solver.Add(x + x == 1);
Assert.Equal(2.0, ct2.GetCoefficient(x));
Constraint ct3 = solver.Add(x + (y + x) == 1);
Assert.Equal(2.0, ct3.GetCoefficient(x));
Assert.Equal(1.0, ct3.GetCoefficient(y));
Constraint ct4 = solver.Add(x + (y + x + 3) == 1);
Assert.Equal(2.0, ct4.GetCoefficient(x));
Assert.Equal(1.0, ct4.GetCoefficient(y));
Assert.Equal(-2.0, ct4.Lb());
Assert.Equal(-2.0, ct4.Ub());
}
[Fact]
public void VarMultiplication()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(3 * x == 1);
Assert.Equal(3.0, ct1.GetCoefficient(x));
Constraint ct2 = solver.Add(x * 3 == 1);
Assert.Equal(3.0, ct2.GetCoefficient(x));
Constraint ct3 = solver.Add(x + (2 * y + 3 * x) == 1);
Assert.Equal(4.0, ct3.GetCoefficient(x));
Assert.Equal(2.0, ct3.GetCoefficient(y));
Constraint ct4 = solver.Add(x + 5 * (y + x + 3) == 1);
Assert.Equal(6.0, ct4.GetCoefficient(x));
Assert.Equal(5.0, ct4.GetCoefficient(y));
Assert.Equal(-14.0, ct4.Lb());
Assert.Equal(-14.0, ct4.Ub());
Constraint ct5 = solver.Add(x + (2 * y + x + 3) * 3 == 1);
Assert.Equal(4.0, ct5.GetCoefficient(x));
Assert.Equal(6.0, ct5.GetCoefficient(y));
Assert.Equal(-8.0, ct5.Lb());
Assert.Equal(-8.0, ct5.Ub());
}
[Fact]
public void BinaryOperator()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(x == y);
Assert.Equal(1.0, ct1.GetCoefficient(x));
Assert.Equal(-1.0, ct1.GetCoefficient(y));
Constraint ct2 = solver.Add(x == 3 * y + 5);
Assert.Equal(1.0, ct2.GetCoefficient(x));
Assert.Equal(-3.0, ct2.GetCoefficient(y));
Assert.Equal(5.0, ct2.Lb());
Assert.Equal(5.0, ct2.Ub());
Constraint ct3 = solver.Add(2 * x - 9 == y);
Assert.Equal(2.0, ct3.GetCoefficient(x));
Assert.Equal(-1.0, ct3.GetCoefficient(y));
Assert.Equal(9.0, ct3.Lb());
Assert.Equal(9.0, ct3.Ub());
Assert.True(x == x);
Assert.True(!(x != x));
Assert.True((x != y));
Assert.True(!(x == y));
}
[Fact]
public void Inequalities()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) >= 3);
Assert.Equal(7.0, ct1.GetCoefficient(x));
Assert.Equal(5.0, ct1.GetCoefficient(y));
Assert.Equal(2.0, ct1.Lb());
Assert.Equal(double.PositiveInfinity, ct1.Ub());
Constraint ct2 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) <= 3);
Assert.Equal(7.0, ct2.GetCoefficient(x));
Assert.Equal(5.0, ct2.GetCoefficient(y));
Assert.Equal(double.NegativeInfinity, ct2.Lb());
Assert.Equal(2.0, ct2.Ub());
Constraint ct3 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) >= 3 - x - y);
Assert.Equal(8.0, ct3.GetCoefficient(x));
Assert.Equal(6.0, ct3.GetCoefficient(y));
Assert.Equal(2.0, ct3.Lb());
Assert.Equal(double.PositiveInfinity, ct3.Ub());
Constraint ct4 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) <= -x - y + 3);
Assert.Equal(8.0, ct4.GetCoefficient(x));
Assert.Equal(6.0, ct4.GetCoefficient(y));
Assert.Equal(double.NegativeInfinity, ct4.Lb());
Assert.Equal(2.0, ct4.Ub());
}
[Fact]
public void SumArray()
{
Solver solver = Solver.CreateSolver("CLP");
Variable[] x = solver.MakeBoolVarArray(10, "x");
Constraint ct1 = solver.Add(x.Sum() == 3);
Assert.Equal(1.0, ct1.GetCoefficient(x[0]));
Constraint ct2 = solver.Add(-2 * x.Sum() == 3);
Assert.Equal(-2.0, ct2.GetCoefficient(x[0]));
LinearExpr[] array = new LinearExpr[] { x[0] + 2.0, x[0] + 3, x[0] + 4 };
Constraint ct3 = solver.Add(array.Sum() == 1);
Assert.Equal(3.0, ct3.GetCoefficient(x[0]));
Assert.Equal(-8.0, ct3.Lb());
Assert.Equal(-8.0, ct3.Ub());
}
[Fact]
public void Objective()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
solver.Maximize(x);
Assert.Equal(0.0, solver.Objective().Offset());
Assert.Equal(1.0, solver.Objective().GetCoefficient(x));
Assert.True(solver.Objective().Maximization());
solver.Minimize(-x - 2 * y + 3);
Assert.Equal(3.0, solver.Objective().Offset());
Assert.Equal(-1.0, solver.Objective().GetCoefficient(x));
Assert.Equal(-2.0, solver.Objective().GetCoefficient(y));
Assert.True(solver.Objective().Minimization());
}
void SolveAndPrint(in Solver solver, in Variable[] variables, in Constraint[] constraints)
{
Console.WriteLine($"Number of variables = {solver.NumVariables()}");
Console.WriteLine($"Number of constraints = {solver.NumConstraints()}");
Solver.ResultStatus resultStatus = solver.Solve();
// Check that the problem has an optimal solution.
if (resultStatus != Solver.ResultStatus.OPTIMAL)
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Constraint ct1 = solver.Add(x >= 1);
Assert.Equal(1.0, ct1.GetCoefficient(x));
Assert.Equal(1.0, ct1.Lb());
Assert.Equal(double.PositiveInfinity, ct1.Ub());
Constraint ct2 = solver.Add(x <= 1);
Assert.Equal(1.0, ct2.GetCoefficient(x));
Assert.Equal(double.NegativeInfinity, ct2.Lb());
Assert.Equal(1.0, ct2.Ub());
Constraint ct3 = solver.Add(x == 1);
Assert.Equal(1.0, ct3.GetCoefficient(x));
Assert.Equal(1.0, ct3.Lb());
Assert.Equal(1.0, ct3.Ub());
Constraint ct4 = solver.Add(1 >= x);
Assert.Equal(1.0, ct4.GetCoefficient(x));
Assert.Equal(double.NegativeInfinity, ct4.Lb());
Assert.Equal(1.0, ct4.Ub());
Constraint ct5 = solver.Add(1 <= x);
Assert.Equal(1.0, ct5.GetCoefficient(x));
Assert.Equal(1.0, ct5.Lb());
Assert.Equal(double.PositiveInfinity, ct5.Ub());
Constraint ct6 = solver.Add(1 == x);
Assert.Equal(1.0, ct6.GetCoefficient(x));
Assert.Equal(1.0, ct6.Lb());
Assert.Equal(1.0, ct6.Ub());
Console.WriteLine("The problem does not have an optimal solution!");
}
[Fact]
public void VarAddition()
else
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(x + y == 1);
Assert.Equal(1.0, ct1.GetCoefficient(x));
Assert.Equal(1.0, ct1.GetCoefficient(y));
Constraint ct2 = solver.Add(x + x == 1);
Assert.Equal(2.0, ct2.GetCoefficient(x));
Constraint ct3 = solver.Add(x + (y + x) == 1);
Assert.Equal(2.0, ct3.GetCoefficient(x));
Assert.Equal(1.0, ct3.GetCoefficient(y));
Constraint ct4 = solver.Add(x + (y + x + 3) == 1);
Assert.Equal(2.0, ct4.GetCoefficient(x));
Assert.Equal(1.0, ct4.GetCoefficient(y));
Assert.Equal(-2.0, ct4.Lb());
Assert.Equal(-2.0, ct4.Ub());
}
[Fact]
public void VarMultiplication()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(3 * x == 1);
Assert.Equal(3.0, ct1.GetCoefficient(x));
Constraint ct2 = solver.Add(x * 3 == 1);
Assert.Equal(3.0, ct2.GetCoefficient(x));
Constraint ct3 = solver.Add(x + (2 * y + 3 * x) == 1);
Assert.Equal(4.0, ct3.GetCoefficient(x));
Assert.Equal(2.0, ct3.GetCoefficient(y));
Constraint ct4 = solver.Add(x + 5 * (y + x + 3) == 1);
Assert.Equal(6.0, ct4.GetCoefficient(x));
Assert.Equal(5.0, ct4.GetCoefficient(y));
Assert.Equal(-14.0, ct4.Lb());
Assert.Equal(-14.0, ct4.Ub());
Constraint ct5 = solver.Add(x + (2 * y + x + 3) * 3 == 1);
Assert.Equal(4.0, ct5.GetCoefficient(x));
Assert.Equal(6.0, ct5.GetCoefficient(y));
Assert.Equal(-8.0, ct5.Lb());
Assert.Equal(-8.0, ct5.Ub());
}
[Fact]
public void BinaryOperator()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(x == y);
Assert.Equal(1.0, ct1.GetCoefficient(x));
Assert.Equal(-1.0, ct1.GetCoefficient(y));
Constraint ct2 = solver.Add(x == 3 * y + 5);
Assert.Equal(1.0, ct2.GetCoefficient(x));
Assert.Equal(-3.0, ct2.GetCoefficient(y));
Assert.Equal(5.0, ct2.Lb());
Assert.Equal(5.0, ct2.Ub());
Constraint ct3 = solver.Add(2 * x - 9 == y);
Assert.Equal(2.0, ct3.GetCoefficient(x));
Assert.Equal(-1.0, ct3.GetCoefficient(y));
Assert.Equal(9.0, ct3.Lb());
Assert.Equal(9.0, ct3.Ub());
Assert.True(x == x);
Assert.True(!(x != x));
Assert.True((x != y));
Assert.True(!(x == y));
}
[Fact]
public void Inequalities()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
Constraint ct1 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) >= 3);
Assert.Equal(7.0, ct1.GetCoefficient(x));
Assert.Equal(5.0, ct1.GetCoefficient(y));
Assert.Equal(2.0, ct1.Lb());
Assert.Equal(double.PositiveInfinity, ct1.Ub());
Constraint ct2 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) <= 3);
Assert.Equal(7.0, ct2.GetCoefficient(x));
Assert.Equal(5.0, ct2.GetCoefficient(y));
Assert.Equal(double.NegativeInfinity, ct2.Lb());
Assert.Equal(2.0, ct2.Ub());
Constraint ct3 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) >= 3 - x - y);
Assert.Equal(8.0, ct3.GetCoefficient(x));
Assert.Equal(6.0, ct3.GetCoefficient(y));
Assert.Equal(2.0, ct3.Lb());
Assert.Equal(double.PositiveInfinity, ct3.Ub());
Constraint ct4 = solver.Add(2 * (x + 3) + 5 * (y + x - 1) <= -x - y + 3);
Assert.Equal(8.0, ct4.GetCoefficient(x));
Assert.Equal(6.0, ct4.GetCoefficient(y));
Assert.Equal(double.NegativeInfinity, ct4.Lb());
Assert.Equal(2.0, ct4.Ub());
}
[Fact]
public void SumArray()
{
Solver solver = Solver.CreateSolver("CLP");
Variable[] x = solver.MakeBoolVarArray(10, "x");
Constraint ct1 = solver.Add(x.Sum() == 3);
Assert.Equal(1.0, ct1.GetCoefficient(x[0]));
Constraint ct2 = solver.Add(-2 * x.Sum() == 3);
Assert.Equal(-2.0, ct2.GetCoefficient(x[0]));
LinearExpr[] array = new LinearExpr[] { x[0] + 2.0, x[0] + 3, x[0] + 4 };
Constraint ct3 = solver.Add(array.Sum() == 1);
Assert.Equal(3.0, ct3.GetCoefficient(x[0]));
Assert.Equal(-8.0, ct3.Lb());
Assert.Equal(-8.0, ct3.Ub());
}
[Fact]
public void Objective()
{
Solver solver = Solver.CreateSolver("CLP");
Variable x = solver.MakeNumVar(0.0, 100.0, "x");
Assert.Equal(0.0, x.Lb());
Assert.Equal(100.0, x.Ub());
Variable y = solver.MakeNumVar(0.0, 100.0, "y");
Assert.Equal(0.0, y.Lb());
Assert.Equal(100.0, y.Ub());
solver.Maximize(x);
Assert.Equal(0.0, solver.Objective().Offset());
Assert.Equal(1.0, solver.Objective().GetCoefficient(x));
Assert.True(solver.Objective().Maximization());
solver.Minimize(-x - 2 * y + 3);
Assert.Equal(3.0, solver.Objective().Offset());
Assert.Equal(-1.0, solver.Objective().GetCoefficient(x));
Assert.Equal(-2.0, solver.Objective().GetCoefficient(y));
Assert.True(solver.Objective().Minimization());
}
void SolveAndPrint(in Solver solver, in Variable[] variables, in Constraint[] constraints)
{
Console.WriteLine($"Number of variables = {solver.NumVariables()}");
Console.WriteLine($"Number of constraints = {solver.NumConstraints()}");
Solver.ResultStatus resultStatus = solver.Solve();
// Check that the problem has an optimal solution.
if (resultStatus != Solver.ResultStatus.OPTIMAL)
Console.WriteLine("Solution:");
foreach (Variable var in variables)
{
Console.WriteLine("The problem does not have an optimal solution!");
Console.WriteLine($"{var.Name()} = {var.SolutionValue()}");
}
else
Console.WriteLine($"Optimal objective value = {solver.Objective().Value()}");
Console.WriteLine("");
Console.WriteLine("Advanced usage:");
Console.WriteLine($"Problem solved in {solver.WallTime()} milliseconds");
Console.WriteLine($"Problem solved in {solver.Iterations()} iterations");
foreach (Variable var in variables)
{
Console.WriteLine("Solution:");
foreach (Variable var in variables)
{
Console.WriteLine($"{var.Name()} = {var.SolutionValue()}");
}
Console.WriteLine($"Optimal objective value = {solver.Objective().Value()}");
Console.WriteLine("");
Console.WriteLine("Advanced usage:");
Console.WriteLine($"Problem solved in {solver.WallTime()} milliseconds");
Console.WriteLine($"Problem solved in {solver.Iterations()} iterations");
foreach (Variable var in variables)
{
Console.WriteLine($"{var.Name()}: reduced cost {var.ReducedCost()}");
}
double[] activities = solver.ComputeConstraintActivities();
foreach (Constraint ct in constraints)
{
Console.WriteLine($"{ct.Name()}: dual value = {ct.DualValue()}",
$" activity = {activities[ct.Index()]}");
}
Console.WriteLine($"{var.Name()}: reduced cost {var.ReducedCost()}");
}
}
void RunLinearProgrammingExample(in String problemType)
{
Console.WriteLine($"------ Linear programming example with {problemType} ------");
Solver solver = Solver.CreateSolver(problemType);
if (solver == null)
return;
// x and y are continuous non-negative variables.
Variable x = solver.MakeNumVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeNumVar(0.0, double.PositiveInfinity, "y");
// Objectif function: Maximize 3x + 4y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 3);
objective.SetCoefficient(y, 4);
objective.SetMaximization();
// x + 2y <= 14.
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 14.0, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 2);
// 3x - y >= 0.
Constraint c1 = solver.MakeConstraint(0.0, double.PositiveInfinity, "c1");
c1.SetCoefficient(x, 3);
c1.SetCoefficient(y, -1);
// x - y <= 2.
Constraint c2 = solver.MakeConstraint(double.NegativeInfinity, 2.0, "c2");
c2.SetCoefficient(x, 1);
c2.SetCoefficient(y, -1);
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1, c2 });
}
void RunMixedIntegerProgrammingExample(in String problemType)
{
Console.WriteLine($"------ Mixed integer programming example with {problemType} ------");
Solver solver = Solver.CreateSolver(problemType);
if (solver == null)
return;
// x and y are integers non-negative variables.
Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y");
// Objectif function: Maximize x + 10 * y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 1);
objective.SetCoefficient(y, 10);
objective.SetMaximization();
// x + 7 * y <= 17.5.
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 17.5, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 7);
// x <= 3.5.
Constraint c1 = solver.MakeConstraint(double.NegativeInfinity, 3.5, "c1");
c1.SetCoefficient(x, 1);
c1.SetCoefficient(y, 0);
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1 });
}
void RunBooleanProgrammingExample(in String problemType)
{
Console.WriteLine($"------ Boolean programming example with {problemType} ------");
Solver solver = Solver.CreateSolver(problemType);
if (solver == null)
return;
// x and y are boolean variables.
Variable x = solver.MakeBoolVar("x");
Variable y = solver.MakeBoolVar("y");
// Objectif function: Maximize 2 * x + y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 2);
objective.SetCoefficient(y, 1);
objective.SetMinimization();
// 1 <= x + 2 * y <= 3.
Constraint c0 = solver.MakeConstraint(1, 3, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 2);
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0 });
}
[Fact]
public void OptimizationProblemType()
{
RunLinearProgrammingExample("GLOP");
RunLinearProgrammingExample("GLPK_LP");
RunLinearProgrammingExample("CLP");
RunLinearProgrammingExample("GUROBI_LP");
RunMixedIntegerProgrammingExample("GLPK");
RunMixedIntegerProgrammingExample("CBC");
RunMixedIntegerProgrammingExample("SCIP");
RunMixedIntegerProgrammingExample("SAT");
RunBooleanProgrammingExample("SAT");
RunBooleanProgrammingExample("BOP");
}
[Fact]
static void testSetHintAndSolverGetters()
{
Console.WriteLine("testSetHintAndSolverGetters");
Solver solver = Solver.CreateSolver("glop");
// x and y are continuous non-negative variables.
Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y");
// Objectif function: Maximize x + 10 * y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 1);
objective.SetCoefficient(y, 10);
objective.SetMaximization();
// x + 7 * y <= 17.5.
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 17.5, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 7);
// x <= 3.5.
Constraint c1 = solver.MakeConstraint(double.NegativeInfinity, 3.5, "c1");
c1.SetCoefficient(x, 1);
c1.SetCoefficient(y, 0);
Constraint[] constraints = solver.constraints();
Assert.Equal(constraints.Length, 2);
Variable[] variables = solver.variables();
Assert.Equal(variables.Length, 2);
solver.SetHint(new Variable[] { x, y }, new double[] { 2.0, 3.0 });
double[] activities = solver.ComputeConstraintActivities();
foreach (Constraint ct in constraints)
{
Console.WriteLine($"{ct.Name()}: dual value = {ct.DualValue()}",
$" activity = {activities[ct.Index()]}");
}
}
}
void RunLinearProgrammingExample(in String problemType)
{
Console.WriteLine($"------ Linear programming example with {problemType} ------");
Solver solver = Solver.CreateSolver(problemType);
if (solver == null)
return;
// x and y are continuous non-negative variables.
Variable x = solver.MakeNumVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeNumVar(0.0, double.PositiveInfinity, "y");
// Objectif function: Maximize 3x + 4y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 3);
objective.SetCoefficient(y, 4);
objective.SetMaximization();
// x + 2y <= 14.
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 14.0, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 2);
// 3x - y >= 0.
Constraint c1 = solver.MakeConstraint(0.0, double.PositiveInfinity, "c1");
c1.SetCoefficient(x, 3);
c1.SetCoefficient(y, -1);
// x - y <= 2.
Constraint c2 = solver.MakeConstraint(double.NegativeInfinity, 2.0, "c2");
c2.SetCoefficient(x, 1);
c2.SetCoefficient(y, -1);
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1, c2 });
}
void RunMixedIntegerProgrammingExample(in String problemType)
{
Console.WriteLine($"------ Mixed integer programming example with {problemType} ------");
Solver solver = Solver.CreateSolver(problemType);
if (solver == null)
return;
// x and y are integers non-negative variables.
Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y");
// Objectif function: Maximize x + 10 * y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 1);
objective.SetCoefficient(y, 10);
objective.SetMaximization();
// x + 7 * y <= 17.5.
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 17.5, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 7);
// x <= 3.5.
Constraint c1 = solver.MakeConstraint(double.NegativeInfinity, 3.5, "c1");
c1.SetCoefficient(x, 1);
c1.SetCoefficient(y, 0);
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1 });
}
void RunBooleanProgrammingExample(in String problemType)
{
Console.WriteLine($"------ Boolean programming example with {problemType} ------");
Solver solver = Solver.CreateSolver(problemType);
if (solver == null)
return;
// x and y are boolean variables.
Variable x = solver.MakeBoolVar("x");
Variable y = solver.MakeBoolVar("y");
// Objectif function: Maximize 2 * x + y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 2);
objective.SetCoefficient(y, 1);
objective.SetMinimization();
// 1 <= x + 2 * y <= 3.
Constraint c0 = solver.MakeConstraint(1, 3, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 2);
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0 });
}
[Fact]
public void OptimizationProblemType()
{
RunLinearProgrammingExample("GLOP");
RunLinearProgrammingExample("GLPK_LP");
RunLinearProgrammingExample("CLP");
RunLinearProgrammingExample("GUROBI_LP");
RunMixedIntegerProgrammingExample("GLPK");
RunMixedIntegerProgrammingExample("CBC");
RunMixedIntegerProgrammingExample("SCIP");
RunMixedIntegerProgrammingExample("SAT");
RunBooleanProgrammingExample("SAT");
RunBooleanProgrammingExample("BOP");
}
[Fact]
static void testSetHintAndSolverGetters()
{
Console.WriteLine("testSetHintAndSolverGetters");
Solver solver = Solver.CreateSolver("glop");
// x and y are continuous non-negative variables.
Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y");
// Objectif function: Maximize x + 10 * y.
Objective objective = solver.Objective();
objective.SetCoefficient(x, 1);
objective.SetCoefficient(y, 10);
objective.SetMaximization();
// x + 7 * y <= 17.5.
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 17.5, "c0");
c0.SetCoefficient(x, 1);
c0.SetCoefficient(y, 7);
// x <= 3.5.
Constraint c1 = solver.MakeConstraint(double.NegativeInfinity, 3.5, "c1");
c1.SetCoefficient(x, 1);
c1.SetCoefficient(y, 0);
Constraint[] constraints = solver.constraints();
Assert.Equal(constraints.Length, 2);
Variable[] variables = solver.variables();
Assert.Equal(variables.Length, 2);
solver.SetHint(new Variable[] { x, y }, new double[] { 2.0, 3.0 });
}
}
} // namespace Google.OrTools.Tests

View File

@@ -17,191 +17,186 @@ using Google.OrTools.ConstraintSolver;
namespace Google.OrTools.Tests
{
public class RoutingSolverTest
public class RoutingSolverTest
{
[Theory]
[InlineData(false)]
[InlineData(true)]
public void SimpleLambdaCallback(bool callGC)
{
[Theory]
[InlineData(false)]
[InlineData(true)]
public void SimpleLambdaCallback(bool callGC)
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
int transitCallbackIndex = routing.RegisterTransitCallback((long fromIndex, long toIndex) =>
{
// Convert from routing variable Index to
// distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
return Math.Abs(toNode - fromNode);
});
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
if (callGC)
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
int transitCallbackIndex = routing.RegisterTransitCallback((long fromIndex, long toIndex) => {
// Convert from routing variable Index to distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
return Math.Abs(toNode - fromNode);
});
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
if (callGC)
{
GC.Collect();
}
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+4)-> 0 := +8
Assert.Equal(8, solution.ObjectiveValue());
}
[Fact]
public void TestTransitMatrix()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[][] matrix = new long[][] {
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
};
int transitCallbackIndex = routing.RegisterTransitMatrix(matrix);
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
[Fact]
public void TestTransitCallback()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
int transitCallbackIndex = routing.RegisterTransitCallback(
(long fromIndex, long toIndex) => {
// Convert from routing variable Index to distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
return Math.Abs(toNode - fromNode);
});
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
Assert.Equal(8, solution.ObjectiveValue());
}
[Fact]
public void TestMatrixDimension()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[][] matrix = new long[][] {
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
new long[] {1, 1, 1, 1, 1},
};
IntBoolPair result = routing.AddMatrixDimension(
matrix,
/*capacity=*/10,
/*fix_start_cumul_to_zero=*/true,
"Dimension");
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(result.first);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
[Fact]
public void TestUnaryTransitVector()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[] vector = {1, 1, 1, 1, 1};
int transitCallbackIndex = routing.RegisterUnaryTransitVector(vector);
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
[Fact]
public void TestUnaryTransitCallback()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
int transitCallbackIndex = routing.RegisterUnaryTransitCallback(
(long fromIndex) => {
// Convert from routing variable Index to distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
return fromNode + 1;
});
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+2)-> 2 --(+3)-> 3 --(+4)-> 4 --(+5)-> 0 := +15
Assert.Equal(15, solution.ObjectiveValue());
}
[Fact]
public void TestVectorDimension()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[] vector = new long[] {1, 1, 1, 1, 1};
IntBoolPair result = routing.AddVectorDimension(
vector,
/*capacity=*/10,
/*fix_start_cumul_to_zero=*/true,
"Dimension");
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(result.first);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
GC.Collect();
}
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+4)-> 0 := +8
Assert.Equal(8, solution.ObjectiveValue());
}
[Fact]
public void TestTransitMatrix()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[][] matrix = new long[][] {
new long[] { 1, 1, 1, 1, 1 }, new long[] { 1, 1, 1, 1, 1 }, new long[] { 1, 1, 1, 1, 1 },
new long[] { 1, 1, 1, 1, 1 }, new long[] { 1, 1, 1, 1, 1 },
};
int transitCallbackIndex = routing.RegisterTransitMatrix(matrix);
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
[Fact]
public void TestTransitCallback()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
int transitCallbackIndex = routing.RegisterTransitCallback((long fromIndex, long toIndex) =>
{
// Convert from routing variable Index to
// distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
return Math.Abs(toNode - fromNode);
});
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
Assert.Equal(8, solution.ObjectiveValue());
}
[Fact]
public void TestMatrixDimension()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[][] matrix = new long[][] {
new long[] { 1, 1, 1, 1, 1 }, new long[] { 1, 1, 1, 1, 1 }, new long[] { 1, 1, 1, 1, 1 },
new long[] { 1, 1, 1, 1, 1 }, new long[] { 1, 1, 1, 1, 1 },
};
IntBoolPair result = routing.AddMatrixDimension(matrix,
/*capacity=*/10,
/*fix_start_cumul_to_zero=*/true, "Dimension");
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(result.first);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
[Fact]
public void TestUnaryTransitVector()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[] vector = { 1, 1, 1, 1, 1 };
int transitCallbackIndex = routing.RegisterUnaryTransitVector(vector);
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
[Fact]
public void TestUnaryTransitCallback()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
int transitCallbackIndex = routing.RegisterUnaryTransitCallback((long fromIndex) =>
{
// Convert from routing variable Index to
// distance matrix NodeIndex.
var fromNode =
manager.IndexToNode(fromIndex);
return fromNode + 1;
});
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+2)-> 2 --(+3)-> 3 --(+4)-> 4 --(+5)-> 0 := +15
Assert.Equal(15, solution.ObjectiveValue());
}
[Fact]
public void TestVectorDimension()
{
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create a distance callback.
long[] vector = new long[] { 1, 1, 1, 1, 1 };
IntBoolPair result = routing.AddVectorDimension(vector,
/*capacity=*/10,
/*fix_start_cumul_to_zero=*/true, "Dimension");
// Define cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(result.first);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
// 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5
Assert.Equal(5, solution.ObjectiveValue());
}
}
} // namespace Google.OrTools.Tests

View File

@@ -18,376 +18,437 @@ using Google.OrTools.Sat;
namespace Google.OrTools.Tests
{
public class SatSolverTest
public class SatSolverTest
{
static IntegerVariableProto NewIntegerVariable(long lb, long ub)
{
static IntegerVariableProto NewIntegerVariable(long lb, long ub)
IntegerVariableProto var = new IntegerVariableProto();
var.Domain.Add(lb);
var.Domain.Add(ub);
return var;
}
static ConstraintProto NewLinear2(int v1, int v2, long c1, long c2, long lb, long ub)
{
LinearConstraintProto linear = new LinearConstraintProto();
linear.Vars.Add(v1);
linear.Vars.Add(v2);
linear.Coeffs.Add(c1);
linear.Coeffs.Add(c2);
linear.Domain.Add(lb);
linear.Domain.Add(ub);
ConstraintProto ct = new ConstraintProto();
ct.Linear = linear;
return ct;
}
static ConstraintProto NewLinear3(int v1, int v2, int v3, long c1, long c2, long c3, long lb, long ub)
{
LinearConstraintProto linear = new LinearConstraintProto();
linear.Vars.Add(v1);
linear.Vars.Add(v2);
linear.Vars.Add(v3);
linear.Coeffs.Add(c1);
linear.Coeffs.Add(c2);
linear.Coeffs.Add(c3);
linear.Domain.Add(lb);
linear.Domain.Add(ub);
ConstraintProto ct = new ConstraintProto();
ct.Linear = linear;
return ct;
}
static CpObjectiveProto NewMinimize1(int v1, long c1)
{
CpObjectiveProto obj = new CpObjectiveProto();
obj.Vars.Add(v1);
obj.Coeffs.Add(c1);
return obj;
}
static CpObjectiveProto NewMaximize1(int v1, long c1)
{
CpObjectiveProto obj = new CpObjectiveProto();
obj.Vars.Add(-v1 - 1);
obj.Coeffs.Add(c1);
obj.ScalingFactor = -1;
return obj;
}
static CpObjectiveProto NewMaximize2(int v1, int v2, long c1, long c2)
{
CpObjectiveProto obj = new CpObjectiveProto();
obj.Vars.Add(-v1 - 1);
obj.Vars.Add(-v2 - 1);
obj.Coeffs.Add(c1);
obj.Coeffs.Add(c2);
obj.ScalingFactor = -1;
return obj;
}
// CpModelProto
[Fact]
public void SimpleLinearModelProto()
{
CpModelProto model = new CpModelProto();
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Variables.Add(NewIntegerVariable(-1000000, 1000000));
model.Constraints.Add(NewLinear2(0, 1, 1, 1, -1000000, 100000));
model.Constraints.Add(NewLinear3(0, 1, 2, 1, 2, -1, 0, 100000));
model.Objective = NewMaximize1(2, 1);
// Console.WriteLine("model = " + model.ToString());
SolveWrapper solve_wrapper = new SolveWrapper();
CpSolverResponse response = solve_wrapper.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, response.Status);
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, 10, 30 }, response.Solution);
// Console.WriteLine("response = " + response.ToString());
}
[Fact]
public void SimpleLinearModelProto2()
{
CpModelProto model = new CpModelProto();
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Constraints.Add(NewLinear2(0, 1, 1, 1, -1000000, 100000));
model.Objective = NewMaximize2(0, 1, 1, -2);
// Console.WriteLine("model = " + model.ToString());
SolveWrapper solve_wrapper = new SolveWrapper();
CpSolverResponse response = solve_wrapper.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, response.Status);
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, -10 }, response.Solution);
// Console.WriteLine("response = " + response.ToString());
}
// CpModel
[Fact]
public void SimpleLinearModel()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
IntVar v3 = model.NewIntVar(-100000, 100000, "v3");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.AddLinearConstraint(v1 + 2 * v2 - v3, 0, 100000);
model.Maximize(v3);
Assert.Equal(v1.Domain.FlattenedIntervals(), new long[] { -10, 10 });
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, 10, 30 }, response.Solution);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void SimpleLinearModel2()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.Maximize(v1 - 2 * v2);
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, -10 }, response.Solution);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void SimpleLinearModel3()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
model.Add(-100000 <= v1 + 2 * v2 <= 100000);
model.Minimize(v1 - 2 * v2);
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(-10, solver.Value(v1));
Assert.Equal(10, solver.Value(v2));
Assert.Equal(new long[] { -10, 10 }, response.Solution);
Assert.Equal(-30, solver.Value(v1 - 2 * v2));
Assert.Equal(-30, response.ObjectiveValue);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void NegativeIntVar()
{
CpModel model = new CpModel();
IntVar boolvar = model.NewBoolVar("boolvar");
IntVar x = model.NewIntVar(0, 10, "x");
IntVar delta = model.NewIntVar(-5, 5, "delta");
IntVar squaredDelta = model.NewIntVar(0, 25, "squaredDelta");
model.Add(x == boolvar * 4);
model.Add(delta == x - 5);
model.AddMultiplicationEquality(squaredDelta, new IntVar[] { delta, delta });
model.Minimize(squaredDelta);
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
CpSolverResponse response = solver.Response;
Console.WriteLine("response = " + response.ToString());
Assert.Equal(CpSolverStatus.Optimal, status);
Assert.Equal(1, solver.Value(boolvar));
Assert.Equal(4, solver.Value(x));
Assert.Equal(-1, solver.Value(delta));
Assert.Equal(1, solver.Value(squaredDelta));
Assert.Equal(new long[] { 1, 4, -1, 1 }, response.Solution);
Assert.Equal(1.0, response.ObjectiveValue, 5);
}
[Fact]
public void NegativeSquareVar()
{
CpModel model = new CpModel();
BoolVar boolvar = model.NewBoolVar("boolvar");
IntVar x = model.NewIntVar(0, 10, "x");
IntVar delta = model.NewIntVar(-5, 5, "delta");
IntVar squaredDelta = model.NewIntVar(0, 25, "squaredDelta");
model.Add(x == 4).OnlyEnforceIf(boolvar);
model.Add(x == 0).OnlyEnforceIf(boolvar.Not());
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 } };
model.AddAllowedAssignments(new IntVar[] { delta, squaredDelta }, tuples);
model.Minimize(squaredDelta);
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
CpSolverResponse response = solver.Response;
Assert.Equal(1, solver.Value(boolvar));
Assert.Equal(4, solver.Value(x));
Assert.Equal(-1, solver.Value(delta));
Assert.Equal(1, solver.Value(squaredDelta));
Assert.Equal(new long[] { 1, 4, -1, 1 }, response.Solution);
Assert.Equal(1.0, response.ObjectiveValue, 6);
}
[Fact]
public void Division()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(0, 10, "v1");
IntVar v2 = model.NewIntVar(1, 10, "v2");
model.AddDivisionEquality(3, v1, v2);
// Console.WriteLine(model.Model);
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(3, solver.Value(v1));
Assert.Equal(1, solver.Value(v2));
Assert.Equal(new long[] { 3, 1 }, response.Solution);
Assert.Equal(0, response.ObjectiveValue);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void Modulo()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(1, 10, "v1");
IntVar v2 = model.NewIntVar(1, 10, "v2");
model.AddModuloEquality(3, v1, v2);
// Console.WriteLine(model.Model);
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(3, solver.Value(v1));
Assert.Equal(4, solver.Value(v2));
Assert.Equal(new long[] { 3, 4 }, response.Solution);
Assert.Equal(0, response.ObjectiveValue);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void LargeWeightedSumLong()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
List<long> coeffs = new List<long>();
for (int i = 0; i < 100000; ++i)
{
IntegerVariableProto var = new IntegerVariableProto();
var.Domain.Add(lb);
var.Domain.Add(ub);
return var;
vars.Add(model.NewBoolVar(""));
coeffs.Add(i + 1);
}
static ConstraintProto NewLinear2(int v1, int v2, long c1, long c2, long lb, long ub)
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.WeightedSum(vars, coeffs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Long: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeWeightedSumInt()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
List<int> coeffs = new List<int>();
for (int i = 0; i < 100000; ++i)
{
LinearConstraintProto linear = new LinearConstraintProto();
linear.Vars.Add(v1);
linear.Vars.Add(v2);
linear.Coeffs.Add(c1);
linear.Coeffs.Add(c2);
linear.Domain.Add(lb);
linear.Domain.Add(ub);
ConstraintProto ct = new ConstraintProto();
ct.Linear = linear;
return ct;
vars.Add(model.NewBoolVar(""));
coeffs.Add(i);
}
static ConstraintProto NewLinear3(int v1, int v2, int v3, long c1, long c2, long c3, long lb, long ub)
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.WeightedSum(vars, coeffs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Int: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeWeightedSumExpr()
{
CpModel model = new CpModel();
List<LinearExpr> exprs = new List<LinearExpr>();
for (int i = 0; i < 100000; ++i)
{
LinearConstraintProto linear = new LinearConstraintProto();
linear.Vars.Add(v1);
linear.Vars.Add(v2);
linear.Vars.Add(v3);
linear.Coeffs.Add(c1);
linear.Coeffs.Add(c2);
linear.Coeffs.Add(c3);
linear.Domain.Add(lb);
linear.Domain.Add(ub);
ConstraintProto ct = new ConstraintProto();
ct.Linear = linear;
return ct;
exprs.Add(model.NewBoolVar("") * i);
}
static CpObjectiveProto NewMinimize1(int v1, long c1)
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.Sum(exprs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Exprs: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeWeightedSumBuilder()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
List<long> coeffs = new List<long>();
for (int i = 0; i < 100000; ++i)
{
CpObjectiveProto obj = new CpObjectiveProto();
obj.Vars.Add(v1);
obj.Coeffs.Add(c1);
return obj;
vars.Add(model.NewBoolVar(""));
coeffs.Add(i + 1);
}
static CpObjectiveProto NewMaximize1(int v1, long c1)
var watch = System.Diagnostics.Stopwatch.StartNew();
LinearExprBuilder obj = LinearExpr.NewBuilder();
for (int i = 0; i < 100000; ++i)
{
CpObjectiveProto obj = new CpObjectiveProto();
obj.Vars.Add(-v1 - 1);
obj.Coeffs.Add(c1);
obj.ScalingFactor = -1;
return obj;
obj.AddTerm(vars[i], coeffs[i]);
}
model.Minimize(obj);
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Proto: Elapsed time {elapsedMs}");
}
static CpObjectiveProto NewMaximize2(int v1, int v2, long c1, long c2)
{
CpObjectiveProto obj = new CpObjectiveProto();
obj.Vars.Add(-v1 - 1);
obj.Vars.Add(-v2 - 1);
obj.Coeffs.Add(c1);
obj.Coeffs.Add(c2);
obj.ScalingFactor = -1;
return obj;
}
[Fact]
public void LinearExprStaticCompileTest()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
BoolVar b1 = model.NewBoolVar("b1");
BoolVar b2 = model.NewBoolVar("b2");
long[] c1 = new long[] { 2L, 4L };
int[] c2 = new int[] { 2, 4 };
LinearExpr e1 = LinearExpr.Sum(new IntVar[] { v1, v2 });
Console.WriteLine(e1.ToString());
LinearExpr e2 = LinearExpr.Sum(new ILiteral[] { b1, b2 });
Console.WriteLine(e2.ToString());
LinearExpr e3 = LinearExpr.Sum(new BoolVar[] { b1, b2 });
Console.WriteLine(e3.ToString());
LinearExpr e4 = LinearExpr.WeightedSum(new IntVar[] { v1, v2 }, c1);
Console.WriteLine(e4.ToString());
LinearExpr e5 = LinearExpr.WeightedSum(new ILiteral[] { b1, b2 }, c1);
Console.WriteLine(e5.ToString());
LinearExpr e6 = LinearExpr.WeightedSum(new BoolVar[] { b1, b2 }, c1);
Console.WriteLine(e6.ToString());
LinearExpr e7 = LinearExpr.WeightedSum(new IntVar[] { v1, v2 }, c2);
Console.WriteLine(e7.ToString());
LinearExpr e8 = LinearExpr.WeightedSum(new ILiteral[] { b1, b2 }, c2);
Console.WriteLine(e8.ToString());
LinearExpr e9 = LinearExpr.WeightedSum(new BoolVar[] { b1, b2 }, c2);
Console.WriteLine(e9.ToString());
}
// CpModelProto
[Fact]
public void SimpleLinearModelProto()
{
CpModelProto model = new CpModelProto();
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Variables.Add(NewIntegerVariable(-1000000, 1000000));
model.Constraints.Add(NewLinear2(0, 1, 1, 1, -1000000, 100000));
model.Constraints.Add(NewLinear3(0, 1, 2, 1, 2, -1, 0, 100000));
model.Objective = NewMaximize1(2, 1);
// Console.WriteLine("model = " + model.ToString());
SolveWrapper solve_wrapper = new SolveWrapper();
CpSolverResponse response = solve_wrapper.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, response.Status);
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, 10, 30 }, response.Solution);
// Console.WriteLine("response = " + response.ToString());
}
[Fact]
public void LinearExprBuilderCompileTest()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
BoolVar b1 = model.NewBoolVar("b1");
BoolVar b2 = model.NewBoolVar("b2");
long[] c1 = new long[] { 2L, 4L };
int[] c2 = new int[] { 2, 4 };
LinearExpr e1 = LinearExpr.NewBuilder().AddSum(new IntVar[] { v1, v2 });
Console.WriteLine(e1.ToString());
LinearExpr e2 = LinearExpr.NewBuilder().AddSum(new ILiteral[] { b1, b2 });
Console.WriteLine(e2.ToString());
LinearExpr e3 = LinearExpr.NewBuilder().AddSum(new BoolVar[] { b1, b2 });
Console.WriteLine(e3.ToString());
LinearExpr e4 = LinearExpr.NewBuilder().AddWeightedSum(new IntVar[] { v1, v2 }, c1);
Console.WriteLine(e4.ToString());
LinearExpr e5 = LinearExpr.NewBuilder().AddWeightedSum(new ILiteral[] { b1, b2 }, c1);
Console.WriteLine(e5.ToString());
LinearExpr e6 = LinearExpr.NewBuilder().AddWeightedSum(new BoolVar[] { b1, b2 }, c1);
Console.WriteLine(e6.ToString());
LinearExpr e7 = LinearExpr.NewBuilder().AddWeightedSum(new IntVar[] { v1, v2 }, c2);
Console.WriteLine(e7.ToString());
LinearExpr e8 = LinearExpr.NewBuilder().AddWeightedSum(new ILiteral[] { b1, b2 }, c2);
Console.WriteLine(e8.ToString());
LinearExpr e9 = LinearExpr.NewBuilder().AddWeightedSum(new BoolVar[] { b1, b2 }, c2);
Console.WriteLine(e9.ToString());
}
[Fact]
public void SimpleLinearModelProto2()
{
CpModelProto model = new CpModelProto();
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Variables.Add(NewIntegerVariable(-10, 10));
model.Constraints.Add(NewLinear2(0, 1, 1, 1, -1000000, 100000));
model.Objective = NewMaximize2(0, 1, 1, -2);
// Console.WriteLine("model = " + model.ToString());
[Fact]
public void ExportModel()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
model.Add(-100000 <= v1 + 2 * v2 <= 100000);
model.Minimize(v1 - 2 * v2);
Assert.True(model.ExportToFile("test_model_dotnet.pbtxt"));
Console.WriteLine("Model written to file");
}
SolveWrapper solve_wrapper = new SolveWrapper();
CpSolverResponse response = solve_wrapper.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, response.Status);
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, -10 }, response.Solution);
// Console.WriteLine("response = " + response.ToString());
}
// CpModel
[Fact]
public void SimpleLinearModel()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
IntVar v3 = model.NewIntVar(-100000, 100000, "v3");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.AddLinearConstraint(v1 + 2 * v2 - v3, 0, 100000);
model.Maximize(v3);
Assert.Equal(v1.Domain.FlattenedIntervals(), new long[] { -10, 10 });
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, 10, 30 }, response.Solution);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void SimpleLinearModel2()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.Maximize(v1 - 2 * v2);
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(30, response.ObjectiveValue);
Assert.Equal(new long[] { 10, -10 }, response.Solution);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void SimpleLinearModel3()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
model.Add(-100000 <= v1 + 2 * v2 <= 100000);
model.Minimize(v1 - 2 * v2);
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(-10, solver.Value(v1));
Assert.Equal(10, solver.Value(v2));
Assert.Equal(new long[] { -10, 10 }, response.Solution);
Assert.Equal(-30, solver.Value(v1 - 2 * v2));
Assert.Equal(-30, response.ObjectiveValue);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void NegativeIntVar()
{
CpModel model = new CpModel();
IntVar boolvar = model.NewBoolVar("boolvar");
IntVar x = model.NewIntVar(0, 10, "x");
IntVar delta = model.NewIntVar(-5, 5, "delta");
IntVar squaredDelta = model.NewIntVar(0, 25, "squaredDelta");
model.Add(x == boolvar * 4);
model.Add(delta == x - 5);
model.AddMultiplicationEquality(squaredDelta, new IntVar[] { delta, delta });
model.Minimize(squaredDelta);
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
CpSolverResponse response = solver.Response;
Console.WriteLine("response = " + response.ToString());
Assert.Equal(CpSolverStatus.Optimal, status);
Assert.Equal(1, solver.Value(boolvar));
Assert.Equal(4, solver.Value(x));
Assert.Equal(-1, solver.Value(delta));
Assert.Equal(1, solver.Value(squaredDelta));
Assert.Equal(new long[] { 1, 4, -1, 1 }, response.Solution);
Assert.Equal(1.0, response.ObjectiveValue, 5);
}
[Fact]
public void NegativeSquareVar()
{
CpModel model = new CpModel();
IntVar boolvar = model.NewBoolVar("boolvar");
IntVar x = model.NewIntVar(0, 10, "x");
IntVar delta = model.NewIntVar(-5, 5, "delta");
IntVar squaredDelta = model.NewIntVar(0, 25, "squaredDelta");
model.Add(x == 4).OnlyEnforceIf(boolvar);
model.Add(x == 0).OnlyEnforceIf(boolvar.Not());
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 } };
model.AddAllowedAssignments(new IntVar[] { delta, squaredDelta }, tuples);
model.Minimize(squaredDelta);
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
CpSolverResponse response = solver.Response;
Assert.Equal(1, solver.Value(boolvar));
Assert.Equal(4, solver.Value(x));
Assert.Equal(-1, solver.Value(delta));
Assert.Equal(1, solver.Value(squaredDelta));
Assert.Equal(new long[] { 1, 4, -1, 1 }, response.Solution);
Assert.Equal(1.0, response.ObjectiveValue, 6);
}
[Fact]
public void Division()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(0, 10, "v1");
IntVar v2 = model.NewIntVar(1, 10, "v2");
model.AddDivisionEquality(3, v1, v2);
// Console.WriteLine(model.Model);
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(3, solver.Value(v1));
Assert.Equal(1, solver.Value(v2));
Assert.Equal(new long[] { 3, 1 }, response.Solution);
Assert.Equal(0, response.ObjectiveValue);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void Modulo()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(1, 10, "v1");
IntVar v2 = model.NewIntVar(1, 10, "v2");
model.AddModuloEquality(3, v1, v2);
// Console.WriteLine(model.Model);
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Assert.Equal(CpSolverStatus.Optimal, status);
CpSolverResponse response = solver.Response;
Assert.Equal(3, solver.Value(v1));
Assert.Equal(4, solver.Value(v2));
Assert.Equal(new long[] { 3, 4 }, response.Solution);
Assert.Equal(0, response.ObjectiveValue);
// Console.WriteLine("response = " + reponse.ToString());
}
[Fact]
public void LargeWeightedSumLong()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
List<long> coeffs = new List<long>();
for (int i = 0; i < 100000; ++i)
{
vars.Add(model.NewBoolVar(""));
coeffs.Add(i + 1);
}
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.WeightedSum(vars, coeffs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Long: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeWeightedSumInt()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
List<int> coeffs = new List<int>();
for (int i = 0; i < 100000; ++i)
{
vars.Add(model.NewBoolVar(""));
coeffs.Add(i);
}
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.WeightedSum(vars, coeffs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Int: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeWeightedSumExpr()
{
CpModel model = new CpModel();
List<LinearExpr> exprs = new List<LinearExpr>();
for (int i = 0; i < 100000; ++i)
{
exprs.Add(model.NewBoolVar("") * i);
}
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize(LinearExpr.Sum(exprs));
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Exprs: Elapsed time {elapsedMs}");
}
[Fact]
public void LargeWeightedSumProto()
{
CpModel model = new CpModel();
List<IntVar> vars = new List<IntVar>();
List<long> coeffs = new List<long>();
for (int i = 0; i < 100000; ++i)
{
vars.Add(model.NewBoolVar(""));
coeffs.Add(i + 1);
}
var watch = System.Diagnostics.Stopwatch.StartNew();
model.Minimize();
for (int i = 0; i < 100000; ++i)
{
model.AddTermToObjective(vars[i], coeffs[i]);
}
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine($"Proto: Elapsed time {elapsedMs}");
}
[Fact]
public void ExportModel()
{
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
model.Add(-100000 <= v1 + 2 * v2 <= 100000);
model.Minimize(v1 - 2 * v2);
Assert.True(model.ExportToFile("test_model_dotnet.pbtxt"));
Console.WriteLine("Model written to file");
}
[Fact]
public void SolveFromString()
{
string model_str = @"
[Fact]
public void SolveFromString()
{
string model_str = @"
{
""variables"": [
{ ""name"": ""C"", ""domain"": [ ""1"", ""9"" ] },
@@ -416,45 +477,45 @@ namespace Google.OrTools.Tests
{ ""linear"": { ""vars"": [ 6, 5, 9, 4, 3, 7, 8, 2, 0, 1 ], ""coeffs"": [ ""1"", ""0"", ""-1"", ""100"", ""1"", ""-1000"", ""-100"", ""10"", ""10"", ""1"" ], ""domain"": [ ""0"", ""0"" ] } }
]
}";
CpModelProto model = Google.Protobuf.JsonParser.Default.Parse<CpModelProto>(model_str);
SolveWrapper solve_wrapper = new SolveWrapper();
CpSolverResponse response = solve_wrapper.Solve(model);
Console.WriteLine(response);
}
[Fact]
public void CaptureLog()
{
Console.WriteLine("CaptureLog test");
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
IntVar v3 = model.NewIntVar(-100000, 100000, "v3");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.AddLinearConstraint(v1 + 2 * v2 - v3, 0, 100000);
model.Maximize(v3);
Assert.Equal(v1.Domain.FlattenedIntervals(), new long[] { -10, 10 });
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
solver.StringParameters = "log_search_progress:true log_to_stdout:false";
string log = "";
solver.SetLogCallback(message => log += message + "\n");
solver.Solve(model);
Assert.NotEmpty(log);
Assert.Contains("OPTIMAL", log);
}
[Fact]
public void TestInterval()
{
Console.WriteLine("TestInterval test");
CpModel model = new CpModel();
IntVar v = model.NewIntVar(-10, 10, "v");
IntervalVar i = model.NewFixedSizeIntervalVar(v, 3, "i");
Assert.Equal("v", i.StartExpr().ShortString());
Assert.Equal("3", i.SizeExpr().ShortString());
Assert.Equal("(v + 3)", i.EndExpr().ShortString());
}
CpModelProto model = Google.Protobuf.JsonParser.Default.Parse<CpModelProto>(model_str);
SolveWrapper solve_wrapper = new SolveWrapper();
CpSolverResponse response = solve_wrapper.Solve(model);
Console.WriteLine(response);
}
[Fact]
public void CaptureLog()
{
Console.WriteLine("CaptureLog test");
CpModel model = new CpModel();
IntVar v1 = model.NewIntVar(-10, 10, "v1");
IntVar v2 = model.NewIntVar(-10, 10, "v2");
IntVar v3 = model.NewIntVar(-100000, 100000, "v3");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.AddLinearConstraint(v1 + 2 * v2 - v3, 0, 100000);
model.Maximize(v3);
Assert.Equal(v1.Domain.FlattenedIntervals(), new long[] { -10, 10 });
// Console.WriteLine("model = " + model.Model.ToString());
CpSolver solver = new CpSolver();
solver.StringParameters = "log_search_progress:true log_to_stdout:false";
string log = "";
solver.SetLogCallback(message => log += message + "\n");
solver.Solve(model);
Assert.NotEmpty(log);
Assert.Contains("OPTIMAL", log);
}
[Fact]
public void TestInterval()
{
Console.WriteLine("TestInterval test");
CpModel model = new CpModel();
IntVar v = model.NewIntVar(-10, 10, "v");
IntervalVar i = model.NewFixedSizeIntervalVar(v, 3, "i");
Assert.Equal("v", i.StartExpr().ToString());
Assert.Equal("3", i.SizeExpr().ToString());
Assert.Equal("v + 3", i.EndExpr().ToString());
}
}
} // namespace Google.OrTools.Tests

View File

@@ -18,39 +18,39 @@ using Google.OrTools.ConstraintSolver;
namespace Google.OrTools.Tests
{
public class Issue18Test
public class Issue18Test
{
[Fact]
public void NewSearchTest()
{
[Fact]
public void NewSearchTest()
Solver solver = new Google.OrTools.ConstraintSolver.Solver("p");
// creating dummy variables
List<IntVar> vars = new List<IntVar>();
for (int i = 0; i < 100000; i++)
{
Solver solver = new Google.OrTools.ConstraintSolver.Solver("p");
// creating dummy variables
List<IntVar> vars = new List<IntVar>();
for (int i = 0; i < 100000; i++)
{
vars.Add(solver.MakeIntVar(0, 1));
}
IntExpr globalSum = solver.MakeSum(vars.ToArray());
DecisionBuilder db = solver.MakePhase(vars.ToArray(), Google.OrTools.ConstraintSolver.Solver.INT_VAR_SIMPLE,
Google.OrTools.ConstraintSolver.Solver.INT_VALUE_SIMPLE);
solver.NewSearch(db, new OptimizeVar(solver, true, globalSum.Var(), 100));
// force Garbage Collector
GC.Collect();
GC.WaitForPendingFinalizers();
// Try to read all solutions
int count = 0;
while (solver.NextSolution())
{
count++;
// Console.WriteLine("solution " + globalSum.Var().Value());
}
Console.WriteLine("Solutions: " + count);
vars.Add(solver.MakeIntVar(0, 1));
}
IntExpr globalSum = solver.MakeSum(vars.ToArray());
DecisionBuilder db = solver.MakePhase(vars.ToArray(), Google.OrTools.ConstraintSolver.Solver.INT_VAR_SIMPLE,
Google.OrTools.ConstraintSolver.Solver.INT_VALUE_SIMPLE);
solver.NewSearch(db, new OptimizeVar(solver, true, globalSum.Var(), 100));
// force Garbage Collector
GC.Collect();
GC.WaitForPendingFinalizers();
// Try to read all solutions
int count = 0;
while (solver.NextSolution())
{
count++;
// Console.WriteLine("solution " + globalSum.Var().Value());
}
Console.WriteLine("Solutions: " + count);
}
}
} // namespace Google.OrTools.Tests

View File

@@ -21,64 +21,64 @@ using Google.OrTools.ConstraintSolver;
namespace Google.OrTools.Tests
{
public class Issue22Test
public class Issue22Test
{
private long Solve(long num_buses_check = 0)
{
private long Solve(long num_buses_check = 0)
ConstraintSolverParameters sPrm = Solver.DefaultSolverParameters();
sPrm.CompressTrail = 0;
Solver solver = new Solver("OrTools", sPrm);
// this works
// IntVar[,] x = solver.MakeIntVarMatrix(2,2, new int[] {-2,0,1,2}, "x");
// this doesn't work
IntVar[,] x = solver.MakeIntVarMatrix(2, 2, new int[] { 0, 1, 2 }, "x");
for (int w = 0; w < 2; w++)
{
ConstraintSolverParameters sPrm = Solver.DefaultSolverParameters();
sPrm.CompressTrail = 0;
Solver solver = new Solver("OrTools", sPrm);
// this works
// IntVar[,] x = solver.MakeIntVarMatrix(2,2, new int[] {-2,0,1,2}, "x");
// this doesn't work
IntVar[,] x = solver.MakeIntVarMatrix(2, 2, new int[] { 0, 1, 2 }, "x");
for (int w = 0; w < 2; w++)
IntVar[] b = new IntVar[2];
for (int i = 0; i < 2; i++)
{
IntVar[] b = new IntVar[2];
b[i] = solver.MakeIsEqualCstVar(x[w, i], 0);
}
solver.Add(solver.MakeSumGreaterOrEqual(b, 2));
}
IntVar[] x_flat = x.Flatten();
DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);
solver.NewSearch(db);
while (solver.NextSolution())
{
Console.WriteLine("x: ");
for (int j = 0; j < 2; j++)
{
Console.Write("worker" + (j + 1).ToString() + ":");
for (int i = 0; i < 2; i++)
{
b[i] = solver.MakeIsEqualCstVar(x[w, i], 0);
Console.Write(" {0,2} ", x[j, i].Value());
}
solver.Add(solver.MakeSumGreaterOrEqual(b, 2));
Console.Write("\n");
}
IntVar[] x_flat = x.Flatten();
DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);
solver.NewSearch(db);
while (solver.NextSolution())
{
Console.WriteLine("x: ");
for (int j = 0; j < 2; j++)
{
Console.Write("worker" + (j + 1).ToString() + ":");
for (int i = 0; i < 2; i++)
{
Console.Write(" {0,2} ", x[j, i].Value());
}
Console.Write("\n");
}
Console.WriteLine("End at---->" + DateTime.Now);
}
Console.WriteLine("\nSolutions: {0}", solver.Solutions());
Console.WriteLine("WallTime: {0}ms", solver.WallTime());
Console.WriteLine("Failures: {0}", solver.Failures());
Console.WriteLine("Branches: {0} ", solver.Branches());
solver.EndSearch();
return 1;
Console.WriteLine("End at---->" + DateTime.Now);
}
[Fact]
public void InitialPropagateTest()
{
Console.WriteLine("Check for minimum number of buses: ");
long num_buses = Solve();
Console.WriteLine("\n... got {0} as minimal value.", num_buses);
Console.WriteLine("\nAll solutions: ", num_buses);
}
Console.WriteLine("\nSolutions: {0}", solver.Solutions());
Console.WriteLine("WallTime: {0}ms", solver.WallTime());
Console.WriteLine("Failures: {0}", solver.Failures());
Console.WriteLine("Branches: {0} ", solver.Branches());
solver.EndSearch();
return 1;
}
[Fact]
public void InitialPropagateTest()
{
Console.WriteLine("Check for minimum number of buses: ");
long num_buses = Solve();
Console.WriteLine("\n... got {0} as minimal value.", num_buses);
Console.WriteLine("\nAll solutions: ", num_buses);
}
}
} // namespace Google.OrTools.Tests

File diff suppressed because it is too large Load Diff

View File

@@ -53,7 +53,7 @@ public class LinearExpr
public static LinearExpr Sum(IEnumerable<BoolVar> vars)
{
return NewBuilder().AddSum(vars);
}
}
public static LinearExpr WeightedSum(IEnumerable<LinearExpr> exprs, IEnumerable<int> coeffs)
{
@@ -73,7 +73,7 @@ public class LinearExpr
public static LinearExpr WeightedSum(IEnumerable<ILiteral> literals, IEnumerable<long> coeffs)
{
return NewBuilder().AddWeightedSum(literals, coeffs);
}
}
public static LinearExpr WeightedSum(IEnumerable<BoolVar> vars, IEnumerable<int> coeffs)
{
@@ -83,29 +83,29 @@ public class LinearExpr
public static LinearExpr WeightedSum(IEnumerable<BoolVar> vars, IEnumerable<long> coeffs)
{
return NewBuilder().AddWeightedSum(vars, coeffs);
}
}
public static LinearExpr Term(LinearExpr expr, long coeff)
{
return Prod(expr, coeff);
}
public static LinearExpr Term(ILiteral literal, long coeff)
public static LinearExpr Term(ILiteral literal, long coeff)
{
if (literal is BoolVar)
if (literal is BoolVar)
{
return Prod((IntVar) literal, coeff);
return Prod((IntVar)literal, coeff);
}
else
{
return Affine((BoolVar) literal.Not(), -coeff, coeff);
return Affine((BoolVar)literal.Not(), -coeff, coeff);
}
}
public static LinearExpr Term(BoolVar var, long coeff)
public static LinearExpr Term(BoolVar var, long coeff)
{
return Prod(var, coeff);
}
}
public static LinearExpr Affine(LinearExpr expr, long coeff, long offset)
{
@@ -445,14 +445,14 @@ public class LinearExprBuilder : LinearExpr
return this;
}
public LinearExprBuilder AddSum(IEnumerable<BoolVar> vars)
public LinearExprBuilder AddSum(IEnumerable<BoolVar> vars)
{
foreach (BoolVar var in vars)
{
AddTerm(var, 1);
}
return this;
}
}
public LinearExprBuilder AddWeightedSum(IEnumerable<LinearExpr> exprs, IEnumerable<long> coefficients)
{
foreach (var p in exprs.Zip(coefficients, (e, c) => new { Expr = e, Coeff = c }))
@@ -506,7 +506,7 @@ public class LinearExprBuilder : LinearExpr
}
return this;
}
public override string ToString()
{
string result = "";