Rust (1987)

Just to replicate Figure 3, p.1025, given the estimated parameter values.


In [1]:
%matplotlib inline

In [2]:
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt

In [3]:
def operator_iteration(T, w_0, tol, max_iter):
    w = w_0
    for i in range(max_iter):
        new_w = T(w)
        if np.abs(new_w - w).max() < tol:
            w = new_w
            break
        w = new_w

    num_iter = i + 1

    return w, num_iter

In [4]:
class Zurcher(object):
    def __init__(self, num_states, beta,
                 c=lambda x, theta_1: 0.001 * theta_1[0] * x):
        self.num_states = num_states  # 0, 5000, ..., 5000*(num_states-1)
        self.num_actions = 2  # 0: keep, 1: replace
        self.beta = beta
        self.c = c
        
    def set_params(self, RC, theta_1, theta_3):
        self.RC, self.theta_1, self.theta_3 = RC, theta_1, theta_3
        
        # Flow utility
        self.u = np.empty((self.num_states, self.num_actions))
        self.u[:, 0] = -self.c(np.arange(self.num_states)+1, self.theta_1)
        self.u[:, 1] = -self.RC - self.c(0, self.theta_1)
        
        # Transition probabilities
        n = self.num_states
        supp_size = len(theta_3)
        p = np.zeros((n, n))
        for i in range(n-supp_size+1):
            p[i, i:i+supp_size] = theta_3
        for i in range(n-supp_size+1, n):
            p[i, i:] = theta_3[:n-i]/theta_3[:n-i].sum()
        self.p = p
        
    def continuation_values(self, ev):
        """
        u + beta * ev
        
        """
        v0 = self.u[:, 0] + self.beta * ev
        v1 = self.u[0, 1] + self.beta * ev[0]
        return v0, v1
        
    def T(self, ev):
        v0, v1 = self.continuation_values(ev)
        return self.p.dot(np.logaddexp(v0, v1))
    
    def replacement_prob(self, ev):
        v0, v1 = self.continuation_values(ev)
        return 1/(1 + np.exp(v0-v1))
    
    def compute_EV(self, w_0=None, tol=1e-5, max_iter=10**5):
        if w_0 is None:
            w_0 = np.zeros(self.num_states)
            
        EV, num_iter = operator_iteration(self.T, w_0=w_0, tol=tol, max_iter=max_iter)
        P_replace = self.replacement_prob(EV)
        
        return EV, num_iter, P_replace

Consider Model 11.


In [5]:
num_states = 90

Estimated parameter values for Group 4, Table IX, p.1021


In [6]:
# Transition probabilities
supp_size = 3
theta_3 = np.empty(supp_size)
theta_3[:-1] = .3919, .5953
theta_3[-1] = 1 - theta_3[:-1].sum()

In [7]:
betas = np.empty(2)
RCs = np.empty(2)
theta_1s = np.empty((2, 1))

In [8]:
# Estimated parameter values for beta = 0
betas[0] = 0

# Replacement cost
RCs[0] = 7.6358
        
# Cost function parameter
theta_1s[0, 0] = 71.5133

In [9]:
# Estimated parameter values for beta = .9999
betas[1] = .9999

# Replacement cost
RCs[1] = 10.0750
        
# Cost function parameter
theta_1s[1, 0] = 2.2930

Create Zurcher instances, one for each of $\beta = 0$ and $\beta = .9999$:


In [10]:
zurchers = [Zurcher(num_states=num_states, beta=betas[i]) for i in range(2)]

In [11]:
for i, zurcher in enumerate(zurchers):
    zurcher.set_params(RC=RCs[i], theta_1=theta_1s[i], theta_3=theta_3)

Solve for $\mathit{EV}$:


In [12]:
EVs = np.empty((2, num_states))
num_iters = np.empty(2, dtype=int)
P_replaces = np.empty((2, num_states))

In [13]:
for i, zurcher in enumerate(zurchers):
    EVs[i], num_iters[i], P_replaces[i] = zurcher.compute_EV()

In [14]:
num_iters


Out[14]:
array([    2, 94775])

In [15]:
EVs


Out[15]:
array([[ -1.15373499e-01,  -1.86846601e-01,  -2.58316724e-01,
         -3.29783649e-01,  -4.01247138e-01,  -4.72706937e-01,
         -5.44162774e-01,  -6.15614354e-01,  -6.87061363e-01,
         -7.58503462e-01,  -8.29940289e-01,  -9.01371454e-01,
         -9.72796537e-01,  -1.04421509e+00,  -1.11562663e+00,
         -1.18703063e+00,  -1.25842655e+00,  -1.32981378e+00,
         -1.40119168e+00,  -1.47255957e+00,  -1.54391670e+00,
         -1.61526227e+00,  -1.68659545e+00,  -1.75791531e+00,
         -1.82922087e+00,  -1.90051108e+00,  -1.97178481e+00,
         -2.04304084e+00,  -2.11427787e+00,  -2.18549451e+00,
         -2.25668925e+00,  -2.32786049e+00,  -2.39900650e+00,
         -2.47012544e+00,  -2.54121531e+00,  -2.61227399e+00,
         -2.68329921e+00,  -2.75428850e+00,  -2.82523926e+00,
         -2.89614866e+00,  -2.96701370e+00,  -3.03783116e+00,
         -3.10859757e+00,  -3.17930923e+00,  -3.24996218e+00,
         -3.32055218e+00,  -3.39107468e+00,  -3.46152483e+00,
         -3.53189741e+00,  -3.60218689e+00,  -3.67238731e+00,
         -3.74249232e+00,  -3.81249514e+00,  -3.88238852e+00,
         -3.95216474e+00,  -4.02181554e+00,  -4.09133213e+00,
         -4.16070514e+00,  -4.22992459e+00,  -4.29897983e+00,
         -4.36785958e+00,  -4.43655181e+00,  -4.50504376e+00,
         -4.57332187e+00,  -4.64137179e+00,  -4.70917829e+00,
         -4.77672526e+00,  -4.84399566e+00,  -4.91097152e+00,
         -4.97763386e+00,  -5.04396269e+00,  -5.10993701e+00,
         -5.17553471e+00,  -5.24073267e+00,  -5.30550664e+00,
         -5.36983130e+00,  -5.43368024e+00,  -5.49702598e+00,
         -5.55984000e+00,  -5.62209274e+00,  -5.68375368e+00,
         -5.74479137e+00,  -5.80517350e+00,  -5.86486701e+00,
         -5.92383815e+00,  -5.98205261e+00,  -6.03947567e+00,
         -6.09607231e+00,  -6.15082833e+00,  -6.17282262e+00],
       [ -1.30118945e+03,  -1.30139322e+03,  -1.30159335e+03,
         -1.30178983e+03,  -1.30198268e+03,  -1.30217190e+03,
         -1.30235748e+03,  -1.30253945e+03,  -1.30271780e+03,
         -1.30289255e+03,  -1.30306370e+03,  -1.30323126e+03,
         -1.30339525e+03,  -1.30355568e+03,  -1.30371256e+03,
         -1.30386591e+03,  -1.30401576e+03,  -1.30416211e+03,
         -1.30430501e+03,  -1.30444446e+03,  -1.30458050e+03,
         -1.30471317e+03,  -1.30484249e+03,  -1.30496850e+03,
         -1.30509123e+03,  -1.30521074e+03,  -1.30532705e+03,
         -1.30544023e+03,  -1.30555031e+03,  -1.30565734e+03,
         -1.30576139e+03,  -1.30586250e+03,  -1.30596074e+03,
         -1.30605615e+03,  -1.30614880e+03,  -1.30623876e+03,
         -1.30632607e+03,  -1.30641082e+03,  -1.30649306e+03,
         -1.30657285e+03,  -1.30665027e+03,  -1.30672538e+03,
         -1.30679823e+03,  -1.30686891e+03,  -1.30693746e+03,
         -1.30700396e+03,  -1.30706847e+03,  -1.30713106e+03,
         -1.30719177e+03,  -1.30725067e+03,  -1.30730782e+03,
         -1.30736328e+03,  -1.30741710e+03,  -1.30746934e+03,
         -1.30752004e+03,  -1.30756926e+03,  -1.30761704e+03,
         -1.30766343e+03,  -1.30770848e+03,  -1.30775222e+03,
         -1.30779470e+03,  -1.30783596e+03,  -1.30787602e+03,
         -1.30791491e+03,  -1.30795268e+03,  -1.30798935e+03,
         -1.30802493e+03,  -1.30805945e+03,  -1.30809293e+03,
         -1.30812538e+03,  -1.30815681e+03,  -1.30818723e+03,
         -1.30821662e+03,  -1.30824499e+03,  -1.30827232e+03,
         -1.30829859e+03,  -1.30832378e+03,  -1.30834783e+03,
         -1.30837072e+03,  -1.30839236e+03,  -1.30841269e+03,
         -1.30843161e+03,  -1.30844902e+03,  -1.30846476e+03,
         -1.30847869e+03,  -1.30849062e+03,  -1.30850032e+03,
         -1.30850753e+03,  -1.30851196e+03,  -1.30851330e+03]])

In [16]:
P_replaces


Out[16]:
array([[  5.18378331e-04,   5.56785584e-04,   5.98036771e-04,
          6.42342217e-04,   6.89927757e-04,   7.41035882e-04,
          7.95926953e-04,   8.54880516e-04,   9.18196702e-04,
          9.86197732e-04,   1.05922953e-03,   1.13766347e-03,
          1.22189818e-03,   1.31236159e-03,   1.40951302e-03,
          1.51384548e-03,   1.62588806e-03,   1.74620864e-03,
          1.87541656e-03,   2.01416573e-03,   2.16315776e-03,
          2.32314537e-03,   2.49493612e-03,   2.67939624e-03,
          2.87745487e-03,   3.09010845e-03,   3.31842554e-03,
          3.56355187e-03,   3.82671573e-03,   4.10923376e-03,
          4.41251710e-03,   4.73807787e-03,   5.08753615e-03,
          5.46262737e-03,   5.86521008e-03,   6.29727433e-03,
          6.76095039e-03,   7.25851810e-03,   7.79241670e-03,
          8.36525517e-03,   8.97982320e-03,   9.63910266e-03,
          1.03462797e-02,   1.11047573e-02,   1.19181687e-02,
          1.27903910e-02,   1.37255595e-02,   1.47280827e-02,
          1.58026576e-02,   1.69542853e-02,   1.81882876e-02,
          1.95103231e-02,   2.09264041e-02,   2.24429131e-02,
          2.40666202e-02,   2.58046988e-02,   2.76647423e-02,
          2.96547794e-02,   3.17832887e-02,   3.40592119e-02,
          3.64919660e-02,   3.90914526e-02,   4.18680659e-02,
          4.48326968e-02,   4.79967339e-02,   5.13720611e-02,
          5.49710489e-02,   5.88065419e-02,   6.28918390e-02,
          6.72406664e-02,   7.18671436e-02,   7.67857397e-02,
          8.20112201e-02,   8.75585825e-02,   9.34429816e-02,
          9.96796411e-02,   1.06283753e-01,   1.13270361e-01,
          1.20654234e-01,   1.28449721e-01,   1.36670595e-01,
          1.45329877e-01,   1.54439655e-01,   1.64010884e-01,
          1.74053181e-01,   1.84574603e-01,   1.95581435e-01,
          2.07077954e-01,   2.19066220e-01,   2.31545848e-01],
       [  4.22143978e-05,   5.18726982e-05,   6.35088435e-05,
          7.74725441e-05,   9.41631651e-05,   1.14034310e-04,
          1.37598361e-04,   1.65430860e-04,   1.98174636e-04,
          2.36543519e-04,   2.81325538e-04,   3.33385420e-04,
          3.93666283e-04,   4.63190345e-04,   5.43058533e-04,
          6.34448873e-04,   7.38613544e-04,   8.56874531e-04,
          9.90617839e-04,   1.14128625e-03,   1.31037064e-03,
          1.49940001e-03,   1.70993020e-03,   1.94353159e-03,
          2.20177594e-03,   2.48622251e-03,   2.79840388e-03,
          3.13981158e-03,   3.51188193e-03,   3.91598230e-03,
          4.35339812e-03,   4.82532083e-03,   5.33283703e-03,
          5.87691907e-03,   6.45841705e-03,   7.07805259e-03,
          7.73641423e-03,   8.43395448e-03,   9.17098868e-03,
          9.94769532e-03,   1.07641179e-02,   1.16201683e-02,
          1.25156310e-02,   1.34501686e-02,   1.44233281e-02,
          1.54345477e-02,   1.64831645e-02,   1.75684212e-02,
          1.86894747e-02,   1.98454029e-02,   2.10352121e-02,
          2.22578441e-02,   2.35121817e-02,   2.47970547e-02,
          2.61112443e-02,   2.74534869e-02,   2.88224767e-02,
          3.02168672e-02,   3.16352710e-02,   3.30762590e-02,
          3.45383573e-02,   3.60200424e-02,   3.75197349e-02,
          3.90357909e-02,   4.05664904e-02,   4.21100235e-02,
          4.36644735e-02,   4.52277959e-02,   4.67977936e-02,
          4.83720870e-02,   4.99480788e-02,   5.15229122e-02,
          5.30934219e-02,   5.46560758e-02,   5.62069079e-02,
          5.77414392e-02,   5.92545865e-02,   6.07405563e-02,
          6.21927240e-02,   6.36034965e-02,   6.49641566e-02,
          6.62646925e-02,   6.74936105e-02,   6.86377380e-02,
          6.96820227e-02,   7.06093391e-02,   7.14003215e-02,
          7.20332483e-02,   7.24839630e-02,   7.27283103e-02]])

In [17]:
# V for beta = .9999
V, _ = zurchers[1].continuation_values(EVs[1])

In [18]:
V


Out[18]:
array([-1301.06162659, -1301.26766751, -1301.47006571, -1301.66882411,
       -1301.86394628, -1302.05543645, -1302.24329965, -1302.42754182,
       -1302.60816987, -1302.78519181, -1302.95861689, -1303.12845571,
       -1303.29472033, -1303.45742441, -1303.61658335, -1303.77221439,
       -1303.92433676, -1304.07297178, -1304.21814297, -1304.35987616,
       -1304.49819957, -1304.63314387, -1304.76474226, -1304.89303046,
       -1305.0180468 , -1305.13983213, -1305.25842985, -1305.37388586,
       -1305.48624843, -1305.59556819, -1305.70189793, -1305.80529254,
       -1305.90580879, -1306.00350523, -1306.09844192, -1306.19068035,
       -1306.28028311, -1306.36731379, -1306.45183671, -1306.53391671,
       -1306.61361897, -1306.69100876, -1306.76615127, -1306.83911139,
       -1306.90995357, -1306.97874157, -1307.04553836, -1307.11040593,
       -1307.17340516, -1307.23459567, -1307.29403572, -1307.35178209,
       -1307.40788997, -1307.46241288, -1307.51540254, -1307.56690888,
       -1307.61697984, -1307.6656614 , -1307.71299746, -1307.75902974,
       -1307.80379773, -1307.8473386 , -1307.88968709, -1307.93087537,
       -1307.97093294, -1308.00988647, -1308.04775958, -1308.08457266,
       -1308.12034259, -1308.15508241, -1308.188801  , -1308.22150257,
       -1308.25318619, -1308.28384517, -1308.3134663 , -1308.34202897,
       -1308.36950422, -1308.39585347, -1308.42102714, -1308.44496303,
       -1308.46758441, -1308.4887978 , -1308.50849052, -1308.52652778,
       -1308.54274951, -1308.55696684, -1308.56895823, -1308.57846548,
       -1308.58518884, -1308.5888177 ])

Plot $c(x) - \beta \mathit{EV}(x)$ and $- \beta \mathit{EV}(x)$ for $\beta = .9999$ (TODO: find out how to "normalize" the values):


In [19]:
fig, ax = plt.subplots(figsize=(8,5))
ax.plot(-zurchers[1].beta * EVs[1], label=r'$c - \beta \mathit{EV}$')
ax.plot(-V, label=r'$- \beta \mathit{EV}$')
#for zurcher in zurchers:
#    ax.plot(-zurcher.u[:, 0], label=r'$c$, $\beta = {0}$'.format(zurcher.beta))
ax.set_title('Estimated Value Functions')
ax.set_xlabel('State')
ax.set_ylabel(r'Non-normalized value $\times\ (-1)$')
plt.legend(loc=2)
plt.show()


Plot $P(1|x)$ for $\beta = 0$ and $\beta = .9999$:


In [20]:
fig, ax = plt.subplots(figsize=(8,5))
for i in range(2):
    ax.plot(P_replaces[i], label=r'$\beta = {0}$'.format(betas[i]))
ax.set_ylim(0, 0.16)
ax.set_yticks(np.linspace(0, 0.16, 17, endpoint=True))
ax.set_title('Estimated Hazard Functions')
ax.set_xlabel('State')
ax.set_ylabel('Probability of engine replacement')
plt.legend(loc=2)
plt.show()


Timing the code (for $\beta = .9999$):


In [21]:
%timeit zurchers[1].compute_EV()


1 loops, best of 3: 3.53 s per loop

In [21]: