@@ -42,7 +42,7 @@ class MarkovChainSampler(object):
42
42
43
43
"""
44
44
45
- def __init__ (self , P , dt = 1 ):
45
+ def __init__ (self , P , dt = 1 , random_state = None ):
46
46
"""
47
47
Constructs a sampling object with transition matrix P. The results will be produced every dt'th time step
48
48
@@ -71,12 +71,26 @@ def __init__(self, P, dt=1):
71
71
# initialize mu
72
72
self .mudist = None
73
73
74
+ self .random_state = random_state
75
+
74
76
# generate discrete random value generators for each line
75
- self .rgs = np .ndarray (( self .n ) , dtype = object )
77
+ self .rgs = np .ndarray (self .n , dtype = object )
76
78
from scipy .stats import rv_discrete
77
- for i in range (self .n ):
78
- nz = np .nonzero (self .P [i ])
79
- self .rgs [i ] = rv_discrete (values = (nz , self .P [i , nz ]))
79
+ for i , row in enumerate (self .P ):
80
+ nz = row .nonzero ()[0 ]
81
+ self .rgs [i ] = rv_discrete (values = (nz , row [nz ]))
82
+
83
+ def _get_start_state (self ):
84
+ if self .mudist is None :
85
+ # compute mu, the stationary distribution of P
86
+ from ..analysis import stationary_distribution
87
+ from scipy .stats import rv_discrete
88
+
89
+ mu = stationary_distribution (self .P )
90
+ self .mudist = rv_discrete (values = (np .arange (self .n ), mu ))
91
+ # sample starting point from mu
92
+ start = self .mudist .rvs (random_state = self .random_state )
93
+ return start
80
94
81
95
def trajectory (self , N , start = None , stop = None ):
82
96
"""
@@ -97,22 +111,12 @@ def trajectory(self, N, start=None, stop=None):
97
111
stop = types .ensure_int_vector_or_None (stop , require_order = False )
98
112
99
113
if start is None :
100
- if self .mudist is None :
101
- # compute mu, the stationary distribution of P
102
- from ..analysis import stationary_distribution
103
- from scipy .stats import rv_discrete
104
-
105
- mu = stationary_distribution (self .P )
106
- self .mudist = rv_discrete (values = (np .arange (self .n ), mu ))
107
- # sample starting point from mu
108
- start = self .mudist .rvs ()
114
+ start = self ._get_start_state ()
109
115
110
116
# evaluate stopping set
111
- stopat = np .ndarray ((self .n ), dtype = bool )
112
- stopat [:] = False
113
- if (stop is not None ):
114
- for s in np .array (stop ):
115
- stopat [s ] = True
117
+ stopat = np .zeros (self .n , dtype = bool )
118
+ if stop is not None :
119
+ stopat [np .array (stop )] = True
116
120
117
121
# result
118
122
traj = np .zeros (N , dtype = int )
@@ -122,9 +126,10 @@ def trajectory(self, N, start=None, stop=None):
122
126
return traj [:1 ]
123
127
# else run until end or stopping state
124
128
for t in range (1 , N ):
125
- traj [t ] = self .rgs [traj [t - 1 ]].rvs ()
129
+ traj [t ] = self .rgs [traj [t - 1 ]].rvs (random_state = self . random_state )
126
130
if stopat [traj [t ]]:
127
- return traj [:t + 1 ]
131
+ traj = np .resize (traj , t + 1 )
132
+ break
128
133
# return
129
134
return traj
130
135
@@ -149,7 +154,7 @@ def trajectories(self, M, N, start=None, stop=None):
149
154
return trajs
150
155
151
156
152
- def generate_traj (P , N , start = None , stop = None , dt = 1 ):
157
+ def generate_traj (P , N , start = None , stop = None , dt = 1 , random_state = None ):
153
158
"""
154
159
Generates a realization of the Markov chain with transition matrix P.
155
160
@@ -167,18 +172,22 @@ def generate_traj(P, N, start=None, stop=None, dt=1):
167
172
dt : int
168
173
trajectory will be saved every dt time steps.
169
174
Internally, the dt'th power of P is taken to ensure a more efficient simulation.
175
+ random_state : None or int or numpy.random.RandomState instance, optional
176
+ This parameter defines the RandomState object to use for drawing random variates.
177
+ If None, the global np.random state is used. If integer, it is used to seed the local RandomState instance.
178
+ Default is None.
170
179
171
180
Returns
172
181
-------
173
182
traj_sliced : (N/dt, ) ndarray
174
183
A discrete trajectory with length N/dt
175
184
176
185
"""
177
- sampler = MarkovChainSampler (P , dt = dt )
186
+ sampler = MarkovChainSampler (P , dt = dt , random_state = random_state )
178
187
return sampler .trajectory (N , start = start , stop = stop )
179
188
180
189
181
- def generate_trajs (P , M , N , start = None , stop = None , dt = 1 ):
190
+ def generate_trajs (P , M , N , start = None , stop = None , dt = 1 , random_state = None ):
182
191
"""
183
192
Generates multiple realizations of the Markov chain with transition matrix P.
184
193
@@ -198,14 +207,18 @@ def generate_trajs(P, M, N, start=None, stop=None, dt=1):
198
207
dt : int
199
208
trajectory will be saved every dt time steps.
200
209
Internally, the dt'th power of P is taken to ensure a more efficient simulation.
210
+ random_state : None or int or numpy.random.RandomState instance, optional
211
+ This parameter defines the RandomState object to use for drawing random variates.
212
+ If None, the global np.random state is used. If integer, it is used to seed the local RandomState instance.
213
+ Default is None.
201
214
202
215
Returns
203
216
-------
204
217
traj_sliced : (N/dt, ) ndarray
205
218
A discrete trajectory with length N/dt
206
219
207
220
"""
208
- sampler = MarkovChainSampler (P , dt = dt )
221
+ sampler = MarkovChainSampler (P , dt = dt , random_state = random_state )
209
222
return sampler .trajectories (M , N , start = start , stop = stop )
210
223
211
224
@@ -235,12 +248,12 @@ def transition_matrix_metropolis_1d(E, d=1.0):
235
248
236
249
"""
237
250
# check input
238
- if ( d <= 0 or d > 1 ) :
251
+ if d <= 0 or d > 1 :
239
252
raise ValueError ('Diffusivity must be in (0,1]. Trying to set the invalid value' , str (d ))
240
253
# init
241
254
n = len (E )
242
255
P = np .zeros ((n , n ))
243
- # set offdiagonals
256
+ # set off diagonals
244
257
P [0 , 1 ] = 0.5 * d * min (1.0 , math .exp (- (E [1 ] - E [0 ])))
245
258
for i in range (1 , n - 1 ):
246
259
P [i , i - 1 ] = 0.5 * d * min (1.0 , math .exp (- (E [i - 1 ] - E [i ])))
0 commit comments