I am trying to understand how to use the ExpressionsBasedModel class to solve least-squares problems and have constructed a minimal problem but I do not obtain the result that I would expect. My toy problem is to minimize
f(x) = (x - 4)^2
with respect to x. It is easy to see that the minimum of this function is x = 4. I wrote this small Java program to minimize it using ojAlgo:
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Variable;
import org.ojalgo.optimisation.Expression;
import org.ojalgo.optimisation.Optimisation.Result;
public class OjalgoDemo {
public static void main(String[] args) {
ExpressionsBasedModel model = new ExpressionsBasedModel();
// Minimize f(x) = (x - 4)^2, which has minimum x = 4
// (x - 4)^2 = x^2 - 8x + 16.
// Note that minimum of
// f(x) = x^2 - 8x + k
// is the same no matter the choice of k.
Variable x = model.addVariable("x");
Expression expr = model.addExpression("objective");
// Add the x^2 term
expr.set(x, x, 1.0);
// Add the -8x term
expr.set(x, -8.0);
Result result = model.minimise();
System.out.println("The state: " + result.getState());
System.out.println("The full result: " + result);
}
}
and when I run it, I get the output
The state: OPTIMAL
The full result: OPTIMAL 0.0 @ { 0 }
but I would expect the output to indicate the solution x = 4:
The state: OPTIMAL
The full result: OPTIMAL 0.0 @ { 4 }
Why does ojAlgo not appear to solve my problem the way I expect it?
I specifically want to use ExpressionsBasedModel to later add linear inequality constraints to the least-squares problem, but before doing that I would like to be able to solve the smallest possible least-squares problem that I can come up with.
I compile and run it using these commands:
javac OjalgoDemo.java -classpath ~/.m2/repository/org/ojalgo/ojalgo/47.3.1/ojalgo-47.3.1.jar
java -classpath ".:/home/rulle/.m2/repository/org/ojalgo/ojalgo/47.3.1/ojalgo-47.3.1.jar" OjalgoDemo
The problem is that you have not set a weight of the expression. If you don't set the weight, it will not contribute to the objective function. In order for the code to work as you would expect, you have to add the line
expr.weight(1.0);
So that it reads
Variable x = model.addVariable("x");
Expression expr = model.addExpression("objective");
// Add the x^2 term
expr.set(x, x, 1.0);
// Add the -8x term
expr.set(x, -8.0);
// THIS FIXES IT
expr.weight(1.0);
Result result = model.minimise();
When executing this code, I get the output
The state: DISTINCT
The full result: DISTINCT -16.0 @ { 4 }
which is what we would expect. -16
comes from the fact that we have not a constant offset. To further see that setting the weight means that expr
will contribute to the objective function, add the line System.out.println("Objective? " + expr.isObjective());
which will show true only if the weight is set.