<jupyter_start><jupyter_text>Modelling Carrer Choices========================The model is based on the following research paper:    <NAME> (1999). The Complexity of Job Mobility among Young Men, Journal of Labor Economics, 17(2), 237-261.    The implementation draws heavily from the material provided on the *Quantitative Economics* website. Model FeaturesIndividuals choose their career and job within a career to max- imize the expected discounted value of lifetime wages. They solve an infinite horizon dynamic programming problem with two state variables. Objective$$\mathrm{E}\sum\limits _{i=1}^{n}\beta^{t}\omega_{t}$$ Payoffs$$w_t = \theta_t + \epsilon_t$$where:* $\theta_t$ contribution of current occupation at time t* $\epsilon_t$ contribution of current job at time t Decision ProblemAt the start of time t, a worker has the following options:* **Stay Put**, retain a current (career, job) pair $(\theta_t,\epsilon_t)$* **New Job**, retain a current career $\theta_t$ but redraw a job $\epsilon_t$ * **New Life**, redraw both a career $\theta_t$ and a job $\epsilon_t$Draws of $\theta$ and $\epsilon$ are independent of each other and past values, with $\theta_t \sim F$ and $\epsilon_t \sim G$. Value Functions$$ V_{SP} = \theta+\varepsilon+\beta V(\theta,\varepsilon) \\V_{NJ} = \theta+\int\varepsilon'G(d\varepsilon')+\beta\int V(\theta,\varepsilon')G(d\varepsilon') \\V_{NL} = \int\theta'F(d\theta')+\int\varepsilon'G(d\varepsilon')+\beta\int\int V(\theta',\varepsilon')G(d\varepsilon')F(d\theta') $$ Course RegistrationPlease register for our class ECON41904 by sending an eMail to <NAME> at: <EMAIL> Housekeeping------------<jupyter_code>%matplotlib inline<jupyter_output><empty_output><jupyter_text>Load Resources--------------<jupyter_code># libraries
import scipy
import numpy as np
    
# project library
from support import *<jupyter_output><empty_output><jupyter_text>Parametrization---------------<jupyter_code># Initialize container
para = dict()

# Preferences
para['beta'] = 0.95  # Time preference

# Distribution Grid
para['B'] = 5.0      # Upper bound for both epsilon and theta
para['N'] = 50       # Number of possible realizations for both epsilon and theta

# Parametrization of Career Distribution
para['F_a'], para['F_b'] = 1.0, 1.0
para['G_a'], para['G_b'] = 1.0, 1.0<jupyter_output><empty_output><jupyter_text>Derived Attributes----------<jupyter_code># Initialize container
attr = dict()

# Grid of random variables
attr['theta']   = np.linspace(0, para['B'], para['N'])
attr['epsilon'] = np.linspace(0, para['B'], para['N'])

# Construct probabilities
attr['F_probs'] = BetaBinomial_pdf(para['N'] - 1, para['F_a'], para['F_b']) 
attr['G_probs'] = BetaBinomial_pdf(para['N'] - 1, para['G_a'], para['G_b'])

# Construct means.
attr['F_mean'] = np.sum(attr['theta'] * attr['F_probs'])
attr['G_mean'] = np.sum(attr['epsilon'] * attr['G_probs'])<jupyter_output><empty_output><jupyter_text>Auxiliary Functions-------------------<jupyter_code>def evaluate_alternative(which, para, attr, v, i, j):
    ''' Evaluate alternatives
    '''
    
    if which == 'Stay Put':
        
        eval_ = attr['theta'][i] + attr['epsilon'][j] + para['beta'] * v[i,j]
        
    elif which == 'New Job': 
        
        eval_ = attr['theta'][i] + attr['G_mean'] + para['beta'] * np.dot(v[i,:], attr['G_probs'])
        
    elif which == 'New Life':
        
        eval_ = attr['G_mean'] + attr['F_mean'] + para['beta'] * np.dot(attr['F_probs'], np.dot(v, attr['G_probs']))
        
    else:
        
        raise AssertionError('Alternative misspecified.')
        
    # Finishing 
    return eval_
    
def get_greedy(v, para, attr):
    ''' Compute optimal actions taking v as the value function
    '''
    # Initialize container
    policy = np.empty(v.shape, dtype = int)

    # Evalaute cases
    for i in range(para['N']):
        
        for j in range(para['N']):
            
            values = [] 
            
            for which in ['Stay Put', 'New Job', 'New Life']:
                             
                values += [evaluate_alternative(which, para, attr, v, i, j)]
      
            # Determine optimal policy
            policy[i,j] = np.argmax(values) + 1
            
    # Finishing 
    return policy

def bellman_operator(v, para, attr):
    ''' The Bellman operator for the model.
    '''
    
    # Initialize container
    new_v = np.empty(v.shape, dtype = float)
    
    # Evalaute cases
    for i in range(para['N']):

        for j in range(para['N']):

            values = [] 
            
            for which in ['Stay Put', 'New Job', 'New Life']:
                             
                values += [evaluate_alternative(which, para, attr, v, i, j)]
                
            new_v[i,j] = np.amax(values)
    
    # Finishing 
    return new_v

def compute_fixed_point(T, v, para, attr, error_tol = 1e-3, max_iter = 50):
    ''' Compute the fixed point.
    '''
    # Initialization
    error = error_tol + 1
    
    iterate = 0

    while True:
        
        new_v = T(v, para, attr)
        
        iterate += 1
        
        error = np.max(np.abs(new_v - v))

        v = new_v
        
        # Terminal conditions
        if iterate > max_iter: break
            
        if error < error_tol: break
    
    # Finishing
    return v<jupyter_output><empty_output><jupyter_text>Solving the Model-----------------<jupyter_code># Starting value
v_init =  np.ones((para['N'],para['N']))*100

# Determine fix point 
v = compute_fixed_point(bellman_operator, v_init, para, attr)

# Determine optimal policy
optimal_policy = get_greedy(v, para, attr)<jupyter_output><empty_output><jupyter_text>Analysis--------  Plot the Optimal Policy<jupyter_code>plot_optimal_policy(optimal_policy, attr)<jupyter_output><empty_output><jupyter_text>***Formatting***<jupyter_code>import urllib; from IPython.core.display import HTML
HTML(urllib.urlopen('http://bit.ly/1K5apRH').read())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1548214881548215, 'fraction_numerical': 0.00850850850850851, 'mean_word_length': 3.0073529411764706, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '625573', 'license': 'MIT', 'n_tokens_mistral': 1960, 'n_tokens_neox': 1874, 'n_words': 506, 'path': 'lectures/economic_models/career_choices/lecture.ipynb', 'repo_name': 'snowdj/course', 'size': '6015'}