Выбор двух чисел из списка в Python с вероятностью, которая уменьшается как относительное расстояние между ними - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь взять список, и из него случайным образом выбрать номер i. После чего я хочу выбрать второй элемент j. Вероятность выбора j уменьшается как 1/|i-j|. Например, относительная вероятность того, что он выберет j в четырех шагах от моего начального i, равна 1/4, вероятность выбора j в непосредственной близости от моего i.

До сих пор я пытался заполнить свой список, выбрать мой i, сначала вычислить вес, используя |i-j| для всех остальных элементов в списке.

import numpy as np
import random as random
list = [1,2,3,4,5,6,7,8,9,10]
a = 1
n1 = random.choice(range(len(list)))
n1_coord = (n1, list[n1])
print(n1_coord)
prob_weights = []
for i in range(0, n1):
    wt = 1/((np.absolute(n1-i)))
    #print(wt)
    prob_weights.append(wt)
for i in range(n1+1,len(list)):
    wt = 1/((np.absolute(n1-i)))
    prob_weights.append(wt)

Есть ли в Python встроенная функция, в которую я могу подать эти веса, в которую выберут j с таким распределением вероятностей. Могу ли я ввести свой массив весов в:

numpy.random.choice(a, size=None, replace=True, p=None)

Полагаю, я позволю p = prob_weights в моем коде?

 import numpy as np
    import random as random
    list = [1,2,3,4,5,6,7,8,9,10]
    a = 1
    n1 = random.choice(range(len(list)))
    n1_coord = (n1, list[n1])
    print(n1_coord)
    prob_weights = []
    for i in range(0, n1):
        wt = 1/((np.absolute(n1-i)))
        #print(wt)
        prob_weights.append(wt)
    for i in range(n1+1,len(list)):
        wt = 1/((np.absolute(n1-i)))
        prob_weights.append(wt)
    n2 = np.random.choice(range(len(list)), p=prob_weights)
    n2_coord = (n2, list[n2])

Запуск этого выше с np.random.choice дает мне ошибку. Я даже не уверен, делает ли это то, что я хочу, чтобы он делал в первую очередь. Есть ли альтернативный способ сделать это?

1 Ответ

0 голосов
/ 13 января 2019

Для этого есть встроенная функция: random.choices, которая принимает аргумент weights.

Учитывая ваш первый выбранный индекс n1, вы можете сделать что-то вроде

indices = range(len(mylist))
weights = [0 if i == n1 else 1 / abs(i - n1) for i in indices]
n2 = random.choices(indices, weights=prb_wts, k=1).

Устанавливая вес первого элемента на ноль, вы предотвращаете его выделение.

Числовые операции обычно бывают быстрее при использовании numpy, поэтому вы можете использовать np.random.choice, который принимает аргумент p:

values = np.array([...])
indices = np.arange(values.size)

n1 = np.random.choice(indices)
i = values[n1]

delta = np.abs(indices - n1)
weights = np.divide(1.0, delta, where=delta)
n2 = np.random.choice(indices, p=weights)
j = values[n2]

Как второстепенные мелочи, не вызывайте переменную list, так как она затеняет встроенную, а import x as x это просто import x.

...