Skip to content

Commit

Permalink
add nearly finished ModelSolver C# class
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Oct 31, 2023
1 parent 183bff7 commit 07d3a2a
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 22 deletions.
9 changes: 5 additions & 4 deletions ortools/linear_solver/csharp/ModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,16 +235,17 @@ public void Maximize(LinearExpr obj)
public void Optimize(LinearExpr obj, bool maximize)
{
helper_.ClearObjective();
double offset = LinearExpr.GetVarValueMap(expr, dict, terms_);
LinearConstraint lin = new LinearConstraint(helper_);
var dict = var_value_map_;
dict.Clear();
double offset = LinearExpr.GetVarValueMap(obj, dict, terms_);
foreach (KeyValuePair<int, double> term in dict)
{
if (term.Value != 0.0)
{
helper_.setVarObjectiveCoefficient(term.Key, term.Value);
helper_.SetVarObjectiveCoefficient(term.Key, term.Value);
}
}
helper_.SetObjectiveOffset(e.getOffset());
helper_.SetObjectiveOffset(offset);
helper_.SetMaximize(maximize);
}

Expand Down
39 changes: 21 additions & 18 deletions ortools/linear_solver/csharp/ModelBuilderExpr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ namespace Google.OrTools.ModelBuilder

internal static class HelperExtensions
{
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public static void AddOrIncrement(this SortedDictionary<int, double> dict, int key, double increment)
// {
// #if NET6_0_OR_GREATER
// System.Runtime.InteropServices.CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out _) += increment;
// #else
// if (dict.TryGetValue(key, out var value))
// {
// dict[key] = value + increment;
// }
// else
// {
// dict.Add(key, increment);
// }
// #endif
// }
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public static void AddOrIncrement(this SortedDictionary<int, double> dict, int key, double increment)
// {
// #if NET6_0_OR_GREATER
// System.Runtime.InteropServices.CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out _) += increment;
// #else
// if (dict.TryGetValue(key, out var value))
// {
// dict[key] = value + increment;
// }
// else
// {
// dict.Add(key, increment);
// }
// #endif
// }

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void TrySetCapacity<TField, TValues>(this RepeatedField<TField> field, IEnumerable<TValues> values)
Expand Down Expand Up @@ -281,9 +281,12 @@ internal static double GetVarValueMap(LinearExpr e, SortedDictionary<int, double
}
break;
case Variable var:
if (dict.TryGetValue(var.Index, out var c)) {
if (dict.TryGetValue(var.Index, out var c))
{
dict[var.Index] = c + coefficient;
} else {
}
else
{
dict.Add(var.Index, coefficient);
}
break;
Expand Down
211 changes: 211 additions & 0 deletions ortools/linear_solver/csharp/ModelSolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// 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.

namespace Google.OrTools.ModelBuilder
{

using Google.OrTools.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Google.Protobuf.Collections;

/** Model solver class */
public class ModelSolver
{
class ModelSolverException : Exception
{
public ModelSolverException(String methodName, String msg) : base(methodName + ": " + msg)
{
}
}

/** Creates the solver with the supplied solver backend. */
public ModelSolver(String solverName)
{
this.helper_ = new ModelSolverHelper(solverName);
this.logCallback_ = null;
}

/** Solves given model, and returns the status of the response. */
public SolveStatus solve(ModelBuilder model)
{
if (logCallback_ == null)
{
helper_.ClearLogCallback();
}
else
{
helper_.SetLogCallbackFromDirectorClass(logCallback_);
}
helper_.Solve(model.Helper);
if (!helper_.HasResponse())
{
return SolveStatus.UNKNOWN_STATUS;
}
return helper_.Status();
}

/** Enables or disables the underlying solver output. */
public void EnableOutput(bool enable)
{
helper_.EnableOutput(enable);
}

/** Sets the time limit for the solve in seconds. */
// public void SetTimeLimit(Duration limit)
// {
// helper_.SetTimeLimitInSeconds((double)limit.toMillis() / 1000.0);
// }

/** Sets solver specific parameters as string. */
public void SetSolverSpecificParameters(String parameters)
{
helper_.SetSolverSpecificParameters(parameters);
}

/** Returns whether solver specified during the ctor was found and correctly installed. */
public bool SolverIsSupported()
{
return helper_.SolverIsSupported();
}

/** Tries to interrupt the solve. Returns true if the feature is supported. */
public bool InterruptSolve()
{
return helper_.InterruptSolve();
}

/** Returns true if solve() was called, and a response was returned. */
public bool HasResponse()
{
return helper_.HasResponse();
}

/** Returns true if solve() was called, and a solution was returned. */
public bool HasSolution()
{
return helper_.HasSolution();
}

/** Checks that the solver has found a solution, and returns the objective value. */
public double ObjectiveValue
{
get {
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.getObjectiveValue()",
"solve() was not called or no solution was found");
}
return helper_.ObjectiveValue();
}
}

/** Checks that the solver has found a solution, and returns the objective value. */
public double BestObjectiveBound
{
get {
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.getBestObjectiveBound()",
"solve() was not called or no solution was found");
}
return helper_.BestObjectiveBound();
}
}

/** Checks that the solver has found a solution, and returns the value of the given variable. */
public double Value(Variable var)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.getValue())",
"solve() was not called or no solution was found");
}
return helper_.VariableValue(var.Index);
}
/**
* Checks that the solver has found a solution, and returns the reduced cost of the given
* variable.
*/
public double ReducedCost(Variable var)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.getReducedCost())",
"solve() was not called or no solution was found");
}
return helper_.ReducedCost(var.Index);
}

/**
* Checks that the solver has found a solution, and returns the dual value of the given
* constraint.
*/
public double DualValue(LinearConstraint ct)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.getDualValue())",
"solve() was not called or no solution was found");
}
return helper_.DualValue(ct.Index);
}

/**
* Checks that the solver has found a solution, and returns the activity of the given constraint.
*/
public double Activity(LinearConstraint ct)
{
if (!helper_.HasSolution())
{
throw new ModelSolverException("ModelSolver.getActivity())",
"solve() was not called or no solution was found");
}
return helper_.Activity(ct.Index);
}

/** Sets the log callback for the solver. */
public LogCallback LogCallback
{
get {
return logCallback_;
}
set {
logCallback_ = value;
}
}

/** Returns the elapsed time since the creation of the solver. */
public double WallTime
{
get {
return helper_.WallTime();
}
}

/** Returns the user time since the creation of the solver. */
public double UserTime
{
get {
return helper_.UserTime();
}
}

private ModelSolverHelper helper_;
private LogCallback logCallback_;
}

} // namespace Google.OrTools.ModelBuilder

0 comments on commit 07d3a2a

Please sign in to comment.