首页 > 解决方案 > 从 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

问题

对于不可能完全解决的问题,是否有可能获得良好的次优解决方案?

可能的问题是我想最小化表达式上的错误,但我认为它实际上最小化了值(同时试图满足约束)

标签: ojalgolinear-optimization

解决方案


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

解决方案

为每个方程引入 positiveError 和negativeError 变量以确保问题有解,但给它们很大的权重,以便求解器避免使用它们

例子

//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

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


推荐阅读