I have the following states and transition matrix
import numpy as np
n_states = 3
states = np.arange(n_states)
T = np.array([
[0.5, 0.5, 0],
[0.5, 0, 0.5],
[0, 0, 1]
])
I would like to simulate n_sims
paths where each path consist of n_steps
. Each path starts at 0. Therefore, I write
n_sims = 100
n_steps = 10
paths = np.zeros((n_sims, n_steps), dtype=int)
With the help of np.random.Generator.choice
I would like to "fill to the right" the paths using the transition matrix.
My attempt look as follows
rng = np.random.default_rng(seed=123)
for s in range(1, n_steps+1):
paths[:,s] = rng.choice(
a=n_states,
size=n_sim,
p=T[paths[:,s-1]]
)
This result in the following error:
ValueError: p must be 1-dimensional
How can I overcome this? If possible, I would like to prevent for-loops and vectorize the code.
IIUC, your process being inherently iterative, you won't benefit much from numpy's vectorization.
You might want to consider using pure python:
def simulation(T, n_states=3, n_sims=100, n_steps=10, seed=123):
rng = np.random.default_rng(seed)
start = np.zeros(n_steps, dtype=np.int64)
out = [start]
for i in range(n_sims-1):
a = np.array([rng.choice(n_states, p=T[x]) for x in start])
out.append(a)
start = a
return np.array(out)
simulation(T, n_states=3, n_sims=100, n_steps=10)
Example output:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 1, 1, 0, 1, 1],
[2, 0, 1, 0, 1, 2, 2, 0, 2, 2],
[2, 0, 0, 1, 0, 2, 2, 1, 2, 2],
[2, 1, 0, 2, 1, 2, 2, 2, 2, 2],
[2, 2, 0, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 0, 2, 1, 2, 2, 2, 2, 2],
[2, 2, 1, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 0, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 0, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 1, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 1, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 0, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 1, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 0, 2, 2, 2, 2, 2],
...
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]])