In [1]:
from __future__ import print_function
import numpy as np
from quantecon.markov import random_discrete_dp

Performance Comparison

Regarding the representation of the transition probability array Q:

  1. current states $\times$ actions $\times$ next states
  2. current state-action pairs $\times$ next states (dense matrix)
  3. current state-action pairs $\times$ next states (sparse matrix)

In [2]:
def compare_performance(num_states, num_actions, beta, k,
                        suppress_vi=False, random_state=0):
    labels = ['n x m x n', 'n*m x n (dense)', 'n*m x n (sparse)']
    flags = [(False, False), (False, True), (True, True)]  # (sparse, sa_pair)
    ddps = {}
    for label, flag in zip(labels, flags):
        ddps[label] = \
            random_discrete_dp(num_states, num_actions, beta, k=k,
                               sparse=flag[0], sa_pair=flag[1],
                               random_state=random_state)

    if suppress_vi:
        methods = ['pi', 'mpi']
    else:
        methods = ['vi', 'pi', 'mpi']
    results = {}
    max_iter = 1000
    for ddp in ddps.values():
        ddp.max_iter = max_iter
    k_mpi = 20

    for label in labels:
        results[label] = {method: ddps[label].solve(method=method, k=k_mpi)
                          for method in methods}

    print('(num_states, num_actions) = ({0}, {1})'
          .format(num_states, num_actions))
    print('Number of possible next states for each (s, a) =', k)
    print('beta =', beta)
    print('=====')
    print('Whether the results by pi agree:',
          all([np.array_equal(results[labels[i]]['pi'].sigma,
                              results[labels[2]]['pi'].sigma)
               for i in [0, 1]]))
    print('Whether the answer is correct ({0}, {1}, {2}):'.format(*labels))
    for method in methods:
        if method != 'pi':
            print(method.ljust(3) + ':',
                  [np.array_equal(results[label][method].sigma,
                                  results[label]['pi'].sigma)
                   for label in labels])
    print('Number of iterations ({0}, {1}, {2}):'.format(*labels))
    for method in methods:
        print(method.ljust(3) + ':',
              [results[label][method].num_iter for label in labels])
    print('=====')

    print('Speed comparison ({0}, {1}, {2}):'.format(*labels))
    for method in methods:
        print('***', method, '***')
        for label in labels:
            global ddps, label, method
            %timeit ddps[label].solve(method=method)

In [3]:
seed = 1234  # Set random seed

In [4]:
compare_performance(num_states=100, num_actions=20, beta=0.95, k=3,
                    random_state=seed)


(num_states, num_actions) = (100, 20)
Number of possible next states for each (s, a) = 3
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [219, 219, 219]
pi : [4, 4, 4]
mpi: [6, 6, 6]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
10 loops, best of 3: 30.5 ms per loop
100 loops, best of 3: 10 ms per loop
100 loops, best of 3: 9.41 ms per loop
*** pi ***
1000 loops, best of 3: 1.6 ms per loop
1000 loops, best of 3: 1.07 ms per loop
100 loops, best of 3: 3.91 ms per loop
*** mpi ***
100 loops, best of 3: 2.06 ms per loop
1000 loops, best of 3: 1.61 ms per loop
100 loops, best of 3: 3.71 ms per loop

In [5]:
compare_performance(num_states=500, num_actions=20, beta=0.95, k=3,
                    random_state=seed)


(num_states, num_actions) = (500, 20)
Number of possible next states for each (s, a) = 3
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [220, 220, 220]
pi : [5, 5, 5]
mpi: [7, 7, 7]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 625 ms per loop
1 loop, best of 3: 239 ms per loop
10 loops, best of 3: 21.2 ms per loop
*** pi ***
10 loops, best of 3: 33.1 ms per loop
10 loops, best of 3: 20.5 ms per loop
10 loops, best of 3: 25.3 ms per loop
*** mpi ***
10 loops, best of 3: 28 ms per loop
100 loops, best of 3: 14.2 ms per loop
100 loops, best of 3: 5.59 ms per loop

In [6]:
compare_performance(num_states=1000, num_actions=20, beta=0.95, k=3,
                    random_state=seed)


(num_states, num_actions) = (1000, 20)
Number of possible next states for each (s, a) = 3
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [219, 219, 219]
pi : [5, 5, 5]
mpi: [7, 7, 7]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 2.36 s per loop
1 loop, best of 3: 866 ms per loop
10 loops, best of 3: 37 ms per loop
*** pi ***
10 loops, best of 3: 167 ms per loop
10 loops, best of 3: 123 ms per loop
10 loops, best of 3: 129 ms per loop
*** mpi ***
10 loops, best of 3: 100 ms per loop
10 loops, best of 3: 46.9 ms per loop
100 loops, best of 3: 6.67 ms per loop

In [7]:
compare_performance(num_states=1000, num_actions=50, beta=0.95, k=3,
                    random_state=seed)


(num_states, num_actions) = (1000, 50)
Number of possible next states for each (s, a) = 3
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [223, 223, 223]
pi : [5, 5, 5]
mpi: [6, 6, 6]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 5.93 s per loop
1 loop, best of 3: 2.12 s per loop
10 loops, best of 3: 72.4 ms per loop
*** pi ***
1 loop, best of 3: 266 ms per loop
10 loops, best of 3: 155 ms per loop
10 loops, best of 3: 131 ms per loop
*** mpi ***
10 loops, best of 3: 186 ms per loop
10 loops, best of 3: 74.1 ms per loop
100 loops, best of 3: 6.96 ms per loop

In [8]:
compare_performance(num_states=500, num_actions=20, beta=0.95, k=100,
                    random_state=seed)


(num_states, num_actions) = (500, 20)
Number of possible next states for each (s, a) = 100
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [218, 218, 218]
pi : [3, 3, 3]
mpi: [4, 4, 4]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 619 ms per loop
1 loop, best of 3: 237 ms per loop
1 loop, best of 3: 199 ms per loop
*** pi ***
10 loops, best of 3: 21.5 ms per loop
100 loops, best of 3: 13.6 ms per loop
10 loops, best of 3: 64.4 ms per loop
*** mpi ***
100 loops, best of 3: 15.9 ms per loop
100 loops, best of 3: 8.07 ms per loop
100 loops, best of 3: 9.92 ms per loop

In [9]:
compare_performance(num_states=500, num_actions=20, beta=0.95, k=50,
                    random_state=seed)


(num_states, num_actions) = (500, 20)
Number of possible next states for each (s, a) = 50
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [218, 218, 218]
pi : [2, 2, 2]
mpi: [4, 4, 4]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 622 ms per loop
1 loop, best of 3: 240 ms per loop
10 loops, best of 3: 103 ms per loop
*** pi ***
100 loops, best of 3: 15.7 ms per loop
100 loops, best of 3: 9.67 ms per loop
10 loops, best of 3: 42 ms per loop
*** mpi ***
100 loops, best of 3: 15.9 ms per loop
100 loops, best of 3: 8.08 ms per loop
100 loops, best of 3: 6.45 ms per loop

In [10]:
compare_performance(num_states=500, num_actions=20, beta=0.95, k=500,
                    random_state=seed)


(num_states, num_actions) = (500, 20)
Number of possible next states for each (s, a) = 500
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [218, 218, 218]
pi : [1, 1, 1]
mpi: [3, 3, 3]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 625 ms per loop
1 loop, best of 3: 235 ms per loop
1 loop, best of 3: 1.01 s per loop
*** pi ***
100 loops, best of 3: 9.67 ms per loop
100 loops, best of 3: 5.66 ms per loop
10 loops, best of 3: 52.3 ms per loop
*** mpi ***
100 loops, best of 3: 11.9 ms per loop
100 loops, best of 3: 6.02 ms per loop
10 loops, best of 3: 27.7 ms per loop

In [11]:
compare_performance(num_states=1000, num_actions=100, beta=0.95, k=1,
                    random_state=seed)


(num_states, num_actions) = (1000, 100)
Number of possible next states for each (s, a) = 1
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [True, True, True]
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
vi : [230, 230, 230]
pi : [11, 11, 11]
mpi: [15, 15, 15]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** vi ***
1 loop, best of 3: 12.2 s per loop
1 loop, best of 3: 4.33 s per loop
10 loops, best of 3: 105 ms per loop
*** pi ***
1 loop, best of 3: 879 ms per loop
1 loop, best of 3: 437 ms per loop
100 loops, best of 3: 18 ms per loop
*** mpi ***
1 loop, best of 3: 876 ms per loop
1 loop, best of 3: 326 ms per loop
10 loops, best of 3: 19.4 ms per loop

In [12]:
compare_performance(num_states=1000, num_actions=200, beta=0.95, k=1,
                    suppress_vi=True, random_state=seed)


(num_states, num_actions) = (1000, 200)
Number of possible next states for each (s, a) = 1
beta = 0.95
=====
Whether the results by pi agree: True
Whether the answer is correct (n x m x n, n*m x n (dense), n*m x n (sparse)):
mpi: [True, True, True]
Number of iterations (n x m x n, n*m x n (dense), n*m x n (sparse)):
pi : [8, 8, 8]
mpi: [16, 16, 16]
=====
Speed comparison (n x m x n, n*m x n (dense), n*m x n (sparse)):
*** pi ***
1 loop, best of 3: 1.15 s per loop
1 loop, best of 3: 492 ms per loop
10 loops, best of 3: 18.9 ms per loop
*** mpi ***
1 loop, best of 3: 1.82 s per loop
1 loop, best of 3: 643 ms per loop
10 loops, best of 3: 29.4 ms per loop

In [13]:
import platform
print(platform.platform())


Darwin-15.6.0-x86_64-i386-64bit

In [14]:
import sys
print(sys.version)


3.5.2 |Anaconda 4.1.1 (x86_64)| (default, Jul  2 2016, 17:52:12) 
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)]

In [15]:
print(np.__version__)


1.11.1

In [16]:
import scipy
print(scipy.__version__)


0.17.1

In [17]:
import numba
print(numba.__version__)


0.26.0

In [ ]: