使用差分进化的函数值

时间:2012-02-17 00:05:48

标签: java chess evolutionary-algorithm differential-evolution

如何使用差分进化来找到函数函数f(x)= -x(x + 1)的最大值,从-500到500?我需要这个用于我正在制作的国际象棋程序,我已经开始研究差分进化并且仍然发现它很难理解,更不用说用于程序了。任何人都可以通过简单的方式向我介绍算法并可能为这样的程序提供一些示例伪代码来帮助我吗?

1 个答案:

答案 0 :(得分:3)

首先,对于迟到的回复感到抱歉。

我敢打赌你不会知道你试图达到最大值的函数的导数,这就是你想要使用差分进化算法而不是牛顿拉斐逊方法的原因。

我找到了一个很好的链接,以直接的方式解释差异进化:http://web.as.uky.edu/statistics/users/viele/sta705s06/diffev.pdf

在第一页上,有一个部分解释了算法:

  

让每一代点由n个点组成,每个点都包含j个术语。

初始化大小为j的数组。从j添加-500 to 500个不同的随机x值,即您正在考虑的时间间隔。理想情况下,您会知道最大值的位置,并且您可能会更有可能将x值放在那里。

  

对于每个j,从点集x中均匀地随机选择两个点yj,1和yj,2   (M)   。   构造候选点cj = x   (M)   j +α(yj,1-yj,2)。基本上,两个y值涉及   选择随机方向和距离,通过添加随机来找到候选者   方向和距离(按α缩放)到当前值。

嗯......这有点复杂。迭代你在最后一步中创建的数组。对于每个x值,选择两个随机索引(yj1yj2)。使用x构建候选cx = α(yj1 − yj2)值,您可以在其中选择α。您可以尝试使用不同的alpha值进行试验。

检查哪一个更大,候选值或j处的x值。如果候选值较大,请将其替换为x处的j值。

执行此操作直到阵列中的所有值或多或少相似。 Tahdah,数组的任何值都将是最大值。只是为了减少随机性(或者这可能不重要......),将它们全部平均化。

about方法越严格,您将获得更好的近似值,但需要的时间就越多。

例如,我会Math.abs(a - b) <= alpha /10而不是Math.abs(a - b) <= alpha /10000来获得更好的近似值。

您将获得所需值的近似值。

快乐的编码!

我为此回复撰写的代码:

public class DifferentialEvolution {

public static final double alpha = 0.001;

public static double evaluate(double x) {
    return -x*(x+1);
}

public static double max(int N) { // N is initial array size.

    double[] xs  = new double[N];

    for(int j = 0; j < N; j++) {
        xs[j] = Math.random()*1000.0 - 500.0; // Number from -500 to 500.
    }

    boolean done = false;
    while(!done) {
        for(int j = 0; j < N; j++) {
            double yj1 = xs[(int)(Math.random()*N)]; // This might include xs[j], but that shouldn't be a problem.
            double yj2 = xs[(int)(Math.random()*N)]; // It will only slow things down a bit.

            double cj = xs[j] + alpha*(yj1-yj2);

            if(evaluate(cj) > evaluate(xs[j])) {
                xs[j] = cj;
            }
        }

        double average = average(xs); // Edited

        done = true;
        for(int j = 0; j < N; j++) { // Edited
            if(!about(xs[j], average)) { // Edited
                done = false;
                break;
            }
        }

    }
    return average(xs);

}

public static double average(double[] values) {
    double sum = 0;
    for(int i = 0; i < values.length; i++) {
        sum += values[i];
    }

    return sum/values.length;

}

public static boolean about(double a, double b) {
    if(Math.abs(a - b) <= alpha /10000) { // This should work.
        return true;
    }
    return false;
}

public static void main(String[] args) {

    long t = System.currentTimeMillis();
    System.out.println(max(3));
    System.out.println("Time (Milliseconds): " + (System.currentTimeMillis() - t));

}

}

如果您在阅读本文后有任何疑问,请随时在评论中提问。我会尽力帮助你。