MathModelSolution Class

Solution of a MathModel by a solver such as [!:Cplex2] or [!:Scip2].

It provides meta information such as solution status and objectiev function value. Further, it allows to access solution values of the decision variables.

# Case 1: Feasible The following example demonstrates a feasible solution case on a trivial model.
C#
Set i = Set("i").HasElementsUntil(3); // { 0, 1, 2 }
Set j = Set("j").HasElementsUntil(4); // { 0, 1, 2, 3 }
VarD2 y = Variable("y").HasIndices(i, j).IsBinary();
Objective maxCount = maximize | sum(over(i, j), y[i, j]);
MathModel model = MathModel.New("dummy model").WithObjective(maxCount).HasNoConstraints();

Cplex solver = new();
CplexParams pars = new();
var resSolution = await solver.Solve(model, pars);
var solution = resSolution.Unwrap(); // normally, check if it is 'IsOk' before unwrapping!

// solution status currently depends on the used solver
Assert.Equal("integer optimal solution", solution.SolutionStatus);

double objFunValue = solution.ObjectiveValue.Unwrap(); // must be okay to Unwrap since status is 'integer optimal'.
Assert.Equal(12, objFunValue);

// ySoln is a map of indices to solution values;
// allows access to solution values of decision variables through indices.
// since y is of type VarD2, it has two indices for i and j.
Dictionary<(int, int), double> ySoln = solution.VarIndicesAndValuesOf(y).Unwrap();
Assert.Equal(1, y[(0, 0)];
Assert.Equal(1, y[(2, 3)];
Assert.False(ySoln.ContainsKey((4, 5)); // y(4, 5) is not a variable of the model, check elements of i and j.
# Case 2: Infeasible The following example demonstrates when a model is infeasible due to a trivially impossible constraint.
C#
Set i = Set("i").HasElementsUntil(3); // { 0, 1, 2 }
Set j = Set("j").HasElementsUntil(4); // { 0, 1, 2, 3 }
VarD2 y = Variable("y").HasIndices(i, j).IsBinary();
Objective maxCount = maximize | sum(over(i, j), y[i, j]);
Constraint impossible = sum(over(i, j), y[i, j]) >= 100;
MathModel model = MathModel.New("dummy model").WithObjective(maxCount).HasConstraints(impossible);

Scip solver = new();
ScipParams pars = new();
var resSolution = await solver.Solve(model, pars);
var solution = resSolution.Unwrap(); // normally, check if it is 'IsOk' before unwrapping!

// solution status currently depends on the used solver
Assert.Equal("infeasible", solution.SolutionStatus);

// at this point we also know that objective function value and variables' values are not available (None):
Assert.Equal(solution.ObjectiveValue.IsNone);
Assert.Equal(solution.VarIndicesAndValuesOf(y).IsNone);
# Case 3: An error occurred with the solver

An easy way to simulate this is to force a wrong path for the solver. In reality, different problems might cause the solver to fail such as out-of-memory problem.

C#
Set i = Set("i").HasElementsUntil(3); // { 0, 1, 2 }
Set j = Set("j").HasElementsUntil(4); // { 0, 1, 2, 3 }
VarD2 y = Variable("y").HasIndices(i, j).IsBinary();
Objective maxCount = maximize | sum(over(i, j), y[i, j]);
MathModel model = MathModel.New("dummy model").WithObjective(maxCount).HasNoConstraints();

Cplex solver = new("wrong path");
var resSolution = await solver.Solve(model);

Assert.True(resSolution.IsErr); // "resSolution.Unwrap()" would've thrown an exception here; better to check before unwrapping
Assert.True(resSolution.ErrorMessage().Unwrap().Contains("wrong path")); // the error message provides detailes about why the solver failed.

Definition

Namespace: Orx.MathProg.Solvers
Assembly: Orx.MathProg (in Orx.MathProg.dll) Version: 1.0.0
C#
public class MathModelSolution
Inheritance
Object    MathModelSolution

Properties

IsFeasible Returns whether or not the solution is feasible.
NumVariablesSol Returns the number of variables read from the solution of the model.
NumVariablesSolNonZero Returns the number of variables with a non-zero value that are read from the solution of the model.

Methods

Equals
(Inherited from Object)
Finalize
(Inherited from Object)
GetHashCode
(Inherited from Object)
GetType
(Inherited from Object)
MemberwiseClone
(Inherited from Object)
Summary Returns text summarizing the solution. For instance:
C#
var resSolution = await solver.Solve(model, pars);
MathModelSolution solution = resSolution.Unwrap(); // normally, check if it is 'IsOk' before unwrapping!
Console.WriteLine(solution.Summary());
logs the following to the console:
C#
model                      : dummy model
solution exists            ? True
status                     : integer optimal solution
objective value            : Some(12)
# variables (lp)           : 12
# variables (sol)          : 12
# non-zero variables (sol) : 12
ToString
(Inherited from Object)
ValueOf Returns Some of the value of the 0-dimensional variable provided that:
  • the solution IsFeasible, and
  • the queried var belongs to the solved model.
Returns None otherwise.
C#
VarD0 fitness = Variable("fit").IsBinary(); // irrelevant to the model
VarD0 utility = Variable("util").IsBinary();
Objective maxUtility = maximize | utility;
MathModel model = MathModel.New().WithObjective(maxUtility).HasNoConstraints();
Scip solver = new();
var resSolution = await solver.Solve(model);
MathModelSolution solution = resSolution.Unwrap(); // normally, check if it is 'IsOk' before unwrapping!

var valUtility = solution.ValueOf(utility);
Assert.Equal(Some(1), valUtility); // alternatively:
Assert.True(valUtility.IsSome);
Assert.True(1, valUtility.Unwrap());

var valFitness = solution.ValueOf(fitness);
Assert.True(valFitness.IsNone); // "valFitness.Unwrap()" would've thrown!
VarIndicesAndValuesOf(VarD1) Returns Some of a map of indices to solution values of 1-dimensional variable provided that:
  • the solution IsFeasible, and
  • the queried var belongs to the solved model.
Returns None otherwise.
C#
Set i = Set("i").HasElementsUntil(3); // { 0, 1, 2 }
VarD1 x = Variable("x").HasIndices(i).IsBinary();
Objective maxXs = maximize | sum(over(i), x[i]);
MathModel model = MathModel.New().WithObjective(maxXs).HasNoConstraints();
Cplex solver = new();
var resSolution = await solver.Solve(model);
MathModelSolution solution = resSolution.Unwrap(); // normally, check if it is 'IsOk' before unwrapping!

VarD1 y = Variable("y").HasIndices(i).IsBinary(); // irrelevant to the model

var maybeXSoln = solution.VarIndicesAndValuesOf(x);
Assert.True(maybeXSoln.IsSome);

Dictionary<int, double> xSoln = maybeXSoln.Unwrap(); // a map from indices of x to the values in the solution
Assert.Equal(1, xSoln[0]);
Assert.Equal(1, xSoln[1]);
Assert.Equal(1, xSoln[2]);
Assert.False(xSoln.ContainsKey(3)); // x(3) is not a part of the model and solution

var maybeYSoln = solution.VarIndicesAndValuesOf(y); // y is not a part of this solution
Assert.True(maybeYSoln.IsNone); // "maybeYSoln.Unwrap()" would've thrown!
VarIndicesAndValuesOf(VarD2) Returns Some of a map of indices to solution values of 2-dimensional variable provided that:
  • the solution IsFeasible, and
  • the queried var belongs to the solved model.
Returns None otherwise.
C#
Set i = Set("i").HasElementsUntil(2); // { 0, 1 }
Set j = Set("j").HasElementsUntil(3); // { 0, 1, 2 }
VarD2 x = Variable("x").HasIndices(i, j).IsBinary();
Objective maxCount = maximize | sum(over(i, j), x[i, j]);
MathModel model = MathModel.New().WithObjective(maxCount).HasNoConstraints();
Cplex solver = new();
var resSolution = await solver.Solve(model);
MathModelSolution solution = resSolution.Unwrap(); // normally, check if it is 'IsOk' before unwrapping!

VarD2 y = Variable("y").HasIndices(i, j).IsBinary(); // irrelevant to the model

var maybeXSoln = solution.VarIndicesAndValuesOf(x);
Assert.True(maybeXSoln.IsSome);

Dictionary<(int, int), double> xSoln = maybeXSoln.Unwrap(); // a map from indices of x to the values in the solution
Assert.Equal(1, xSoln[(0, 0)]);
Assert.Equal(1, xSoln[(0, 1)]);
Assert.Equal(1, xSoln[(0, 2)]);
Assert.Equal(1, xSoln[(1, 0)]);
Assert.Equal(1, xSoln[(1, 1)]);
Assert.Equal(1, xSoln[(1, 2)]);
Assert.False(xSoln.ContainsKey((1, 3))); // x(1, 3) is not a part of the model and solution

var maybeYSoln = solution.VarIndicesAndValuesOf(y); // y is not a part of this solution
Assert.True(maybeYSoln.IsNone); // "maybeYSoln.Unwrap()" would've thrown!
VarIndicesAndValuesOf(VarD3) Returns Some of a map of indices to solution values of 3-dimensional variable provided that:
  • the solution IsFeasible, and
  • the queried var belongs to the solved model.
Returns None otherwise.

See VarIndicesAndValuesOf(VarD2) for a documentation corresponding to two-index variables.

Fields

ObjectiveValue Objective function value of the solution:
  • Some of the objective function value if the model is IsFeasible,
  • None otherwise.
Underlying value can be unwrapped,
C#
double objValue = solution.ObjectiveValue.Unwrap();
provided that "solution.IsFeasible" or equivalantly "solution.ObjectiveValue.IsSome".
SolutionStatus Status of the solution. Value of this text field depends on the solver used to create the solution.

See Also