从ojalgo获得线性优化的良好次优解



简介

我正试图使用ojalgo库来生成一个控制放置在任意位置的推进器的解决方案,以生成所需的整体旋转和平移。有时要求的轮换和翻译是不可能的,但我希望在这种情况下尝试一下。

问题

我创建了一个我设置的ExpressionsBasedModel的最小示例。

如果我请求一组可能的条件,我会得到一个好结果:

Variable thruster1 = new Variable("t1").lower(0).upper(1).weight(0.1);
Variable thruster2 = new Variable("t2").lower(0).upper(1).weight(0.1);
ExpressionsBasedModel model = new ExpressionsBasedModel();
model.addVariable(thruster1);
model.addVariable(thruster2);
double targetXThrust = 2;

model.addExpression("XMotion")
.weight(1)
.set(thruster1, 1)
.set(thruster2, 1).lower(targetXThrust).upper(targetXThrust);
Optimisation.Result minimised = model.minimise();
System.out.println(minimised); //outputs 1,1

但如果我要求一些不太可能的

double targetXThrust = 2.1;

model.addExpression("XMotion")
.weight(1)
.set(thruster1, 1)
.set(thruster2, 1).lower(targetXThrust).upper(targetXThrust);
System.out.println(minimised); //outputs 0.5,0.5

理想情况下,我想要一个好的次优解(1,1),但它似乎放弃了,并返回0.5,0.5,而不是

问题

对于一个不可能完全解决的问题,有可能得到一个好的次优解决方案吗?

可能的问题是,我想最大限度地减少表达式上的错误,但我认为这实际上是在最小化值(同时试图满足约束)

事实上,我已经谈到了我以前称之为hacky的问题,因为它将其重新定义为一个实际的优化问题,所以我将其作为一个解决方案发布(尽管仍有更好的答案)

解决方案

为每个方程引入正误差和负误差变量,以确保问题有一个解决方案,但给它们很大的权重,这样求解器就可以避免使用它们

示例

//thrusters at powers between 0 and 1 (hard limits)
Variable thruster1 = new Variable("t1").lower(0).upper(1).weight(0.1); //we'd rather an engine was off if possible so give it a small weight
Variable thruster2 = new Variable("t2").lower(0).upper(1).weight(0.1);
Variable positiveError = new Variable("positiveError").lower(0).weight(10000); //we'd rather a solution was found if at all possible
Variable negativeError = new Variable("negativeError").lower(0).weight(10000);
ExpressionsBasedModel model = new ExpressionsBasedModel();
model.addVariable(thruster1);
model.addVariable(thruster2);
model.addVariable(positiveError);
model.addVariable(negativeError);
double targetXThrust = 2.1;
model.addExpression("XMotion")
.set(thruster1, 1)
.set(positiveError, 1)
.set(negativeError, -1)
.set(thruster2, 1)
.lower(targetXThrust)
.upper(targetXThrust);
Optimisation.Result minimised = model.minimise();
System.out.println(minimised); //prints 1, 1, 0.1, 0

这种方法还允许我定义我更关心的错误,因为我可以给不同的错误变量不同的权重

最新更新