Генерация случайного целого числа numpy вектора с фиксированной суммой - PullRequest
0 голосов
/ 22 сентября 2019

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

self.position = np.array([rd.randint(0,2), rd.randint(0,2), rd.randint(0,100), rd.randint(0,50), rd.randint(0,1)])

Ответы [ 2 ]

1 голос
/ 22 сентября 2019

Хотя решение, предложенное Rmano , является верным, в нем отсутствует полная случайность, поскольку после того, как вы рисуете первое случайное целое число, другое является псевдослучайным или вовсе не случайным из-за зависимости.

По моему мнению, более случайным решением будет:

import numpy as np

def generate_fix_sum_random_vec(limit, num_elem, tries=10):
    v = np.random.randint(0, limit, num_elem)
    s = sum(v)
    if (np.sum(np.round(v/s*limit)) == limit):
        return np.round(v / s * limit)
    elif (np.sum(np.floor(v/s*limit)) == limit):
        return np.floor(v / s * limit)
    elif (np.sum(np.ceil(v/s*limit)) == limit):
        return np.ceil(v / s * limit)
    else:
        return generate_fix_sum_random_vec(limit, num_elem, tries-1)



for i in range(25):
    test_vec = generate_fix_sum_random_vec(100, 3)
    test_vec = test_vec.astype(int)
    print("vec: ", test_vec, "sum of vector: ", np.sum(test_vec))

Это решение является более надежным и может быть допустимым для любого предела суммы вектора, и оно легко применимо к вектору любой длины с помощьюизменение num_elem.Более того, он ничего не предполагает и просто пытается найти соответствие.

Вывод цикла:

vec:  [53 32 15] sum of vector:  100
vec:  [40 38 22] sum of vector:  100
vec:  [56 38  6] sum of vector:  100
vec:  [ 5 17 78] sum of vector:  100
vec:  [12 29 59] sum of vector:  100
vec:  [ 1 34 65] sum of vector:  100
vec:  [ 3 56 41] sum of vector:  100
vec:  [35 65  0] sum of vector:  100
vec:  [54  9 37] sum of vector:  100
vec:  [45  8 47] sum of vector:  100
vec:  [30 56 14] sum of vector:  100
vec:  [34 63  3] sum of vector:  100
vec:  [17 40 43] sum of vector:  100
vec:  [56 36  8] sum of vector:  100
vec:  [52 45  3] sum of vector:  100
vec:  [35 34 31] sum of vector:  100
vec:  [25 41 34] sum of vector:  100
vec:  [ 1 78 21] sum of vector:  100
vec:  [ 1 49 50] sum of vector:  100
vec:  [51 31 18] sum of vector:  100
vec:  [50 10 40] sum of vector:  100
vec:  [36 63  1] sum of vector:  100
vec:  [30 30 40] sum of vector:  100
vec:  [27 30 43] sum of vector:  100
vec:  [21 27 52] sum of vector:  100

Необходимо проверить, действительно ли результатвекторная сумма до желаемого значения, потому что это не гарантируется

0 голосов
/ 22 сентября 2019

Ответ на комментарий ниже от ОП:

Я не уверен, сколько случайности вы получите, как это, но:

def three_to_100_b():
    a3 = random.randint(0,1)
    a2 = random.randint(0,50)
    a1 = 100-a3-a2
    return a1, a2, a3

даст вам три псевдо - случайные числа, первое в диапазоне 0-100, второе в диапазоне 0-50, последнее 0 или 1 и суммирование 100.

Но обратите внимание, что случайность между a1и a2 действительно маленький --- они находятся по прямой линии +0 или -1 по определению ...

enter image description here

Обратите внимание, новыйответ --- у старого есть недостатки в случайности.

Один из способов иметь три числа на сумму до 100 состоит в том, чтобы сгенерировать три случайных числа, а затем масштабировать их так, чтобы их суммы были равны 100. Это слишкоммногословно, но идея такова:

#! /usr/bin/env python3

import random

def three_to_100():
    r1 = random.randint(0,100)
    r2 = random.randint(0,100)
    r3 = random.randint(0,100)
    a1 = r1*100/(r1+r2+r3)
    a2 = r2*100/(r1+r2+r3)
    a3 = 100 - a1 - a2
    return a1, a2,a3

#main
print("x\t y\t z")
for i in range(1000):
    # print(three_to_100())
    a=three_to_100()
    print("{}\t  {}\t {}".format(*a))

Я построил пары (x, y) для первых 1000 чисел (третье число представлено цветом точки), и у меня есть:

Output of the x,y,z tuples

старый ответ

Вы можете сгенерировать число от 0 до 100, затем еще одно от 0до (100 - первое число) и т. д.Последнее не будет случайным:

#! /usr/bin/env python3

import random

def three_to_100():
    r1 = random.randint(0,100)
    r2 = random.randint(0,100-r1)
    r3 = 100 - r1 - r2
    return r1, r2,r3

#main
for i in range(10):
    print(three_to_100())

Вывод будет:

[romano:~/tmp] % ./randsum.py 
(26, 7, 67)
(85, 13, 2)
(43, 41, 16)
(75, 22, 3)
(66, 19, 15)
(30, 16, 54)
(43, 30, 27)
(36, 2, 62)
(31, 2, 67)
(91, 0, 9)

Это график первых двух чисел - они кажутся довольно случайными, но, возможно, этоПравда, они кажутся немного переполненными по оси XY.

distribution of 1000 numbers

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...