Beispiel #1
0
    def discretize_gdp(self, N=3):

        Σ = self.Σ
        ρ = self.ρ

        n_nodes = N
        n_std = 2.5
        n_integration_nodes = 5

        try:
            assert Σ.shape[0] == 1
        except:
            raise Exception("Not implemented.")

        try:
            assert ρ.shape[0] == ρ.shape[1] == 1
        except:
            raise Exception("Not implemented.")

        ρ = ρ[0, 0]
        σ = np.sqrt(Σ[0, 0])

        from dolo.numeric.discretization import gauss_hermite_nodes

        epsilons, weights = gauss_hermite_nodes([n_integration_nodes], Σ)

        min = -n_std * (σ / (np.sqrt(1 - ρ**2)))
        max = n_std * (σ / (np.sqrt(1 - ρ**2)))

        from .grids import CartesianGrid

        grid = CartesianGrid([min], [max], [n_nodes])

        nodes = np.linspace(min, max, n_nodes)[:, None]
        iweights = weights[None, :].repeat(n_nodes, axis=0)
        integration_nodes = np.zeros((n_nodes, n_integration_nodes))[:, :,
                                                                     None]
        for i in range(n_nodes):
            for j in range(n_integration_nodes):
                integration_nodes[i, j, :] = ρ * nodes[i, :] + epsilons[j]

        return GDP(nodes, integration_nodes, iweights, grid=grid)
Beispiel #2
0
def evaluate_policy(model, dr, tol=1e-8, grid={}, distribution={}, maxit=2000, verbose=False, hook=None,
                    integration_orders=None):
    '''
    Compute value function corresponding to policy ``dr``

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

    model:
        "dtcscc" model. Must contain a 'value' function.

    dr:
        decision rule to evaluate

    Returns:
    --------

    decision rule:
        value function (a function of the space similar to a decision rule
        object)

    '''

    assert (model.model_type == 'dtcscc')

    vfun = model.functions["value"]
    gfun = model.functions['transition']

    parms = model.calibration['parameters']

    n_vals = len(model.symbols['values'])

    t1 = time.time()
    err = 1.0

    it = 0

    approx = model.get_grid(**grid)
    interp_type = approx.interpolation

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

    drv = create_interpolator(approx, approx.interpolation)

    grid = drv.grid

    N = drv.grid.shape[0]

    controls = dr(grid)

    guess_0 = model.calibration['values']
    guess_0 = guess_0[None, :].repeat(N, axis=0)


    if not integration_orders:
        integration_orders = [3] * sigma.shape[0]
    [nodes, weights] = gauss_hermite_nodes(integration_orders, sigma)

    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)

    err_0 = 1.0

    while err > tol and it < maxit:

        if hook:
            hook()

        t_start = time.time()
        it += 1

        # update spline coefficients with current values
        drv.set_values(guess_0)

        # update the geuss of value functions
        guess = update_value(gfun, vfun, grid, controls, dr, drv,
                             nodes, weights, parms, n_vals)

        # compute error
        err = abs(guess - guess_0).max()
        err_SA = err / err_0
        err_0 = err

        # update guess
        guess_0[:] = guess.copy()

        # print update to user, if verbose
        t_end = time.time()
        elapsed = t_end - t_start
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err, err_SA, 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)

    return drv
Beispiel #3
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
Beispiel #4
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
Beispiel #5
0
def test_simulations():

    from dolo import yaml_import, approximate_controls
    model = yaml_import('../../examples/models/rbc.yaml')

    dr = approximate_controls(model)

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

    import numpy

    s0 = dr.S_bar

    horizon = 50

    import time
    t1 = time.time()
    simul = simulate(model, dr, s0, sigma, n_exp=1000, parms=parms, seed=1, horizon=horizon)
    t2 = time.time()

    print("Took: {}".format(t2-t1))


    from dolo.numeric.discretization import gauss_hermite_nodes
    N = 80
    [x,w] = gauss_hermite_nodes(N, sigma)


    t3 = time.time()
    simul_2 = simulate(model, dr, s0, sigma, n_exp=1000, parms=parms, horizon=horizon, seed=1, solve_expectations=True, nodes=x, weights=w)
    t4 = time.time()

    print("Took: {}".format(t4-t3))

    from matplotlib.pyplot import hist, show, figure, plot, title


    timevec = numpy.array(range(simul.shape[2]))


    figure()
    for k in range(10):
        plot(simul[:,k,0] - simul_2[:,k,0])
    title("Productivity")
    show()

    figure()
    for k in range(10):
        plot(simul[:,k,1] - simul_2[:,k,1])
    title("Investment")
    show()

#
#    figure()
#    plot(simul[0,0,:])
#    plot(simul_2[0,0,:])
#    show()

    figure()
    for i in range( horizon ):
        hist( simul[i,:,0], bins=50 )

    show()
Beispiel #6
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
Beispiel #7
0
def evaluate_policy(model, dr, tol=1e-8,  maxit=2000, verbose=False, hook=None, integration_orders=None):
    """Compute value function corresponding to policy ``dr``

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

    model:
        "fg" or "fga" model. Must contain a 'value' function.

    dr:
        decision rule to evaluate

    Returns:
    --------

    decision rule:
        value function (a function of the space similar to a decision rule object)

    """

    assert(model.model_spec=='fga')

    vfun = model.functions["value"]
    gfun = model.functions['transition']
    afun = model.functions['auxiliary']

    parms = model.calibration['parameters']

    n_vals = len(model.symbols['values'])

    import time

    t1 = time.time()
    err = 1

    it = 0

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


    from dolo.numeric.interpolation.splines import MultivariateSplines
    drv = MultivariateSplines(a,b,orders)
    grid = drv.grid

    N = drv.grid.shape[0]

    controls = dr(grid)

    auxiliaries = model.functions['auxiliary'](grid, controls, parms)

    guess_0 = model.calibration['values']
    guess_0 = guess_0[None,:].repeat(N, axis=0)

    sigma = model.covariances
    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)

    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)


    err_0 = 1

    while err > tol and it < maxit:

        if hook:
            hook()

        t_start = time.time()
        it +=1

        drv.set_values(guess_0)

        guess = update_value(gfun, afun, vfun, grid, controls, auxiliaries, dr, drv, epsilons, weights, parms, n_vals)


        err = abs(guess-guess_0).max()
        err_SA = err/err_0
        err_0 = err

        guess_0 = guess

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


    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 drv
Beispiel #8
0
def evaluate_policy(model,
                    dr,
                    tol=1e-8,
                    maxit=2000,
                    verbose=False,
                    hook=None,
                    integration_orders=None):
    """Compute value function corresponding to policy ``dr``

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

    model:
        "fg" or "fga" model. Must contain a 'value' function.

    dr:
        decision rule to evaluate

    Returns:
    --------

    decision rule:
        value function (a function of the space similar to a decision rule
        object)

    """

    assert (model.model_type == 'dtcscc')

    vfun = model.functions["value"]
    gfun = model.functions['transition']
    afun = model.functions['auxiliary']

    parms = model.calibration['parameters']

    n_vals = len(model.symbols['values'])

    t1 = time.time()
    err = 1.0

    it = 0

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

    drv = MultivariateSplines(a, b, orders)
    grid = drv.grid

    N = drv.grid.shape[0]

    controls = dr(grid)

    auxiliaries = afun(grid, controls, parms)

    guess_0 = model.calibration['values']
    guess_0 = guess_0[None, :].repeat(N, axis=0)

    sigma = model.covariances

    if not integration_orders:
        integration_orders = [3] * sigma.shape[0]
    [epsilons, weights] = gauss_hermite_nodes(integration_orders, sigma)

    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)

    err_0 = 1.0

    while err > tol and it < maxit:

        if hook:
            hook()

        t_start = time.time()
        it += 1

        # update spline coefficients with current values
        drv.set_values(guess_0)

        # update the geuss of value functions
        guess = update_value(gfun, afun, vfun, grid, controls, dr, drv,
                             epsilons, weights, parms, n_vals)

        # compute error
        err = abs(guess - guess_0).max()
        err_SA = err / err_0
        err_0 = err

        # update guess
        guess_0[:] = guess.copy()

        # print update to user, if verbose
        t_finish = time.time()
        elapsed = t_finish - t_start
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err, err_SA, 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)

    return drv
Beispiel #9
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
Beispiel #10
0
def evaluate_policy(model,
                    dr,
                    tol=1e-8,
                    grid={},
                    distribution={},
                    maxit=2000,
                    verbose=False,
                    hook=None,
                    integration_orders=None):
    '''
    Compute value function corresponding to policy ``dr``

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

    model:
        "dtcscc" model. Must contain a 'value' function.

    dr:
        decision rule to evaluate

    Returns:
    --------

    decision rule:
        value function (a function of the space similar to a decision rule
        object)

    '''

    assert (model.model_type == 'dtcscc')

    vfun = model.functions["value"]
    gfun = model.functions['transition']

    parms = model.calibration['parameters']

    n_vals = len(model.symbols['values'])

    t1 = time.time()
    err = 1.0

    it = 0

    approx = model.get_grid(**grid)
    interp_type = approx.interpolation

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

    drv = create_interpolator(approx, approx.interpolation)

    grid = drv.grid

    N = drv.grid.shape[0]

    controls = dr(grid)

    guess_0 = model.calibration['values']
    guess_0 = guess_0[None, :].repeat(N, axis=0)

    if not integration_orders:
        integration_orders = [3] * sigma.shape[0]
    [nodes, weights] = gauss_hermite_nodes(integration_orders, sigma)

    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)

    err_0 = 1.0

    while err > tol and it < maxit:

        if hook:
            hook()

        t_start = time.time()
        it += 1

        # update spline coefficients with current values
        drv.set_values(guess_0)

        # update the geuss of value functions
        guess = update_value(gfun, vfun, grid, controls, dr, drv, nodes,
                             weights, parms, n_vals)

        # compute error
        err = abs(guess - guess_0).max()
        err_SA = err / err_0
        err_0 = err

        # update guess
        guess_0[:] = guess.copy()

        # print update to user, if verbose
        t_end = time.time()
        elapsed = t_end - t_start
        if verbose:
            print('|{0:4} | {1:10.3e} | {2:8.3f} | {3:8.3f} |'.format(
                it, err, err_SA, 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)

    return drv
Beispiel #11
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
Beispiel #12
0
def test_simulations():

    import time
    from matplotlib.pyplot import hist, show, figure, plot, title
    from dolo import yaml_import, approximate_controls
    from dolo.numeric.discretization import gauss_hermite_nodes
    model = yaml_import('../../examples/models/rbc.yaml')

    dr = approximate_controls(model)

    parms = model.calibration['parameters']
    sigma = model.get_calibration().sigma

    s0 = dr.S_bar

    horizon = 50

    t1 = time.time()
    simul = simulate(model,
                     dr,
                     s0,
                     sigma,
                     n_exp=1000,
                     parms=parms,
                     seed=1,
                     horizon=horizon)
    t2 = time.time()

    print("Took: {}".format(t2 - t1))

    N = 80
    [x, w] = gauss_hermite_nodes(N, sigma)

    t3 = time.time()
    simul_2 = simulate(model,
                       dr,
                       s0,
                       sigma,
                       n_exp=1000,
                       parms=parms,
                       horizon=horizon,
                       seed=1,
                       solve_expectations=True,
                       nodes=x,
                       weights=w)
    t4 = time.time()

    print("Took: {}".format(t4 - t3))

    timevec = numpy.array(range(simul.shape[2]))

    figure()
    for k in range(10):
        plot(simul[:, k, 0] - simul_2[:, k, 0])
    title("Productivity")
    show()

    figure()
    for k in range(10):
        plot(simul[:, k, 1] - simul_2[:, k, 1])
    title("Investment")
    show()

    #
    #    figure()
    #    plot(simul[0,0,:])
    #    plot(simul_2[0,0,:])
    #    show()

    figure()
    for i in range(horizon):
        hist(simul[i, :, 0], bins=50)

    show()
Beispiel #13
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
Beispiel #14
0
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
    sigma = model.covariances
    nodes, weights = gauss_hermite_nodes([5], model.covariances)

    # draw sequence of innovations
    np.random.seed(seed)
    epsilon = numpy.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)

    return coefs