quant-econ Solutions: Modeling Career Choice


In [5]:
%matplotlib inline

In [6]:
import numpy as np
import matplotlib.pyplot as plt
from quantecon import DiscreteRV, CareerWorkerProblem, compute_fixed_point

Exercise 1

Simulate job / career paths.

In reading the code, recall that optimal_policy[i, j] = policy at $(\theta_i, \epsilon_j)$ = either 1, 2 or 3; meaning 'stay put', 'new job' and 'new life'.


In [7]:
wp = CareerWorkerProblem()
v_init = np.ones((wp.N, wp.N))*100
v = compute_fixed_point(wp.bellman, v_init, verbose=False)
optimal_policy = wp.get_greedy(v)
F = DiscreteRV(wp.F_probs)
G = DiscreteRV(wp.G_probs)

def gen_path(T=20):
    i = j = 0  
    theta_index = []
    epsilon_index = []
    for t in range(T):
        if optimal_policy[i, j] == 1:    # Stay put
            pass
        elif optimal_policy[i, j] == 2:  # New job
            j = int(G.draw())
        else:                            # New life
            i, j  = int(F.draw()), int(G.draw())
        theta_index.append(i)
        epsilon_index.append(j)
    return wp.theta[theta_index], wp.epsilon[epsilon_index]

theta_path, epsilon_path = gen_path()

fig, axes = plt.subplots(2, 1, figsize=(10, 8))
for ax in axes:
    ax.plot(epsilon_path, label='epsilon')
    ax.plot(theta_path, label='theta')
    ax.legend(loc='lower right')

plt.show()


Exercise 2

The median for the original parameterization can be computed as follows


In [8]:
wp = CareerWorkerProblem()
v_init = np.ones((wp.N, wp.N))*100
v = compute_fixed_point(wp.bellman, v_init)
optimal_policy = wp.get_greedy(v)
F = DiscreteRV(wp.F_probs)
G = DiscreteRV(wp.G_probs)

def gen_first_passage_time():
    t = 0
    i = j = 0  
    theta_index = []
    epsilon_index = []
    while 1:
        if optimal_policy[i, j] == 1:    # Stay put
            return t
        elif optimal_policy[i, j] == 2:  # New job
            j = int(G.draw())
        else:                            # New life
            i, j  = int(F.draw()), int(G.draw())
        t += 1

M = 25000 # Number of samples
samples = np.empty(M)
for i in range(M): 
    samples[i] = gen_first_passage_time()
print np.median(samples)


Computed iterate 1 with error 5.000000
Computed iterate 2 with error 4.750000
Computed iterate 3 with error 4.512500
Computed iterate 4 with error 4.286875
Computed iterate 5 with error 4.072531
Computed iterate 6 with error 3.868905
Computed iterate 7 with error 3.675459
Computed iterate 8 with error 3.491686
Computed iterate 9 with error 3.317102
Computed iterate 10 with error 3.151247
Computed iterate 11 with error 2.993685
Computed iterate 12 with error 2.844000
Computed iterate 13 with error 2.701800
Computed iterate 14 with error 2.566710
Computed iterate 15 with error 2.438375
Computed iterate 16 with error 2.316456
Computed iterate 17 with error 2.200633
Computed iterate 18 with error 2.090602
Computed iterate 19 with error 1.986072
Computed iterate 20 with error 1.886768
Computed iterate 21 with error 1.792430
Computed iterate 22 with error 1.702808
Computed iterate 23 with error 1.617668
Computed iterate 24 with error 1.536784
Computed iterate 25 with error 1.459945
Computed iterate 26 with error 1.386948
Computed iterate 27 with error 1.317600
Computed iterate 28 with error 1.251720
Computed iterate 29 with error 1.189134
Computed iterate 30 with error 1.129678
Computed iterate 31 with error 1.073194
Computed iterate 32 with error 1.019534
Computed iterate 33 with error 0.968557
Computed iterate 34 with error 0.920130
Computed iterate 35 with error 0.874123
Computed iterate 36 with error 0.830417
Computed iterate 37 with error 0.788896
Computed iterate 38 with error 0.749451
Computed iterate 39 with error 0.711979
Computed iterate 40 with error 0.676380
Computed iterate 41 with error 0.642561
Computed iterate 42 with error 0.610433
Computed iterate 43 with error 0.579911
Computed iterate 44 with error 0.550916
Computed iterate 45 with error 0.523370
Computed iterate 46 with error 0.497201
Computed iterate 47 with error 0.472341
Computed iterate 48 with error 0.448724
Computed iterate 49 with error 0.426288
Computed iterate 50 with error 0.404974
7.0

To compute the median with $\beta=0.99$ instead of the default value $\beta=0.95$, replace wp = WorkerProblem() with wp = WorkerProblem(beta=0.99)

The medians are subject to randomness, but should be about 7 and 11 respectively. Not surprisingly, more patient workers will wait longer to settle down to their final job

Exercise 3

Here’s the code to reproduce the original figure


In [9]:
from matplotlib import cm

wp = CareerWorkerProblem()
v_init = np.ones((wp.N, wp.N))*100
v = compute_fixed_point(wp.bellman, v_init)
optimal_policy = wp.get_greedy(v)

fig, ax = plt.subplots(figsize=(6,6))
tg, eg = np.meshgrid(wp.theta, wp.epsilon)
lvls=(0.5, 1.5, 2.5, 3.5)
ax.contourf(tg, eg, optimal_policy.T, levels=lvls, cmap=cm.winter, alpha=0.5)
ax.contour(tg, eg, optimal_policy.T, colors='k', levels=lvls, linewidths=2)
ax.set_xlabel('theta', fontsize=14)
ax.set_ylabel('epsilon', fontsize=14)
ax.text(1.8, 2.5, 'new life', fontsize=14)
ax.text(4.5, 2.5, 'new job', fontsize=14, rotation='vertical')
ax.text(4.0, 4.5, 'stay put', fontsize=14)


Computed iterate 1 with error 5.000000
Computed iterate 2 with error 4.750000
Computed iterate 3 with error 4.512500
Computed iterate 4 with error 4.286875
Computed iterate 5 with error 4.072531
Computed iterate 6 with error 3.868905
Computed iterate 7 with error 3.675459
Computed iterate 8 with error 3.491686
Computed iterate 9 with error 3.317102
Computed iterate 10 with error 3.151247
Computed iterate 11 with error 2.993685
Computed iterate 12 with error 2.844000
Computed iterate 13 with error 2.701800
Computed iterate 14 with error 2.566710
Computed iterate 15 with error 2.438375
Computed iterate 16 with error 2.316456
Computed iterate 17 with error 2.200633
Computed iterate 18 with error 2.090602
Computed iterate 19 with error 1.986072
Computed iterate 20 with error 1.886768
Computed iterate 21 with error 1.792430
Computed iterate 22 with error 1.702808
Computed iterate 23 with error 1.617668
Computed iterate 24 with error 1.536784
Computed iterate 25 with error 1.459945
Computed iterate 26 with error 1.386948
Computed iterate 27 with error 1.317600
Computed iterate 28 with error 1.251720
Computed iterate 29 with error 1.189134
Computed iterate 30 with error 1.129678
Computed iterate 31 with error 1.073194
Computed iterate 32 with error 1.019534
Computed iterate 33 with error 0.968557
Computed iterate 34 with error 0.920130
Computed iterate 35 with error 0.874123
Computed iterate 36 with error 0.830417
Computed iterate 37 with error 0.788896
Computed iterate 38 with error 0.749451
Computed iterate 39 with error 0.711979
Computed iterate 40 with error 0.676380
Computed iterate 41 with error 0.642561
Computed iterate 42 with error 0.610433
Computed iterate 43 with error 0.579911
Computed iterate 44 with error 0.550916
Computed iterate 45 with error 0.523370
Computed iterate 46 with error 0.497201
Computed iterate 47 with error 0.472341
Computed iterate 48 with error 0.448724
Computed iterate 49 with error 0.426288
Computed iterate 50 with error 0.404974
Out[9]:
<matplotlib.text.Text at 0x409cdd0>

Now we want to set G_a = G_b = 100 and generate a new figure with these parameters.

To do this replace:

wp = CareerWorkerProblem()

with:

wp = CareerWorkerProblem(G_a=100, G_b=100)

In the new figure, you will see that the region for which the worker will stay put has grown because the distribution for $\epsilon$ has become more concentrated around the mean, making high-paying jobs less realistic


In [ ]: