Daisuke Oyama
Faculty of Economics, University of Tokyo
From Miranda and Fackler, Applied Computational Economics and Finance, 2002, Section 7.6.2
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from quantecon.markov import DiscreteDP
maxage = 5 # Maximum asset age
repcost = 75 # Replacement cost
beta = 0.9 # Discount factor
m = 2 # Number of actions; 0: keep, 1: replace
S = np.arange(1, maxage+1) # State space
n = len(S) # Number of states
# Reward array
R = np.empty((n, m))
R[:, 0] = 50 - 2.5 * S - 2.5 * S**2
R[:, 1] = 50 - repcost
# Infeasible action
R[-1, 0] = -np.inf
R
array([[ 45., -25.], [ 35., -25.], [ 20., -25.], [ 0., -25.], [-inf, -25.]])
# (Degenerate) transition probability array
Q = np.zeros((n, m, n))
for i in range(n):
Q[i, 0, np.minimum(i+1, n-1)] = 1
Q[i, 1, 0] = 1
Q
array([[[ 0., 1., 0., 0., 0.], [ 1., 0., 0., 0., 0.]], [[ 0., 0., 1., 0., 0.], [ 1., 0., 0., 0., 0.]], [[ 0., 0., 0., 1., 0.], [ 1., 0., 0., 0., 0.]], [[ 0., 0., 0., 0., 1.], [ 1., 0., 0., 0., 0.]], [[ 0., 0., 0., 0., 1.], [ 1., 0., 0., 0., 0.]]])
# Create a DiscreteDP
ddp = DiscreteDP(R, Q, beta)
# Solve the dynamic optimization problem (by policy iteration)
res = ddp.solve()
# Number of iterations
res.num_iter
1
# Optimal value function
res.v
array([ 216.56004653, 190.62227392, 172.91363769, 169.90404187, 169.90404187])
# Optimal policy
res.sigma
array([0, 0, 0, 1, 1])
# Transition probability matrix
res.mc.P
array([[ 0., 1., 0., 0., 0.], [ 0., 0., 1., 0., 0.], [ 0., 0., 0., 1., 0.], [ 1., 0., 0., 0., 0.], [ 1., 0., 0., 0., 0.]])
# Simulate the controlled Markov chain
res.mc.state_values = S # Set the state values
initial_state_value = 1
nyrs = 12
spath = res.mc.simulate(nyrs+1, init=initial_state_value)
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].plot(np.arange(n)+1, res.v)
axes[0].set_xlim(1, 5)
axes[0].set_ylim(160, 220)
axes[0].set_xticks(np.linspace(1, 5, 5, endpoint=True))
axes[0].set_xlabel('Age of Machine')
axes[0].set_ylabel('Value')
axes[0].set_title('Optimal Value Function')
axes[1].plot(spath)
axes[1].set_xlim(0, nyrs)
axes[1].set_ylim(1, 4)
axes[1].set_yticks(np.linspace(1, 4, 4, endpoint=True))
axes[1].set_xlabel('Year')
axes[1].set_ylabel('Age of Machine')
axes[1].set_title('Optimal State Path')
plt.show()