2

我正在尝试学习遗传算法,目前正在研究“交叉”两个“基因”。基因是一个整数数组,由 1 和 0 组成。为了举例说明我的问题,假设我们有两个基因。

int[] geneA = {1,0,0,0,0};
int[] geneB = {0,1,1,1,0};

交叉的预期结果,例如在位置 3 将是:

geneA = [1,0,0,1,0]
geneB = [0,1,1,0,0]

这意味着索引为 3 或以上的每个元素都将与另一个基因的等效元素交换。为此,我编写了以下方法:

private void crossOver(int[] geneA, int[] geneB, int pos) {
    int copyA[];
    int copyB[];
    copyA = geneA;
    copyB = geneB;
    for(int i = pos; i < geneA.length; i++) {
        geneA[i] = copyB[i];
        geneB[i] = copyA[i];
    }
    System.out.println(Arrays.toString(geneA);
    System.out.println(Arrays.toString(geneB);
}

然而,似乎geneB 的元素只是简单地以3 或更高的索引复制到geneA 中。控制台输出如下:

[1, 0, 0, 1, 0]
[0, 1, 1, 1, 0]

非常感谢任何解释或帮助。提前致谢!

4

4 回答 4

4

copyA = geneA不创建副本。两个变量现在都引用同一个数组。

无需浪费时间和空间复制整个阵列。

交换值时,只需将其中一个值存储在临时变量中。

private static void crossOver(int[] geneA, int[] geneB, int pos) {
    for (int i = pos; i < geneA.length; i++) {
        int temp = geneA[i];
        geneA[i] = geneB[i];
        geneB[i] = temp;
    }
}

这将就地更新数组,因此调用者将看到更改。

int[] geneA = {1,0,0,0,0};
int[] geneB = {0,1,1,1,0};
crossOver(geneA, geneB, 3);
System.out.println(Arrays.toString(geneA));
System.out.println(Arrays.toString(geneB));

输出

[1, 0, 0, 1, 0]
[0, 1, 1, 0, 0]
于 2018-10-16T20:59:42.303 回答
2

我认为当你创建数组的副本时你会出错......目前你没有制作副本但 copyA 和 copyB 只是指向geneA和geneB resp的引用

像这样使用 Arrays.copy,

copyA = Arrays.copyOf(geneA, geneA.length);
copyB = Arrays.copyOf(geneB, geneB.length);
于 2018-10-16T20:55:40.283 回答
1

此代码将起作用:

void crossOver(int[] geneA, int[] geneB, int pos) {
    int copyA[];
    int copyB[];
    copyA = Arrays.copyOf(geneA,geneA.length);
    copyB = Arrays.copyOf(geneB,geneB.length);
    for(int i = pos; i < geneA.length; i++) {
        geneA[i] = copyB[i];
        geneB[i] = copyA[i];
    }
    System.out.println(Arrays.toString(geneA));
    System.out.println(Arrays.toString(geneB));
}

您的代码的问题是您正在通过以下方式复制数组:

copyA = geneA;
copyB = geneB;

这只是指向相同的参考。因此,在其余代码中,您处理的是同一个数组,而不是处理副本。

相反,复制数组的正确方法是:

copyA = Arrays.copyOf(geneA,geneA.length);
copyB = Arrays.copyOf(geneB,geneB.length);
于 2018-10-16T20:56:20.640 回答
1

有问题。你很容易复制两个数组,copyA并且copyB不会制作新副本。它只是复制数组的引用,并且两个数组都引用相同的内存。所以其中一个的任何变化都会改变另一个。为此,您可以Arrays.copyof()改用。
我认为这就是你想要的:

    private void crossOver(int[] geneA, int[] geneB, int pos) {
        int[] copyA = Arrays.copyOf(geneA, geneA.length);
        int[] copyB = Arrays.copyOf(geneB, geneB.length);
        for(int i = pos; i < geneA.length; i++) {
            geneA[i] = copyB[i];
            geneB[i] = copyA[i];
        }
        System.out.println(Arrays.toString(geneA));
        System.out.println(Arrays.toString(geneB));
    }

取而代之的是,正如我所看到的,您在进行复制和交换之后进行了更改geneAgeneB所以我认为这段代码可以用更少的代码做同样的事情,但我不知道这是否是您想要的:

    private void crossOver(int[] geneA, int[] geneB, int pos) {
        for(int i = pos; i < geneA.length; i++) {
            int temp = geneA[i];
            geneA[i] = geneB[i];
            geneB[i] = temp;
        }
        System.out.println(Arrays.toString(geneA));
        System.out.println(Arrays.toString(geneB));
    }

我希望这对你有帮助。

于 2018-10-16T20:56:30.530 回答