From 5fa6f76cab901684d667a0a63844914b157d1251 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Sun, 5 Nov 2023 19:18:48 +0100 Subject: [PATCH] ModelBuilder C# class -> Model, ModelSolver c# class -> Solver to avoir name conflict between the class and the namespace --- ortools/linear_solver/csharp/ModelBuilder.cs | 20 +++--- .../csharp/ModelBuilderConstraint.cs | 2 +- .../linear_solver/csharp/ModelBuilderTests.cs | 65 +++++++++++++++++++ ortools/linear_solver/csharp/ModelSolver.cs | 34 +++++----- ortools/linear_solver/samples/AssignmentMb.cs | 4 +- ortools/linear_solver/samples/BinPackingMb.cs | 4 +- ortools/linear_solver/samples/CloneModelMb.cs | 6 +- .../samples/SimpleLpProgramMb.cs | 4 +- .../samples/SimpleMipProgramMb.cs | 4 +- 9 files changed, 104 insertions(+), 39 deletions(-) create mode 100644 ortools/linear_solver/csharp/ModelBuilderTests.cs diff --git a/ortools/linear_solver/csharp/ModelBuilder.cs b/ortools/linear_solver/csharp/ModelBuilder.cs index 39925942bd..ca1c2f54b2 100644 --- a/ortools/linear_solver/csharp/ModelBuilder.cs +++ b/ortools/linear_solver/csharp/ModelBuilder.cs @@ -26,13 +26,13 @@ using Google.Protobuf.Collections; /// Main modeling class. /// /// -/// 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 { /// /// Main constructor. /// - public ModelBuilder() + public Model() { helper_ = new ModelBuilderHelper(); constantMap_ = new Dictionary(); @@ -44,9 +44,9 @@ public class ModelBuilder /// Returns a cloned model. /// /// A deep copy of the model. - public ModelBuilder Clone() + public Model Clone() { - ModelBuilder clonedModel = new ModelBuilder(); + Model clonedModel = new Model(); clonedModel.Helper.OverwriteModel(Helper); foreach (KeyValuePair entry in constantMap_) { @@ -197,8 +197,8 @@ public class ModelBuilder /// Adds an enforced Linear constraint to the model. /// /// A bounded linear expression - /// The indicator value of the constraint. + /// The indicator variable of the constraint. + /// The indicator value of the constraint. /// A linear expression /// Throw when the constraint is not supported by the linear solver 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 term in dict) { helper_.AddEnforcedConstraintTerm(lin.Index, term.Key, term.Value); diff --git a/ortools/linear_solver/csharp/ModelBuilderConstraint.cs b/ortools/linear_solver/csharp/ModelBuilderConstraint.cs index 7f90260111..6059c9a10b 100644 --- a/ortools/linear_solver/csharp/ModelBuilderConstraint.cs +++ b/ortools/linear_solver/csharp/ModelBuilderConstraint.cs @@ -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) diff --git a/ortools/linear_solver/csharp/ModelBuilderTests.cs b/ortools/linear_solver/csharp/ModelBuilderTests.cs new file mode 100644 index 0000000000..58eb0bbfbc --- /dev/null +++ b/ortools/linear_solver/csharp/ModelBuilderTests.cs @@ -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 diff --git a/ortools/linear_solver/csharp/ModelSolver.cs b/ortools/linear_solver/csharp/ModelSolver.cs index 13e20f1f60..4adf539927 100644 --- a/ortools/linear_solver/csharp/ModelSolver.cs +++ b/ortools/linear_solver/csharp/ModelSolver.cs @@ -25,11 +25,11 @@ using Google.Protobuf.Collections; /// /// Model solver class /// -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. /// /// the name of the solver backend - public ModelSolver(String solverName) + public Solver(String solverName) { this.helper_ = new ModelSolverHelper(solverName); this.logCallback_ = null; @@ -49,7 +49,7 @@ public class ModelSolver /// /// the model to solve /// the status of the solve - public SolveStatus Solve(ModelBuilder model) + public SolveStatus Solve(Model model) { if (logCallback_ == null) { @@ -125,7 +125,7 @@ public class ModelSolver } /// - /// 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. /// 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 } /// - /// 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. /// 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 } /// - /// 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. /// 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); } /// - /// 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. /// 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); } /// - /// 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. /// 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); } /// - /// 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. /// 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); diff --git a/ortools/linear_solver/samples/AssignmentMb.cs b/ortools/linear_solver/samples/AssignmentMb.cs index 52e2195f03..5fbeb34b30 100644 --- a/ortools/linear_solver/samples/AssignmentMb.cs +++ b/ortools/linear_solver/samples/AssignmentMb.cs @@ -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] diff --git a/ortools/linear_solver/samples/BinPackingMb.cs b/ortools/linear_solver/samples/BinPackingMb.cs index cee853d690..3c9c159ffe 100644 --- a/ortools/linear_solver/samples/BinPackingMb.cs +++ b/ortools/linear_solver/samples/BinPackingMb.cs @@ -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] diff --git a/ortools/linear_solver/samples/CloneModelMb.cs b/ortools/linear_solver/samples/CloneModelMb.cs index f4c79a24ac..33cb558593 100644 --- a/ortools/linear_solver/samples/CloneModelMb.cs +++ b/ortools/linear_solver/samples/CloneModelMb.cs @@ -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] diff --git a/ortools/linear_solver/samples/SimpleLpProgramMb.cs b/ortools/linear_solver/samples/SimpleLpProgramMb.cs index 96773513f5..67d70dfc9f 100644 --- a/ortools/linear_solver/samples/SimpleLpProgramMb.cs +++ b/ortools/linear_solver/samples/SimpleLpProgramMb.cs @@ -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; diff --git a/ortools/linear_solver/samples/SimpleMipProgramMb.cs b/ortools/linear_solver/samples/SimpleMipProgramMb.cs index e3f8875d7b..b14253f28a 100644 --- a/ortools/linear_solver/samples/SimpleMipProgramMb.cs +++ b/ortools/linear_solver/samples/SimpleMipProgramMb.cs @@ -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;