Случайно заполнить массив NumPy целыми числами, так что целые сгруппированы в более крупные непрерывные блоки

Я пытаюсь создать агентную модель в Python. Для окружающей среды я использовал массивный массив размером MxN. Каждый пиксель представляет собой участок земли. Я хотел бы назначить каждого участка земли таким владельцем, чтобы создаваемые большие блоки были смежными. В идеале я хотел бы иметь возможность указать количество блоков большего размера.

Это то, что я представляю

У меня удивительно трудное время, когда я пытаюсь создать рандомизированную карту. Мне удалось взломать действительно грубое решение, но у него все еще есть некоторые серьезные недостатки. Я думал, что я буду вызывать идеи у других людей, прежде чем принять эту судьбу.

1 ответ

Решение

Не мог удержаться от того, чтобы дать ему шанс, так что вот попытка использования scipy.ndimage.grey_dilation который кажется достаточно быстрым. grey_dilation расширяет территорию, используя "элементы структуры" - "ядра роста" в коде ниже. У меня нет никакого опыта относительно того, насколько они контролируют процесс, но вы можете играть с ними:

import numpy as np
from scipy import ndimage

growth_kernels = """
010 000 010 111
111 111 010 111
010 000 010 111
"""

growth_kernels = """
555555555 543212345
444444444 543212345
333333333 543212345
222222222 543212345
111101111 543202345
222222222 543212345
333333333 543212345
444444444 543212345
555555555 543212345
"""

def patches(shape, N, maxiter=100):
    # load kernels
    kernels = np.array([[[int(d) for d in s] for s in l.strip().split()]
                        for l in growth_kernels.split('\n')
                        if l.strip()], np.int)
    nlev = np.max(kernels) + 1
    # special case for binary kernels
    if nlev == 2:
        kernels = 2 - kernels
        nlev = 3
    kernels = -kernels.swapaxes(0, 1) * N
    key, kex = kernels.shape[1:]
    kernels[:, key//2, kex//2] = 0
    # seed patches leave a gap between 0 and the first patch
    out = np.zeros(shape, int)
    out.ravel()[np.random.choice(out.size, N)] = np.arange((nlev-1)*N+1, nlev*N+1)
    # shuffle labels after each iteration, so larger numbers do not get
    # a systematic advantage
    shuffle = np.arange((nlev+1)*N+1)
    # also map negative labels to zero
    shuffle[nlev*N+1:] = 0
    shuffle_helper = shuffle[1:nlev*N+1].reshape(nlev, -1)
    for j in range(maxiter):
        # pick one of the kernels
        k = np.random.randint(0, kernels.shape[0])
        # grow patches
        out = ndimage.grey_dilation(
            out, kernels.shape[1:], structure=kernels[k], mode='constant')
        # shuffle
        shuffle_helper[...] = np.random.permutation(
            shuffle[(nlev-1)*N+1:nlev*N+1])
        out = shuffle[out]
        if np.all(out):
            break
    return out % N

res = patches((30, 80), 26)
print(len(np.unique(res)))
for line in res:
    print(''.join(chr(j+65) for j in line))

Образец вывода:

WWWWWKKKKKKKKKKKKMMMLLLLLLLLLLJJJJJJJJJCCCCCCCCCCCCCCCCCSSSSSSSSSAAAAAAAAAAAAAAA
WWWWWKKKKKKKKKKKKMMMLLLLLLLLLLJJJJJJJJJCCCCCCCCCCCCCSSSSSSSSSSSSSAAAAAAAAAAAAAAA
WWWWWKKKKKKKKKKKKMMMLLLLLLLLLLJJJJJJJJJJJJJCCCCCCCCCSSSSSSSSSSSSSAAAAAAAAAAAAAAA
WWWWWKKKKKKKKKKKKMMMLLLLLLLLLLLLLLJJJJJJJJJCCCCCCCCCSSSSSRRRRRRRRRAAAAAAAAAAAAAA
WWWFFFFKKKKKKKKKKMMMLLLLLLLLLLLLLLJJJJJJJJJCCCCCCCCCSSSSSRRRRRRRRRAAAAAAAAAAAAAA
WWWFFFFKKKKKMMMMMMMMMLLLLLLLLLLLLLJJJJJJJJJCCCCCCCCCSSSSSRRRRRRRRRAAAAAAAAAAAAAA
WWWFFFFKKKKKMMMMMMMMMLLLLLLLLLLLLLJJJJJJJJJJJJJCSSSSSSSSSRRZZZZZZZZZZZGGGGGGGGGG
WWWFFFFFFFFFMMMMMMMMTTTTTTLLLLLLLLJJJJJJJJJJJJJCSSSSSSSSSRRZZZZZZZZZZZGGGGGGGGGG
WWWFFFFFFFFFMMMMMMMMTTTTTTLLLLLLLLJJJJJJJJJJJJJHSSSSSSSSSRRZZZZZZZZZZZGGGGGGGGGG
FFFFFFNNNNNNMMMMMMMMTTTTTTLLLLLLLLJJJJJJJJJJJJJHSSSSSSSSSRRZZZZZZZZZZZGGGGGGGGGG
FFFFFFNNNNNNMMMMMMMMTTTTTTLLLLLLLLJJJJJHHHHHHHHHSRRRRRRRRRRZZZZZZZZZZZGGGGGGGGGG
FFFFFFNNNNNNMMMMMMMMTTTTTTLLLLLLLLLHHHHHHHHHHHHHSRRRRRRRRRRZZZZZZZZZZZGGGGGGGGGO
FFFFFFNNNNNNMMMMMMMMTTTTTTTTTTTTHHHHHHHHHHHHHHHHDRRRRZZZZZZZZZZZZZZZZZGGGGGGGGGO
NNNNNNNNNNNNMMMMMMMMTTTTTTTTTTTTHHHHHHHHDDDDDDDDDDRRRZZZZZZZZZZZZZZZZZGGGGGGGGGO
NNNNNNNNNNNNNNNTTTTTTTTTTTTTTTTTHHHHHHHHDDDDDDDDDDUUUZZZZZZZZZZZZZZZZZGGGGGGGGGO
EEEEENNNNNNNNNNTTTTTTTTTTTTTTTTTHHHHHHHHDDDDDDDDDDUUUUUUUUUUUUUUUUZZZZGOOOOOOOOO
EEEEENNNNNNNNNNNTTTTTTTTTTTTTTTHHHHHHHHHDDDDDDDDDUUUUUUUUUUUUUUUUUZZZZGOOOOOOOOO
EEEEENNNNNNNNNNNTTTTTTTTTTTTTTTHHHHHHHHHDDDDDDDDDUUUUUUUUUUUUUUUUUZZZZGOOOOOOOOO
EEEEEEEEEEEENNNNTTTTTTTTTTTTTTTHHHHHHHHHDDDDDDDDDUUUUUUUUUUUUUUUUUXXXXGOOOOOOOOO
EEEEEEEEEEEENNNNTTTTTTTTTTTTTTTHHDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUXXXXXOOOOOOOOO
EEEEEEEEEEEENNNNVVVVVVVVVVVTTTTHHDDDDDDDDDDDDDDDDPPPPPBBUUUUUUUUUUXXXXXOOOOOOOOO
EEEEEEEEEEEEVVVVVVVVVVVVVVVTTTTQQDDDDDDDDDDDDDDDDPPPPPBBUUUUUUUUUUXXXXXXXXXXXXXX
EEEEEEEEEEEEVVVVVVVVVVVVVVVTTTTQQQQQQQQQQQQQQPPPPPPPPPBBUUUUUUUUUUXXXXXXXXXXXXXX
EEEEEEEEEEEEVVVVVVVVVVVVVVVTTTTQQQQQQQQQQQQQQQQQPPPPPPBBUUUUUUUUUUXXXXXXXXXXXXXX
EEEEEEEEEEVVVVVVVVVVVVVVVVVVVHHQQQQQQQQQQQQQQQQQPPPPPPBBUUUUUIIIIIIIIXXXXXXXXXXX
EEEEEEEEEEVVVVVVVVVVVVVVVVVVVQQQQQQQQQQQQQQQQQQQPPPPPPBBBBBIIIIIIIIYYYYYXXXXXXXX
EEEEEEEEEEVVVVVVVVVVVVVVVVVVVQQQQQQQQQQQQQQQQQQQPPPPPPBBBBBIIIIIIIIYYYYYXXXXXXXX
EEEEEEEEEEVVVVVVVVVVVVVVVVVVVQQQQQQQQQQQQQQQQQQQPPPPPPBBBBBIIIIIIIIYYYYYXXXXXXXX
EEEEEEEEEEVVVVVVVVVVVVVVVVVVVQQQQQQQQQQQQQQQQQQQPPPPPPBBBBBIIIIIIIIYYYYYXXXXXXXX
EEEEEEEEEEVVVVVVVVVVVVVVVVVVVQQQQQQQQQQQQQQQQQQQPPBBBBBBIIIIIIIIIIIYYYYYXXXXXXXX
Другие вопросы по тегам