Skip to content

Commit 94438cd

Browse files
committed
Merge pull request #193 from QuantEcon/mc-fix
Fix: MarkovChain.simulate
2 parents 0f5cea6 + b767f69 commit 94438cd

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

quantecon/markov/core.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
8686
"""
8787
from __future__ import division
88+
import numbers
8889
import numpy as np
8990
from scipy import sparse
9091
from fractions import gcd
@@ -348,10 +349,18 @@ def simulate(self, ts_length, init=None, num_reps=None, random_state=None):
348349
random_state = check_random_state(random_state)
349350
dim = 1 # Dimension of the returned array: 1 or 2
350351

352+
msg_out_or_range = 'index {init} is out of the state space'
353+
351354
try:
352355
k = len(init) # init is an array
353356
dim = 2
354357
init_states = np.asarray(init, dtype=int)
358+
# Check init_states are in the state space
359+
if (init_states >= self.n).any() or (init_states < -self.n).any():
360+
idx = np.where(
361+
(init_states >= self.n) + (init_states < -self.n)
362+
)[0][0]
363+
raise ValueError(msg_out_or_range.format(init=idx))
355364
if num_reps is not None:
356365
k *= num_reps
357366
init_states = np.tile(init_states, num_reps)
@@ -362,7 +371,10 @@ def simulate(self, ts_length, init=None, num_reps=None, random_state=None):
362371
k = num_reps
363372
if init is None:
364373
init_states = random_state.randint(self.n, size=k)
365-
elif isinstance(init, int):
374+
elif isinstance(init, numbers.Integral):
375+
# Check init is in the state space
376+
if init >= self.n or init < -self.n:
377+
raise ValueError(msg_out_or_range.format(init=init))
366378
init_states = np.ones(k, dtype=int) * init
367379
else:
368380
raise ValueError(
@@ -526,7 +538,7 @@ def mc_sample_path(P, init=0, sample_size=1000, random_state=None):
526538
"""
527539
random_state = check_random_state(random_state)
528540

529-
if isinstance(init, int):
541+
if isinstance(init, numbers.Integral):
530542
X_0 = init
531543
else:
532544
cdf0 = np.cumsum(init)

quantecon/markov/tests/test_core.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,21 @@ def test_simulate_init_array_num_reps():
267267
assert_array_equal(X[:, 0], init*num_reps)
268268

269269

270+
def test_simulate_init_type():
271+
P = [[0.4, 0.6], [0.2, 0.8]]
272+
mc = MarkovChain(P)
273+
274+
seed = 0
275+
ts_length = 3
276+
init = 0 # int
277+
X = mc.simulate(ts_length, init=init, random_state=seed)
278+
279+
inits_np_int = [t(init) for t in [np.int32, np.int64]]
280+
for init in inits_np_int:
281+
X_np_int = mc.simulate(ts_length, init=init, random_state=seed)
282+
assert_array_equal(X_np_int, X)
283+
284+
270285
def test_simulate_dense_vs_sparse():
271286
n = 5
272287
a = 1/3
@@ -393,6 +408,18 @@ def test_raises_value_error_non_sum_one():
393408
assert_raises(ValueError, MarkovChain, sparse.csr_matrix(P))
394409

395410

411+
def test_raises_value_error_simulate_init_out_of_range():
412+
P = [[0.4, 0.6], [0.2, 0.8]]
413+
mc = MarkovChain(P)
414+
415+
n = mc.n
416+
ts_length = 3
417+
assert_raises(ValueError, mc.simulate, ts_length, init=n)
418+
assert_raises(ValueError, mc.simulate, ts_length, init=-(n+1))
419+
assert_raises(ValueError, mc.simulate, ts_length, init=[0, n])
420+
assert_raises(ValueError, mc.simulate, ts_length, init=[0, -(n+1)])
421+
422+
396423
if __name__ == '__main__':
397424
import sys
398425
import nose

0 commit comments

Comments
 (0)