Introduction
I'm trying to use the ojalgo library to produce a solution to controlling thrusters placed in arbitrary places to generate an overall requested rotation and translation. Sometimes the requested rotation and translation will not be possible but I'd like it to have a go in those situations.
Issue
I've created this minimal example of the ExpressionsBasedModel I've set up.
If I request a set of conditions that are possible I get a good result:
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
But if I request something that isn't quite possible
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
I would ideally like a good suboptimal solution (1,1) but instead it seems to give up and returns 0.5,0.5 instead
Question
Is it possible to get a good suboptimal solution for an impossible to fully fulfil problem?
Possible the problem is that I want to minimise the error on the expressions, but I think its actually minimising the values (while trying to meet the constraints)
Actually, I've come around to what I previously was calling hacky, as it recasts it as an actual optimisation problem, so I'm posting it as a solution (still open to better answers though)
Solution
Introduce positiveError and negativeError variables for each equation to ensure that the problem has a solution, but give them large weights so the solver avoids using them
Example
This approach also allows me to define which error I care more about, as I can give different error variables different weights