5

I'm trying to solve a constrained non-linear 267 dimensional optimization problem with the java optimization library supplied by Apache Commons.

After 3 days of deciphering, this is what I have:

public class optimize2 {

public static void main(String []args){

    double[] point = {1.,2.};
    double[] cost = {3., 2.};
    MultivariateFunction function = new MultivariateFunction() {
            public double value(double[] point) {
                    double x = point[0];
                    double y = point[1];
                    return x * y;
            }
    };


    MultivariateOptimizer optimize = new BOBYQAOptimizer(5);
    optimize.optimize(
            new MaxEval(200),
            GoalType.MAXIMIZE,
            new InitialGuess(point),
            new ObjectiveFunction(function),
            new LinearConstraint(cost, Relationship.EQ, 30));
}

}

For whatever reason optimize.optimize() is throwing a null pointer error. Maybe I'm just being dumb but I can't figure out how to get this to work.

Here is the error:

Exception in thread "main" java.lang.NullPointerException at org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer.setup(BOBYQAOptimizer.java:2401) at org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer.doOptimize(BOBYQAOptimizer.java:236) at org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer.doOptimize(BOBYQAOptimizer.java:49) at org.apache.commons.math3.optim.BaseOptimizer.optimize(BaseOptimizer.java:143) at org.apache.commons.math3.optim.BaseMultivariateOptimizer.optimize(BaseMultivariateOptimizer.java:66) at org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer.optimize(MultivariateOptimizer.java:64) at Test.Code.optimize2.main(optimize2.java:39)

Kammeot
  • 469
  • 7
  • 18
  • Post the complete error message including the stacktrace. – jlordo Jun 05 '13 at 21:23
  • The *BOBYQA* algorithm does not support linear or nonlinear constraints, only variable bounds. I am not 100% sure, but I don't actually think that any of the nonlinear opt algorithms in *Apache Commons Math* is capable of handling constraints other than variable bounds. Powell's *COBYLA2* algorithm does have support for arbitrary constraints. I have converted the Fortran code of the original implementation to Java, you can find it [here](https://github.com/cureos/jcobyla) and [here](http://www.codeproject.com/Articles/508513/Derivative-free-nonlinear-optimization-for-NET-and). – Anders Gustafsson Jun 07 '13 at 06:16

1 Answers1

6

Looking directly into the BOBYQA code, it actually seems like the problem is that you have not explicitly defined any variable bounds. Line 2401 (setup method) reads as follows:

boundDifference[i] = upperBound[i] - lowerBound[i];

In the doOptimze method, prior to calling setup the bounds are set using these methods:

final double[] lowerBound = getLowerBound();
final double[] upperBound = getUpperBound();

These methods are defined in BaseMultivariateOptimizer like this:

public double[] getLowerBound() {
    return lowerBound == null ? null : lowerBound.clone();
}

(and analogously for getUpperBound()). But lowerBound and upperBound in BaseMultivariateOptimizer are only set if the optimization data in the optimize call contains bounds information. If the bounds are not set in the call to optimize, you should therefore receive a NullPointerException.

Looking at the BOBYQA test code it seems like it should be sufficient if you add the following argument to the optimize call:

SimpleBounds.unbounded(point.length)

Having said that, I also do not think you will be able to completely solve your problem using any of the nonlinear optimizers in Apache Commons Math, since as far as I can tell none of these optimizers can handle linear or nonlinear constraints. I recommend that you take a look at for example Michael Powell's COBYLA2 algorithm instead. I have migrated the original FORTRAN code of this algorithm to Java, and you can find the code here and here.

Anders Gustafsson
  • 15,837
  • 8
  • 56
  • 114
  • Ok, so I was trying out Jcobyla and I'm a bit confused about the representation of the constraints. Say I wanted the constraint 500 = x[1] + x[0]. How would I represent that in the compute function. – Kammeot Jun 08 '13 at 01:32
  • 2
    @InspiredOne The constraints in *COBYLA2* should be formulated such that each constraint function is required to be non-negative, i.e. **C(x) >= 0**. I think that the feasible way to handle an equality constraint **C=e** is to formulate it as a squared difference with a small tolerance, **(C-e)^2 <= tol** or reformulated to fit *COBYLA2* , **tol - (C-e)^2 >= 0**. – Anders Gustafsson Jun 09 '13 at 17:37
  • 1
    Thanks, that cleared it up. I'm so excited to continue with my project. I've been stuck with optimization problems for a week. You are the best :) – Kammeot Jun 09 '13 at 23:50