我试图在C#中使用Optano建模(使用GLPK求解器)来最小化一个函数。目标函数不是一个直截了当的公式,而是返回单个数字的方法中的一系列计算(在这种情况下,数据集的方差,但是还有其他需要方法解决的问题)。我希望能够把这种方法作为目标。
我能够在Microsoft.Solver.Foundation中做到这一点,但这是( a)十年的不支持,b)许可证的限制,c)我很确定有一个错误破坏了我的一个模型。
我的Optano设置如下所示。
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);
}
}
}
}如果我从GetResult()方法返回一个double,就会出现类型冲突,因为AddObjective()需要一个目标,而目标本身需要一个表达式。但是,Expression.Sum()接受一个列表并返回一个表达式,这就是为什么我将一个单长度的列表传递给它,然后将它传递给一个新的目标。
无论我做什么,它总是将方差最小化到0,并返回变量(其中有5),其中一个等于1,其余的等于0。我知道Excel的实际结果应该是什么(其中只有两个应该是零,方差应该是0.032)。
因此,问题是,如何使求解器最小化GetResult()方法的结果?
发布于 2022-03-11 22:05:12
几个注意事项:我不知道Optano框架,也不太了解C#,但我熟悉您正在使用的求解器。我想你对建造一个模型有误解.
求解器需要一个表达式,它可以计算任意次数。它无法访问神奇的GetResult函数。Optano只是在构建一个表达式,求解者可以在内部计算任意次数,因此不可能在函数中进行一些任意复杂的数学运算,并返回一个数字,并将该数字作为目标值传递。
因此,您需要在Optano框架中构建一个表达式并返回该表达式,这应该是对模型中的变量和常量执行的简单数学运算。
也许有一种方法可以在您试图解决之前打印您的模型,以验证您是否有一个好的表达式?
发布于 2022-03-21 12:49:04
“目标函数不是直截了当的公式,而是返回单个数字的方法中的一系列计算(在这种情况下,数据集的方差,但还有其他需要方法解决的问题)。”我希望你能意识到GLPK只适用于线性模型。
https://stackoverflow.com/questions/71444323
复制相似问题