Пример #1
0
def euler_residuals(f,
                    g,
                    s,
                    x,
                    dr,
                    dp,
                    p_,
                    diff=True,
                    with_jres=False,
                    set_dr=True,
                    jres=None,
                    S_ij=None):

    t1 = time.time()

    if set_dr:
        dr.set_values(x)

    N = s.shape[0]
    n_s = s.shape[1]
    n_x = x.shape[2]

    n_ms = max(dp.n_nodes, 1)  # number of markov states
    n_im = dp.n_inodes(0)

    res = numpy.zeros_like(x)

    if with_jres:
        if jres is None:
            jres = numpy.zeros((n_ms, n_im, N, n_x, n_x))
        if S_ij is None:
            S_ij = numpy.zeros((n_ms, n_im, N, n_s))

    for i_ms in range(n_ms):
        m_ = dp.node(i_ms)
        xm = x[i_ms, :, :]
        for I_ms in range(n_im):
            M_ = dp.inode(i_ms, I_ms)
            w = dp.iweight(i_ms, I_ms)
            S = g(m_, s, xm, M_, p_, diff=False)
            XM = dr.eval_ijs(i_ms, I_ms, S)
            if with_jres:
                ff = SerialDifferentiableFunction(
                    lambda u: f(m_, s, xm, M_, S, u, p_, diff=False))
                rr, rr_XM = ff(XM)

                rr = f(m_, s, xm, M_, S, XM, p_, diff=False)
                jres[i_ms, I_ms, :, :, :] = w * rr_XM
                S_ij[i_ms, I_ms, :, :] = S
            else:
                rr = f(m_, s, xm, M_, S, XM, p_, diff=False)
            res[i_ms, :, :] += w * rr

    t2 = time.time()

    if with_jres:
        return res, jres, S_ij
    else:
        return res
Пример #2
0
def time_iteration(model,
                   dr0=None,
                   dprocess=None,
                   with_complementarities=True,
                   verbose=True,
                   grid={},
                   maxit=1000,
                   inner_maxit=10,
                   tol=1e-6,
                   hook=None,
                   details=False,
                   interp_method='cubic'):
    '''
    Finds a global solution for ``model`` using backward time-iteration.

    This algorithm iterates on the residuals of the arbitrage equations

    Parameters
    ----------
    model : Model
        model to be solved
    verbose : boolean
        if True, display iterations
    dr0 : decision rule
        initial guess for the decision rule
    dprocess : DiscretizedProcess (model.exogenous.discretize())
        discretized process to be used
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    grid: grid options
        overload the values set in `options:grid` section
    maxit: maximum number of iterations
    inner_maxit: maximum number of iteration for inner solver
    tol: tolerance criterium for successive approximations
    hook: Callable
        function to be called within each iteration, useful for debugging purposes


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

    from dolo import dprint

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

    if dprocess is None:
        dprocess = model.exogenous.discretize()

    n_ms = dprocess.n_nodes  # number of exogenous states
    n_mv = dprocess.n_inodes(
        0)  # this assume number of integration nodes is constant

    x0 = model.calibration['controls']
    parms = model.calibration['parameters']
    n_x = len(x0)
    n_s = len(model.symbols['states'])

    endo_grid = model.get_endo_grid(**grid)

    exo_grid = dprocess.grid

    mdr = DecisionRule(exo_grid,
                       endo_grid,
                       dprocess=dprocess,
                       interp_method=interp_method)

    grid = mdr.endo_grid.nodes
    N = grid.shape[0]

    controls_0 = numpy.zeros((n_ms, N, n_x))
    if dr0 is None:
        controls_0[:, :, :] = x0[None, None, :]
    else:
        if isinstance(dr0, AlgoResult):
            dr0 = dr0.dr
        try:
            for i_m in range(n_ms):
                controls_0[i_m, :, :] = dr0(i_m, grid)
        except Exception:
            for i_m in range(n_ms):
                m = dprocess.node(i_m)
                controls_0[i_m, :, :] = dr0(m, grid)

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

    if 'controls_lb' in model.functions and with_complementarities == True:
        lb_fun = model.functions['controls_lb']
        ub_fun = model.functions['controls_ub']
        lb = numpy.zeros_like(controls_0) * numpy.nan
        ub = numpy.zeros_like(controls_0) * numpy.nan
        for i_m in range(n_ms):
            m = dprocess.node(i_m)[None, :]
            p = parms[None, :]
            m = numpy.repeat(m, N, axis=0)
            p = numpy.repeat(p, N, axis=0)

            lb[i_m, :, :] = lb_fun(m, grid, p)
            ub[i_m, :, :] = ub_fun(m, grid, p)

    else:
        with_complementarities = False

    sh_c = controls_0.shape

    controls_0 = controls_0.reshape((-1, n_x))

    from dolo.numeric.optimize.newton import newton, SerialDifferentiableFunction
    from dolo.numeric.optimize.ncpsolve import ncpsolve

    err = 10
    it = 0

    if with_complementarities:
        lb = lb.reshape((-1, n_x))
        ub = ub.reshape((-1, n_x))

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

    import time
    t1 = time.time()

    err_0 = numpy.nan

    verbit = (verbose == 'full')

    while err > tol and it < maxit:

        it += 1

        t_start = time.time()

        mdr.set_values(controls_0.reshape(sh_c))

        fn = lambda x: residuals_simple(f, g, grid, x.reshape(sh_c), mdr,
                                        dprocess, parms).reshape((-1, n_x))
        dfn = SerialDifferentiableFunction(fn)

        res = fn(controls_0)

        if hook:
            hook()

        if with_complementarities:
            [controls, nit] = ncpsolve(dfn,
                                       lb,
                                       ub,
                                       controls_0,
                                       verbose=verbit,
                                       maxit=inner_maxit)
        else:
            [controls, nit] = newton(dfn,
                                     controls_0,
                                     verbose=verbit,
                                     maxit=inner_maxit)

        err = abs(controls - controls_0).max()

        err_SA = err / err_0
        err_0 = err

        controls_0 = controls

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

        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'.format(
                it, err, err_SA, elapsed, nit))

    controls_0 = controls.reshape(sh_c)

    mdr.set_values(controls_0)

    t2 = time.time()

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

    if not details:
        return mdr

    return TimeIterationResult(
        mdr,
        it,
        with_complementarities,
        dprocess,
        err < tol,  # x_converged: bool
        tol,  # x_tol
        err,  #: float
        None,  # log: object # TimeIterationLog
        None  # trace: object #{Nothing,IterationTrace}
    )
Пример #3
0
def improved_time_iteration(
    model,
    method="jac",
    dr0=None,
    dprocess=None,
    interp_method="cubic",
    mu=2,
    maxbsteps=10,
    verbose=False,
    tol=1e-8,
    smaxit=500,
    maxit=1000,
    complementarities=True,
    compute_radius=False,
    invmethod="iti",
    details=True,
):
    def vprint(*args, **kwargs):
        if verbose:
            print(*args, **kwargs)

    itprint = IterationsPrinter(
        ("N", int),
        ("f_x", float),
        ("d_x", float),
        ("Time_residuals", float),
        ("Time_inversion", float),
        ("Time_search", float),
        ("Lambda_0", float),
        ("N_invert", int),
        ("N_search", int),
        verbose=verbose,
    )
    itprint.print_header("Start Improved Time Iterations.")

    f = model.functions["arbitrage"]
    g = model.functions["transition"]
    x_lb = model.functions["arbitrage_lb"]
    x_ub = model.functions["arbitrage_ub"]

    parms = model.calibration["parameters"]

    if dprocess is not None:
        from dolo.numeric.grids import ProductGrid

        endo_grid = model.domain.discretize()
        grid = ProductGrid(dprocess.grid, endo_grid, names=["exo", "endo"])
    else:
        grid, dprocess = model.discretize()

    endo_grid = grid["endo"]
    exo_grid = grid["exo"]

    n_m = max(dprocess.n_nodes, 1)
    n_s = len(model.symbols["states"])

    if interp_method in ("cubic", "linear"):
        ddr = DecisionRule(
            exo_grid, endo_grid, dprocess=dprocess, interp_method=interp_method
        )
        ddr_filt = DecisionRule(
            exo_grid, endo_grid, dprocess=dprocess, interp_method=interp_method
        )
    else:
        raise Exception("Unsupported interpolation method.")

    # s = ddr.endo_grid
    s = endo_grid.nodes
    N = s.shape[0]
    n_x = len(model.symbols["controls"])
    x0 = (
        model.calibration["controls"][
            None,
            None,
        ]
        .repeat(n_m, axis=0)
        .repeat(N, axis=1)
    )

    if dr0 is not None:
        for i_m in range(n_m):
            x0[i_m, :, :] = dr0.eval_is(i_m, s)
    ddr.set_values(x0)

    steps = 0.5 ** numpy.arange(maxbsteps)

    lb = x0.copy()
    ub = x0.copy()
    for i_m in range(n_m):
        m = dprocess.node(i_m)
        lb[i_m, :] = x_lb(m, s, parms)
        ub[i_m, :] = x_ub(m, s, parms)

    x = x0

    # both affect the precision

    ddr.set_values(x)

    ## memory allocation

    n_im = dprocess.n_inodes(0)  # we assume it is constant for now

    jres = numpy.zeros((n_m, n_im, N, n_x, n_x))
    S_ij = numpy.zeros((n_m, n_im, N, n_s))

    for it in range(maxit):

        jres[...] = 0.0
        S_ij[...] = 0.0

        t1 = time.time()

        # compute derivatives and residuals:
        # res: residuals
        # dres: derivatives w.r.t. x
        # jres: derivatives w.r.t. ~x
        # fut_S: future states

        ddr.set_values(x)
        #
        # ub[ub>100000] = 100000
        # lb[lb<-100000] = -100000
        #
        # sh_x = x.shape
        # rr =euler_residuals(f,g,s,x,ddr,dp,parms, diff=False, with_jres=False,set_dr=True)
        # print(rr.shape)
        #
        # from iti.fb import smooth_
        # jj = smooth_(rr, x, lb, ub)
        #
        # print("Errors with complementarities")
        # print(abs(jj.max()))
        #
        # exit()
        #

        from dolo.numeric.optimize.newton import SerialDifferentiableFunction

        sh_x = x.shape
        ff = SerialDifferentiableFunction(
            lambda u: euler_residuals(
                f,
                g,
                s,
                u.reshape(sh_x),
                ddr,
                dprocess,
                parms,
                diff=False,
                with_jres=False,
                set_dr=False,
            ).reshape((-1, sh_x[2]))
        )
        res, dres = ff(x.reshape((-1, sh_x[2])))
        res = res.reshape(sh_x)
        dres = dres.reshape((sh_x[0], sh_x[1], sh_x[2], sh_x[2]))
        junk, jres, fut_S = euler_residuals(
            f,
            g,
            s,
            x,
            ddr,
            dprocess,
            parms,
            diff=False,
            with_jres=True,
            set_dr=False,
            jres=jres,
            S_ij=S_ij,
        )

        # if there are complementerities, we modify derivatives
        if complementarities:
            res, dres, jres = smooth(res, dres, jres, x - lb)
            res[...] *= -1
            dres[...] *= -1
            jres[...] *= -1
            res, dres, jres = smooth(res, dres, jres, ub - x, pos=-1.0)
            res[...] *= -1
            dres[...] *= -1
            jres[...] *= -1

        err_0 = abs(res).max()

        # premultiply by A
        jres[...] *= -1.0

        for i_m in range(n_m):
            for j_m in range(n_im):
                M = jres[i_m, j_m, :, :, :]
                X = dres[i_m, :, :, :].copy()
                sol = solve_tensor(X, M)

        t2 = time.time()

        # new version
        if invmethod == "gmres":
            ddx = solve_gu(dres.copy(), res.copy())
            L = Operator(jres, fut_S, ddr_filt)
            n0 = L.counter
            L.addid = True
            ttol = err_0 / 100
            sol = scipy.sparse.linalg.gmres(
                L, ddx.ravel(), tol=ttol
            )  # , maxiter=1, restart=smaxit)
            lam0 = 0.01
            nn = L.counter - n0
            tot = sol[0].reshape(ddx.shape)
        else:
            # compute inversion
            tot, nn, lam0 = invert_jac(
                res,
                dres,
                jres,
                fut_S,
                ddr_filt,
                tol=tol,
                maxit=smaxit,
                verbose=(verbose == "full"),
            )

        # lam, lam_max, lambdas = radius_jac(res,dres,jres,fut_S,tol=tol,maxit=1000,verbose=(verbose=='full'),filt=ddr_filt)

        # backsteps
        t3 = time.time()
        for i_bckstps, lam in enumerate(steps):
            new_x = x - tot * lam
            new_err = euler_residuals(
                f, g, s, new_x, ddr, dprocess, parms, diff=False, set_dr=True
            )

            if complementarities:
                new_err = smooth_nodiff(new_err, new_x - lb)
                new_err = smooth_nodiff(-new_err, ub - new_x)

            new_err = abs(new_err).max()
            if new_err < err_0:
                break

        err_2 = abs(tot).max()
        t4 = time.time()
        itprint.print_iteration(
            N=it,
            f_x=err_0,
            d_x=err_2,
            Time_residuals=t2 - t1,
            Time_inversion=t3 - t2,
            Time_search=t4 - t3,
            Lambda_0=lam0,
            N_invert=nn,
            N_search=i_bckstps,
        )
        if err_0 < tol:
            break

        x = new_x

    ddr.set_values(x)

    itprint.print_finished()

    # if compute_radius:
    #     return ddx,L
    #     lam, lam_max, lambdas = radius_jac(res,dres,jres,fut_S,ddr_filt,tol=tol,maxit=smaxit,verbose=(verbose=='full'))
    #     return ddr, lam, lam_max, lambdas
    # else:
    if not details:
        return ddr
    else:
        ddx = solve_gu(dres.copy(), res.copy())
        L = Operator(jres, fut_S, ddr_filt)

        if compute_radius:
            lam = scipy.sparse.linalg.eigs(L, k=1, return_eigenvectors=False)
            lam = abs(lam[0])
        else:
            lam = np.nan
        # lam, lam_max, lambdas = radius_jac(res,dres,jres,fut_S,ddr_filt,tol=tol,maxit=smaxit,verbose=(verbose=='full'))
        return ImprovedTimeIterationResult(
            ddr, it, err_0, err_2, err_0 < tol, complementarities, lam, None, L
        )
Пример #4
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
Пример #5
0
def time_iteration(model,
                   initial_guess=None,
                   with_complementarities=True,
                   verbose=True,
                   grid={},
                   maxit=1000,
                   inner_maxit=10,
                   tol=1e-6,
                   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
        "dtmscc" model to be solved
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    grid: grid 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
    '''

    from dolo import dprint

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

    process = model.exogenous
    dprocess = process.discretize()

    n_ms = dprocess.n_nodes()  # number of exogenous states
    n_mv = dprocess.n_inodes(
        0)  # this assume number of integration nodes is constant

    x0 = model.calibration['controls']
    parms = model.calibration['parameters']
    n_x = len(x0)
    n_s = len(model.symbols['states'])

    endo_grid = model.get_grid(**grid)

    interp_type = 'cubic'

    exo_grid = dprocess.grid

    mdr = DecisionRule(exo_grid, endo_grid)

    grid = mdr.endo_grid.nodes()
    N = grid.shape[0]

    controls_0 = numpy.zeros((n_ms, N, n_x))
    if initial_guess is None:
        controls_0[:, :, :] = x0[None, None, :]
    else:
        for i_m in range(n_ms):
            controls_0[i_m, :, :] = initial_guess(i_m, grid)

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

    if 'controls_lb' in model.functions and with_complementarities == True:
        lb_fun = model.functions['controls_lb']
        ub_fun = model.functions['controls_ub']
        lb = numpy.zeros_like(controls_0) * numpy.nan
        ub = numpy.zeros_like(controls_0) * numpy.nan
        for i_m in range(n_ms):
            m = dprocess.node(i_m)[None, :]
            p = parms[None, :]
            m = numpy.repeat(m, N, axis=0)
            p = numpy.repeat(p, N, axis=0)

            lb[i_m, :, :] = lb_fun(m, grid, p)
            ub[i_m, :, :] = ub_fun(m, grid, p)

    else:
        with_complementarities = False

    sh_c = controls_0.shape

    controls_0 = controls_0.reshape((-1, n_x))

    from dolo.numeric.optimize.newton import newton, SerialDifferentiableFunction
    from dolo.numeric.optimize.ncpsolve import ncpsolve

    err = 10
    it = 0

    if with_complementarities:
        vprint("Solving WITH complementarities.")
        lb = lb.reshape((-1, n_x))
        ub = ub.reshape((-1, n_x))

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

    import time
    t1 = time.time()

    err_0 = numpy.nan

    verbit = (verbose == 'full')

    while err > tol and it < maxit:

        it += 1

        t_start = time.time()

        mdr.set_values(controls_0.reshape(sh_c))

        fn = lambda x: residuals_simple(f, g, grid, x.reshape(sh_c), mdr,
                                        dprocess, parms).reshape((-1, n_x))
        dfn = SerialDifferentiableFunction(fn)

        res = fn(controls_0)

        if hook:
            hook()

        if with_complementarities:
            [controls, nit] = ncpsolve(dfn,
                                       lb,
                                       ub,
                                       controls_0,
                                       verbose=verbit,
                                       maxit=inner_maxit)
        else:
            [controls, nit] = newton(dfn,
                                     controls_0,
                                     verbose=verbit,
                                     maxit=inner_maxit)

        err = abs(controls - controls_0).max()

        err_SA = err / err_0
        err_0 = err

        controls_0 = controls

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

        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'.format(
                it, err, err_SA, elapsed, nit))

    controls_0 = controls.reshape(sh_c)

    t2 = time.time()

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

    return mdr
Пример #6
0
def simulate(model,
             dr,
             s0=None,
             n_exp=0,
             horizon=40,
             seed=1,
             discard=False,
             solve_expectations=False,
             nodes=None,
             weights=None,
             forcing_shocks=None,
             return_array=False):
    '''
    Simulate a model using the specified decision rule.

    Parameters
    ---------
    model: NumericModel
        a "dtcscc" model

    dr: decision rule

    s0: ndarray
        initial state where all simulations start
    n_exp: int
        number of simulations. Use 0 for impulse-response functions
    horizon: int
        horizon for the simulations
    seed: int
        used to initialize the random number generator. Use it to replicate
        exact same results among simulations
    discard: boolean (False)
        if True, then all simulations containing at least one non finite value
        are discarded
    solve_expectations: boolean (False)
        if True, Euler equations are solved at each step using the controls to
        form expectations
    nodes: ndarray
        if `solve_expectations` is True use ``nodes`` for integration
    weights: ndarray
        if `solve_expectations` is True use ``weights`` for integration
    forcing_shocks: ndarray
        specify an exogenous process of shocks (requires ``n_exp<=1``)
    return_array: boolean (False)
        if True, then all return a numpy array containing simulated data,
        otherwise return a pandas DataFrame or Panel.

    Returns
    -------
    ndarray or pandas.Dataframe:
         - if `n_exp<=1` returns a DataFrame object
         - if `n_exp>1` returns a ``horizon x n_exp x n_v`` array where ``n_v``
           is the number of variables.
    '''

    if n_exp == 0:
        irf = True
        n_exp = 1
    else:
        irf = False

    calib = model.calibration

    parms = numpy.array(calib['parameters'])

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

    if s0 is None:
        s0 = calib['states']

    # s0 = numpy.atleast_2d(s0.flatten()).T
    x0 = dr(s0)
    s_simul = numpy.zeros((horizon, n_exp, s0.shape[0]))
    x_simul = numpy.zeros((horizon, n_exp, x0.shape[0]))

    s_simul[0, :, :] = s0[None, :]
    x_simul[0, :, :] = x0[None, :]

    fun = model.functions

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

    numpy.random.seed(seed)

    for i in range(horizon):
        mean = numpy.zeros(sigma.shape[0])
        if irf:
            if forcing_shocks is not None and i < forcing_shocks.shape[0]:
                epsilons = forcing_shocks[i, :]
            else:
                epsilons = numpy.zeros((1, sigma.shape[0]))
        else:
            epsilons = numpy.random.multivariate_normal(mean, sigma, n_exp)
        s = s_simul[i, :, :]

        x = dr(s)

        if solve_expectations:

            lbfun = model.functions['controls_lb']
            ubfun = model.functions['controls_ub']
            lb = lbfun(s, parms)
            ub = ubfun(s, parms)

            def fobj(t):
                return step_residual(s, t, dr, f, g, parms, nodes, weights)

            dfobj = SerialDifferentiableFunction(fobj)
            [x, nit] = ncpsolve(dfobj, lb, ub, x)

        x_simul[i, :, :] = x

        ss = g(s, x, epsilons, parms)
        if i < (horizon - 1):
            s_simul[i + 1, :, :] = ss

    if 'auxiliary' not in fun:  # TODO: find a better test than this
        l = [s_simul, x_simul]
        varnames = model.symbols['states'] + model.symbols['controls']
    else:
        aux = fun['auxiliary']

        a_simul = aux(s_simul.reshape((n_exp * horizon, -1)),
                      x_simul.reshape((n_exp * horizon, -1)), parms)
        a_simul = a_simul.reshape(horizon, n_exp, -1)

        l = [s_simul, x_simul, a_simul]
        varnames = model.symbols['states'] + model.symbols[
            'controls'] + model.symbols['auxiliaries']

    simul = numpy.concatenate(l, axis=2)

    if discard:
        iA = -numpy.isnan(x_simul)
        valid = numpy.all(numpy.all(iA, axis=0), axis=1)
        simul = simul[:, valid, :]
        n_kept = s_simul.shape[1]
        if n_exp > n_kept:
            print('Discarded {}/{}'.format(n_exp - n_kept, n_exp))

    if return_array:
        return simul

    if irf or (n_exp == 1):
        simul = simul[:, 0, :]
        ts = pandas.DataFrame(simul, columns=varnames)
        return ts
    else:
        panel = pandas.Panel(simul.swapaxes(0, 1), minor_axis=varnames)
        return panel
Пример #7
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
Пример #8
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,
                   integration='gauss-hermite',
                   integration_orders=None,
                   T=200,
                   n_s=3,
                   hook=None):
    """Finds a global solution for ``model`` using backward time-iteration.

    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 nods in each dimension if ``interp_type="spline" ``


    Returns:
    --------
    decision rule object (SmolyakGrid or MultivariateSplines)
    """
    def vprint(t):
        if verbose:
            print(t)

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

    if initial_dr == None:
        if pert_order == 1:
            from dolo.algos.perturbations import approximate_controls
            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 = numpy.row_stack([a, b])
        bounds = numpy.array(bounds, dtype=float)

    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 = numpy.sqrt(numpy.diag(Q))
        bounds = numpy.row_stack([
            initial_dr.S_bar - devs * n_s,
            initial_dr.S_bar + devs * n_s,
        ])

    if interp_orders == 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)
    elif interp_type == 'multilinear':
        from dolo.numeric.interpolation.multilinear import MultilinearInterpolator
        dr = MultilinearInterpolator(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...

    from dolo.algos.convert import get_fg_functions

    f, g = get_fg_functions(model)

    import time

    fun = lambda x: 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['arbitrage_lb']
        ubfun = model.functions['arbitrage_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} |'.format(
            'N', ' Error', 'Gain', 'Time', 'nit')
        stars = '-' * len(headline)
        print(stars)
        print(headline)
        print(stars)

    err_0 = 1

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

        dr.set_values(x0)

        from dolo.numeric.optimize.newton import serial_newton, SerialDifferentiableFunction
        from dolo.numeric.optimize.ncpsolve import ncpsolve
        sdfun = SerialDifferentiableFunction(fun)

        if with_complementarities:
            [x, nit] = ncpsolve(sdfun, lb, ub, x0, verbose=verbit)

        else:
            [x, nit] = serial_newton(sdfun, x0, verbose=verbit)

        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('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'.format(
                it, err, err_SA, elapsed, nit))

        x0 = x0 + (x - x0)
        if hook:
            hook(dr, it, err)
        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"))

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

    return dr
Пример #9
0
def time_iteration(model,
                   initial_guess=None,
                   with_complementarities=True,
                   verbose=True,
                   orders=None,
                   output_type='dr',
                   maxit=1000,
                   inner_maxit=10,
                   tol=1e-6,
                   hook=None):

    assert (model.model_type == 'dtmscc')

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

    [P, Q] = model.markov_chain

    n_ms = P.shape[0]  # number of markov states
    n_mv = P.shape[1]  # number of markov variables

    x0 = model.calibration['controls']
    parms = model.calibration['parameters']
    n_x = len(x0)
    n_s = len(model.symbols['states'])

    approx = model.options['approximation_space']
    a = approx['a']
    b = approx['b']
    if orders is None:
        orders = approx['orders']

    from dolo.numeric.decision_rules_markov import MarkovDecisionRule

    mdr = MarkovDecisionRule(n_ms, a, b, orders)

    grid = mdr.grid
    N = grid.shape[0]

    #    if isinstance(initial_guess, numpy.ndarray):
    #        print("Using initial guess (1)")
    #        controls = initial_guess
    #    elif isinstance(initial_guess, dict):
    #        print("Using initial guess (2)")
    #        controls_0 = initial_guess['controls']
    #        ap_space = initial_guess['approximation_space']
    #        if False in (approx['orders']==orders):
    #            print("Interpolating initial guess")
    #            old_dr = MarkovDecisionRule(controls_0.shape[0], ap_space['smin'], ap_space['smax'], ap_space['orders'])
    #            old_dr.set_values(controls_0)
    #            controls_0 = numpy.zeros( (n_ms, N, n_x) )
    #            for i in range(n_ms):
    #                e = old_dr(i,grid)
    #                controls_0[i,:,:] = e
    #    else:
    #        controls_0 = numpy.zeros((n_ms, N, n_x))

    controls_0 = numpy.zeros((n_ms, N, n_x))

    if initial_guess is None:
        controls_0[:, :, :] = x0[None, None, :]
    else:
        for i_m in range(n_ms):
            m = P[i_m, :][None, :]
            controls_0[i_m, :, :] = initial_guess(i_m, grid)

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

    if 'controls_lb' in model.functions and with_complementarities == True:
        lb_fun = model.functions['controls_lb']
        ub_fun = model.functions['controls_ub']
        lb = numpy.zeros_like(controls_0) * numpy.nan
        ub = numpy.zeros_like(controls_0) * numpy.nan
        for i_m in range(n_ms):
            m = P[i_m, :][None, :]
            p = parms[None, :]
            m = numpy.repeat(m, N, axis=0)
            p = numpy.repeat(p, N, axis=0)

            lb[i_m, :, :] = lb_fun(m, grid, p)
            ub[i_m, :, :] = ub_fun(m, grid, p)

    else:
        with_complementarities = False

    # mdr.set_values(controls)

    sh_c = controls_0.shape

    controls_0 = controls_0.reshape((-1, n_x))

    from dolo.numeric.optimize.newton import newton, SerialDifferentiableFunction
    from dolo.numeric.optimize.ncpsolve import ncpsolve

    err = 10
    it = 0

    if with_complementarities:
        vprint("Solving WITH complementarities.")
        lb = lb.reshape((-1, n_x))
        ub = ub.reshape((-1, n_x))

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

    import time
    t1 = time.time()

    err_0 = numpy.nan

    verbit = (verbose == 'full')

    while err > tol and it < maxit:

        it += 1

        t_start = time.time()

        mdr.set_values(controls_0.reshape(sh_c))

        fn = lambda x: residuals(f, g, grid, x.reshape(sh_c), mdr, P, Q, parms
                                 ).reshape((-1, n_x))
        dfn = SerialDifferentiableFunction(fn)

        if hook:
            hook()

        if with_complementarities:
            [controls, nit] = ncpsolve(dfn,
                                       lb,
                                       ub,
                                       controls_0,
                                       verbose=verbit,
                                       maxit=inner_maxit)
        else:
            [controls, nit] = newton(dfn,
                                     controls_0,
                                     verbose=verbit,
                                     maxit=inner_maxit)

        err = abs(controls - controls_0).max()

        err_SA = err / err_0
        err_0 = err

        controls_0 = controls

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

        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'.format(
                it, err, err_SA, elapsed, nit))

    controls_0 = controls.reshape(sh_c)

    t2 = time.time()

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

    if output_type == 'dr':
        return mdr
    elif output_type == 'controls':
        return controls_0
    else:
        raise Exception("Unsupported ouput type {}.".format(output_type))
Пример #10
0
def improved_time_iteration(model,
                            method='jac',
                            initial_dr=None,
                            interp_type='spline',
                            mu=2,
                            maxbsteps=10,
                            verbose=False,
                            tol=1e-8,
                            smaxit=500,
                            maxit=1000,
                            complementarities=True,
                            compute_radius=False,
                            invmethod='gmres',
                            details=True):
    def vprint(*args, **kwargs):
        if verbose:
            print(*args, **kwargs)

    itprint = IterationsPrinter(
        ('N', int), ('f_x', float), ('d_x', float), ('Time_residuals', float),
        ('Time_inversion', float), ('Time_search', float), ('Lambda_0', float),
        ('N_invert', int), ('N_search', int),
        verbose=verbose)
    itprint.print_header('Start Improved Time Iterations.')

    f = model.functions['arbitrage']
    g = model.functions['transition']
    x_lb = model.functions['controls_lb']
    x_ub = model.functions['controls_ub']

    parms = model.calibration['parameters']

    dp = model.exogenous.discretize()

    n_m = max(dp.n_nodes(), 1)

    n_s = len(model.symbols['states'])

    grid = model.get_grid()

    if interp_type == 'spline':
        ddr = DecisionRule(dp.grid, grid)
        ddr_filt = DecisionRule(dp.grid, grid)
    elif interp_type == 'smolyak':
        ddr = SmolyakDecisionRule(n_m, grid.min, grid.max, mu)
        ddr_filt = SmolyakDecisionRule(n_m, grid.min, grid.max, mu)
        derivative_type = 'numerical'

    # s = ddr.endo_grid
    s = grid.nodes()
    N = s.shape[0]
    n_x = len(model.symbols['controls'])
    x0 = model.calibration['controls'][None,
                                       None, ].repeat(n_m,
                                                      axis=0).repeat(N, axis=1)

    if initial_dr is not None:
        for i_m in range(n_m):
            x0[i_m, :, :] = initial_dr.eval_is(i_m, s)
    ddr.set_values(x0)

    steps = 0.5**numpy.arange(maxbsteps)

    lb = x0.copy()
    ub = x0.copy()
    for i_m in range(n_m):
        m = dp.node(i_m)
        lb[i_m, :] = x_lb(m, s, parms)
        ub[i_m, :] = x_ub(m, s, parms)

    x = x0

    # both affect the precision

    ddr.set_values(x)

    ## memory allocation

    n_im = dp.n_inodes(0)  # we assume it is constant for now

    jres = numpy.zeros((n_m, n_im, N, n_x, n_x))
    S_ij = numpy.zeros((n_m, n_im, N, n_s))

    for it in range(maxit):

        jres[...] = 0.0
        S_ij[...] = 0.0

        t1 = time.time()

        # compute derivatives and residuals:
        # res: residuals
        # dres: derivatives w.r.t. x
        # jres: derivatives w.r.t. ~x
        # fut_S: future states

        ddr.set_values(x)
        #
        # ub[ub>100000] = 100000
        # lb[lb<-100000] = -100000
        #
        # sh_x = x.shape
        # rr =euler_residuals(f,g,s,x,ddr,dp,parms, diff=False, with_jres=False,set_dr=True)
        # print(rr.shape)
        #
        # from iti.fb import smooth_
        # jj = smooth_(rr, x, lb, ub)
        #
        # print("Errors with complementarities")
        # print(abs(jj.max()))
        #
        # exit()
        #

        from dolo.numeric.optimize.newton import SerialDifferentiableFunction
        sh_x = x.shape
        ff = SerialDifferentiableFunction(
            lambda u: euler_residuals(f,
                                      g,
                                      s,
                                      u.reshape(sh_x),
                                      ddr,
                                      dp,
                                      parms,
                                      diff=False,
                                      with_jres=False,
                                      set_dr=False).reshape((-1, sh_x[2])))
        res, dres = ff(x.reshape((-1, sh_x[2])))
        res = res.reshape(sh_x)
        dres = dres.reshape((sh_x[0], sh_x[1], sh_x[2], sh_x[2]))
        junk, jres, fut_S = euler_residuals(f,
                                            g,
                                            s,
                                            x,
                                            ddr,
                                            dp,
                                            parms,
                                            diff=False,
                                            with_jres=True,
                                            set_dr=False,
                                            jres=jres,
                                            S_ij=S_ij)

        # if there are complementerities, we modify derivatives
        if complementarities:
            res, dres, jres = smooth(res, dres, jres, x - lb)
            res[...] *= -1
            dres[...] *= -1
            jres[...] *= -1
            res, dres, jres = smooth(res, dres, jres, ub - x, pos=-1.0)
            res[...] *= -1
            dres[...] *= -1
            jres[...] *= -1

        err_0 = (abs(res).max())

        # premultiply by A
        jres[...] *= -1.0

        for i_m in range(n_m):
            for j_m in range(n_im):
                M = jres[i_m, j_m, :, :, :]
                X = dres[i_m, :, :, :].copy()
                sol = solve_tensor(X, M)

        t2 = time.time()

        # new version
        if invmethod == 'gmres':
            import scipy.sparse.linalg
            ddx = solve_gu(dres.copy(), res.copy())
            L = Operator(jres, fut_S, ddr_filt)
            n0 = L.counter
            L.addid = True
            ttol = err_0 / 100
            sol = scipy.sparse.linalg.gmres(
                L, ddx.ravel(), tol=ttol)  #, maxiter=1, restart=smaxit)
            lam0 = 0.01
            nn = L.counter - n0
            tot = sol[0].reshape(ddx.shape)
        else:
            # compute inversion
            tot, nn, lam0 = invert_jac(res,
                                       dres,
                                       jres,
                                       fut_S,
                                       ddr_filt,
                                       tol=tol,
                                       maxit=smaxit,
                                       verbose=(verbose == 'full'))

        # lam, lam_max, lambdas = radius_jac(res,dres,jres,fut_S,tol=tol,maxit=1000,verbose=(verbose=='full'),filt=ddr_filt)

        # backsteps
        t3 = time.time()
        for i_bckstps, lam in enumerate(steps):
            new_x = x - tot * lam
            new_err = euler_residuals(f,
                                      g,
                                      s,
                                      new_x,
                                      ddr,
                                      dp,
                                      parms,
                                      diff=False,
                                      set_dr=True)

            if complementarities:
                new_err = smooth_nodiff(new_err, new_x - lb)
                new_err = smooth_nodiff(-new_err, ub - new_x)

            new_err = abs(new_err).max()
            if new_err < err_0:
                break

        err_2 = abs(tot).max()
        t4 = time.time()
        itprint.print_iteration(N=it,
                                f_x=err_0,
                                d_x=err_2,
                                Time_residuals=t2 - t1,
                                Time_inversion=t3 - t2,
                                Time_search=t4 - t3,
                                Lambda_0=lam0,
                                N_invert=nn,
                                N_search=i_bckstps)
        if err_0 < tol:
            break

        x = new_x

    ddr.set_values(x)

    itprint.print_finished()

    # if compute_radius:
    #     return ddx,L
    #     lam, lam_max, lambdas = radius_jac(res,dres,jres,fut_S,ddr_filt,tol=tol,maxit=smaxit,verbose=(verbose=='full'))
    #     return ddr, lam, lam_max, lambdas
    # else:
    if not details:
        return ddr
    else:
        ddx = solve_gu(dres.copy(), res.copy())
        L = Operator(jres, fut_S, ddr_filt)
        lam = scipy.sparse.linalg.eigs(L, k=1, return_eigenvectors=False)
        lam = abs(lam[0])
        # lam, lam_max, lambdas = radius_jac(res,dres,jres,fut_S,ddr_filt,tol=tol,maxit=smaxit,verbose=(verbose=='full'))
        return ImprovedTimeIterationResult(ddr, it, err_0, err_2, err_0 < tol,
                                           complementarities, lam, None, L)
Пример #11
0
def time_iteration(model,
                   initial_guess=None,
                   with_complementarities=True,
                   verbose=True,
                   grid={},
                   output_type='dr',
                   maxit=1000,
                   inner_maxit=10,
                   tol=1e-6,
                   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
        "dtmscc" model to be solved
    verbose : boolean
        if True, display iterations
    initial_dr : decision rule
        initial guess for the decision rule
    with_complementarities : boolean (True)
        if False, complementarity conditions are ignored
    grid: grid 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
    '''

    assert (model.model_type == 'dtmscc')

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

    [P, Q] = model.markov_chain

    n_ms = P.shape[0]  # number of markov states
    n_mv = P.shape[1]  # number of markov variables

    x0 = model.calibration['controls']
    parms = model.calibration['parameters']
    n_x = len(x0)
    n_s = len(model.symbols['states'])

    approx = model.get_grid(**grid)
    a = approx.a
    b = approx.b
    orders = approx.orders
    interp_type = approx.interpolation  # unused

    from dolo.numeric.decision_rules_markov import MarkovDecisionRule

    mdr = MarkovDecisionRule(n_ms, a, b, orders)

    grid = mdr.grid
    N = grid.shape[0]

    controls_0 = numpy.zeros((n_ms, N, n_x))

    if initial_guess is None:
        controls_0[:, :, :] = x0[None, None, :]
    else:
        for i_m in range(n_ms):
            m = P[i_m, :][None, :]
            controls_0[i_m, :, :] = initial_guess(i_m, grid)

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

    if 'controls_lb' in model.functions and with_complementarities == True:
        lb_fun = model.functions['controls_lb']
        ub_fun = model.functions['controls_ub']
        lb = numpy.zeros_like(controls_0) * numpy.nan
        ub = numpy.zeros_like(controls_0) * numpy.nan
        for i_m in range(n_ms):
            m = P[i_m, :][None, :]
            p = parms[None, :]
            m = numpy.repeat(m, N, axis=0)
            p = numpy.repeat(p, N, axis=0)

            lb[i_m, :, :] = lb_fun(m, grid, p)
            ub[i_m, :, :] = ub_fun(m, grid, p)

    else:
        with_complementarities = False

    # mdr.set_values(controls)

    sh_c = controls_0.shape

    controls_0 = controls_0.reshape((-1, n_x))

    from dolo.numeric.optimize.newton import newton, SerialDifferentiableFunction
    from dolo.numeric.optimize.ncpsolve import ncpsolve

    err = 10
    it = 0

    if with_complementarities:
        vprint("Solving WITH complementarities.")
        lb = lb.reshape((-1, n_x))
        ub = ub.reshape((-1, n_x))

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

    import time
    t1 = time.time()

    err_0 = numpy.nan

    verbit = (verbose == 'full')

    while err > tol and it < maxit:

        it += 1

        t_start = time.time()

        mdr.set_values(controls_0.reshape(sh_c))

        fn = lambda x: residuals(f, g, grid, x.reshape(sh_c), mdr, P, Q, parms
                                 ).reshape((-1, n_x))
        dfn = SerialDifferentiableFunction(fn)

        if hook:
            hook()

        if with_complementarities:
            [controls, nit] = ncpsolve(dfn,
                                       lb,
                                       ub,
                                       controls_0,
                                       verbose=verbit,
                                       maxit=inner_maxit)
        else:
            [controls, nit] = newton(dfn,
                                     controls_0,
                                     verbose=verbit,
                                     maxit=inner_maxit)

        err = abs(controls - controls_0).max()

        err_SA = err / err_0
        err_0 = err

        controls_0 = controls

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

        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} | {4:3} |'.format(
                it, err, err_SA, elapsed, nit))

    controls_0 = controls.reshape(sh_c)

    t2 = time.time()

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

    if output_type == 'dr':
        return mdr
    elif output_type == 'controls':
        return controls_0
    else:
        raise Exception("Unsupported ouput type {}.".format(output_type))
Пример #12
0
def time_iteration(
    model: Model,
    *,  #
    dr0: DecisionRule = None,  #
    verbose: bool = True,  #
    details: bool = True,  #
    ignore_constraints: bool = False,  #
    trace: bool = False,  #
    dprocess=None,
    maxit=1000,
    inner_maxit=10,
    tol=1e-6,
    hook=None,
    interp_method="cubic",
    # obsolete
    with_complementarities=None,
) -> TimeIterationResult:
    """Finds a global solution for ``model`` using backward time-iteration.


    This algorithm iterates on the residuals of the arbitrage equations

    Parameters
    ----------
    model : Model
        model to be solved
    verbose : bool
        if True, display iterations
    dr0 : decision rule
        initial guess for the decision rule
    with_complementarities : bool (True)
        if False, complementarity conditions are ignored
    maxit: maximum number of iterations
    inner_maxit: maximum number of iteration for inner solver
    tol: tolerance criterium for successive approximations
    hook: Callable
        function to be called within each iteration, useful for debugging purposes


    Returns
    -------
    decision rule :
        approximated solution
    """

    # deal with obsolete options
    if with_complementarities is not None:
        # TODO warn
        pass
    else:
        with_complementarities = not ignore_constraints

    if trace:
        trace_details = []
    else:
        trace_details = None

    from dolo import dprint

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

    grid, dprocess_ = model.discretize()

    if dprocess is None:
        dprocess = dprocess_

    n_ms = dprocess.n_nodes  # number of exogenous states
    n_mv = dprocess.n_inodes(
        0)  # this assume number of integration nodes is constant

    x0 = model.calibration["controls"]
    parms = model.calibration["parameters"]
    n_x = len(x0)
    n_s = len(model.symbols["states"])

    endo_grid = grid["endo"]
    exo_grid = grid["exo"]

    mdr = DecisionRule(exo_grid,
                       endo_grid,
                       dprocess=dprocess,
                       interp_method=interp_method)

    s = mdr.endo_grid.nodes
    N = s.shape[0]

    controls_0 = numpy.zeros((n_ms, N, n_x))
    if dr0 is None:
        controls_0[:, :, :] = x0[None, None, :]
    else:
        if isinstance(dr0, AlgoResult):
            dr0 = dr0.dr
        try:
            for i_m in range(n_ms):
                controls_0[i_m, :, :] = dr0(i_m, s)
        except Exception:
            for i_m in range(n_ms):
                m = dprocess.node(i_m)
                controls_0[i_m, :, :] = dr0(m, s)

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

    if "arbitrage_lb" in model.functions and with_complementarities == True:
        lb_fun = model.functions["arbitrage_lb"]
        ub_fun = model.functions["arbitrage_ub"]
        lb = numpy.zeros_like(controls_0) * numpy.nan
        ub = numpy.zeros_like(controls_0) * numpy.nan
        for i_m in range(n_ms):
            m = dprocess.node(i_m)[None, :]
            p = parms[None, :]
            m = numpy.repeat(m, N, axis=0)
            p = numpy.repeat(p, N, axis=0)

            lb[i_m, :, :] = lb_fun(m, s, p)
            ub[i_m, :, :] = ub_fun(m, s, p)

    else:
        with_complementarities = False

    sh_c = controls_0.shape

    controls_0 = controls_0.reshape((-1, n_x))

    from dolo.numeric.optimize.newton import newton, SerialDifferentiableFunction
    from dolo.numeric.optimize.ncpsolve import ncpsolve

    err = 10
    it = 0

    if with_complementarities:
        lb = lb.reshape((-1, n_x))
        ub = ub.reshape((-1, n_x))

    itprint = IterationsPrinter(
        ("N", int),
        ("Error", float),
        ("Gain", float),
        ("Time", float),
        ("nit", int),
        verbose=verbose,
    )
    itprint.print_header("Start Time Iterations.")

    import time

    t1 = time.time()

    err_0 = numpy.nan

    verbit = verbose == "full"

    while err > tol and it < maxit:

        it += 1

        t_start = time.time()

        mdr.set_values(controls_0.reshape(sh_c))

        if trace:
            trace_details.append({"dr": copy.deepcopy(mdr)})

        fn = lambda x: residuals_simple(f, g, s, x.reshape(sh_c), mdr,
                                        dprocess, parms).reshape((-1, n_x))
        dfn = SerialDifferentiableFunction(fn)

        res = fn(controls_0)

        if hook:
            hook()

        if with_complementarities:
            [controls, nit] = ncpsolve(dfn,
                                       lb,
                                       ub,
                                       controls_0,
                                       verbose=verbit,
                                       maxit=inner_maxit)
        else:
            [controls, nit] = newton(dfn,
                                     controls_0,
                                     verbose=verbit,
                                     maxit=inner_maxit)

        err = abs(controls - controls_0).max()

        err_SA = err / err_0
        err_0 = err

        controls_0 = controls

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

        itprint.print_iteration(N=it,
                                Error=err_0,
                                Gain=err_SA,
                                Time=elapsed,
                                nit=nit),

    controls_0 = controls.reshape(sh_c)

    mdr.set_values(controls_0)
    if trace:
        trace_details.append({"dr": copy.deepcopy(mdr)})

    itprint.print_finished()

    if not details:
        return mdr

    return TimeIterationResult(
        mdr,
        it,
        with_complementarities,
        dprocess,
        err < tol,  # x_converged: bool
        tol,  # x_tol
        err,  #: float
        None,  # log: object # TimeIterationLog
        trace_details,  # trace: object #{Nothing,IterationTrace}
    )