ModelBuilder C# class -> Model, ModelSolver c# class -> Solver to avoir name conflict between the class and the namespace

This commit is contained in:
Laurent Perron
2023-11-05 19:18:48 +01:00
parent 54843e4f9b
commit 5fa6f76cab
9 changed files with 104 additions and 39 deletions

View File

@@ -26,13 +26,13 @@ using Google.Protobuf.Collections;
/// Main modeling class.
/// </summary>
///
/// Proposes a factory to create all modeling objects understood by the ModelSolver.
public class ModelBuilder
/// Proposes a factory to create all modeling objects understood by the Solver.
public class Model
{
/// <summary>
/// Main constructor.
/// </summary>
public ModelBuilder()
public Model()
{
helper_ = new ModelBuilderHelper();
constantMap_ = new Dictionary<double, int>();
@@ -44,9 +44,9 @@ public class ModelBuilder
/// Returns a cloned model.
/// </summary>
/// <returns>A deep copy of the model.</returns>
public ModelBuilder Clone()
public Model Clone()
{
ModelBuilder clonedModel = new ModelBuilder();
Model clonedModel = new Model();
clonedModel.Helper.OverwriteModel(Helper);
foreach (KeyValuePair<double, int> entry in constantMap_)
{
@@ -197,8 +197,8 @@ public class ModelBuilder
/// Adds an enforced Linear constraint to the model.
/// </summary>
/// <param name="lin">A bounded linear expression</param>
/// <param name="iVar>The indicator variable of the constraint.</param>
/// <param name="iValue>The indicator value of the constraint.</param>
/// <param name="iVar">The indicator variable of the constraint.</param>
/// <param name="iValue">The indicator value of the constraint.</param>
/// <returns>A linear expression</returns>
/// <exception cref="ArgumentException">Throw when the constraint is not supported by the linear solver</exception>
public EnforcedLinearConstraint AddEnforced(BoundedLinearExpression lin, Variable iVar, bool iValue)
@@ -232,12 +232,12 @@ public class ModelBuilder
public EnforcedLinearConstraint AddEnforcedLinearConstraint(LinearExpr expr, double lb, double ub, Variable iVar,
bool iValue)
{
var dict = tmp_var_value_map_;
dict.Clear();
double offset = LinearExpr.GetVarValueMap(expr, dict, tmp_terms_);
EnforcedLinearConstraint lin = new EnforcedLinearConstraint(helper_);
lin.IndicatorVariable = iVar;
lin.IndicatorValue = iValue;
var dict = tmp_var_value_map_;
dict.Clear();
double offset = LinearExpr.GetVarValueMap(expr, dict, tmp_terms_);
foreach (KeyValuePair<int, double> term in dict)
{
helper_.AddEnforcedConstraintTerm(lin.Index, term.Key, term.Value);

View File

@@ -148,7 +148,7 @@ public class EnforcedLinearConstraint
public EnforcedLinearConstraint(ModelBuilderHelper helper)
{
helper_ = helper;
index_ = helper_.AddLinearConstraint();
index_ = helper_.AddEnforcedLinearConstraint();
}
public EnforcedLinearConstraint(ModelBuilderHelper helper, int index)

View File

@@ -0,0 +1,65 @@
// Copyright 2010-2022 Google LLC
// 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.
using System;
using System.Collections.Generic;
using Xunit;
using Google.OrTools.ModelBuilder;
namespace Google.OrTools.Tests
{
public class ModelBuilderTest
{
[Fact]
public void BasicApiTest()
{
Model model = new Model();
Variable v1 = model.NewIntVar(-10, 10, "v1");
Variable v2 = model.NewIntVar(-10, 10, "v2");
Variable v3 = model.NewIntVar(-100000, 100000, "v3");
model.AddLinearConstraint(v1 + v2, -1000000, 100000);
model.AddLinearConstraint(v1 + 2 * v2 - v3, 0, 100000);
model.Maximize(v3);
Solver solver = new Solver("scip");
SolveStatus status = solver.Solve(model);
Assert.Equal(SolveStatus.OPTIMAL, status);
Assert.Equal(30, solver.ObjectiveValue);
Assert.Equal(10, solver.Value(v1));
Assert.Equal(10, solver.Value(v2));
Assert.Equal(30, solver.Value(v3));
}
[Fact]
public void EnforcedLinearApiTest()
{
Model model = new Model();
model.Name = "minimal enforced linear test";
double infinity = double.PositiveInfinity;
Variable x = model.NewNumVar(0.0, infinity, "x");
Variable y = model.NewNumVar(0.0, infinity, "y");
Variable z = model.NewBoolVar("z");
Assert.Equal(3, model.VariablesCount());
EnforcedLinearConstraint c0 = model.AddEnforced(x + 2 * y >= 10.0, z, false);
// Assert.Equal(1, model.ConstraintsCount());
// Assert.Equal(10.0, c0.LowerBound);
// Assert.Equal(c0.IndicatorVariable.Index, z.Index);
// Assert.False(c0.IndicatorValue);
}
}
} // namespace Google.OrTools.Tests

View File

@@ -25,11 +25,11 @@ using Google.Protobuf.Collections;
/// <summary>
/// Model solver class
/// </summary>
public class ModelSolver
public class Solver
{
class ModelSolverException : Exception
class SolverException : Exception
{
public ModelSolverException(String methodName, String msg) : base(methodName + ": " + msg)
public SolverException(String methodName, String msg) : base(methodName + ": " + msg)
{
}
}
@@ -38,7 +38,7 @@ public class ModelSolver
/// Creates the solver with the supplied solver backend.
/// </summary>
/// <param name="solverName">the name of the solver backend</param>
public ModelSolver(String solverName)
public Solver(String solverName)
{
this.helper_ = new ModelSolverHelper(solverName);
this.logCallback_ = null;
@@ -49,7 +49,7 @@ public class ModelSolver
/// </summary>
/// <param name="model">the model to solve</param>
/// <returns>the status of the solve</returns>
public SolveStatus Solve(ModelBuilder model)
public SolveStatus Solve(Model model)
{
if (logCallback_ == null)
{
@@ -125,7 +125,7 @@ public class ModelSolver
}
/// <summary>
/// The best objective value found during search. This raises a ModelSolverException is no solution has been found,
/// The best objective value found during search. This raises a SolverException is no solution has been found,
/// or if Solve() has not been called.
/// </summary>
public double ObjectiveValue
@@ -133,7 +133,7 @@ public class ModelSolver
get {
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.ObjectiveValue",
throw new SolverException("Solver.ObjectiveValue",
"Solve() was not called or no solution was found");
}
return helper_.ObjectiveValue();
@@ -141,7 +141,7 @@ public class ModelSolver
}
/// <summary>
/// The best objective bound found during search. This raises a ModelSolverException is no solution has been found,
/// The best objective bound found during search. This raises a SolverException is no solution has been found,
/// or if Solve() has not been called.
/// </summary>
public double BestObjectiveBound
@@ -149,7 +149,7 @@ public class ModelSolver
get {
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.BestObjectiveBound",
throw new SolverException("Solver.BestObjectiveBound",
"Solve() was not called or no solution was found");
}
return helper_.BestObjectiveBound();
@@ -157,54 +157,54 @@ public class ModelSolver
}
/// <summary>
/// The value of a variable in the current solution. This raises a ModelSolverException is no solution has been
/// The value of a variable in the current solution. This raises a SolverException is no solution has been
/// found, or if Solve() has not been called.
/// </summary>
public double Value(Variable var)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.Value())", "Solve() was not called or no solution was found");
throw new SolverException("Solver.Value())", "Solve() was not called or no solution was found");
}
return helper_.VariableValue(var.Index);
}
/// <summary>
/// The reduced cost of a variable in the current solution. This raises a ModelSolverException is no solution has
/// The reduced cost of a variable in the current solution. This raises a SolverException is no solution has
/// been found, or if Solve() has not been called.
/// </summary>
public double ReducedCost(Variable var)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.ReducedCost())",
throw new SolverException("Solver.ReducedCost())",
"Solve() was not called or no solution was found");
}
return helper_.ReducedCost(var.Index);
}
/// <summary>
/// The dual value of a linear constraint in the current solution. This raises a ModelSolverException is no solution
/// The dual value of a linear constraint in the current solution. This raises a SolverException is no solution
/// has been found, or if Solve() has not been called.
/// </summary>
public double DualValue(LinearConstraint ct)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.DualValue())",
throw new SolverException("Solver.DualValue())",
"Solve() was not called or no solution was found");
}
return helper_.DualValue(ct.Index);
}
/// <summary>
/// The activity of a constraint in the current solution. This raises a ModelSolverException is no solution has been
/// The activity of a constraint in the current solution. This raises a SolverException is no solution has been
/// found, or if Solve() has not been called.
/// </summary>
public double Activity(LinearConstraint ct)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.Activity())",
throw new SolverException("Solver.Activity())",
"Solve() was not called or no solution was found");
}
return helper_.Activity(ct.Index);

View File

@@ -31,7 +31,7 @@ public class AssignmentMb
// [END data_model]
// [START model]
ModelBuilder model = new ModelBuilder();
Model model = new Model();
// [END model]
// Variables.
@@ -88,7 +88,7 @@ public class AssignmentMb
// [START solver]
// Create the solver with the SCIP backend and check it is supported.
ModelSolver solver = new ModelSolver("SCIP");
Solver solver = new Solver("SCIP");
if (!solver.SolverIsSupported())
return;
// [END solver]

View File

@@ -37,7 +37,7 @@ public class BinPackingMb
// [END program_part1]
// [START model]
ModelBuilder model = new ModelBuilder();
Model model = new Model();
// [END model]
// [START program_part2]
@@ -85,7 +85,7 @@ public class BinPackingMb
// [START solver]
// Create the solver with the SCIP backend and check it is supported.
ModelSolver solver = new ModelSolver("SCIP");
Solver solver = new Solver("SCIP");
if (!solver.SolverIsSupported())
return;
// [END solver]

View File

@@ -24,7 +24,7 @@ public class SimpleMipProgramMb
{
// [START model]
// Create the model builder.
ModelBuilder model = new ModelBuilder();
Model model = new Model();
// [END model]
// [START variables]
@@ -49,7 +49,7 @@ public class SimpleMipProgramMb
// [Start clone]
// Clone the model.
Console.WriteLine("Cloning the model");
ModelBuilder modelCopy = model.Clone();
Model modelCopy = model.Clone();
Variable xCopy = modelCopy.VarFromIndex(x.Index);
Variable yCopy = modelCopy.VarFromIndex(y.Index);
Variable zCopy = modelCopy.NewBoolVar("z");
@@ -67,7 +67,7 @@ public class SimpleMipProgramMb
// [START solver]
// Create the solver with the CP-SAT backend and checks it is supported.
ModelSolver solver = new ModelSolver("sat");
Solver solver = new Solver("sat");
if (!solver.SolverIsSupported())
return;
// [END solver]

View File

@@ -24,7 +24,7 @@ public class SimpleLpProgramMb
{
// [START model]
// Create the model builder.
ModelBuilder model = new ModelBuilder();
Model model = new Model();
// [END model]
// [START variables]
@@ -52,7 +52,7 @@ public class SimpleLpProgramMb
// [START solver]
// Create the model solver with the GLOP backend.
ModelSolver solver = new ModelSolver("GLOP");
Solver solver = new Solver("GLOP");
if (!solver.SolverIsSupported())
{
return;

View File

@@ -24,7 +24,7 @@ public class SimpleMipProgramMb
{
// [START model]
// Create the model builder.
ModelBuilder model = new ModelBuilder();
Model model = new Model();
// [END model]
// [START variables]
@@ -52,7 +52,7 @@ public class SimpleMipProgramMb
// [START solver]
// Create the model solver with the SCIP backend.
ModelSolver solver = new ModelSolver("SCIP");
Solver solver = new Solver("SCIP");
if (!solver.SolverIsSupported())
{
return;