python filling an list with random amount [lb,ub] - python

I want to fill some list with size N with random variable between LB and UB in python 3.6.
Would you please guide me?

Something simple like this works, using random.randint:
>>> import random
>>> N = 5 # count
>>> LB = 0 # lower bound
>>> UB = 10 # upper bound
>>> [random.randint(LB, UB) for _ in range(N)]
[6, 6, 5, 3, 2]

Take a look into either random or numpy.random (the second is better in my opinion, but requires numpy to be installed).
The specific function to use depends on which numbers you want, and how you want them to be distributed:
if you want uniformly distributed integers, you can use random.randint(LB, UB). If you want floats, you can use random.uniform(LB, UB). You can also have normally distributed numbers for example.
numpy's random makes it much easier, as it can return a list. e.g.:
numpy.random.randint(LB, UB, N)

Related

Random list with specific length and sum

I need a list of random floats with a sum of 1 and a certain length.
To my knowledge, the methods I have seen generate all possible scenarios, and it is possible that there are no lists with a specific length among the cases. Although making the remaining elements of the list equal to zero is an option, it doesn't seem like a good idea!
It is costly and time-consuming to just make this list by trial and error, so the program is time-consuming.
Try:
import numpy as np
n = 100
a = np.random.normal(size=n)
a /= a.sum()
After that:
>>> a.sum()
0.9999999999999998
Note: if your list is short and you are worried of the absolutely exceptional case where the initial a.sum() be 0, then:
while True:
a = np.random.normal(size=n)
if not np.allclose(a.sum(), 0):
a /= a.sum()
break

How do I reproduce the same random integer array in matlab and python?

How do I get the same random numbers in Python and Matlab?
For example, my Matlab code prints random integers of 1 and 2 with the given seed:
>> rng(1);
>> randi(2,1,10)
ans =
1 2 1 1 1 1 1 1 1 2
However, when I have the same seed using NumPy, I get a different order of random numbers:
np.random.seed(1)
np.random.randint(1,3,10)
array([2, 2, 1, 1, 2, 2, 2, 2, 2, 1])
Is there any way the two methods can produce the same order of random numbers?
As seen in this answer, it is possible to produce the same random stream of uniformly distributed numbers in both MATLAB and Python/NumPy. Both use the same MT19937 Mersenne Twister:
>> format long
>> rng(1)
>> rand(1,3)
ans =
0.417022004702574 0.720324493442158 0.000114374817345
>>> import numpy as np
>>> np.random.seed(1)
>>> np.random.rand(1,3)
array([[4.17022005e-01, 7.20324493e-01, 1.14374817e-04]])
So the difference we are seeing here is in how these numbers are converted into integers in the given range. But fortunately this is a trivial step that we can implement identically in both languages:
rng(1)
upper = 2;
lower = 1;
v = floor((rand(1,10) * (upper-lower+1)) + lower);
np.random.seed(1)
upper = 2;
lower = 1;
v = np.floor((np.random.rand(1,10) * (upper-lower+1)) + lower).astype(np.int64)
Note that this is not the best way to produce integers in a given range, this method is biased because the input random numbers can obtain only a set of discrete values, and these discrete values do not necessarily distribute uniformly within the set of output discrete values. Of course the effect is very small, and might not be important for your application. For more details on this, and a correct (but more complex) algorithm, see this anser.

Python Lottery Number Generation

I am working on a lottery number generation program. I have a fixed list of allowed numbers (1-80) from which users can choose 6 numbers. Each number can only be picked once. I want to generate all possible combinations efficiently. Current implementation takes more than 30 seconds if allowed_numbers is [1,...,60]. Above that, it freezes my system.
from itertools import combinations
import numpy as np
LOT_SIZE = 6
allowed_numbers = np.arange(1, 61)
all_combinations = np.array(list(combinations(allowed_numbers, LOT_SIZE)))
print(len(all_combinations))
I think I would need a numpy array (not sure if 2D). Something like,
[[1,2,3,4,5,6],
[1,2,3,4,5,,7],...]
because I want to (quickly) perform several operations on these combinations. These operations may include,
Removing combinations that have only even numbers
Removing combinations who's sum is greater than 150 etc.
Checking if there is only one pair of consecutive numbers (Acceptable: [1,2,4,6,8,10] {Pair: (1,2)}| Not-acceptable: [1,2,4,5,7,9] {Pairs: (1,2) and (4,5)} )
Any help will be appreciated.
Thanks
Some options:
1) apply filters on the iterable instead of on the data, using filter:
def filt(x):
return sum(x) < 7
list(filter(filt, itertools.combinations(allowed, n)))
will save ~15% time vs. constructing the list and applying the filters then, i.e.:
[i for i in itertools.combinations(allowed, n) if filt(i) if filt(i)]
2) Use np.fromiter
arr = np.fromiter(itertools.chain.from_iterable(itertools.combinations(allowed, n)), int).reshape(-1, n)
return arr[arr.sum(1) < 7]
3) work on the generator object itself. In the example above, you can stop the itertools.combinations when the first number is above 7 (as an example):
def my_generator():
for i in itertools.combinations(allowed, n):
if i[0] >= 7:
return
elif sum(i) < 7:
yield i
list(my_generator()) # will build 3x times faster than option 1
Note that np.fromiter becomes less efficient on compound expressions, so the mask is applied afterwards
You can use itertools.combinations(allowed_numbers, 6) to get all combinations of length 6 from your list (this is the fastest way to get this operation done).

How to generate random variables and sum all them in python

My problem explicitly is
Z=sum_(i)^12 (x_i).
where i is indices and x_i's are random number...
I need an explicit code in Python to produce 12 random variables and sum all them.
I tried write code using if, while loop, but I could not get it.
I need your help...
In order to be able to use arbitrary variable just structure it as a function.
You can structure it similar to l82Munch, but this may be more readable for you since your just starting. Note that range is a generator function that returns a list up to the last call. So range(1,3) returns [1,2]
import random
def rand_sum(i, j):
sum_list = []
for rand_num in range(i, j+1):
sum_list.append(random.random()) # Check random docs for a function that returns
return sum(sum_list) # a different set of randoms if this isn't
# appropriate
import random
rand_sum = sum( random.random() for x in range(12) )
See the random documentation for more info.
In probabilistic modelling, you can define distributions then sum them.
Personally, I use OpenTURNS platform for that.
import openturns as ot
x1 = ot.Normal(0, 2) # Normal distribution mean = 0, std = 2
x2 = ot.Uniform(3, 5) # Uniform distribution between 3 and 5
sum = x1 + x2
That's it.
If x1,..., x12 are 12 distributions identically distributed you can write:
sum_12 = sum([x1] * 12)

Generating a set random list of integers based on a distribution

I hope I can explain this well, if I don't I'll try again.
I want to generate an array of 5 random numbers that all add up to 10 but whose allocation are chosen on an interval of [0,2n/m].
I'm using numpy.
The code I have so far looks like this:
import numpy as np
n=10
m=5
#interval that numbers are generated on
randNumbers= np.random.uniform(0,np.divide(np.multiply(2.0,n),fronts),fronts)
#Here I normalize the random numbers
normNumbers = np.divide(randNumbers,np.sum(randNumbers))
#Next I multiply the normalized numbers by n
newList = np.multiply(normNumbers,n)
#Round the numbers two whole numbers
finalList = np.around(newList)
This works for the most part, however the rounding is off, it will add up to 9 or 11 as opposed to 10. Is there a way to do what I'm trying to do without worrying about rounding errors, or maybe a way to work around them? If you would like for me to be more clear I can, because I have trouble explaining what I'm trying to do with this when talking :).
This generates all the possible combinations that sum to 10 and selects a random one
from itertools import product
from random import choice
n=10
m=5
finalList = choice([x for x in product(*[range(2*n/m+1)]*m) if sum(x) == 10])
There may be a more efficient way, but this will select fairly between the outcomes
Lets see how this works when n=10 and m=5
2*n/m+1 = 5, so the expression becomes
finalList = choice([x for x in product(*[range(5)]*5) if sum(x) == 10])
`*[range(5)]*5 is using argument unpacking. This is equivalent to
finalList = choice([x for x in product(range(5),range(5),range(5),range(5),range(5)) if sum(x) == 10])
product() gives the cartesian product of the parameters, which in this case has 5**5 elements, but we then filter out the ones that don't add to 10, which leaves a list of 381 values
choice() is used to select a random value from the resultant list
Just generate four of the numbers using the technique above, then subtract the sum of the four from 10 to pick the last number.

Categories