如何用两个整数数组做一个 "cross-over"

How to do a "cross-over" with two integer arrays

我正在尝试学习遗传算法,目前正在研究 "crossing over" 两个 "genes"。 基因是一个整数数组,由 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]

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

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

像这样使用Arrays.copy,

copyA = Arrays.copyOf(geneA, geneA.length);
copyB = Arrays.copyOf(geneB, geneB.length);

此代码有效:

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

有问题。您可以很容易地将两个数组复制到 copyAcopyB,这不会生成新副本。它只是复制数组的引用并且两个数组都引用相同的内存。所以其中一个的任何变化也会改变另一个。为此,您可以改用 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));
    }

希望对你有所帮助。

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

没有必要浪费时间和space复制整个数组。

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

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]