Exemple #1
0
def test_simulate_issue591():
    """
    Test MarkovChasin.simulate for P with dtype=np.float32
    https://github.com/QuantEcon/QuantEcon.py/issues/591
    """
    num_states = 5
    transition_states = 4

    transition_seed = 2
    random_state = np.random.RandomState(transition_seed)
    transitions = random_state.uniform(0., 1., transition_states)
    transitions /= np.sum(transitions)
    P = np.zeros((num_states, num_states), dtype=np.float32)
    P[0, :transition_states] = transitions
    P[1:, 0] = 1.
    mc = MarkovChain(P=P)

    simulate_seed = 22220
    ts_length = 10000
    seq = mc.simulate(ts_length=ts_length,
                      init=0,
                      num_reps=1,
                      random_state=simulate_seed)
    max_state_in_seq = np.max(seq)

    assert_array_less(max_state_in_seq, num_states)
Exemple #2
0
def test_simulate_init_array_num_reps():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    ts_length = 10
    init = [0, 1]
    num_reps = 3

    X = mc.simulate(ts_length, init, num_reps)
    assert_array_equal(X[:, 0], init * num_reps)
Exemple #3
0
def test_simulate_init_array_num_reps():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    ts_length = 10
    init=[0, 1]
    num_reps=3

    X = mc.simulate(ts_length, init, num_reps)
    assert_array_equal(X[:, 0], init*num_reps)
Exemple #4
0
def test_simulate_init_type():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    seed = 0
    ts_length = 3
    init = 0  # int
    X = mc.simulate(ts_length, init=init, random_state=seed)

    inits_np_int = [t(init) for t in [np.int32, np.int64]]
    for init in inits_np_int:
        X_np_int = mc.simulate(ts_length, init=init, random_state=seed)
        assert_array_equal(X_np_int, X)
Exemple #5
0
def test_simulate_init_type():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    seed = 0
    ts_length = 3
    init = 0  # int
    X = mc.simulate(ts_length, init=init, random_state=seed)

    inits_np_int = [t(init) for t in [np.int32, np.int64]]
    for init in inits_np_int:
        X_np_int = mc.simulate(ts_length, init=init, random_state=seed)
        assert_array_equal(X_np_int, X)
Exemple #6
0
def test_simulate_ergodicity():
    P = [[0.4, 0.6], [0.2, 0.8]]
    stationary_dist = [0.25, 0.75]
    init = 0
    mc = MarkovChain(P)

    seed = 4433
    ts_length = 100
    num_reps = 300
    tol = 0.1

    x = mc.simulate(ts_length, init=init, num_reps=num_reps, random_state=seed)
    frequency_1 = x[:, -1].mean()
    ok_(np.abs(frequency_1 - stationary_dist[1]) < tol)
Exemple #7
0
def test_simulate_ergodicity():
    P = [[0.4, 0.6], [0.2, 0.8]]
    stationary_dist = [0.25, 0.75]
    init = 0
    mc = MarkovChain(P)

    seed = 4433
    ts_length = 100
    num_reps = 300
    tol = 0.1

    x = mc.simulate(ts_length, init=init, num_reps=num_reps, random_state=seed)
    frequency_1 = x[:, -1].mean()
    ok_(np.abs(frequency_1 - stationary_dist[1]) < tol)
Exemple #8
0
def test_mc_stationary_distributions_state_values():
    P = [[0.4, 0.6, 0], [0.2, 0.8, 0], [0, 0, 1]]
    state_values = ['a', 'b', 'c']
    mc = MarkovChain(P, state_values=state_values)
    stationary_dists_expected = [[0.25, 0.75, 0], [0, 0, 1]]
    stationary_dists = mc.stationary_distributions
    assert_allclose(stationary_dists, stationary_dists_expected)
Exemple #9
0
def test_simulate_dense_vs_sparse():
    n = 5
    a = 1 / 3
    b = (1 - a) / 2
    P = np.zeros((n, n))
    for i in range(n):
        P[i, (i - 1) % n], P[i, i], P[i, (i + 1) % n] = b, a, b
    mcs = [MarkovChain(P), MarkovChain(sparse.csr_matrix(P))]

    ts_length = 10
    inits = (None, 0, [0, 1])
    num_repss = (None, 2)

    random_state = 0
    for init, num_reps in itertools.product(inits, num_repss):
        assert_array_equal(
            *(mc.simulate(ts_length, init, num_reps, random_state=random_state)
              for mc in mcs))
Exemple #10
0
    def setUp(self):
        state_values = [[0, 1], [2, 3], [4, 5]]  # Pass python list
        self.state_values = np.array(state_values)

        self.mc_reducible_dict = {
            'mc': MarkovChain([[1, 0, 0], [1, 0, 0], [0, 0, 1]],
                              state_values=state_values),
            'coms': [[0], [1], [2]],
            'recs': [[0], [2]]
        }

        self.mc_periodic_dict = {
            'mc': MarkovChain([[0, 1, 0], [0, 0, 1], [1, 0, 0]],
                              state_values=state_values),
            'coms': [[0, 1, 2]],
            'recs': [[0, 1, 2]],
            'cycs': [[0], [1], [2]]
        }
Exemple #11
0
def test_raises_value_error_simulate_init_out_of_range():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    n = mc.n
    ts_length = 3
    assert_raises(ValueError, mc.simulate, ts_length, init=n)
    assert_raises(ValueError, mc.simulate, ts_length, init=-(n + 1))
    assert_raises(ValueError, mc.simulate, ts_length, init=[0, n])
    assert_raises(ValueError, mc.simulate, ts_length, init=[0, -(n + 1)])
Exemple #12
0
def test_simulate_shape():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    (ts_length, init, num_reps) = (10, None, None)
    assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                       (ts_length,))

    (ts_length, init, num_reps) = (10, [0, 1], None)
    assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                       (len(init), ts_length))

    (ts_length, init, num_reps) = (10, [0, 1], 3)
    assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                       (len(init)*num_reps, ts_length))

    for (ts_length, init, num_reps) in [(10, None, 3), (10, None, 1)]:
        assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                           (num_reps, ts_length))
Exemple #13
0
    def setUp(self):
        """ Setup a KMRMarkovMatrix and Compute Stationary Values """
        self.P = KMR_Markov_matrix_sequential(self.N, self.p, self.epsilon)
        self.mc = MarkovChain(self.P)
        self.stationary = self.mc.stationary_distributions
        stat_shape = self.stationary.shape

        if len(stat_shape) == 1:
            self.n_stat_dists = 1
        else:
            self.n_stat_dists = stat_shape[0]
Exemple #14
0
def test_simulate_shape():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mcs = [MarkovChain(P), MarkovChain(sparse.csr_matrix(P))]

    for mc in mcs:
        (ts_length, init, num_reps) = (10, None, None)
        assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                           (ts_length,))

        (ts_length, init, num_reps) = (10, [0, 1], None)
        assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                           (len(init), ts_length))

        (ts_length, init, num_reps) = (10, [0, 1], 3)
        assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                           (len(init)*num_reps, ts_length))

        for (ts_length, init, num_reps) in [(10, None, 3), (10, None, 1)]:
            assert_array_equal(mc.simulate(ts_length, init, num_reps).shape,
                               (num_reps, ts_length))
Exemple #15
0
def test_get_index():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    eq_(mc.get_index(0), 0)
    eq_(mc.get_index(1), 1)
    assert_raises(ValueError, mc.get_index, 2)
    assert_array_equal(mc.get_index([1, 0]), [1, 0])
    assert_raises(ValueError, mc.get_index, [[1]])

    mc.state_values = [1, 2]
    eq_(mc.get_index(1), 0)
    eq_(mc.get_index(2), 1)
    assert_raises(ValueError, mc.get_index, 0)
    assert_array_equal(mc.get_index([2, 1]), [1, 0])
    assert_raises(ValueError, mc.get_index, [[1]])

    mc.state_values = [[1, 2], [3, 4]]
    eq_(mc.get_index([1, 2]), 0)
    assert_raises(ValueError, mc.get_index, 1)
    assert_array_equal(mc.get_index([[3, 4], [1, 2]]), [1, 0])
Exemple #16
0
def test_simulate_for_matrices_with_C_F_orders():
    """
    Test MarkovChasin.simulate for matrices with C- and F-orders
    See the issue and fix on Numba:
    github.com/numba/numba/issues/1103
    github.com/numba/numba/issues/1104
    """
    P_C = np.array([[0.5, 0.5], [0, 1]], order='C')
    P_F = np.array([[0.5, 0.5], [0, 1]], order='F')
    init = 1
    ts_length = 10
    sample_path = np.ones(ts_length, dtype=int)

    computed_C_and_F = \
        MarkovChain(np.array([[1.]])).simulate(ts_length, init=0)
    assert_array_equal(computed_C_and_F, np.zeros(ts_length, dtype=int))

    computed_C = MarkovChain(P_C).simulate(ts_length, init)
    computed_F = MarkovChain(P_F).simulate(ts_length, init=init)
    assert_array_equal(computed_C, sample_path)
    assert_array_equal(computed_F, sample_path)
Exemple #17
0
def test_get_index():
    P = [[0.4, 0.6], [0.2, 0.8]]
    mc = MarkovChain(P)

    eq_(mc.get_index(0), 0)
    eq_(mc.get_index(1), 1)
    assert_raises(ValueError, mc.get_index, 2)
    assert_array_equal(mc.get_index([1, 0]), [1, 0])
    assert_raises(ValueError, mc.get_index, [[1]])

    mc.state_values = [1, 2]
    eq_(mc.get_index(1), 0)
    eq_(mc.get_index(2), 1)
    assert_raises(ValueError, mc.get_index, 0)
    assert_array_equal(mc.get_index([2, 1]), [1, 0])
    assert_raises(ValueError, mc.get_index, [[1]])

    mc.state_values = [[1, 2], [3, 4]]
    eq_(mc.get_index([1, 2]), 0)
    assert_raises(ValueError, mc.get_index, 1)
    assert_array_equal(mc.get_index([[3, 4], [1, 2]]), [1, 0])
Exemple #18
0
def test_raises_value_error_non_2dim():
    """Test with non 2dim input"""
    mc = MarkovChain(np.array([0.4, 0.6]))
Exemple #19
0
def test_raises_value_error_non_sym():
    """Test with non symmetric input"""
    mc = MarkovChain(np.array([[0.4, 0.6]]))
Exemple #20
0
def test_raises_value_error_non_nonnegative():
    """Test with non nonnegative input"""
    mc = MarkovChain(np.array([[0.4, 0.6], [-0.2, 1.2]]))
Exemple #21
0
def test_raises_value_error_non_sum_one():
    """Test with input such that some of the rows does not sum to one"""
    mc = MarkovChain(np.array([[0.4, 0.6], [0.2, 0.9]]))
Exemple #22
0
def test_markovchain_pmatrices():
    """
    Test the methods of MarkovChain, as well as mc_compute_stationary,
    with P matrix and known solutions
    """
    # Matrix with two recurrent classes [0, 1] and [3, 4, 5],
    # which have periods 2 and 3, respectively
    Q = np.zeros((6, 6))
    Q[0, 1], Q[1, 0] = 1, 1
    Q[2, [0, 3]] = 1 / 2
    Q[3, 4], Q[4, 5], Q[5, 3] = 1, 1, 1
    Q_stationary_dists = \
        np.array([[1/2, 1/2, 0, 0, 0, 0], [0, 0, 0, 1/3, 1/3, 1/3]])

    testset = [
        {
            'P': np.array([[0.4, 0.6], [0.2, 0.8]]),  # P matrix
            'stationary_dists': np.array([[0.25, 0.75]]),  # Known solution
            'comm_classes': [np.arange(2)],
            'rec_classes': [np.arange(2)],
            'is_irreducible': True,
            'period': 1,
            'is_aperiodic': True,
            'cyclic_classes': [np.arange(2)],
        },
        {
            'P': sparse.csr_matrix([[0.4, 0.6], [0.2, 0.8]]),
            'stationary_dists': np.array([[0.25, 0.75]]),
            'comm_classes': [np.arange(2)],
            'rec_classes': [np.arange(2)],
            'is_irreducible': True,
            'period': 1,
            'is_aperiodic': True,
            'cyclic_classes': [np.arange(2)],
        },
        {
            'P': np.array([[0, 1], [1, 0]]),
            'stationary_dists': np.array([[0.5, 0.5]]),
            'comm_classes': [np.arange(2)],
            'rec_classes': [np.arange(2)],
            'is_irreducible': True,
            'period': 2,
            'is_aperiodic': False,
            'cyclic_classes': [np.array([0]), np.array([1])],
        },
        {
            'P': np.eye(2),
            'stationary_dists': np.array([[1, 0], [0, 1]]),
            'comm_classes': [np.array([0]), np.array([1])],
            'rec_classes': [np.array([0]), np.array([1])],
            'is_irreducible': False,
            'period': 1,
            'is_aperiodic': True,
        },
        # Reducible mc with a unique recurrent class,
        # where n-1 is a transient state
        {
            'P': np.array([[1, 0], [1, 0]]),
            'stationary_dists': np.array([[1, 0]]),
            'comm_classes': [np.array([0]), np.array([1])],
            'rec_classes': [np.array([0])],
            'is_irreducible': False,
            'period': 1,
            'is_aperiodic': True,
        },
        {
            'P': Q,
            'stationary_dists': Q_stationary_dists,
            'comm_classes':
            [np.array([0, 1]),
             np.array([2]),
             np.array([3, 4, 5])],
            'rec_classes': [np.array([0, 1]),
                            np.array([3, 4, 5])],
            'is_irreducible': False,
            'period': 6,
            'is_aperiodic': False,
        },
        {
            'P': sparse.csr_matrix(Q),
            'stationary_dists': Q_stationary_dists,
            'comm_classes':
            [np.array([0, 1]),
             np.array([2]),
             np.array([3, 4, 5])],
            'rec_classes': [np.array([0, 1]),
                            np.array([3, 4, 5])],
            'is_irreducible': False,
            'period': 6,
            'is_aperiodic': False,
        }
    ]

    # Loop Through TestSet #
    for test_dict in testset:
        mc = MarkovChain(test_dict['P'])
        computed = mc.stationary_distributions
        assert_allclose(computed, test_dict['stationary_dists'])

        assert (mc.num_communication_classes == len(test_dict['comm_classes']))
        assert (mc.is_irreducible == test_dict['is_irreducible'])
        assert (mc.num_recurrent_classes == len(test_dict['rec_classes']))
        list_of_array_equal(
            sorted(mc.communication_classes, key=lambda x: x[0]),
            sorted(test_dict['comm_classes'], key=lambda x: x[0]))
        list_of_array_equal(
            sorted(mc.recurrent_classes, key=lambda x: x[0]),
            sorted(test_dict['rec_classes'], key=lambda x: x[0]))
        assert (mc.period == test_dict['period'])
        assert (mc.is_aperiodic == test_dict['is_aperiodic'])
        try:
            list_of_array_equal(
                sorted(mc.cyclic_classes, key=lambda x: x[0]),
                sorted(test_dict['cyclic_classes'], key=lambda x: x[0]))
        except NotImplementedError:
            assert (mc.is_irreducible is False)

        # Test of mc_compute_stationary
        computed = mc_compute_stationary(test_dict['P'])
        assert_allclose(computed, test_dict['stationary_dists'])
Exemple #23
0
def test_light_bulb_replacement():
    """
    How many of the bulbs on average will have to be replaced each month?
        How much the budget for the repairs should be?
    Time of fauliure is uncertain
        variety of maintenance optioins
    failed bulbs are replaced monthly - use this for time intervals for dist
    """
    # Define state space, the age of the bulb
    state_space = [0, 1, 2, 3, 4]  # new, 1 month, 2 month, etc.
    num_states = len(state_space)
    num_bulbs = 1_000
    # probability of bulb failing based on age of bulb in months
    prob = [0.5, 0.1, 0.1, 0.1, 0.2]
    cdf = np.cumsum(prob)
    cond_prob = [
        p / (1 - cdf[ind - 1]) if ind > 0 else p for ind, p in enumerate(prob)
    ]
    cond_prob[-1] = 1  # roundoff error overriding
    transition_matrix = np.zeros(shape=(num_states, num_states))
    transition_matrix[:, 0] = cond_prob
    for row in range(num_states - 1):
        transition_matrix[row, row + 1] = 1 - transition_matrix[row, 0]

    # Costs of inspecting & replacing light bulbs
    inspect_cost = 0.10
    replace_cost = 2
    test_cost_vector = [
        inspect_cost + replace_cost * transition_matrix[x, 0]
        for x in range(num_states)
    ]
    inspect_vector = [inspect_cost] * num_states
    replace_matrix = np.array([[replace_cost] * num_states] +
                              ([[0] * num_states] * (num_states - 1))).T

    # Transient probabilities
    #  all bulbs start at age 0 (new sign)
    #  estimate how many bulbs will be replaced during each of first 12 months?
    # q(n): probability dist for age of bulb at time n
    test_q = np.array([[1, 0, 0, 0, 0]])  # row 0 is q(0), row 1 is q(1), etc.
    # q_n = q_(n-1) * P
    for _ in range(1, 13):  # for the 12 months
        test_q = np.vstack((test_q, np.matmul(test_q[-1], transition_matrix)))
    # Calculate expected transient costs - don't include month 0
    exp_trans_cost = np.delete(np.matmul(test_q, test_cost_vector), 0)
    test_trans_cost = sum(exp_trans_cost) * num_bulbs
    print("test trans cost: ", test_trans_cost)
    num_replaced = int(sum(test_q[1:, 0]) * num_bulbs)
    print("Num Replaced: ", num_replaced)

    # Steady state probabilities
    # for discrete-time markov chains, as long as each state can be
    #  reached from every other state, the transient probabilities
    #  will approach equilibrium.
    markov_obj = MarkovChain(P=transition_matrix, state_values=state_space)
    test_steady_state = markov_obj.stationary_distributions
    print('steady state: ', test_steady_state)

    analysis = analyze_dtmc(transition_matrix,
                            state_space,
                            trans_kwargs={
                                "ts_length": 12,
                                "init": [1, 0, 0, 0, 0]
                            },
                            cost_kwargs={
                                "state": inspect_vector,
                                "transition": replace_matrix,
                                "num": num_bulbs
                            })
    test = {
        'cdfs':
        np.array([[0.5, 1., 1., 1., 1.], [0.2, 0.2, 1., 1., 1.],
                  [0.25, 0.25, 0.25, 1., 1.],
                  [0.33333333, 0.33333333, 0.33333333, 0.33333333, 1.],
                  [1., 1., 1., 1., 1.]]),
        'steady_state': {
            'cost': {
                'kwargs': {
                    'num':
                    1000,
                    'state': [0.1, 0.1, 0.1, 0.1, 0.1],
                    'transition':
                    np.array([[2, 0, 0, 0, 0], [2, 0, 0, 0,
                                                0], [2, 0, 0, 0, 0],
                              [2, 0, 0, 0, 0], [2, 0, 0, 0, 0]])
                },
                'total': 933.3333333333333,
                'vector': 0.9333333333333332
            },
            'output':
            np.array([0.41666667, 0.20833333, 0.16666667, 0.125, 0.08333333])
        },
        'transient': {
            'cost': {
                'kwargs': {
                    'num':
                    1000,
                    'state': [0.1, 0.1, 0.1, 0.1, 0.1],
                    'transition':
                    np.array([[2, 0, 0, 0, 0], [2, 0, 0, 0,
                                                0], [2, 0, 0, 0, 0],
                              [2, 0, 0, 0, 0], [2, 0, 0, 0, 0]])
                },
                'total':
                12009.303421875004,
                'vector':
                np.array([
                    1.1, 0.8, 0.75, 0.795, 1.0825, 0.99575, 0.920625,
                    0.8976375, 0.90770625, 0.95175438, 0.94762406, 0.93364684,
                    0.92705939
                ])
            },
            'kwargs': {
                'init': [1, 0, 0, 0, 0],
                'ts_length': 12
            },
            'output':
            np.array(
                [[1., 0., 0., 0., 0.], [0.5, 0.5, 0., 0., 0.],
                 [0.35, 0.25, 0.4, 0.,
                  0.], [0.325, 0.175, 0.2, 0.3,
                        0.],
                 [0.3475, 0.1625, 0.14, 0.15,
                  0.2], [0.49125, 0.17375, 0.13, 0.105,
                         0.1], [0.447875, 0.245625, 0.139, 0.0975, 0.07],
                 [0.4103125, 0.2239375, 0.1965, 0.10425, 0.065],
                 [0.39881875, 0.20515625, 0.17915, 0.147375, 0.0695],
                 [0.40385313, 0.19940938, 0.164125, 0.1343625, 0.09825],
                 [0.42587719, 0.20192656, 0.1595275, 0.12309375, 0.089575],
                 [0.42381203, 0.21293859, 0.16154125, 0.11964563, 0.0820625],
                 [0.41682342, 0.21190602, 0.17035088, 0.12115594, 0.07976375]])
        }
    }
    # Assert two dictionaries have equal values
    assert all(is_analysis_equal(analysis, test))
    # Assert that both have the same keys
    assert test.keys() == analysis.keys()
    assert test['steady_state'].keys() == analysis["steady_state"].keys()
    assert test['steady_state']['cost'].keys() == \
        analysis['steady_state']['cost'].keys()
    assert test['steady_state']['cost']['kwargs'].keys() == \
        analysis['steady_state']['cost']['kwargs'].keys()

    assert test['transient'].keys() == analysis["transient"].keys()
    assert test['transient']["kwargs"].keys() == \
        analysis["transient"]["kwargs"].keys()
    assert test['transient']['cost'].keys() == \
        analysis['transient']['cost'].keys()
    assert test['transient']['cost']['kwargs'].keys() == \
        analysis['transient']['cost']['kwargs'].keys()

    # Test print_markov
    captured_output = io.StringIO()
    sys.stdout = captured_output
    print_markov(analysis)
    sys.stdout = sys.__stdout__  # reset stdout
    test_str = ("CDFs:\n"
                "[[0.5        1.         1.         1.         1.        ]\n"
                " [0.2        0.2        1.         1.         1.        ]\n"
                " [0.25       0.25       0.25       1.         1.        ]\n"
                " [0.33333333 0.33333333 0.33333333 0.33333333 1.        ]\n"
                " [1.         1.         1.         1.         1.        ]]\n"
                "\nSteady State Probs:\n"
                "[0.41666667 0.20833333 0.16666667 0.125      0.08333333]\n\n"
                "Transient Probabilities (length 12)\n"
                "Initial Conditions:\n"
                "[1, 0, 0, 0, 0]\n"
                "Output:\n"
                "[[1.         0.         0.         0.         0.        ]\n"
                " [0.5        0.5        0.         0.         0.        ]\n"
                " [0.35       0.25       0.4        0.         0.        ]\n"
                " [0.325      0.175      0.2        0.3        0.        ]\n"
                " [0.3475     0.1625     0.14       0.15       0.2       ]\n"
                " [0.49125    0.17375    0.13       0.105      0.1       ]\n"
                " [0.447875   0.245625   0.139      0.0975     0.07      ]\n"
                " [0.4103125  0.2239375  0.1965     0.10425    0.065     ]\n"
                " [0.39881875 0.20515625 0.17915    0.147375   0.0695    ]\n"
                " [0.40385313 0.19940938 0.164125   0.1343625  0.09825   ]\n"
                " [0.42587719 0.20192656 0.1595275  0.12309375 0.089575  ]\n"
                " [0.42381203 0.21293859 0.16154125 0.11964563 0.0820625 ]\n"
                " [0.41682342 0.21190602 0.17035088 0.12115594 0.07976375]]\n"
                "\nCost kwargs:\n"
                "{'state': [0.1, 0.1, 0.1, 0.1, 0.1], 'transition': "
                "array([[2, 0, 0, 0, 0],\n"
                "       [2, 0, 0, 0, 0],\n"
                "       [2, 0, 0, 0, 0],\n"
                "       [2, 0, 0, 0, 0],\n"
                "       [2, 0, 0, 0, 0]]), 'num': 1000}\n"
                "Expected Steady State Cost:\n"
                "$0.93\n"
                "Expected Total Steady State Cost: $933.33\n"
                "Expected Transient Cost:\n"
                "[1.1        0.8        0.75       0.795      1.0825"
                "     0.99575\n"
                " 0.920625   0.8976375  0.90770625 0.95175438 0.94762406"
                " 0.93364684\n"
                " 0.92705939]\n"
                "Expected Total Transient Cost: $12,009.30\n")
    assert captured_output.getvalue() == test_str