Apache Commons优化问题

5

我正在尝试使用Apache Commons提供的Java优化库解决一个受限的非线性267维优化问题。

经过3天的解码,这是我得到的结果:

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));
}

由于某种原因,optimize.optimize() 抛出了一个空指针错误。也许我只是太蠢了,但我无法弄清楚如何使其工作。

以下是错误信息:

线程 "main" 中的异常 java.lang.NullPointerException 在 org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer.setup(BOBYQAOptimizer.java:2401) 在 org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer.doOptimize(BOBYQAOptimizer.java:236) 在 org.apache.commons.math3.optim.nonlinear.scalar.noderiv.BOBYQAOptimizer.doOptimize(BOBYQAOptimizer.java:49) 在 org.apache.commons.math3.optim.BaseOptimizer.optimize(BaseOptimizer.java:143) 在 org.apache.commons.math3.optim.BaseMultivariateOptimizer.optimize(BaseMultivariateOptimizer.java:66) 在 org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer.optimize(MultivariateOptimizer.java:64) 在 Test.Code.optimize2.main(optimize2.java:39)


请发布完整的错误消息,包括堆栈跟踪。 - jlordo
BOBYQA算法不支持线性或非线性约束,只支持变量边界。我不是100%确定,但实际上我认为Apache Commons Math中的任何非线性优化算法都无法处理除变量边界之外的约束。Powell的COBYLA2算法确实支持任意约束。我已将原始实现的Fortran代码转换为Java,您可以在这里这里找到它。 - Anders Gustafsson
1个回答

6
直接查看BOBYQA代码,实际上似乎问题是您没有明确定义任何变量边界。第2401行(setup方法)的内容如下:
boundDifference[i] = upperBound[i] - lowerBound[i];

doOptimize方法中,在调用setup之前,使用以下方法设置边界:
final double[] lowerBound = getLowerBound();
final double[] upperBound = getUpperBound();

这些方法在BaseMultivariateOptimizer中定义,格式如下:
public double[] getLowerBound() {
    return lowerBound == null ? null : lowerBound.clone();
}

(对于getUpperBound()同样适用)。但在BaseMultivariateOptimizer中,只有当调用optimize时的优化数据包含边界信息时,lowerBoundupperBound才会被设置。如果在调用optimize时未设置边界,则您应该收到一个NullPointerException

通过查看BOBYQA测试代码,似乎只需要将以下参数添加到optimize调用中即可:

SimpleBounds.unbounded(point.length)

话虽如此,我认为您无法完全使用Apache Commons Math中的任何非线性优化器来解决问题,因为据我所知,这些优化器都无法处理线性或非线性约束。我建议您看一下Michael Powell的COBYLA2算法。我已经将该算法的原始FORTRAN代码迁移到了Java,并且您可以在这里这里找到代码。


好的,我正在尝试使用Jcobyla,并且对约束条件的表示有些困惑。假设我想要约束条件500 = x[1] + x[0],那么在计算函数中该如何表示呢? - Kammeot
2
@InspiredOne 在COBYLA2中的约束条件应该被规定为每个约束函数都必须是非负的,即C(x) >= 0。我认为处理等式约束C=e的可行方法是将其规定为带有小公差的平方差,即**(C-e)^2 <= tol或者重新制定以适应COBYLA2,即**tol - (C-e)^2 >= 0 - Anders Gustafsson
1
谢谢,这解决了我的疑惑。我很兴奋能够继续我的项目。我已经被优化问题困扰了一个星期。你是最棒的 :) - Kammeot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接