9.6.1 Asset Replacement

設定は7.6.2 Asset Replacementを引き継いでいる。

毎年初めにkeepかreplaceか選択する。a年経過後のoutputがq(a)、replacement costがk

kが$k_{t+1} = \bar{k} + γ(k_t- \bar{k}) + ε$で決定される

state variables: k, a

action variables: x (1:keep, 2:replace)

Reward functionは、 $f(p, a, x) = pq(a)$ ($x = keep$)、$f(p, a, x) = pq(0)-c$ ($x = replace$)

Value functionは、 $V(p, a) = \max \{pq(a) + δE_ε V(h(p, ε), a+1), pq(0) - c + E_ε V(h(p, ε), 1) \}$


In [1]:
using QuantEcon
using Plots

In [2]:
function q(a)
    return 50 - 2.5 * a - 2.5 * a^2
end


Out[2]:
q (generic function with 1 method)

In [3]:
struct AssetReplacement
    price::Float64
    kbar::Float64
    gamma::Float64
    abar::Int
    sigma::Float64
    delta::Float64
    k_vec::Vector{Float64}
    
    function AssetReplacement(price=2,
                              kbar=100,
                              gamma=0.5,
                              abar=6,
                              sigma=15,
                              delta=0.9,
                              k_vec=collect(linspace(30, 190, 100)))
        return new(price, kbar, gamma, abar, sigma, delta, k_vec)
    end
end

In [4]:
function update_bellman!(ar::AssetReplacement, Vs, Vs_new)
    price, kbar, gamma, abar, sigma, delta = ar.price, ar.kbar, ar.gamma, ar.abar, ar.sigma, ar.delta
    
    
    V_funcs = [LinInterp(ar.k_vec, Vs[:, a]) for a in 1:abar]
    e, w = qnwnorm(5, 0, sigma)
    policy = similar(Vs, Int)
    for a in 1: abar-1
        for (k_idx, k) in enumerate(ar.k_vec)
            V_keep = price * q(a) + delta * dot(V_funcs[a+1].(e .+ kbar .+ (gamma * (k-kbar))), w)
            V_replace = price * q(0) - k + delta * dot(V_funcs[1].(e .+kbar .+ (gamma * (k-kbar))), w)
            Vs_new[k_idx, a] = max(V_keep, V_replace)
            if V_keep > V_replace
                policy[k_idx, a] = 1
            else
                policy[k_idx, a] = 2
            end
        end
    end
    for (k_idx, k) in enumerate(ar.k_vec)
        Vs_new[k_idx, abar] = price * q(0) - k + delta * dot(V_funcs[1].(e .+kbar .+ (gamma * (k-kbar))), w)
        policy[k_idx, abar] = 2
    end
    
    return Vs_new, policy
end


Out[4]:
update_bellman! (generic function with 1 method)

In [5]:
ar = AssetReplacement()


Out[5]:
AssetReplacement(2.0, 100.0, 0.5, 6, 15.0, 0.9, [30.0, 31.6162, 33.2323, 34.8485, 36.4646, 38.0808, 39.697, 41.3131, 42.9293, 44.5455  …  175.455, 177.071, 178.687, 180.303, 181.919, 183.535, 185.152, 186.768, 188.384, 190.0])

In [6]:
Vs = ones(length(ar.k_vec), ar.abar);

In [7]:
Vs_computed = similar(Vs)

tol=sqrt(eps())
max_iter=500
error = tol + 1
i = 0
resid = similar(Vs)
while error > tol && i < max_iter
    update_bellman!(ar, Vs, Vs_computed)
    copy!(resid, Vs-Vs_computed)
    error = maximum(abs, resid)
    copy!(Vs, Vs_computed)
    i += 1
end

In [8]:
_,policy = update_bellman!(ar, Vs, similar(Vs))


Out[8]:
([585.137 585.137 … 585.137 585.137; 583.358 583.358 … 583.358 583.358; … ; 547.154 497.884 … 410.929 410.929; 546.958 497.524 … 409.157 409.157], [2 2 … 2 2; 2 2 … 2 2; … ; 1 1 … 2 2; 1 1 … 2 2])

In [9]:
policy


Out[9]:
100×6 Array{Int64,2}:
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 1  2  2  2  2  2
 ⋮              ⋮
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  2  2  2
 1  1  1  1  2  2
 1  1  1  1  2  2
 1  1  1  1  2  2
 1  1  1  1  2  2

In [10]:
Vs


Out[10]:
100×6 Array{Float64,2}:
 585.137  585.137  585.137  585.137  585.137  585.137
 583.358  583.358  583.358  583.358  583.358  583.358
 581.58   581.58   581.58   581.58   581.58   581.58 
 580.179  579.802  579.802  579.802  579.802  579.802
 579.554  578.024  578.024  578.024  578.024  578.024
 578.979  576.245  576.245  576.245  576.245  576.245
 578.516  574.467  574.467  574.467  574.467  574.467
 578.054  572.689  572.689  572.689  572.689  572.689
 577.591  570.911  570.911  570.911  570.911  570.911
 577.128  569.133  569.133  569.133  569.133  569.133
 576.69   567.354  567.354  567.354  567.354  567.354
 576.257  565.576  565.576  565.576  565.576  565.576
 575.879  563.798  563.798  563.798  563.798  563.798
   ⋮                                            ⋮    
 549.389  501.484  461.549  428.672  428.672  428.672
 549.138  501.124  460.749  426.896  426.896  426.896
 548.891  500.764  459.949  425.121  425.121  425.121
 548.649  500.404  459.148  423.346  423.346  423.346
 548.42   500.044  458.348  421.571  421.571  421.571
 548.196  499.684  457.548  419.796  419.796  419.796
 547.982  499.324  456.748  418.021  418.021  418.021
 547.77   498.964  455.948  416.247  416.247  416.247
 547.561  498.604  455.148  415.148  414.474  414.474
 547.355  498.244  454.348  414.348  412.701  412.701
 547.154  497.884  453.548  413.548  410.929  410.929
 546.958  497.524  452.748  412.748  409.157  409.157

In [11]:
plotlyjs()


Plotly javascript loaded.

To load again call

init_notebook(true)

Out[11]:
Plots.PlotlyJSBackend()

In [12]:
plot(ar.k_vec, [Vs[:, a] for a in 1:ar.abar-1], xlims=(0, 200), label=["age = 1" "age = 2" "age = 3" "age = 4" "age = 5"])


Out[12]:

In [13]:
plot(ar.k_vec, [policy[:, a] for a in 1:ar.abar-1], xlims=(0, 200), label=["age = 1" "age = 2" "age = 3" "age = 4" "age = 5"])


Out[13]: