示例#1
0
def test_denhaan_errors():

    from dolo import yaml_import
    from dolo.algos.dtcscc.time_iteration import time_iteration as time_iteration

    model = yaml_import('examples/models/rbc.yaml')

    from dolo.algos.dtcscc.perturbations import approximate_controls

    dr = approximate_controls(model)

    dr_global = time_iteration(model, verbose=False)

    s0 = model.calibration['states']
    sigma = model.get_distribution().sigma

    from dolo.algos.dtcscc.accuracy import denhaanerrors

    denerr_1 = denhaanerrors(model, dr)
    denerr_2 = denhaanerrors(model, dr_global)

    print(denerr_1)
    print(denerr_2)
    print(denerr_2['max_errors'][0])

    assert (max(denerr_2['max_errors']) < 10 - 7
            )  # errors with solyak colocations at order 4 are very small
示例#2
0
def test_denhaan_errors():

        from dolo import yaml_import
        from dolo.algos.dtcscc.time_iteration import time_iteration as time_iteration

        model = yaml_import('examples/models/rbc.yaml')

        from dolo.algos.dtcscc.perturbations import approximate_controls

        dr = approximate_controls(model)

        dr_global = time_iteration(model, verbose=False)

        s0 = model.calibration['states']
        sigma = model.get_distribution().sigma

        from dolo.algos.dtcscc.accuracy import denhaanerrors

        denerr_1 = denhaanerrors(model, dr)
        denerr_2 = denhaanerrors(model, dr_global)

        print(denerr_1)
        print(denerr_2)
        print(denerr_2['max_errors'][0])


        assert( max(denerr_2['max_errors']) < 10-7) # errors with solyak colocations at order 4 are very small
示例#3
0
def test_omega_errors():

        from dolo import yaml_import
        from dolo.algos.dtcscc.time_iteration import time_iteration as time_iteration

        model = yaml_import('examples/models/rbc.yaml')

        from dolo.algos.dtcscc.perturbations import approximate_controls

        dr = approximate_controls(model)
        dr_global = time_iteration(model, smolyak_order=3, verbose=False, pert_order=1)

        sigma = model.covariances

        model.sigma = sigma

        s_0 = dr.S_bar

        from dolo.algos.dtcscc.accuracy import  omega

        res_1 = omega( model, dr, orders=[10,10], time_discount=0.96)
        res_2 = omega( model, dr_global)

        print(res_1)
        print(res_2)
示例#4
0
def test_omega_errors():

    from dolo import yaml_import
    from dolo.algos.dtcscc.time_iteration import time_iteration as time_iteration

    model = yaml_import('examples/models/rbc.yaml')

    from dolo.algos.dtcscc.perturbations import approximate_controls

    dr = approximate_controls(model)
    dr_global = time_iteration(model,
                               smolyak_order=3,
                               verbose=False,
                               pert_order=1)

    sigma = model.covariances

    model.sigma = sigma

    s_0 = dr.S_bar

    from dolo.algos.dtcscc.accuracy import omega

    res_1 = omega(model, dr, orders=[10, 10], time_discount=0.96)
    res_2 = omega(model, dr_global)

    print(res_1)
    print(res_2)
示例#5
0
文件: commands.py 项目: jagman88/dolo
def approximate_controls(model, *args, **kwargs):

    if model.model_type == 'dtcscc':
        order = kwargs.get('order')
        if order is None or order==1:
            from dolo.algos.dtcscc.perturbations import approximate_controls
        else:
            from dolo.algos.dtcscc.perturbations_higher_order import approximate_controls
    else:
        raise Exception("Model type {} not supported.".format(model.model_type))

    return approximate_controls(model, *args, **kwargs)
示例#6
0
def approximate_controls(model, *args, **kwargs):

    if model.model_type == 'dtcscc':
        order = kwargs.get('order')
        if order is None or order == 1:
            from dolo.algos.dtcscc.perturbations import approximate_controls
        else:
            from dolo.algos.dtcscc.perturbations_higher_order import approximate_controls
    else:
        raise Exception("Model type {} not supported.".format(
            model.model_type))

    return approximate_controls(model, *args, **kwargs)
示例#7
0
def test_omega_errors():

    from dolo import yaml_import
    from dolo.algos.dtcscc.time_iteration import time_iteration as time_iteration

    model = yaml_import('examples/models/compat/rbc.yaml')

    from dolo.algos.dtcscc.perturbations import approximate_controls

    dr = approximate_controls(model)
    dr_global = time_iteration(model, verbose=False, pert_order=1)

    sigma = model.get_distribution().sigma

    s_0 = dr.S_bar

    from dolo.algos.dtcscc.accuracy import omega

    res_1 = omega(model, dr, grid=dict(orders=[10, 10]), time_discount=0.96)
    res_2 = omega(model, dr_global)

    print(res_1)
    print(res_2)
示例#8
0
def test_omega_errors():

        from dolo import yaml_import
        from dolo.algos.dtcscc.time_iteration import time_iteration as time_iteration

        model = yaml_import('examples/models/compat/rbc.yaml')

        from dolo.algos.dtcscc.perturbations import approximate_controls

        dr = approximate_controls(model)
        dr_global = time_iteration(model, verbose=False, pert_order=1)

        sigma = model.get_distribution().sigma

        s_0 = dr.S_bar

        from dolo.algos.dtcscc.accuracy import omega

        res_1 = omega(model, dr, grid=dict(orders=[10, 10]), time_discount=0.96)
        res_2 = omega(model, dr_global)

        print(res_1)
        print(res_2)
示例#9
0
def time_iteration(model,  bounds=None, verbose=False, initial_dr=None,
                   pert_order=1, with_complementarities=True,
                   interp_type='smolyak', smolyak_order=3, interp_orders=None,
                   maxit=500, tol=1e-8, inner_maxit=10,
                   integration='gauss-hermite', integration_orders=None,
                   T=200, n_s=3, hook=None):
    '''
    Finds a global solution for ``model`` using backward time-iteration.

    This algorithm iterates on the residuals of the arbitrage equations

    Parameters
    ----------
    model : NumericModel
        "fg" or "fga" model to be solved
    bounds : ndarray
        boundaries for approximations. First row contains minimum values.
        Second row contains maximum values.
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    interp_type : {`smolyak`, `spline`}
        type of interpolation to use for future controls
    smolyak_orders : int
        parameter ``l`` for Smolyak interpolation
    interp_orders : 1d array-like
        list of integers specifying the number of nodes in each dimension if
        ``interp_type="spline" ``

    Returns
    -------
    decision rule :
        approximated solution
    '''

    def vprint(t):
        if verbose:
            print(t)

    parms = model.calibration['parameters']
    sigma = model.covariances

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

        if interp_type == 'perturbations':
            return initial_dr

    if bounds is not None:
        pass

    elif model.options and 'approximation_space' in model.options:

        vprint('Using bounds specified by model')

        approx = model.options['approximation_space']
        a = approx['a']
        b = approx['b']

        bounds = np.row_stack([a, b])
        bounds = np.array(bounds, dtype=float)

        if interp_orders is None:
            interp_orders = approx.get('orders', [5] * bounds.shape[1])

    else:
        vprint('Using asymptotic bounds given by first order solution.')

        from dolo.numeric.timeseries import asymptotic_variance
        # this will work only if initial_dr is a Taylor expansion
        Q = asymptotic_variance(initial_dr.A.real, initial_dr.B.real,
                                initial_dr.sigma, T=T)

        devs = np.sqrt(np.diag(Q))
        bounds = np.row_stack([
            initial_dr.S_bar - devs * n_s,
            initial_dr.S_bar + devs * n_s,
        ])

        if interp_orders is None:
            interp_orders = [5] * bounds.shape[1]

    if interp_type == 'smolyak':
        from dolo.numeric.interpolation.smolyak import SmolyakGrid
        dr = SmolyakGrid(bounds[0, :], bounds[1, :], smolyak_order)
    elif interp_type == 'spline':
        from dolo.numeric.interpolation.splines import MultivariateSplines
        dr = MultivariateSplines(bounds[0, :], bounds[1, :], interp_orders)

    if integration == 'optimal_quantization':
        from dolo.numeric.discretization import quantization_nodes
        # number of shocks
        [epsilons, weights] = quantization_nodes(N_e, sigma)
    elif integration == 'gauss-hermite':
        from dolo.numeric.discretization import gauss_hermite_nodes
        if not integration_orders:
            integration_orders = [3] * sigma.shape[0]
        [epsilons, weights] = gauss_hermite_nodes(integration_orders, sigma)

    vprint('Starting time iteration')

    # TODO: transpose

    grid = dr.grid

    xinit = initial_dr(grid)
    xinit = xinit.real  # just in case...

    f = model.functions['arbitrage']
    g = model.functions['transition']

    # define objective function (residuals of arbitrage equations)
    def fun(x):
        return step_residual(grid, x, dr, f, g, parms, epsilons, weights)

    ##
    t1 = time.time()
    err = 1
    x0 = xinit
    it = 0

    verbit = True if verbose == 'full' else False

    if with_complementarities:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} | {4:3} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time', 'nit')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'

    err_0 = 1

    while err > tol and it < maxit:
        # update counters
        t_start = time.time()
        it += 1

        # update interpolation coefficients (NOTE: filters through `fun`)
        dr.set_values(x0)

        # Derivative of objective function
        sdfun = SerialDifferentiableFunction(fun)

        # Apply solver with current decision rule for controls
        if with_complementarities:
            [x, nit] = ncpsolve(sdfun, lb, ub, x0, verbose=verbit,
                                maxit=inner_maxit)
        else:
            [x, nit] = serial_newton(sdfun, x0, verbose=verbit)

        # update error and print if `verbose`
        err = abs(x-x0).max()
        err_SA = err/err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed, nit))

        # Update control vector
        x0[:] = x  # x0 = x0 + (x-x0)

        # call user supplied hook, if any
        if hook:
            hook(dr, it, err)

        # warn and bail if we get inf
        if False in np.isfinite(x0):
            print('iteration {} failed : non finite value')
            return [x0, x]

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#10
0
文件: pea.py 项目: gitter-badger/dolo
def pea(model, maxit=100, tol=1e-8, initial_dr=None, verbose=False):

    t1 = time.time()

    g = model.functions['transition']
    d = model.functions['direct_response']
    h = model.functions['expectation']

    p = model.calibration['parameters']

    if initial_dr is None:
        drp = approximate_controls(model)
    else:
        drp = approximate_controls(model)

    nodes, weights = gauss_hermite_nodes([5], model.covariances)

    ap = model.options['approximation_space']
    a = ap['a']
    b = ap['b']
    orders = ap['orders']
    grid = mlinspace(a,b,orders)

    dr = MultivariateCubicSplines(a,b,orders)

    N = grid.shape[0]
    z = np.zeros((N,len(model.symbols['expectations'])))

    x_0 = drp(grid)

    it = 0
    err = 10
    err_0 = 10

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err>tol and it<=maxit:

        t_start = time.time()

        dr.set_values(x_0)

        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i,:]
            S = g(grid, x_0, e, p)
            # evaluate future controls
            X = dr(S)
            z += weights[i]*h(S,X,p)

        # TODO: check that control is admissible
        new_x = d(grid, z, p)

        # check whether they differ from the preceding guess
        err = (abs(new_x - x_0).max())

        x_0 = new_x

        if verbose:

            # update error and print if `verbose`
            err_SA = err/err_0
            err_0 = err
            t_finish = time.time()
            elapsed = t_finish - t_start
            if verbose:
                print(fmt_str.format(it, err, err_SA, elapsed))


    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#11
0
def parameterized_expectations_direct(model,
                                      verbose=False,
                                      dr0=None,
                                      pert_order=1,
                                      grid={},
                                      distribution={},
                                      maxit=100,
                                      tol=1e-8):
    '''
    Finds a global solution for ``model`` using parameterized expectations
    function. Requires the model to be written with controls as a direct
    function of the model objects.

    The algorithm iterates on the expectations function in the arbitrage
    equation. It follows the discussion in section 9.9 of Miranda and
    Fackler (2002).

    Parameters
    ----------
    model : NumericModel
        "dtcscc" model to be solved
    verbose : boolean
        if True, display iterations
    dr0 : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    grid: grid options
    distribution: distribution options
    maxit: maximum number of iterations
    tol: tolerance criterium for successive approximations

    Returns
    -------
    decision rule :
        approximated solution
    '''

    t1 = time.time()
    g = model.functions['transition']
    d = model.functions['direct_response']
    h = model.functions['expectation']
    parms = model.calibration['parameters']

    if dr0 is None:
        if pert_order == 1:
            dr0 = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    approx = model.get_endo_grid(**grid)
    grid = approx.grid
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)
    expect = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    N = grid.shape[0]
    z = np.zeros((N, len(model.symbols['expectations'])))

    x_0 = dr0(grid)
    x_0 = x_0.real  # just in case ...
    h_0 = h(grid, x_0, parms)

    it = 0
    err = 10
    err_0 = 10

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:

        it += 1
        t_start = time.time()

        # dr.set_values(x_0)
        expect.set_values(h_0)

        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i, :]
            S = g(grid, x_0, e, parms)
            # evaluate expectation over the future state
            z += weights[i] * expect(S)

        # TODO: check that control is admissible
        new_x = d(grid, z, parms)
        new_h = h(grid, new_x, parms)

        # update error
        err = (abs(new_h - h_0).max())

        # Update guess for decision rule and expectations function
        x_0 = new_x
        h_0 = new_h

        # print error information if `verbose`
        err_SA = err / err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    # Interpolation for the decision rule
    dr.set_values(x_0)

    return dr
示例#12
0
def parameterized_expectations(model, verbose=False, initial_dr=None,
                               pert_order=1, with_complementarities=True,
                               grid={}, distribution={},
                               maxit=100, tol=1e-8, inner_maxit=10,
                               direct=False):

    '''
    Find global solution for ``model`` via parameterized expectations.
    Controls must be expressed as a direct function of equilibrium objects.
    Algorithm iterates over the expectations function in the arbitrage equation.

    Parameters:
    ----------

    model : NumericModel
        ``dtcscc`` model to be solved

    verbose : boolean
        if True, display iterations

    initial_dr : decision rule
        initial guess for the decision rule

    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess

    grid : grid options

    distribution : distribution options

    maxit : maximum number of iterations

    tol : tolerance criterium for successive approximations

    inner_maxit : maximum number of iteration for inner solver

    direct : if True, solve with direct method. If false, solve indirectly

    Returns
    -------

    decision rule :
        approximated solution

    '''

    t1 = time.time()

    g = model.functions['transition']
    h = model.functions['expectation']
    d = model.functions['direct_response']
    f = model.functions['arbitrage_exp']  # f(s, x, z, p, out)
    parms = model.calibration['parameters']

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    approx = model.get_grid(**grid)
    grid = approx.grid
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)
    expect = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    N = grid.shape[0]
    z = np.zeros((N, len(model.symbols['expectations'])))

    x_0 = initial_dr(grid)
    x_0 = x_0.real  # just in case ...
    h_0 = h(grid, x_0, parms)

    it = 0
    err = 10
    err_0 = 10

    verbit = True if verbose == 'full' else False

    if with_complementarities is True:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:

        it += 1
        t_start = time.time()

        # dr.set_values(x_0)
        expect.set_values(h_0)

        # evaluate expectation over the future state
        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i, :]
            S = g(grid, x_0, e, parms)
            z += weights[i]*expect(S)

        if direct is True:
            # Use control as direct function of arbitrage equation
            new_x = d(grid, z, parms)
            if with_complementarities is True:
                new_x = np.minimum(new_x, ub)
                new_x = np.maximum(new_x, lb)
        else:
            # Find control by solving arbitrage equation
            def fun(x): return f(grid, x, z, parms)
            sdfun = SerialDifferentiableFunction(fun)

            if with_complementarities is True:
                [new_x, nit] = ncpsolve(sdfun, lb, ub, x_0, verbose=verbit,
                                        maxit=inner_maxit)
            else:
                [new_x, nit] = serial_newton(sdfun, x_0, verbose=verbit)

        new_h = h(grid, new_x, parms)

        # update error
        err = (abs(new_h - h_0).max())

        # Update guess for decision rule and expectations function
        x_0 = new_x
        h_0 = new_h

        # print error infomation if `verbose`
        err_SA = err/err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    # Interpolation for the decision rule
    dr.set_values(x_0)

    return dr
示例#13
0
def solve_policy(model,
                 tol=1e-6,
                 grid={},
                 distribution={},
                 integration_orders=None,
                 maxit=500,
                 maxit_howard=500,
                 verbose=False,
                 hook=None,
                 initial_dr=None,
                 pert_order=1):
    '''
    Solve for the value function and associated decision rule by iterating over
    the value function.

    Parameters
    -----------
    model :
        ``dtcscc`` model. Must contain a ``felicity`` function.

    Returns
    --------
    dr : Markov decision rule
        The solved decision rule/policy function
    drv : decision rule
        The solved value function
    '''

    assert (model.model_type == 'dtcscc')

    def vprint(t):
        if verbose:
            print(t)

    # transition(s, x, e, p, out), felicity(s, x, p, out)
    transition = model.functions['transition']
    felicity = model.functions['felicity']
    controls_lb = model.functions['controls_lb']
    controls_ub = model.functions['controls_ub']

    parms = model.calibration['parameters']
    discount = model.calibration['beta']

    x0 = model.calibration['controls']
    s0 = model.calibration['states']
    r0 = felicity(s0, x0, parms)

    approx = model.get_grid(**grid)
    # a = approx.a
    # b = approx.b
    # orders = approx.orders
    distrib = model.get_distribution(**distribution)
    sigma = distrib.sigma

    # Possibly use the approximation orders?
    if integration_orders is None:
        integration_orders = [3] * sigma.shape[0]
    [nodes, weights] = gauss_hermite_nodes(integration_orders, sigma)

    interp_type = approx.interpolation
    drv = create_interpolator(approx, interp_type)
    if initial_dr is None:
        if pert_order == 1:
            dr = approximate_controls(model)
        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")
    else:
        dr = initial_dr

    grid = drv.grid
    N = grid.shape[0]  # Number of states
    n_x = grid.shape[1]  # Number of controls

    controls = dr(grid)
    controls_0 = np.zeros((N, n_x))
    controls_0[:, :] = model.calibration['controls'][None, :]

    values_0 = np.zeros((N, 1))
    values_0[:, :] = r0 / (1 - discount)

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'.format(
            'N', ' Error', 'Gain', 'Time')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

    t1 = time.time()

    # FIRST: value function iterations, 10 iterations to start
    it = 0
    err_v = 100
    err_v_0 = 0.0
    gain_v = 0.0
    err_x = 100
    err_x_0 = 100

    if verbose:
        print(stars)
        print('Starting value function iteration')
        print(stars)

    while err_v > tol and it < 10:

        t_start = time.time()
        it += 1

        # update interpolation object with current values
        drv.set_values(values_0)

        values = values_0.copy()
        controls = controls_0.copy()

        for n in range(N):
            s = grid[n, :]
            x = controls[n, :]
            lb = controls_lb(s, parms)
            ub = controls_ub(s, parms)
            bnds = [e for e in zip(lb, ub)]

            def valfun(xx):
                return -choice_value(transition, felicity, s, xx, drv, nodes,
                                     weights, parms, discount)[0]

            res = minimize(valfun, x, bounds=bnds, tol=1e-4)

            controls[n, :] = res.x
            values[n, 0] = -valfun(res.x)

        # compute error, update value and dr
        err_x = abs(controls - controls_0).max()
        err_v = abs(values - values_0).max()
        t_end = time.time()
        elapsed = t_end - t_start

        values_0 = values
        controls_0 = controls

        gain_x = err_x / err_x_0
        gain_v = err_v / err_v_0

        err_x_0 = err_x
        err_v_0 = err_v

        # print update to user, if verbose
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err_v, gain_v, elapsed))

    # SECOND: Howard improvement step, 10-20 iterations
    it = 0
    err_v = 100
    err_v_0 = 0.0
    gain_v = 0.0

    if verbose:
        print(stars)
        print('Starting Howard improvement step')
        print(stars)

    while err_v > tol and it < maxit_howard:

        t_start = time.time()
        it += 1

        # update interpolation object with current values
        drv.set_values(values_0)

        values = values_0.copy()
        controls = controls_0.copy()
        # controls = controls_0.copy()  # No need to keep updating

        for n in range(N):
            s = grid[n, :]
            x = controls[n, :]
            values[n, 0] = choice_value(transition, felicity, s, x, drv, nodes,
                                        weights, parms, discount)[0]

        # compute error, update value function
        err_v = abs(values - values_0).max()
        values_0 = values

        t_end = time.time()
        elapsed = t_end - t_start

        gain_v = err_v / err_v_0
        err_v_0 = err_v

        # print update to user, if verbose
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err_v, gain_v, elapsed))

    # THIRD: Back to value function iteration until convergence.
    it = 0
    err_v = 100
    err_v_0 = 0.0
    gain_v = 0.0
    err_x = 100
    err_x_0 = 100

    if verbose:
        print(stars)
        print('Starting value function iteration')
        print(stars)

    while err_v > tol and it < maxit:

        t_start = time.time()
        it += 1

        # update interpolation object with current values
        drv.set_values(values_0)

        values = values_0.copy()
        controls = controls_0.copy()

        for n in range(N):
            s = grid[n, :]
            x = controls[n, :]
            lb = controls_lb(s, parms)
            ub = controls_ub(s, parms)
            bnds = [e for e in zip(lb, ub)]

            def valfun(xx):
                return -choice_value(transition, felicity, s, xx, drv, nodes,
                                     weights, parms, discount)[0]

            res = minimize(valfun, x, bounds=bnds, tol=1e-4)

            controls[n, :] = res.x
            values[n, 0] = -valfun(res.x)

        # compute error, update value and dr
        err_x = abs(controls - controls_0).max()
        err_v = abs(values - values_0).max()
        t_end = time.time()
        elapsed = t_end - t_start

        values_0 = values
        controls_0 = controls

        gain_x = err_x / err_x_0
        gain_v = err_v / err_v_0

        err_x_0 = err_x
        err_v_0 = err_v

        # print update to user, if verbose
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err_v, gain_v, elapsed))

    if it == maxit:
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    # final value function and decision rule
    drv.set_values(values_0)
    dr = create_interpolator(approx, interp_type)
    dr.set_values(controls_0)

    return dr, drv
示例#14
0
def time_iteration(model, verbose=False, initial_dr=None, pert_order=1,
                   with_complementarities=True, grid={}, distribution={},
                   maxit=500, tol=1e-8, inner_maxit=10, hook=None):
    '''
    Finds a global solution for ``model`` using backward time-iteration.

    This algorithm iterates on the residuals of the arbitrage equations

    Parameters
    ----------
    model : NumericModel
        "dtcscc" model to be solved
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    grid: grid options
    distribution: distribution options
    maxit: maximum number of iterations
    inner_maxit: maximum number of iteration for inner solver
    tol: tolerance criterium for successive approximations

    Returns
    -------
    decision rule :
        approximated solution
    '''

    def vprint(t):
        if verbose:
            print(t)

    f = model.functions['arbitrage']
    g = model.functions['transition']

    parms = model.calibration['parameters']

    approx = model.get_grid(**grid)
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    vprint('Starting time iteration')

    # TODO: transpose

    grid = dr.grid

    x_0 = initial_dr(grid)
    x_0 = x_0.real  # just in case...

    # define objective function (residuals of arbitrage equations)
    def fun(x):
        return step_residual(grid, x, dr, f, g, parms, nodes, weights)

    ##
    t1 = time.time()
    err = 1
    err_0 = 1
    it = 0

    verbit = True if verbose == 'full' else False

    if with_complementarities:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} | {4:3} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time', 'nit')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'

    while err > tol and it < maxit:
        # update counters
        t_start = time.time()
        it += 1

        # update interpolation coefficients (NOTE: filters through `fun`)
        dr.set_values(x_0)

        # Derivative of objective function
        sdfun = SerialDifferentiableFunction(fun)

        # Apply solver with current decision rule for controls
        if with_complementarities:
            [x, nit] = ncpsolve(sdfun, lb, ub, x_0, verbose=verbit,
                                maxit=inner_maxit)
        else:
            [x, nit] = serial_newton(sdfun, x_0, verbose=verbit)

        # update error and print if `verbose`
        err = abs(x-x_0).max()
        err_SA = err/err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed, nit))

        # Update control vector
        x_0[:] = x  # x0 = x0 + (x-x0)

        # call user supplied hook, if any
        if hook:
            hook(dr, it, err)

        # warn and bail if we get inf
        if False in np.isfinite(x_0):
            print('iteration {} failed : non finite value')
            return [x_0, x]

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final time and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#15
0
def time_iteration(model,
                   bounds=None,
                   verbose=False,
                   initial_dr=None,
                   pert_order=1,
                   with_complementarities=True,
                   interp_type='smolyak',
                   smolyak_order=3,
                   interp_orders=None,
                   maxit=500,
                   tol=1e-8,
                   inner_maxit=10,
                   integration='gauss-hermite',
                   integration_orders=None,
                   T=200,
                   n_s=3,
                   hook=None):
    '''
    Finds a global solution for ``model`` using backward time-iteration.

    This algorithm iterates on the residuals of the arbitrage equations

    Parameters
    ----------
    model : NumericModel
        "fg" or "fga" model to be solved
    bounds : ndarray
        boundaries for approximations. First row contains minimum values.
        Second row contains maximum values.
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    interp_type : {`smolyak`, `spline`}
        type of interpolation to use for future controls
    smolyak_orders : int
        parameter ``l`` for Smolyak interpolation
    interp_orders : 1d array-like
        list of integers specifying the number of nodes in each dimension if
        ``interp_type="spline" ``

    Returns
    -------
    decision rule :
        approximated solution
    '''
    def vprint(t):
        if verbose:
            print(t)

    parms = model.calibration['parameters']
    sigma = model.covariances

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

        if interp_type == 'perturbations':
            return initial_dr

    if bounds is not None:
        pass

    elif model.options and 'approximation_space' in model.options:

        vprint('Using bounds specified by model')

        approx = model.options['approximation_space']
        a = approx['a']
        b = approx['b']

        bounds = np.row_stack([a, b])
        bounds = np.array(bounds, dtype=float)

        if interp_orders is None:
            interp_orders = approx.get('orders', [5] * bounds.shape[1])

    else:
        vprint('Using asymptotic bounds given by first order solution.')

        from dolo.numeric.timeseries import asymptotic_variance
        # this will work only if initial_dr is a Taylor expansion
        Q = asymptotic_variance(initial_dr.A.real,
                                initial_dr.B.real,
                                initial_dr.sigma,
                                T=T)

        devs = np.sqrt(np.diag(Q))
        bounds = np.row_stack([
            initial_dr.S_bar - devs * n_s,
            initial_dr.S_bar + devs * n_s,
        ])

        if interp_orders is None:
            interp_orders = [5] * bounds.shape[1]

    if interp_type == 'smolyak':
        from dolo.numeric.interpolation.smolyak import SmolyakGrid
        dr = SmolyakGrid(bounds[0, :], bounds[1, :], smolyak_order)
    elif interp_type == 'spline':
        from dolo.numeric.interpolation.splines import MultivariateSplines
        dr = MultivariateSplines(bounds[0, :], bounds[1, :], interp_orders)

    if integration == 'optimal_quantization':
        from dolo.numeric.discretization import quantization_nodes
        # number of shocks
        [epsilons, weights] = quantization_nodes(N_e, sigma)
    elif integration == 'gauss-hermite':
        from dolo.numeric.discretization import gauss_hermite_nodes
        if not integration_orders:
            integration_orders = [3] * sigma.shape[0]
        [epsilons, weights] = gauss_hermite_nodes(integration_orders, sigma)

    vprint('Starting time iteration')

    # TODO: transpose

    grid = dr.grid

    xinit = initial_dr(grid)
    xinit = xinit.real  # just in case...

    f = model.functions['arbitrage']
    g = model.functions['transition']

    # define objective function (residuals of arbitrage equations)
    def fun(x):
        return step_residual(grid, x, dr, f, g, parms, epsilons, weights)

    ##
    t1 = time.time()
    err = 1
    x0 = xinit
    it = 0

    verbit = True if verbose == 'full' else False

    if with_complementarities:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} | {4:3} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time', 'nit')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'

    err_0 = 1

    while err > tol and it < maxit:
        # update counters
        t_start = time.time()
        it += 1

        # update interpolation coefficients (NOTE: filters through `fun`)
        dr.set_values(x0)

        # Derivative of objective function
        sdfun = SerialDifferentiableFunction(fun)

        # Apply solver with current decision rule for controls
        if with_complementarities:
            [x, nit] = ncpsolve(sdfun,
                                lb,
                                ub,
                                x0,
                                verbose=verbit,
                                maxit=inner_maxit)
        else:
            [x, nit] = serial_newton(sdfun, x0, verbose=verbit)

        # update error and print if `verbose`
        err = abs(x - x0).max()
        err_SA = err / err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed, nit))

        # Update control vector
        x0[:] = x  # x0 = x0 + (x-x0)

        # call user supplied hook, if any
        if hook:
            hook(dr, it, err)

        # warn and bail if we get inf
        if False in np.isfinite(x0):
            print('iteration {} failed : non finite value')
            return [x0, x]

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#16
0
def parameterized_expectations_direct(model, verbose=False, initial_dr=None,
                                      pert_order=1, grid={}, distribution={},
                                      maxit=100, tol=1e-8):
    '''
    Finds a global solution for ``model`` using parameterized expectations
    function. Requires the model to be written with controls as a direct
    function of the model objects.

    The algorithm iterates on the expectations function in the arbitrage
    equation. It follows the discussion in section 9.9 of Miranda and
    Fackler (2002).

    Parameters
    ----------
    model : NumericModel
        "dtcscc" model to be solved
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    grid: grid options
    distribution: distribution options
    maxit: maximum number of iterations
    tol: tolerance criterium for successive approximations

    Returns
    -------
    decision rule :
        approximated solution
    '''

    t1 = time.time()
    g = model.functions['transition']
    d = model.functions['direct_response']
    h = model.functions['expectation']
    parms = model.calibration['parameters']

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    approx = model.get_grid(**grid)
    grid = approx.grid
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)
    expect = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    N = grid.shape[0]
    z = np.zeros((N, len(model.symbols['expectations'])))

    x_0 = initial_dr(grid)
    x_0 = x_0.real  # just in case ...
    h_0 = h(grid, x_0, parms)

    it = 0
    err = 10
    err_0 = 10

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:

        it += 1
        t_start = time.time()

        # dr.set_values(x_0)
        expect.set_values(h_0)

        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i, :]
            S = g(grid, x_0, e, parms)
            # evaluate expectation over the future state
            z += weights[i]*expect(S)

        # TODO: check that control is admissible
        new_x = d(grid, z, parms)
        new_h = h(grid, new_x, parms)

        # update error
        err = (abs(new_h - h_0).max())

        # Update guess for decision rule and expectations function
        x_0 = new_x
        h_0 = new_h

        # print error information if `verbose`
        err_SA = err/err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    # Interpolation for the decision rule
    dr.set_values(x_0)

    return dr
示例#17
0
def time_iteration_direct(model, verbose=False, initial_dr=None,
                          pert_order=1, with_complementarities=True, grid={}, distribution={}, maxit=500,
                          tol=1e-8):
    '''
    Finds a global solution for ``model`` using backward time-iteration.
    Requires the model to be written with controls as a direct function of the
    model objects.

    This algorithm iterates on the (directly expressed) decision rule, which is
    a re-expression of the arbitrage equation.

    Parameters
    ----------
    model : NumericModel
        "dtcscc" model to be solved
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    grid: grid options
    distribution: distribution options
    maxit: maximum number of iterations
    tol: tolerance criterium for successive approximations

    Returns
    -------
    decision rule :
        approximated solution
    '''

    def vprint(t):
        if verbose:
            print(t)

    g = model.functions['transition']
    d = model.functions['direct_response']
    h = model.functions['expectation']

    parms = model.calibration['parameters']

    approx = model.get_grid(**grid)
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    vprint('Starting direct response time iteration')

    grid = approx.grid

    N = grid.shape[0]
    z = np.zeros((N, len(model.symbols['expectations'])))

    x_0 = initial_dr(grid)
    x_0 = x_0.real  # just in case...

    if with_complementarities:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    ##
    t1 = time.time()
    err = 10
    err_0 = 10
    it = 0

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:
        # update counters
        t_start = time.time()
        it += 1

        # update interpolation coefficients
        dr.set_values(x_0)

        # Compute expectations function
        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i, :]
            S = g(grid, x_0, e, parms)
            # evaluate future controls
            X = dr(S)
            z += weights[i]*h(S, X, parms)

        # Update control
        if with_complementarities:
            new_x = d(grid, z, parms)
            new_x = np.minimum(new_x, ub)
            new_x = np.maximum(new_x, lb)
        else:
            new_x = d(grid, z, parms)

        # update error
        err = (abs(new_x - x_0).max())

        # Update control vector
        x_0[:] = new_x

        # print error information if `verbose`
        err_SA = err/err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final time and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#18
0
def nonlinear_system(model, initial_dr=None, maxit=10, tol=1e-8,  grid={}, distribution={}, verbose=True):

    '''
    Finds a global solution for ``model`` by solving one large system of equations
    using a simple newton algorithm.

    Parameters
    ----------
    model: NumericModel
        "dtcscc" model to be solved
    verbose: boolean
        if True, display iterations
    initial_dr: decision rule
        initial guess for the decision rule
    maxit:  int
        maximum number of iterationsd
    tol: tolerance criterium for successive approximations
    grid: grid options
    distribution: distribution options

    Returns
    -------
    decision rule :
        approximated solution
    '''


    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} |'
        headline = headline.format('N', ' Error', 'Time')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)
        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} |'

    f = model.functions['arbitrage']
    g = model.functions['transition']
    p = model.calibration['parameters']

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    approx = model.get_grid(**grid)
    ms = create_interpolator(approx, approx.interpolation)

    grid = ms.grid

    if initial_dr is None:
        dr = approximate_controls(model)
    else:
        dr = initial_dr

    ms.set_values(dr(grid))

    x = dr(grid)
    x0 = x.copy()

    it = 0
    err = 10


    a0 = x0.copy().reshape((x0.shape[0]*x0.shape[1],))
    a = a0.copy()

    while err > tol and it < maxit:

        it += 1
        t1 = time.time()

        r, da = residuals(f, g, grid, a.reshape(x0.shape), ms, nodes, weights, p, diff=True)[:2]
        r = r.flatten()

        err = abs(r).max()

        t2 = time.time()

        if verbose:
            print(fmt_str.format(it, err, t2-t1))

        if err > tol:
            a -= scipy.sparse.linalg.spsolve(da, r)

    if verbose:
        print(stars)

    return ms
示例#19
0
def time_iteration(model, verbose=False, initial_dr=None, pert_order=1,
                   with_complementarities=True, grid={}, distribution={},
                   maxit=500, tol=1e-8, inner_maxit=10, hook=None):
    '''
    Finds a global solution for ``model`` using backward time-iteration.

    This algorithm iterates on the residuals of the arbitrage equations

    Parameters
    ----------
    model : NumericModel
        "dtcscc" model to be solved
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    grid: grid options
    distribution: distribution options
    maxit: maximum number of iterations
    inner_maxit: maximum number of iteration for inner solver
    tol: tolerance criterium for successive approximations

    Returns
    -------
    decision rule :
        approximated solution
    '''

    def vprint(t):
        if verbose:
            print(t)

    f = model.functions['arbitrage']
    g = model.functions['transition']

    parms = model.calibration['parameters']

    approx = model.get_grid(**grid)
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    if initial_dr is None:
        if pert_order == 1:
            initial_dr = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    vprint('Starting time iteration')

    # TODO: transpose

    grid = dr.grid

    x_0 = initial_dr(grid)
    x_0 = x_0.real  # just in case...

    # define objective function (residuals of arbitrage equations)
    def fun(x):
        return step_residual(grid, x, dr, f, g, parms, nodes, weights)

    ##
    t1 = time.time()
    err = 1
    err_0 = 1
    it = 0

    verbit = True if verbose == 'full' else False

    if with_complementarities:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} | {4:3} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time', 'nit')
        stars = '-'*len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'

    while err > tol and it < maxit:
        # update counters
        t_start = time.time()
        it += 1

        # update interpolation coefficients (NOTE: filters through `fun`)
        dr.set_values(x_0)

        # Derivative of objective function
        sdfun = SerialDifferentiableFunction(fun)

        # Apply solver with current decision rule for controls
        if with_complementarities:
            [x, nit] = ncpsolve(sdfun, lb, ub, x_0, verbose=verbit,
                                maxit=inner_maxit)
        else:
            [x, nit] = serial_newton(sdfun, x_0, verbose=verbit)

        # update error and print if `verbose`
        err = abs(x-x_0).max()
        err_SA = err/err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed, nit))

        # Update control vector
        x_0[:] = x  # x0 = x0 + (x-x0)

        # call user supplied hook, if any
        if hook:
            hook(dr, it, err)

        # warn and bail if we get inf
        if False in np.isfinite(x_0):
            print('iteration {} failed : non finite value')
            return [x_0, x]

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final time and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#20
0
def parameterized_expectations(model,
                               verbose=False,
                               dr0=None,
                               pert_order=1,
                               with_complementarities=True,
                               grid={},
                               distribution={},
                               maxit=100,
                               tol=1e-8,
                               inner_maxit=10,
                               direct=False):
    '''
    Find global solution for ``model`` via parameterized expectations.
    Controls must be expressed as a direct function of equilibrium objects.
    Algorithm iterates over the expectations function in the arbitrage equation.

    Parameters:
    ----------

    model : NumericModel
        ``dtcscc`` model to be solved

    verbose : boolean
        if True, display iterations

    dr0 : decision rule
        initial guess for the decision rule

    pert_order : {1}
        if no initial guess is supplied, the perturbation solution at order
        ``pert_order`` is used as initial guess

    grid : grid options

    distribution : distribution options

    maxit : maximum number of iterations

    tol : tolerance criterium for successive approximations

    inner_maxit : maximum number of iteration for inner solver

    direct : if True, solve with direct method. If false, solve indirectly

    Returns
    -------

    decision rule :
        approximated solution

    '''

    t1 = time.time()

    g = model.functions['transition']
    h = model.functions['expectation']
    d = model.functions['direct_response']
    f = model.functions['arbitrage_exp']  # f(s, x, z, p, out)
    parms = model.calibration['parameters']

    if dr0 is None:
        if pert_order == 1:
            dr0 = approximate_controls(model)

        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")

    approx = model.get_endo_grid(**grid)
    grid = approx.grid
    interp_type = approx.interpolation
    dr = create_interpolator(approx, interp_type)
    expect = create_interpolator(approx, interp_type)

    distrib = model.get_distribution(**distribution)
    nodes, weights = distrib.discretize()

    N = grid.shape[0]
    z = np.zeros((N, len(model.symbols['expectations'])))

    x_0 = dr0(grid)
    x_0 = x_0.real  # just in case ...
    h_0 = h(grid, x_0, parms)

    it = 0
    err = 10
    err_0 = 10

    verbit = True if verbose == 'full' else False

    if with_complementarities is True:
        lbfun = model.functions['controls_lb']
        ubfun = model.functions['controls_ub']
        lb = lbfun(grid, parms)
        ub = ubfun(grid, parms)
    else:
        lb = None
        ub = None

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:

        it += 1
        t_start = time.time()

        # dr.set_values(x_0)
        expect.set_values(h_0)

        # evaluate expectation over the future state
        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i, :]
            S = g(grid, x_0, e, parms)
            z += weights[i] * expect(S)

        if direct is True:
            # Use control as direct function of arbitrage equation
            new_x = d(grid, z, parms)
            if with_complementarities is True:
                new_x = np.minimum(new_x, ub)
                new_x = np.maximum(new_x, lb)
        else:
            # Find control by solving arbitrage equation
            def fun(x):
                return f(grid, x, z, parms)

            sdfun = SerialDifferentiableFunction(fun)

            if with_complementarities is True:
                [new_x, nit] = ncpsolve(sdfun,
                                        lb,
                                        ub,
                                        x_0,
                                        verbose=verbit,
                                        maxit=inner_maxit)
            else:
                [new_x, nit] = serial_newton(sdfun, x_0, verbose=verbit)

        new_h = h(grid, new_x, parms)

        # update error
        err = (abs(new_h - h_0).max())

        # Update guess for decision rule and expectations function
        x_0 = new_x
        h_0 = new_h

        # print error infomation if `verbose`
        err_SA = err / err_0
        err_0 = err
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    # Interpolation for the decision rule
    dr.set_values(x_0)

    return dr
示例#21
0
            err_0 = err
            t_finish = time.time()
            elapsed = t_finish - t_start
            if verbose:
                print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr


if __name__ == '__main__':

    from dolo import *

    model = yaml_import("examples/models/rbc_full.yaml")
    drp = approximate_controls(model)
    sol = pea(model, initial_dr=drp, verbose=True)
    sol = pea(model, initial_dr=drp, verbose=True)

# computes expectations # based on xinit
示例#22
0
文件: pea.py 项目: gitter-badger/dolo
            t_finish = time.time()
            elapsed = t_finish - t_start
            if verbose:
                print(fmt_str.format(it, err, err_SA, elapsed))


    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr


if __name__ == '__main__':

    from dolo import *

    model = yaml_import("examples/models/rbc_full.yaml")
    drp = approximate_controls(model)
    sol = pea(model, initial_dr=drp, verbose=True)
    sol = pea(model, initial_dr=drp, verbose=True)

# computes expectations # based on xinit
示例#23
0
def pea(model, maxit=100, tol=1e-8, initial_dr=None, verbose=False):

    t1 = time.time()

    g = model.functions['transition']
    d = model.functions['direct_response']
    h = model.functions['expectation']

    p = model.calibration['parameters']

    if initial_dr is None:
        drp = approximate_controls(model)
    else:
        drp = approximate_controls(model)

    nodes, weights = gauss_hermite_nodes([5], model.covariances)

    ap = model.options['approximation_space']
    a = ap['a']
    b = ap['b']
    orders = ap['orders']
    grid = mlinspace(a, b, orders)

    dr = MultivariateCubicSplines(a, b, orders)

    N = grid.shape[0]
    z = np.zeros((N, len(model.symbols['expectations'])))

    x_0 = drp(grid)

    it = 0
    err = 10
    err_0 = 10

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:

        t_start = time.time()

        dr.set_values(x_0)

        z[...] = 0
        for i in range(weights.shape[0]):
            e = nodes[i, :]
            S = g(grid, x_0, e, p)
            # evaluate future controls
            X = dr(S)
            z += weights[i] * h(S, X, p)

        # TODO: check that control is admissible
        new_x = d(grid, z, p)

        # check whether they differ from the preceding guess
        err = (abs(new_x - x_0).max())

        x_0 = new_x

        if verbose:

            # update error and print if `verbose`
            err_SA = err / err_0
            err_0 = err
            t_finish = time.time()
            elapsed = t_finish - t_start
            if verbose:
                print(fmt_str.format(it, err, err_SA, elapsed))

    if it == maxit:
        import warnings
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    return dr
示例#24
0
def solve_policy(model, tol=1e-6, grid={}, distribution={}, integration_orders=None, maxit=500, maxit_howard=500, verbose=False, hook=None, initial_dr=None, pert_order=1):
    '''
    Solve for the value function and associated decision rule by iterating over
    the value function.

    Parameters
    -----------
    model :
        ``dtcscc`` model. Must contain a ``felicity`` function.

    Returns
    --------
    dr : Markov decision rule
        The solved decision rule/policy function
    drv : decision rule
        The solved value function
    '''

    assert (model.model_type == 'dtcscc')

    def vprint(t):
        if verbose:
            print(t)

    # transition(s, x, e, p, out), felicity(s, x, p, out)
    transition = model.functions['transition']
    felicity = model.functions['felicity']
    controls_lb = model.functions['controls_lb']
    controls_ub = model.functions['controls_ub']

    parms = model.calibration['parameters']
    discount = model.calibration['beta']

    x0 = model.calibration['controls']
    s0 = model.calibration['states']
    r0 = felicity(s0, x0, parms)

    approx = model.get_grid(**grid)
    # a = approx.a
    # b = approx.b
    # orders = approx.orders
    distrib = model.get_distribution(**distribution)
    sigma = distrib.sigma

    # Possibly use the approximation orders?
    if integration_orders is None:
        integration_orders = [3] * sigma.shape[0]
    [nodes, weights] = gauss_hermite_nodes(integration_orders, sigma)

    interp_type = approx.interpolation
    drv = create_interpolator(approx, interp_type)
    if initial_dr is None:
        if pert_order == 1:
            dr = approximate_controls(model)
        if pert_order > 1:
            raise Exception("Perturbation order > 1 not supported (yet).")
    else:
        dr = initial_dr

    grid = drv.grid
    N = grid.shape[0]       # Number of states
    n_x = grid.shape[1]     # Number of controls

    controls = dr(grid)
    controls_0 = np.zeros((N, n_x))
    controls_0[:, :] = model.calibration['controls'][None, :]

    values_0 = np.zeros((N, 1))
    values_0[:, :] = r0/(1-discount)

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'.format('N', ' Error','Gain', 'Time')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

    t1 = time.time()

    # FIRST: value function iterations, 10 iterations to start
    it = 0
    err_v = 100
    err_v_0 = 0.0
    gain_v = 0.0
    err_x = 100
    err_x_0 = 100

    if verbose:
        print(stars)
        print('Starting value function iteration')
        print(stars)

    while err_v > tol and it < 10:

        t_start = time.time()
        it += 1

        # update interpolation object with current values
        drv.set_values(values_0)

        values = values_0.copy()
        controls = controls_0.copy()

        for n in range(N):
            s = grid[n, :]
            x = controls[n, :]
            lb = controls_lb(s, parms)
            ub = controls_ub(s, parms)
            bnds = [e for e in zip(lb, ub)]

            def valfun(xx):
                return -choice_value(transition, felicity, s, xx, drv, nodes,
                                     weights, parms, discount)[0]
            res = minimize(valfun, x, bounds=bnds, tol=1e-4)

            controls[n, :] = res.x
            values[n, 0] = -valfun(res.x)

        # compute error, update value and dr
        err_x = abs(controls - controls_0).max()
        err_v = abs(values - values_0).max()
        t_end = time.time()
        elapsed = t_end - t_start

        values_0 = values
        controls_0 = controls

        gain_x = err_x / err_x_0
        gain_v = err_v / err_v_0

        err_x_0 = err_x
        err_v_0 = err_v

        # print update to user, if verbose
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err_v, gain_v, elapsed))

    # SECOND: Howard improvement step, 10-20 iterations
    it = 0
    err_v = 100
    err_v_0 = 0.0
    gain_v = 0.0

    if verbose:
        print(stars)
        print('Starting Howard improvement step')
        print(stars)

    while err_v > tol and it < maxit_howard:

        t_start = time.time()
        it += 1

        # update interpolation object with current values
        drv.set_values(values_0)

        values = values_0.copy()
        controls = controls_0.copy()
        # controls = controls_0.copy()  # No need to keep updating

        for n in range(N):
            s = grid[n, :]
            x = controls[n, :]
            values[n, 0] = choice_value(transition, felicity, s, x, drv, nodes,
                                        weights, parms, discount)[0]

        # compute error, update value function
        err_v = abs(values - values_0).max()
        values_0 = values

        t_end = time.time()
        elapsed = t_end - t_start

        gain_v = err_v / err_v_0
        err_v_0 = err_v

        # print update to user, if verbose
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err_v, gain_v, elapsed))

    # THIRD: Back to value function iteration until convergence.
    it = 0
    err_v = 100
    err_v_0 = 0.0
    gain_v = 0.0
    err_x = 100
    err_x_0 = 100

    if verbose:
        print(stars)
        print('Starting value function iteration')
        print(stars)

    while err_v > tol and it < maxit:

        t_start = time.time()
        it += 1

        # update interpolation object with current values
        drv.set_values(values_0)

        values = values_0.copy()
        controls = controls_0.copy()

        for n in range(N):
            s = grid[n, :]
            x = controls[n, :]
            lb = controls_lb(s, parms)
            ub = controls_ub(s, parms)
            bnds = [e for e in zip(lb, ub)]

            def valfun(xx):
                return -choice_value(transition, felicity, s, xx, drv, nodes,
                                     weights, parms, discount)[0]
            res = minimize(valfun, x, bounds=bnds, tol=1e-4)

            controls[n, :] = res.x
            values[n, 0] = -valfun(res.x)

        # compute error, update value and dr
        err_x = abs(controls - controls_0).max()
        err_v = abs(values - values_0).max()
        t_end = time.time()
        elapsed = t_end - t_start

        values_0 = values
        controls_0 = controls

        gain_x = err_x / err_x_0
        gain_v = err_v / err_v_0

        err_x_0 = err_x
        err_v_0 = err_v

        # print update to user, if verbose
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err_v, gain_v, elapsed))

    if it == maxit:
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    # final value function and decision rule
    drv.set_values(values_0)
    dr = create_interpolator(approx, interp_type)
    dr.set_values(controls_0)

    return dr, drv
示例#25
0
文件: gssa.py 项目: dvillacreses/dolo
def gssa(model, maxit=100, tol=1e-8, initial_dr=None, verbose=False,
         n_sim=10000, deg=3, damp=0.1, seed=42):
    """
    Sketch of algorithm:

    0. Choose levels for the initial states and the simulation length (n_sim)
    1. Obtain an initial decision rule -- here using first order perturbation
    2. Draw a sequence of innovations epsilon
    3. Iterate on the following steps:
        - Use the epsilons, initial states, and proposed decision rule to
          simulate model forward. Will leave us with time series of states and
          controls
        - Evaluate expectations using quadrature
        - Use direct response to get alternative proposal for controls
        - Regress updated controls on the simulated states to get proposal
          coefficients. New coefficients are convex combination of previous
          coefficients and proposal coefficients. Weights controlled by damp,
          where damp is the weight on the old coefficients. This should be
          fairly low to increase chances of convergence.
        - Check difference between the simulated series of controls and the
          direct response version of controls

    """
    # verify input arguments
    if deg < 0 or deg > 5:
        raise ValueError("deg must be in [1, 5]")

    if damp < 0 or damp > 1:
        raise ValueError("damp must be in [0, 1]")

    t1 = time.time()

    # extract model functions and parameters
    g = model.__original_functions__['transition']
    g_gu = model.__original_gufunctions__['transition']
    h_gu = model.__original_gufunctions__['expectation']
    d_gu = model.__original_gufunctions__['direct_response']
    p = model.calibration['parameters']
    n_s = len(model.symbols["states"])
    n_x = len(model.symbols["controls"])
    n_z = len(model.symbols["expectations"])
    n_eps = len(model.symbols["shocks"])
    s0 = model.calibration["states"]
    x0 = model.calibration["controls"]

    # construct initial decision rule if not supplied
    if initial_dr is None:
        drp = approximate_controls(model)
    else:
        drp = initial_dr

    # set up quadrature weights and nodes
    distrib = model.get_distribution()
    nodes, weights = distrib.discretize()

    # draw sequence of innovations
    np.random.seed(seed)
    distrib = model.get_distribution()
    sigma = distrib.sigma
    epsilon = np.random.multivariate_normal(np.zeros(n_eps), sigma, n_sim)

    # simulate initial decision rule and do initial regression for coefs
    init_sim = simulate(model, drp, horizon=n_sim, return_array=True,
                        forcing_shocks=epsilon)
    s_sim = init_sim[:, 0, 0:n_s]
    x_sim = init_sim[:, 0, n_s:n_s + n_x]
    Phi_sim = complete_polynomial(s_sim.T, deg).T
    coefs = np.ascontiguousarray(lstsq(Phi_sim, x_sim)[0])

    # NOTE: the ascontiguousarray above was needed for numba to compile the
    #       `np.dot` in the simulation function in no python mode. Appearantly
    #       the array returned from lstsq is not C-contiguous

    # allocate for simulated series of expectations and next period states
    z_sim = np.empty((n_sim, n_z))
    S = np.empty_like(s_sim)
    X = np.empty_like(x_sim)
    H = np.empty_like(z_sim)
    new_x = np.empty_like(x_sim)

    # set initial states and controls
    s_sim[0, :] = s0
    x_sim[0, :] = x0

    Phi_t = np.empty(n_complete(n_s, deg))  # buffer array for simulation

    # create jitted function that will simulate states and controls, using
    # the epsilon shocks from above (define here as closure over all data
    # above).
    @jit(nopython=True)
    def simulate_states_controls(s, x, Phi_t, coefs):
        for t in range(1, n_sim):
            g(s[t - 1, :], x[t - 1, :], epsilon[t, :], p, s[t, :])

            # fill Phi_t with new complete poly version of s[t, :]
            _complete_poly_impl_vec(s[t, :], deg, Phi_t)

            # do inner product to get new controls
            x[t, :] = Phi_t @coefs

    it = 0
    err = 10.0
    err_0 = 10

    if verbose:
        headline = '|{0:^4} | {1:10} | {2:8} | {3:8} |'
        headline = headline.format('N', ' Error', 'Gain', 'Time')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

        # format string for within loop
        fmt_str = '|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'

    while err > tol and it <= maxit:
        t_start = time.time()

        # simulate with new coefficients
        simulate_states_controls(s_sim, x_sim, Phi_t, coefs)

        # update expectations of z
        # update_expectations(s_sim, x_sim, z_sim, Phi_sim)
        z_sim[:, :] = 0.0
        for i in range(weights.shape[0]):
            e = nodes[i, :]  # extract nodes
            # evaluate future states at each node (stores in S)
            g_gu(s_sim, x_sim, e, p, S)

            # evaluate future controls at each future state
            _complete_poly_impl(S.T, deg, Phi_sim.T)
            np.dot(Phi_sim, coefs, out=X)

            # compute expectation (stores in H)
            h_gu(S, X, p, H)
            z_sim += weights[i] * H

        # get controls on the simulated points from direct_resposne
        # (stores in new_x)
        d_gu(s_sim, z_sim, p, new_x)

        # update basis matrix and do regression of new_x on s_sim to get
        # updated coefficients
        _complete_poly_impl(s_sim.T, deg, Phi_sim.T)
        new_coefs = np.ascontiguousarray(lstsq(Phi_sim, new_x)[0])

        # check whether they differ from the preceding guess
        err = (abs(new_x - x_sim).max())

        # update the series of controls and coefficients
        x_sim[:, :] = new_x
        coefs = (1 - damp) * new_coefs + damp * coefs

        if verbose:
            # update error and print if `verbose`
            err_SA = err / err_0
            err_0 = err
            t_finish = time.time()
            elapsed = t_finish - t_start
            if verbose:
                print(fmt_str.format(it, err, err_SA, elapsed))

        it += 1

    if it == maxit:
        warnings.warn(UserWarning("Maximum number of iterations reached"))

    # compute final fime and do final printout if `verbose`
    t2 = time.time()
    if verbose:
        print(stars)
        print('Elapsed: {} seconds.'.format(t2 - t1))
        print(stars)

    cp = CompletePolynomial(deg, len(s0))
    cp.fit_values(s_sim, x_sim)
    return cp