How to generate k percentages? [duplicate] - python

This question already has answers here:
Getting N random numbers whose sum is M
(9 answers)
Closed 8 months ago.
Given k a random integer between 2 and 7. How to generate a list of k positive numbers whose sum is equal to 1?
Examples of possible expected results:
k = 3 -> list = [0.23, 0.57, 0.2]
k = 3 -> list = [0.41, 0.44, 0.15]
K = 2 -> list = [0.95, 0.5]

You can generate k random numbers (for example in the range 0-1), then divide by their sum.
Example with numpy (for efficiency):
k = 3
import numpy as np
a = np.random.random(k)
out = (a/a.sum()).tolist()
pure python:
k = 3
import random
l = [random.random() for _ in range(k)]
s = sum(l)
out = [e/s for e in l]
example: [0.27830153962545046, 0.19826407925979248, 0.523434381114757]

I hope you are well.
you can use this code to do this:
import numpy as np
def softmax(x):
res = np.exp(x - np.max(x))
return res / res.sum()
size=5
list=np.random.random(size)
list=softmax(list)

Using a infinite loop which break once get all k numbers. Repeated numbers may occurs.
import random
#random.seed(3) # for testing purposes
k = 5
partition_of_unit = []
while True:
if len(partition_of_unit) == k-1:
break
n = random.random()
if sum(partition_of_unit) + n < 1:
partition_of_unit.append(n)
partition_of_unit.append(1-sum(partition_of_unit))
print(partition_of_unit)
#[0.6229016948897019, 0.029005228283614737, 0.11320596465314436, 0.013114189588902203, 0.22177292258463677]
print(sum(partition_of_unit))
#1.0

Related

How do I run this function for multiple values of N?

I am trying to run the code below for N = np.linspace(20,250,47), but I get multiple errors when trying to change the N. I am new to python and am not sure how to get multiple values of this function using multiple values of N. Below is the code with N = 400 and it does work, but I am not sure how to make it work for multiple N's at the same time.
import matplotlib.pyplot as plt
import numpy as np
S0 = 9
K = 10
T = 3
r = 0.06
sigma = 0.3
N = 400
dt = T / N
u = exp(sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
d = exp(-sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
p = 0.5
def binomial_tree_put(N, T, S0, sigma, r, K, array_out=False):
dt = T / N
u = exp(sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
d = exp(-sigma*sqrt(dt)+(r-0.5*sigma**2)*dt)
p = 0.5
price_tree = np.zeros([N+1,N+1])
for i in range(N+1):
for j in range(i+1):
price_tree[j,i] = S0*(d**j)*(u**(i-j))
option = np.zeros([N+1,N+1])
option[:,N] = np.maximum(np.zeros(N+1), K - price_tree[:,N])
for i in np.arange(N-1, -1, -1):
for j in np.arange(0, i+1):
option[j, i] = np.exp(-r*dt)*(p*option[j, i+1]+(1-p)*option[j+1, i+1])
if array_out:
return [option[0,0], price_tree, option]
else:
return option[0,0]
Suppose you have a list of values for N e.g N = [400, 300, 500, 800], then you need to call the function for every value, you can use a loop for that.
For example,
for num in N:
binomial_tree_put(num, *other arguments*)
np.linspace() creates an np.array but the function expects a sinlge integer. If you want to execute a function for each element contained inside a array/list, you can do that inside a loop like this:
# your code as defined above goes here
for num in np.linspace(20,250,47):
N = int(num) # you could just put N in the line above - this is just to illustrate
binomial_tree_put(N, T, S0, sigma, r, K, array_out=False)
Be aware, depending on how long your function takes to execute and how many elements are in your iterable (e.g. 47 for your case), it may take a while to execute.
Edit: I also noticed you seem to be missing an import in your example code. exp() and sqrt() are part of the math module.
You can also use partial function, like this:
from functools import partial
N = [1, 2, ...] # all your N values
binom_fct = partial(binomial_tree_put, T=T, S0=S0, sigma=sigma, r=r, K=K, array_out=array_out)
for num in N:
binom_fct(num)
partial help here

Filling up a NumPy array based on the index of the element

Assume:
u = 1.2
d = 0.8
n = 3
I was wondering how I can get an array with 3 (n) elements where the value of each element is:
The solution to variables above would be:
[1.2^2 + 0.8^0, 1.2^1 + 0.8^1, 1.2^0 + 0.8^1]
Thanks!
You could achieve this with Basic slicing and indexing.
import numpy as np
u=1.2
d=0.8
n=3
array=np.zeros(n)
for i in range(n):
if i + 1 <= n:
array[i:n]=u**(n-i-1)
array[i:n] =d**(i)

itertools combinations in tandem with looping

I have the following Python code. Because random is being used, it generates a new answer every time:
import random
import numpy as np
N = 64 # Given
T = 5 # Given
FinalLengths = []
for i in range(T):
c = range(1, N)
x = random.sample(c, 2) # Choose 2 random numbers between 1 and N-1
LrgstNode = max(x)
SmlstNode = min(x)
RopeLengths = [SmlstNode, LrgstNode - SmlstNode, N - LrgstNode]
S = max(RopeLengths)
N = S
FinalLengths.append(S)
avgS = np.mean(FinalLengths) # Find average
print("The mean of S is {}".format(avgS))
My research has led me to possibly using itertools combinations in order to produce all possible combinations within the range and get the avg to converge. If so, how?
Thank you.
It sounds like you're after something like this:
import random
import numpy as np
from itertools import combinations
N = 64 # Given
T = 5 # Given
FinalLengths = []
for i in range(T):
c = list(range(1, N))
for x in combinations(c, 2):
S = max([min(x), max(x) - min(x), N - max(x)])
N = S
FinalLengths.append(S)
avgS = np.mean(FinalLengths) # Find average
print("The mean of S is {}".format(avgS))
To use combinations(l, size) we can pass in a list l and the size of each combination tuple, and int size. That's all there is to it!

Generate an array of N elements containing the first n values of z_n

I have been given the following assignment:
Write a function that can generate an array with N elements. The values are mathematically defined as:
z_n = alpha (1+sqrt{3})^n + beta (1-sqrt{3})^n for all n>=1
The number of elements and the two real numbers alpha and beta are given as input. Output should be a vector with the first n values.
Along with this code, which I have to complete:
def make_sequence(N:int, alpha:float, beta:float) -> np.ndarray:
return
This is what I have been able to come up with:
def make_sequence(N:int, alpha:float, beta:float) -> np.ndarray:
z_n = np.empty((N, 1))
N = 10
n = 1
for alpha in range(1, N):
z_n[n] = alpha*(1+sqrt(3))^n + beta*(1-sqrt(3))^n
n += 1
return z_n
Can anybody help me get it right?
The problem: the ^ is the bitwise xor operation, not power. In that case you can use **. Furthermore you assign to alpha in the for loop.
So you can solve it like:
def make_sequence(N:int, alpha:float, beta:float) -> np.ndarray:
result = np.empty((N, 1))
for n in range(1, N+1):
result[n-1] = alpha*(1+sqrt(3))**n + beta*(1-sqrt(3))**n
return result
Nevertheless, you can make it more declarative by first generate an arange, and then use broadcasting:
def make_sequence(N:int, alpha:float, beta:float) -> np.ndarray:
result = np.arange(1,N+1)
return alpha*(1+sqrt(3))**result + beta*(1-sqrt(3))**result
For 10 elements with alpha=0.5 and beta=0.25, we get:
>>> make_sequence(10,0.5,0.25)
array([ 1.18301270e+00, 3.86602540e+00, 1.00980762e+01,
2.79282032e+01, 7.60525589e+01, 2.07961524e+02,
5.68028166e+02, 1.55197938e+03, 4.24001509e+03,
1.15839890e+04])

python: random sample with probabilities [duplicate]

This question already has answers here:
Weighted random sample in python
(6 answers)
Generate random numbers with a given (numerical) distribution
(13 answers)
Closed 7 years ago.
Suppose I want to create a sample of N elements chosen from [1,2,3] such that 1, 2 and 3 will be represented with weights 0.4,0.4 and 0.2 respectively. How would I do this.
I know how to do it in R without using loops:
mySample <- sample(c(1,2,3),size = 100,replace=T,prob = c(.4,.4,.2))
You can generate a random number in [0,1) then if it is in [0,.4) pick "1", else if it is in [.4,.8) pick "2" and else pick "3". the code is:
from random import random;
N = 10;
elements = [1,2,3];
weights = [.4, .4 , .2];
samples = range(N);
r = 0;
temp = 0;
for i in range(10):
r = random();
temp = 0;
for j in range(len(elements)):
temp += weights[j];
if(temp>r):
samples[i] = elements[j];
break;

Categories