2025-01-10 11:35:44 +01:00
|
|
|
// Copyright 2010-2025 Google LLC
|
2021-05-20 17:56:00 +02:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
2019-01-30 15:06:00 +01:00
|
|
|
using System;
|
2019-07-01 13:41:17 +02:00
|
|
|
using Xunit;
|
2020-10-28 09:43:50 +01:00
|
|
|
using Google.OrTools.LinearSolver;
|
2024-07-27 14:57:51 +03:00
|
|
|
using Xunit.Abstractions;
|
2018-08-30 13:24:33 +02:00
|
|
|
|
2020-11-03 10:04:19 +01:00
|
|
|
namespace Google.OrTools.Tests
|
|
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
public class LinearSolverTest
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
private readonly ITestOutputHelper output;
|
|
|
|
|
|
|
|
|
|
public LinearSolverTest(ITestOutputHelper output)
|
|
|
|
|
{
|
|
|
|
|
this.output = output;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void VarOperator()
|
2020-11-03 10:04:19 +01:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2022-06-03 18:03:31 +02:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
2022-06-03 18:03:31 +02:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2019-04-23 13:16:20 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void VarAddition()
|
|
|
|
|
{
|
|
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2022-06-03 18:03:31 +02:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
2022-06-03 18:03:31 +02:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void VarMultiplication()
|
|
|
|
|
{
|
|
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2022-06-03 18:03:31 +02:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
2022-06-03 18:03:31 +02:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2020-02-17 13:37:48 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void BinaryOperator()
|
|
|
|
|
{
|
|
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2022-06-03 18:03:31 +02:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
2022-06-03 18:03:31 +02:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
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));
|
|
|
|
|
}
|
2019-04-23 13:16:20 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void Inequalities()
|
|
|
|
|
{
|
|
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2022-06-03 18:03:31 +02:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
2022-06-03 18:03:31 +02:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2020-06-24 18:11:12 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void SumArray()
|
|
|
|
|
{
|
|
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2022-06-03 18:03:31 +02:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2019-07-01 13:41:17 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
Variable[] x = solver.MakeBoolVarArray(10, "x");
|
|
|
|
|
Constraint ct1 = solver.Add(x.Sum() == 3);
|
|
|
|
|
Assert.Equal(1.0, ct1.GetCoefficient(x[0]));
|
2019-07-01 13:41:17 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
Constraint ct2 = solver.Add(-2 * x.Sum() == 3);
|
|
|
|
|
Assert.Equal(-2.0, ct2.GetCoefficient(x[0]));
|
2022-01-10 18:44:12 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2022-01-10 18:44:12 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void Objective()
|
|
|
|
|
{
|
|
|
|
|
Solver solver = Solver.CreateSolver("CLP");
|
|
|
|
|
if (solver is null)
|
2020-11-03 10:04:19 +01:00
|
|
|
{
|
2024-07-12 15:51:52 +02:00
|
|
|
return;
|
2024-02-02 14:29:03 +01:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2024-02-02 14:29:03 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
void SolveAndPrint(in Solver solver, in Variable[] variables, in Constraint[] constraints)
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"Number of variables = {solver.NumVariables()}");
|
|
|
|
|
output.WriteLine($"Number of constraints = {solver.NumConstraints()}");
|
2024-02-02 14:29:03 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
Solver.ResultStatus resultStatus = solver.Solve();
|
|
|
|
|
// Check that the problem has an optimal solution.
|
|
|
|
|
if (resultStatus != Solver.ResultStatus.OPTIMAL)
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine("The problem does not have an optimal solution!");
|
2024-07-12 15:51:52 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine("Solution:");
|
2024-07-12 15:51:52 +02:00
|
|
|
foreach (Variable var in variables)
|
2020-11-03 10:04:19 +01:00
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"{var.Name()} = {var.SolutionValue()}");
|
2020-11-03 10:04:19 +01:00
|
|
|
}
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"Optimal objective value = {solver.Objective().Value()}");
|
|
|
|
|
output.WriteLine("");
|
|
|
|
|
output.WriteLine("Advanced usage:");
|
|
|
|
|
output.WriteLine($"Problem solved in {solver.WallTime()} milliseconds");
|
|
|
|
|
output.WriteLine($"Problem solved in {solver.Iterations()} iterations");
|
2024-07-12 15:51:52 +02:00
|
|
|
if (!solver.IsMip())
|
2022-01-10 18:44:12 +01:00
|
|
|
{
|
2024-02-02 14:29:03 +01:00
|
|
|
foreach (Variable var in variables)
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"{var.Name()}: reduced cost {var.ReducedCost()}");
|
2024-02-02 14:29:03 +01:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
|
|
|
|
|
double[] activities = solver.ComputeConstraintActivities();
|
|
|
|
|
foreach (Constraint ct in constraints)
|
2024-02-02 14:29:03 +01:00
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"{ct.Name()}: dual value = {ct.DualValue()}",
|
2024-09-18 11:56:23 +02:00
|
|
|
$" activity = {activities[ct.Index()]}");
|
2024-02-02 14:29:03 +01:00
|
|
|
}
|
2022-01-10 18:44:12 +01:00
|
|
|
}
|
2020-11-03 10:04:19 +01:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
}
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
void RunLinearProgrammingExample(in String problemType)
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"------ Linear programming example with {problemType} ------");
|
2024-07-12 15:51:52 +02:00
|
|
|
|
|
|
|
|
Solver solver = Solver.CreateSolver(problemType);
|
|
|
|
|
if (solver is 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)
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"------ Mixed integer programming example with {problemType} ------");
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
Solver solver = Solver.CreateSolver(problemType);
|
|
|
|
|
if (solver == null)
|
|
|
|
|
return;
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// 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");
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// Objectif function: Maximize x + 10 * y.
|
|
|
|
|
Objective objective = solver.Objective();
|
|
|
|
|
objective.SetCoefficient(x, 1);
|
|
|
|
|
objective.SetCoefficient(y, 10);
|
|
|
|
|
objective.SetMaximization();
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// x + 7 * y <= 17.5.
|
|
|
|
|
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 17.5, "c0");
|
|
|
|
|
c0.SetCoefficient(x, 1);
|
|
|
|
|
c0.SetCoefficient(y, 7);
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// x <= 3.5.
|
|
|
|
|
Constraint c1 = solver.MakeConstraint(double.NegativeInfinity, 3.5, "c1");
|
|
|
|
|
c1.SetCoefficient(x, 1);
|
|
|
|
|
c1.SetCoefficient(y, 0);
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0, c1 });
|
|
|
|
|
}
|
|
|
|
|
void RunBooleanProgrammingExample(in String problemType)
|
|
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine($"------ Boolean programming example with {problemType} ------");
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
Solver solver = Solver.CreateSolver(problemType);
|
|
|
|
|
if (solver == null)
|
|
|
|
|
return;
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// x and y are boolean variables.
|
|
|
|
|
Variable x = solver.MakeBoolVar("x");
|
|
|
|
|
Variable y = solver.MakeBoolVar("y");
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// Objectif function: Maximize 2 * x + y.
|
|
|
|
|
Objective objective = solver.Objective();
|
|
|
|
|
objective.SetCoefficient(x, 2);
|
|
|
|
|
objective.SetCoefficient(y, 1);
|
|
|
|
|
objective.SetMinimization();
|
2020-11-03 10:04:19 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
// 1 <= x + 2 * y <= 3.
|
|
|
|
|
Constraint c0 = solver.MakeConstraint(1, 3, "c0");
|
|
|
|
|
c0.SetCoefficient(x, 1);
|
|
|
|
|
c0.SetCoefficient(y, 2);
|
2020-06-24 18:11:12 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
SolveAndPrint(solver, new Variable[] { x, y }, new Constraint[] { c0 });
|
|
|
|
|
}
|
2019-01-30 15:06:00 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[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");
|
|
|
|
|
}
|
2022-01-10 18:44:12 +01:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
2024-07-27 14:57:51 +03:00
|
|
|
public void testSetHintAndSolverGetters()
|
2024-07-12 15:51:52 +02:00
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine("testSetHintAndSolverGetters");
|
2024-07-12 15:51:52 +02:00
|
|
|
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 });
|
|
|
|
|
}
|
2023-06-28 18:23:48 +02:00
|
|
|
|
2024-07-12 15:51:52 +02:00
|
|
|
[Fact]
|
2024-07-27 14:57:51 +03:00
|
|
|
public void Given_a_LinearExpr_and_a_solution_When_SolutionValue_is_called_then_the_result_is_correct()
|
2024-07-12 15:51:52 +02:00
|
|
|
{
|
2024-07-27 14:57:51 +03:00
|
|
|
output.WriteLine(
|
2024-07-12 15:51:52 +02:00
|
|
|
nameof(Given_a_LinearExpr_and_a_solution_When_SolutionValue_is_called_then_the_result_is_correct));
|
|
|
|
|
Solver solver = Solver.CreateSolver("glop");
|
|
|
|
|
// x, y and z are fixed; we don't want to test the solver here.
|
|
|
|
|
Variable x = solver.MakeIntVar(3, 3, "x");
|
|
|
|
|
Variable y = solver.MakeIntVar(4, 4, "y");
|
|
|
|
|
Variable z = solver.MakeIntVar(5, 5, "z");
|
|
|
|
|
|
|
|
|
|
LinearExpr part1 = x * 2; // 6
|
|
|
|
|
LinearExpr part2 = y * 3 + z + 4; // 21
|
|
|
|
|
LinearExpr objective = part1 + part2; // 27
|
|
|
|
|
LinearExpr anew = new();
|
|
|
|
|
solver.Maximize(objective);
|
|
|
|
|
solver.Solve();
|
|
|
|
|
Assert.Equal(27, objective.SolutionValue(), precision: 9);
|
|
|
|
|
Assert.Equal(6, part1.SolutionValue(), precision: 9);
|
|
|
|
|
Assert.Equal(21, part2.SolutionValue(), precision: 9);
|
|
|
|
|
Assert.Equal(0, anew.SolutionValue(), precision: 9);
|
|
|
|
|
Assert.Equal(27, (objective + anew).SolutionValue(), precision: 9);
|
2023-06-28 18:23:48 +02:00
|
|
|
}
|
2024-07-12 15:51:52 +02:00
|
|
|
}
|
2020-11-03 10:04:19 +01:00
|
|
|
} // namespace Google.OrTools.Tests
|