Единый заказ на основе кроссовера - PullRequest
0 голосов
/ 19 октября 2018

У меня есть два массива A & B следующим образом:

A = [2,6,4,5,3,1]
B = [1,4,3,6,5,2]

Из которых я сформировал массив Numpy;

oldArr = np.array([[2,6,4,5,3,1],[1,4,3,6,5,2]])

Затем я должен случайно выбрать (например) 3 столбца,скажем,

idx = np.random.randint(len(oldArr[0]), size = len(oldArr[0])/2)

Это даст индекс случайных чисел;

array([3, 4, 0])

и соответствующие значения;

[[5 3 2]
 [6 5 1]]

Теперь я хочу построитьновый массив как таковой: я должен держать эти случайные числа в одной и той же позиции и поменять местами 0-й и 1-й строки таким образом, чтобы числа не повторялись в новом массиве и должны были поместить неповторяющиеся числа в том же порядке.

[2,_,_,5,3,_] # Random number positions didnt change
[1,_,_,6,5,_]

После перестановки в моем случае это должно быть так (мы видим, что числа уникальны в необработанных строках);

[2,1,4,5,3,6] 
[1,2,4,6,5,3]

Я вставил сюда изображение для представления влучший способ.enter image description here

Кто-нибудь может дать некоторые подсказки, как получить новый массив ?.Спасибо !!

1 Ответ

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

Вот решение с использованием маскировки и argsort.Предполагается, что A и B являются тасовками друг друга.

Сортирует не закрепленные значения в A в порядке их появления в B и наоборот.

import numpy as np

def reorder(a, b, idx):
    ab = np.stack([a, b])
    mask = np.ones(a.shape, bool)
    mask[idx] = False
    aidx, bidx = xidx = ab.argsort(axis=1)
    assert np.all(a[aidx] == b[bidx])
    xmask = np.empty(ab.shape, bool)
    xmask[[[0], [1]], xidx] = mask[xidx[::-1]]
    ab[::-1][np.broadcast_to(mask, ab.shape)] = ab[xmask]
    return ab

A = np.array([2,6,4,5,3,1])
B = np.array([1,4,3,6,5,2])
idx = np.array([3, 4, 0])

def make(n):
    a, b, i = (np.random.permutation(n) for _ in 'xxx')
    return a, b, i[:n//2]

def check(a, b, i):
    m = np.ones(a.shape, bool)
    m[i] = False
    result = reorder(a, b, i)
    assert np.all(np.sort(result) == np.sort(a))
    # warning: expensive!
    assert np.all(np.diff(np.where(result[1][m, None]==a)[1]) >= 0)
    assert np.all(np.diff(np.where(result[0][m, None]==b)[1]) >= 0)

for a, b, i in [(A, B, idx), make(10), make(20)]:
    m = np.zeros(a.shape, int)
    m[i] = 1
    print(np.stack([a, b, m]), '\n')
    print(reorder(a, b, i), '\n')
    check(a, b, i)

Пробный прогон (отпечатки (A; B, маска, результат) для 3 примеров; первый пример из OP):

[[2 6 4 5 3 1]
 [1 4 3 6 5 2]
 [1 0 0 1 1 0]] 

[[2 1 4 5 3 6]
 [1 2 4 6 5 3]] 

[[4 2 1 6 0 7 9 3 8 5]
 [1 7 5 3 9 8 2 0 6 4]
 [0 1 0 1 1 0 0 1 1 0]] 

[[1 2 7 6 0 5 9 3 8 4]
 [4 7 2 3 9 1 8 0 6 5]] 

[[ 1  4 15 18  6 19  7 13  0  8  5 17 14 12  3  9  2 11 16 10]
 [ 0  6  3  1 11 12  4  7 19 10  8 13  9 14  5 17 18 15 16  2]
 [ 1  1  0  1  0  0  1  1  0  0  1  1  1  0  1  0  0  0  1  0]] 

[[ 1  4  0 18  6 11  7 13 12 19  5 17 14 10  3  8  9 15 16  2]
 [ 0  6 15  1 18 19  4  7 17 14  8 13  9 12  5  3  2 11 16 10]] 
...