'Use a method as an objective in Optano Modelling
I'm trying to use Optano Modelling (with a GLPK solver) in C# to minimise a function. The objective function is not a straightforward formula but a series of calculations in a method that returns a single number (in this case, the variance of a dataset, but there are other things I need to solve for as well that require methods). I want to be able to pass this method in as the objective.
I was able to do this with Microsoft.Solver.Foundation, but that's a) ten years out of support, b) restricted in scale by the license and c) I'm pretty sure there's a bug in that breaks one of my models.
My Optano setup is as follows.
using (ModelScope modelScope = new ModelScope())
{
OPTANO.Modeling.Optimization.Model model = new OPTANO.Modeling.Optimization.Model();
foreach (KeyValuePair<string, decimal> weight in Weights)
{
model.AddVariable(new Variable(weight.Key, 0, 1, VariableType.Continuous));
}
model.AddConstraint(Expression.Sum(model.Variables) == 1);
model.AddObjective(new Objective(Expression.Sum(GetResult(model.Variables.ToArray())), "MinimumResult", ObjectiveSense.Minimize));
List<double> GetResult(Variable[] variables)
{
//*****Calculate stuff*****
return result;//Return a List<double> containing a single element.
}
using (GLPKSolver solver = new GLPKSolver())
{
var solution = solver.Solve(model);
if (solution.ModelStatus == OPTANO.Modeling.Optimization.Solver.ModelStatus.Feasible)
{
Console.WriteLine("Minimum result: " + solution.GetObjectiveValue("MinimumResult"));
Console.WriteLine("\nWeights:");
foreach (KeyValuePair<string, double> solvedValue in solution.VariableValues)
{
Console.WriteLine(solvedValue);
}
}
}
}
If I return a double from the GetResult() method, there's a type conflict because AddObjective() expects an Objective, which itself expects an expression. However, Expression.Sum() takes a List and returns an Expression, which is why I pass a single-length List to it, and pass that in turn to a new Objective.
Whatever I do, it always minimises the variance to 0 and returns the variables (of which there are 5) with one being equal to 1 and the rest 0. I know what the actual result should be from Excel Solver (only two of them should be zero and the variance should be 0.032).
So the question is, how can I get the solver to minimise the result of the GetResult() method?
Solution 1:[1]
A couple caveats: I don't know Optano framework, and not much C#, but I am familiar with the solver you are using. I think you have a misconception regarding the construction of a model...
The solver needs an expression that it can evaluate an arbitrary number of times. It does not have access to your magic GetResult function. Optano is just building an expression that the solver can evaluate an arbitrary number of times internally, so it isn't possible to do some arbitrarily complicated math in a function and return a number, and pass along that number as the objective value.
So, you need to build an expression in the Optano framework and return that, which should just be simple math performed on variables and constants in the model...
Perhaps there is a way to print your model before you try to solve it to verify that you have a good expression?
Solution 2:[2]
"The objective function is not a straightforward formula but a series of calculations in a method that returns a single number (in this case, the variance of a dataset, but there are other things I need to solve for as well that require methods)." I hope you realize that GLPK is only for linear models.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | AirSquid |
| Solution 2 | Erwin Kalvelagen |
