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: 32.1 ms per loop
100 loops, best of 3: 16.1 ms per loop
100 loops, best of 3: 9.34 ms per loop
*** pi ***
100 loops, best of 3: 1.94 ms per loop
1000 loops, best of 3: 1.38 ms per loop
100 loops, best of 3: 3.82 ms per loop
*** mpi ***
1000 loops, best of 3: 2.08 ms per loop
1000 loops, best of 3: 1.69 ms per loop
100 loops, best of 3: 3.74 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 loops, best of 3: 937 ms per loop
1 loops, best of 3: 477 ms per loop
10 loops, best of 3: 21.3 ms per loop
*** pi ***
10 loops, best of 3: 46.2 ms per loop
10 loops, best of 3: 32.4 ms per loop
10 loops, best of 3: 27.2 ms per loop
*** mpi ***
10 loops, best of 3: 46.8 ms per loop
10 loops, best of 3: 29.4 ms per loop
100 loops, best of 3: 5.33 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 loops, best of 3: 3.1 s per loop
1 loops, best of 3: 1.78 s per loop
10 loops, best of 3: 37.9 ms per loop
*** pi ***
1 loops, best of 3: 262 ms per loop
1 loops, best of 3: 214 ms per loop
10 loops, best of 3: 143 ms per loop
*** mpi ***
10 loops, best of 3: 146 ms per loop
10 loops, best of 3: 105 ms per loop
100 loops, best of 3: 6.58 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 loops, best of 3: 7.81 s per loop
1 loops, best of 3: 4.54 s per loop
10 loops, best of 3: 76.1 ms per loop
*** pi ***
1 loops, best of 3: 353 ms per loop
1 loops, best of 3: 279 ms per loop
10 loops, best of 3: 149 ms per loop
*** mpi ***
1 loops, best of 3: 261 ms per loop
10 loops, best of 3: 162 ms per loop
100 loops, best of 3: 7.22 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 loops, best of 3: 918 ms per loop
1 loops, best of 3: 461 ms per loop
1 loops, best of 3: 218 ms per loop
*** pi ***
10 loops, best of 3: 32 ms per loop
10 loops, best of 3: 22.8 ms per loop
10 loops, best of 3: 74.2 ms per loop
*** mpi ***
10 loops, best of 3: 26.2 ms per loop
100 loops, best of 3: 16.9 ms per loop
100 loops, best of 3: 10.8 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 loops, best of 3: 920 ms per loop
1 loops, best of 3: 458 ms per loop
10 loops, best of 3: 115 ms per loop
*** pi ***
10 loops, best of 3: 24.5 ms per loop
100 loops, best of 3: 17.9 ms per loop
10 loops, best of 3: 45.8 ms per loop
*** mpi ***
10 loops, best of 3: 25.3 ms per loop
100 loops, best of 3: 15.4 ms per loop
100 loops, best of 3: 6.81 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 loops, best of 3: 925 ms per loop
1 loops, best of 3: 488 ms per loop
1 loops, best of 3: 1.06 s per loop
*** pi ***
100 loops, best of 3: 13.8 ms per loop
100 loops, best of 3: 9.41 ms per loop
10 loops, best of 3: 54.7 ms per loop
*** mpi ***
100 loops, best of 3: 19.2 ms per loop
100 loops, best of 3: 11.5 ms per loop
10 loops, best of 3: 28.5 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 loops, best of 3: 16.2 s per loop
1 loops, best of 3: 9.77 s per loop
10 loops, best of 3: 116 ms per loop
*** pi ***
1 loops, best of 3: 1.23 s per loop
1 loops, best of 3: 853 ms per loop
100 loops, best of 3: 19.7 ms per loop
*** mpi ***
1 loops, best of 3: 1.25 s per loop
1 loops, best of 3: 799 ms per loop
10 loops, best of 3: 21.7 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 loops, best of 3: 1.52 s per loop
1 loops, best of 3: 1 s per loop
10 loops, best of 3: 20.5 ms per loop
*** mpi ***
1 loops, best of 3: 2.3 s per loop
1 loops, best of 3: 1.43 s per loop
10 loops, best of 3: 33 ms per loop

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


Darwin-13.4.0-x86_64-i386-64bit

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


2.7.10 (default, Jun 10 2015, 19:43:32) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)]

In [15]:
print(np.__version__)


1.10.1

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


0.16.1

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


0.22.1

In [ ]: