Как сделать «кроссинговер» с двумя целочисленными массивами - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь узнать о генетических алгоритмах и в настоящее время работаю над "пересечением" двух "генов".Ген - это целочисленный массив, состоящий из единиц и нулей.Чтобы проиллюстрировать мою проблему, скажем, у нас есть два гена.

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

Однако, похоже, что элементы гена B просто копируются в ген A с индексом 3 или выше.Вывод на консоль выглядит следующим образом:

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

Любые объяснения или помощь приветствуются.Заранее спасибо!

Ответы [ 4 ]

0 голосов
/ 16 октября 2018

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]
0 голосов
/ 16 октября 2018

Этот код будет работать:

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);
0 голосов
/ 16 октября 2018

Есть проблема.Вы очень легко копируете оба массива в 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));
    }

вместо этого, как я вижу, вы меняете geneA и geneB после создания копиии обмен, поэтому я думаю, что этот код будет делать то же самое с меньшим количеством кода, но я не знаю, это то, что вы хотите или нет:

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

Надеюсь, это поможет вам.

0 голосов
/ 16 октября 2018

Я думаю, что вы ошибаетесь, когда создаете копии массивов ... в настоящее время вы не копируете копии, но copyA и copyB - это просто ссылки, указывающие на geneA и geneB или

Используйте Arrays.copy примерно так,

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