Exemplo n.º 1
0
def deterministic_solve(model, shocks=None, start_states=None, T=100, ignore_constraints=False, maxit=100, initial_guess=None, verbose=False, tol=1e-6):
    '''Computes a perfect foresight simulation using a stacked-time algorithm.

    The initial state is specified either by providing a series of exogenous shocks and assuming the model is initially
    in equilibrium with the first value of the shock, or by specifying an initial value for the states.

    Parameters
    ----------
    a : array_like
        The shape and data-type of `a` define these same attributes of
        the returned array.
    dtype : data-type, optional
        .. versionadded:: 1.6.0
        Overrides the data type of the result.
    order : {'C', 'F', 'A', or 'K'}, optional
        .. versionadded:: 1.6.0
        Overrides the memory layout of the result. 'C' means C-order,
        'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
        'C' otherwise. 'K' means match the layout of `a` as closely
        as possible.
    subok : bool, optional.
        If True, then the newly created array will use the sub-class
        type of 'a', otherwise it will be a base-class array. Defaults
        to True.

    Parameters
    ----------
    model : NumericModel
        "fg" or "fga" model to be solved
    shocks : ndarray
        :math:`n_e\\times N` matrix containing :math:`N` realizations of the shocks. :math:`N` must be smaller than :math:`T`.    The exogenous process is assumed to remain constant and equal to its last value after `N` periods.
    start_states : ndarray or dict
        a vector with the value of initial states, or a calibration dictionary with the initial values of states and controls
    T : int
        horizon for the perfect foresight simulation
    maxit : int
        maximum number of iteration for the nonlinear solver
    verbose : boolean
        if True, the solver displays iterations
    tol : float
        stopping criterium for the nonlinear solver
    ignore_constraints : bool
        if True, complementarity constraints are ignored.

    Returns
    -------
    pandas dataframe

        a dataframe with T+1 observations of the model variables along the simulation (states, controls, auxiliaries). The first observation is the steady-state corresponding to the first value of the shocks. The simulation should return
        to a steady-state corresponding to the last value of the exogenous shocks.
    '''

    # TODO:

    # if model.model_spec == 'fga':
    #     from dolo.compiler.converter import GModel_fg_from_fga
    #     model = GModel_fg_from_fga(model)

    # definitions
    n_s = len(model.calibration['states'])
    n_x = len(model.calibration['controls'])

    if shocks is None:
        shocks = numpy.zeros( (len(model.calibration['shocks']),1))

    # until last period, exogenous shock takes its last value
    epsilons = numpy.zeros( (T+1, shocks.shape[1]))
    epsilons[:(shocks.shape[0]-1),:] = shocks[1:,:]
    epsilons[(shocks.shape[0]-1):,:] = shocks[-1:,:]

    # final initial and final steady-states consistent with exogenous shocks
    if isinstance(start_states,dict):
        # at least that part is clear
        start_equilibrium = start_states
        start_s = start_equilibrium['states']
        start_x = start_equilibrium['controls']
        final_s = start_equilibrium['states']
        final_x = start_equilibrium['controls']
    elif isinstance(start_states, numpy.ndarray):
        start_s = start_states
        start_x = model.calibration['controls']
        final_s = model.calibration['states']
        final_x = model.calibration['controls']
    else:
        # raise Exception("You must compute initial calibration yourself")
        final_dict = {model.symbols['shocks'][i]: shocks[i,-1] for i in range(len(model.symbols['shocks']))}
        start_dict = {model.symbols['shocks'][i]: shocks[i,0] for i in range(len(model.symbols['shocks']))}
        start_calib = find_deterministic_equilibrium( model, constraints=start_dict)
        final_calib = find_deterministic_equilibrium( model, constraints=start_dict)

        start_s = start_calib['states']
        start_x = start_calib['controls']
        final_s = final_calib['states']
        final_x = final_calib['controls']


#        if start_constraints:
#        ### we ignore start_constraints
#            start_dict.update(start_constraints)
#            final_equilibrium = start_constraints.copy()
#        else:
#        final_equilibrium = find_deterministic_equilibrium( model, constraints=final_dict)
#        final_s = final_equilibrium['states']
#        final_x = final_equilibrium['controls']


#        start_s = start_states
#        start_x = final_x

    #TODO: for start_x, it should be possible to use first order guess




    final = numpy.concatenate( [final_s, final_x] )
    start = numpy.concatenate( [start_s, start_x] )

    if verbose==True:
        print("Initial states : {}".format(start_s))
        print("Final controls : {}".format(final_x))

    p = model.calibration['parameters']

    if initial_guess is None:

        initial_guess = numpy.row_stack( [start*(1-l) + final*l for l in linspace(0.0,1.0,T+1)] )

    else:
        from pandas import DataFrame
        if isinstance( initial_guess, DataFrame ):
            initial_guess = array( initial_guess ).T.copy()
        initial_guess = initial_guess[:,:n_s+n_x]
        initial_guess[0,:n_s] = start_s
        initial_guess[-1,n_s:] = final_x

    sh = initial_guess.shape

    if model.x_bounds and not ignore_constraints:
        initial_states = initial_guess[:,:n_s]
        [lb, ub] = [ u( initial_states, p ) for u in model.x_bounds]
        lower_bound = initial_guess*0 - numpy.inf
        lower_bound[:, n_s:] = lb
        upper_bound = initial_guess*0 + numpy.inf
        upper_bound[:, n_s:] = ub
        test1 = max( lb.max(axis=0) - lb.min(axis=0) )
        test2 = max( ub.max(axis=0) - ub.min(axis=0) )
        if test1 >0.00000001 or test2>0.00000001:
            raise Exception("Not implemented: perfect foresight solution requires that controls have constant bounds.")
    else:
        ignore_constraints=True
        lower_bound = None
        upper_bound = None


    nn = sh[0]*sh[1]

    fobj  = lambda vec: det_residual(model, vec.reshape(sh), start_s, final_x, epsilons)[0].ravel()



    if not ignore_constraints:

        from dolo.numeric.optimize.ncpsolve import ncpsolve
        ff  = lambda vec: det_residual(model, vec.reshape(sh), start_s, final_x, epsilons, jactype='sparse')

        from dolo.numeric.optimize.newton import newton
        x0 = initial_guess.ravel()

        sol, nit = ncpsolve(ff, lower_bound.ravel(), upper_bound.ravel(), initial_guess.ravel(), verbose=verbose, maxit=maxit, tol=tol, jactype='sparse')

        sol = sol.reshape(sh)

    else:

        from scipy.optimize import root
        from numpy import array
        # ff  = lambda vec: det_residual(model, vec.reshape(sh), start_s, final_x, epsilons, jactype='full')
        ff  = lambda vec: det_residual(model, vec.reshape(sh), start_s, final_x, epsilons, diff=False).ravel()
        x0 = initial_guess.ravel()
        sol = root(ff, x0, jac=False)

        res = ff(sol.x)


        sol = sol.x.reshape(sh)

    import pandas
    if 'auxiliary' in model.functions:
        colnames = model.symbols['states'] + model.symbols['controls'] + model.symbols['auxiliaries']
        # compute auxiliaries
        y = model.functions['auxiliary'](sol[:,:n_s], sol[:,n_s:], p)
        sol = numpy.column_stack([sol,y])
    else:
        colnames = model.symbols['states'] + model.symbols['controls']

    sol = numpy.column_stack([sol,epsilons])
    colnames = colnames + model.symbols['shocks']

    ts = pandas.DataFrame(sol, columns=colnames)
    return ts
Exemplo n.º 2
0

    e_z = atleast_2d( linspace(0.0, 0.0, 10) ).T

    start_s = model.calibration['states'].copy()
    start_s[0] = 1.5

    import time

    #sol1 = deterministic_solve(model, shocks=e_z, T=50, use_pandas=True, ignore_constraints=True, start_s=start_s)

    #sol1 = deterministic_solve(model, T=50, use_pandas=True, ignore_constraints=True, start_s=start_s)

    from dolo.algos.steady_state import find_deterministic_equilibrium

    calib = find_deterministic_equilibrium(model)

    t2 = time.time()

    sol1 = deterministic_solve(model, start_states=start_s,  T=50, use_pandas=True, ignore_constraints=False, verbose=True)

    t3 = time.time()

    t1 = time.time()

    sol2 = deterministic_solve(model, start_states=start_s,  T=50, use_pandas=True, ignore_constraints=True, verbose=True)

    t2 = time.time()


Exemplo n.º 3
0
def approximate_controls(model, verbose=False, steady_state=None, eigmax=1.0, solve_steady_state=False, order=1):
    """Compute first order approximation of optimal controls

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

    model: NumericModel
        Model to be solved

    verbose: boolean
        If True: displays number of contracting eigenvalues

    steady_state: ndarray
        Use supplied steady-state value to compute the approximation. The routine doesn't check whether it is really
        a solution or not.

    solve_steady_state: boolean
        Use nonlinear solver to find the steady-state

    orders: {1}
        Approximation order. (Currently, only first order is supported).

    Returns:
    --------

    TaylorExpansion:
        Decision Rule for the optimal controls around the steady-state.

    """

    if order > 1:
        raise Exception("Not implemented.")

    # get steady_state
    import numpy

    # if model.model_spec == 'fga':
    #     model = GModel_fg_from_fga(model)

    # g = model.functions['transition']
    # f = model.functions['arbitrage']
    from dolo.algos.dtcscc.convert import get_fg_functions

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

    if steady_state is not None:
        calib = steady_state
    else:
        calib = model.calibration

    if solve_steady_state:
        from dolo.algos.dtcscc.steady_state import find_deterministic_equilibrium

        calib = find_deterministic_equilibrium(model)

    p = calib["parameters"]
    s = calib["states"]
    x = calib["controls"]
    e = calib["shocks"]

    if model.covariances is not None:
        sigma = model.covariances
    else:
        sigma = numpy.zeros((len(e), len(e)))

    from numpy.linalg import solve

    l = g(s, x, e, p, diff=True)
    [junk, g_s, g_x, g_e] = l[:4]  # [el[0,...] for el in l[:4]]

    l = f(s, x, e, s, x, p, diff=True)
    [res, f_s, f_x, f_e, f_S, f_X] = l  # [el[0,...] for el in l[:6]]

    n_s = g_s.shape[0]  # number of controls
    n_x = g_x.shape[1]  # number of states
    n_e = g_e.shape[1]
    n_v = n_s + n_x

    A = row_stack([column_stack([eye(n_s), zeros((n_s, n_x))]), column_stack([-f_S, -f_X])])

    B = row_stack([column_stack([g_s, g_x]), column_stack([f_s, f_x])])

    from dolo.numeric.extern.qz import qzordered

    [S, T, Q, Z, eigval] = qzordered(A, B, n_s)
    Q = Q.real  # is it really necessary ?
    Z = Z.real

    diag_S = numpy.diag(S)
    diag_T = numpy.diag(T)

    tol_geneigvals = 1e-10
    try:
        assert sum((abs(diag_S) < tol_geneigvals) * (abs(diag_T) < tol_geneigvals)) == 0
    except Exception as e:
        print(e)
        # print(numpy.column_stack([diag_S, diag_T]))
        raise GeneralizedEigenvaluesError(diag_S, diag_T)

    # Check Blanchard=Kahn conditions
    n_big_one = sum(eigval > eigmax)
    n_expected = n_x
    if verbose:
        print("There are {} eigenvalues greater than {}. Expected: {}.".format(n_big_one, eigmax, n_x))
    if n_expected != n_big_one:
        raise BlanchardKahnError(n_big_one, n_expected)

    Z11 = Z[:n_s, :n_s]
    Z12 = Z[:n_s, n_s:]
    Z21 = Z[n_s:, :n_s]
    Z22 = Z[n_s:, n_s:]
    S11 = S[:n_s, :n_s]
    T11 = T[:n_s, :n_s]

    # first order solution
    C = solve(Z11.T, Z21.T).T
    P = np.dot(solve(S11.T, Z11.T).T, solve(Z11.T, T11.T).T)
    Q = g_e

    s = s.ravel()
    x = x.ravel()

    A = g_s + dot(g_x, C)
    B = g_e

    dr = CDR([s, x, C])
    dr.A = A
    dr.B = B
    dr.sigma = sigma

    return dr
Exemplo n.º 4
0
def approximate_controls(model, verbose=False, steady_state=None, eigmax=1.0-1e-6,
                         solve_steady_state=False, order=1):
    """Compute first order approximation of optimal controls

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

    model: NumericModel
        Model to be solved

    verbose: boolean
        If True: displays number of contracting eigenvalues

    steady_state: ndarray
        Use supplied steady-state value to compute the approximation.
        The routine doesn't check whether it is really a solution or not.

    solve_steady_state: boolean
        Use nonlinear solver to find the steady-state

    orders: {1}
        Approximation order. (Currently, only first order is supported).

    Returns:
    --------

    TaylorExpansion:
        Decision Rule for the optimal controls around the steady-state.

    """

    if order > 1:
        raise Exception("Not implemented.")

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

    if steady_state is not None:
        calib = steady_state
    else:
        calib = model.calibration

    if solve_steady_state:
        calib = find_deterministic_equilibrium(model)

    p = calib['parameters']
    s = calib['states']
    x = calib['controls']
    e = calib['shocks']

    distrib = model.get_distribution()
    sigma = distrib.sigma

    l = g(s, x, e, p, diff=True)
    [junk, g_s, g_x, g_e] = l[:4]  # [el[0,...] for el in l[:4]]

    l = f(s, x, e, s, x, p, diff=True)
    [res, f_s, f_x, f_e, f_S, f_X] = l  # [el[0,...] for el in l[:6]]

    n_s = g_s.shape[0]           # number of controls
    n_x = g_x.shape[1]   # number of states
    n_e = g_e.shape[1]
    n_v = n_s + n_x

    A = row_stack([
        column_stack([eye(n_s), zeros((n_s, n_x))]),
        column_stack([-f_S    , -f_X             ])
    ])

    B = row_stack([
        column_stack([g_s, g_x]),
        column_stack([f_s, f_x])
    ])


    [S, T, Q, Z, eigval] = qzordered(A, B, 1.0-1e-8)

    Q = Q.real  # is it really necessary ?
    Z = Z.real

    diag_S = np.diag(S)
    diag_T = np.diag(T)

    tol_geneigvals = 1e-10

    try:
        ok = sum((abs(diag_S) < tol_geneigvals) *
                 (abs(diag_T) < tol_geneigvals)) == 0
        assert(ok)
    except Exception as e:
        raise GeneralizedEigenvaluesError(diag_S=diag_S, diag_T=diag_T)

    if max(eigval[:n_s]) >= 1 and min(eigval[n_s:]) < 1:
        # BK conditions are met
        pass
    else:
        eigval_s = sorted(eigval, reverse=True)
        ev_a = eigval_s[n_s-1]
        ev_b = eigval_s[n_s]
        cutoff = (ev_a - ev_b)/2
        if not ev_a > ev_b:
            raise GeneralizedEigenvaluesSelectionError(
                    A=A, B=B, eigval=eigval, cutoff=cutoff,
                    diag_S=diag_S, diag_T=diag_T, n_states=n_s
                )
        import warnings
        if cutoff > 1:
            warnings.warn("Solution is not convergent.")
        else:
            warnings.warn("There are multiple convergent solutions. The one with the smaller eigenvalues was selected.")
        [S, T, Q, Z, eigval] = qzordered(A, B, cutoff)

    Z11 = Z[:n_s, :n_s]
    # Z12 = Z[:n_s, n_s:]
    Z21 = Z[n_s:, :n_s]
    # Z22 = Z[n_s:, n_s:]
    # S11 = S[:n_s, :n_s]
    # T11 = T[:n_s, :n_s]

    # first order solution
    # P = (solve(S11.T, Z11.T).T @ solve(Z11.T, T11.T).T)
    C = solve(Z11.T, Z21.T).T
    Q = g_e

    s = s.ravel()
    x = x.ravel()

    A = g_s + g_x @ C
    B = g_e

    dr = CDR([s, x, C])
    dr.A = A
    dr.B = B
    dr.sigma = sigma

    return dr
Exemplo n.º 5
0
def approximate_controls(model,
                         verbose=False,
                         steady_state=None,
                         eigmax=1.0 - 1e-6,
                         solve_steady_state=False,
                         order=1):
    """Compute first order approximation of optimal controls

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

    model: NumericModel
        Model to be solved

    verbose: boolean
        If True: displays number of contracting eigenvalues

    steady_state: ndarray
        Use supplied steady-state value to compute the approximation.
        The routine doesn't check whether it is really a solution or not.

    solve_steady_state: boolean
        Use nonlinear solver to find the steady-state

    orders: {1}
        Approximation order. (Currently, only first order is supported).

    Returns:
    --------

    TaylorExpansion:
        Decision Rule for the optimal controls around the steady-state.

    """

    if order > 1:
        raise Exception("Not implemented.")

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

    if steady_state is not None:
        calib = steady_state
    else:
        calib = model.calibration

    if solve_steady_state:
        calib = find_deterministic_equilibrium(model)

    p = calib['parameters']
    s = calib['states']
    x = calib['controls']
    e = calib['shocks']

    distrib = model.get_distribution()
    sigma = distrib.sigma

    l = g(s, x, e, p, diff=True)
    [junk, g_s, g_x, g_e] = l[:4]  # [el[0,...] for el in l[:4]]

    l = f(s, x, e, s, x, p, diff=True)
    [res, f_s, f_x, f_e, f_S, f_X] = l  # [el[0,...] for el in l[:6]]

    n_s = g_s.shape[0]  # number of controls
    n_x = g_x.shape[1]  # number of states
    n_e = g_e.shape[1]
    n_v = n_s + n_x

    A = row_stack([
        column_stack([eye(n_s), zeros((n_s, n_x))]),
        column_stack([-f_S, -f_X])
    ])

    B = row_stack([column_stack([g_s, g_x]), column_stack([f_s, f_x])])

    [S, T, Q, Z, eigval] = qzordered(A, B, 1.0 - 1e-8)

    Q = Q.real  # is it really necessary ?
    Z = Z.real

    diag_S = np.diag(S)
    diag_T = np.diag(T)

    tol_geneigvals = 1e-10

    try:
        ok = sum((abs(diag_S) < tol_geneigvals) *
                 (abs(diag_T) < tol_geneigvals)) == 0
        assert (ok)
    except Exception as e:
        raise GeneralizedEigenvaluesError(diag_S=diag_S, diag_T=diag_T)

    if max(eigval[:n_s]) >= 1 and min(eigval[n_s:]) < 1:
        # BK conditions are met
        pass
    else:
        eigval_s = sorted(eigval, reverse=True)
        ev_a = eigval_s[n_s - 1]
        ev_b = eigval_s[n_s]
        cutoff = (ev_a - ev_b) / 2
        if not ev_a > ev_b:
            raise GeneralizedEigenvaluesSelectionError(A=A,
                                                       B=B,
                                                       eigval=eigval,
                                                       cutoff=cutoff,
                                                       diag_S=diag_S,
                                                       diag_T=diag_T,
                                                       n_states=n_s)
        import warnings
        if cutoff > 1:
            warnings.warn("Solution is not convergent.")
        else:
            warnings.warn(
                "There are multiple convergent solutions. The one with the smaller eigenvalues was selected."
            )
        [S, T, Q, Z, eigval] = qzordered(A, B, cutoff)

    Z11 = Z[:n_s, :n_s]
    # Z12 = Z[:n_s, n_s:]
    Z21 = Z[n_s:, :n_s]
    # Z22 = Z[n_s:, n_s:]
    # S11 = S[:n_s, :n_s]
    # T11 = T[:n_s, :n_s]

    # first order solution
    # P = (solve(S11.T, Z11.T).T @ solve(Z11.T, T11.T).T)
    C = solve(Z11.T, Z21.T).T
    Q = g_e

    s = s.ravel()
    x = x.ravel()

    A = g_s + g_x @ C
    B = g_e

    dr = CDR([s, x, C])
    dr.A = A
    dr.B = B
    dr.sigma = sigma

    return dr
Exemplo n.º 6
0
def approximate_controls(model,
                         verbose=False,
                         steady_state=None,
                         eigmax=1.0,
                         solve_steady_state=False,
                         order=1):
    """Compute first order approximation of optimal controls

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

    model: NumericModel
        Model to be solved

    verbose: boolean
        If True: displays number of contracting eigenvalues

    steady_state: ndarray
        Use supplied steady-state value to compute the approximation.
        The routine doesn't check whether it is really a solution or not.

    solve_steady_state: boolean
        Use nonlinear solver to find the steady-state

    orders: {1}
        Approximation order. (Currently, only first order is supported).

    Returns:
    --------

    TaylorExpansion:
        Decision Rule for the optimal controls around the steady-state.

    """

    if order > 1:
        raise Exception("Not implemented.")

    # get steady_state
    # if model.model_spec == 'fga':
    #     model = GModel_fg_from_fga(model)

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

    if steady_state is not None:
        calib = steady_state
    else:
        calib = model.calibration

    if solve_steady_state:
        calib = find_deterministic_equilibrium(model)

    p = calib['parameters']
    s = calib['states']
    x = calib['controls']
    e = calib['shocks']

    if model.covariances is not None:
        sigma = model.covariances
    else:
        sigma = zeros((len(e), len(e)))

    l = g(s, x, e, p, diff=True)
    [junk, g_s, g_x, g_e] = l[:4]  # [el[0,...] for el in l[:4]]

    l = f(s, x, e, s, x, p, diff=True)
    [res, f_s, f_x, f_e, f_S, f_X] = l  # [el[0,...] for el in l[:6]]

    n_s = g_s.shape[0]  # number of controls
    n_x = g_x.shape[1]  # number of states
    n_e = g_e.shape[1]
    n_v = n_s + n_x

    A = row_stack([
        column_stack([eye(n_s), zeros((n_s, n_x))]),
        column_stack([-f_S, -f_X])
    ])

    B = row_stack([column_stack([g_s, g_x]), column_stack([f_s, f_x])])

    [S, T, Q, Z, eigval] = qzordered(A, B, n_s)
    Q = Q.real  # is it really necessary ?
    Z = Z.real

    diag_S = np.diag(S)
    diag_T = np.diag(T)

    tol_geneigvals = 1e-10
    try:
        ok = sum((abs(diag_S) < tol_geneigvals) *
                 (abs(diag_T) < tol_geneigvals)) == 0
        assert (ok)
    except Exception as e:
        print(e)
        # print(np.column_stack([diag_S, diag_T]))
        raise GeneralizedEigenvaluesError(diag_S, diag_T)

    # Check Blanchard=Kahn conditions
    n_big_one = sum(eigval > eigmax)
    n_expected = n_x
    if verbose:
        msg = "There are {} eigenvalues greater than {}. Expected: {}."
        print(msg.format(n_big_one, eigmax, n_x))
    if n_expected != n_big_one:
        raise BlanchardKahnError(n_big_one,
                                 n_expected,
                                 eigval=eigval,
                                 eigmax=eigmax)

    Z11 = Z[:n_s, :n_s]
    Z12 = Z[:n_s, n_s:]
    Z21 = Z[n_s:, :n_s]
    Z22 = Z[n_s:, n_s:]
    S11 = S[:n_s, :n_s]
    T11 = T[:n_s, :n_s]

    # first order solution
    C = solve(Z11.T, Z21.T).T
    P = dot(solve(S11.T, Z11.T).T, solve(Z11.T, T11.T).T)
    Q = g_e

    s = s.ravel()
    x = x.ravel()

    A = g_s + dot(g_x, C)
    B = g_e

    dr = CDR([s, x, C])
    dr.A = A
    dr.B = B
    dr.sigma = sigma

    return dr