Example #1
0
def get_preconditioner():
    """Compute the preconditioner M"""
    diags_x = zeros((3, nx))
    diags_x[0, :] = 1 / hx / hx
    diags_x[1, :] = -2 / hx / hx
    diags_x[2, :] = 1 / hx / hx
    Lx = spdiags(diags_x, [-1, 0, 1], nx, nx)

    diags_y = zeros((3, ny))
    diags_y[0, :] = 1 / hy / hy
    diags_y[1, :] = -2 / hy / hy
    diags_y[2, :] = 1 / hy / hy
    Ly = spdiags(diags_y, [-1, 0, 1], ny, ny)

    J1 = spkron(Lx, eye(ny)) + spkron(eye(nx), Ly)

    # Now we have the matrix `J_1`. We need to find its inverse `M` --
    # however, since an approximate inverse is enough, we can use
    # the *incomplete LU* decomposition

    J1_ilu = spilu(J1)

    # This returns an object with a method .solve() that evaluates
    # the corresponding matrix-vector product. We need to wrap it into
    # a LinearOperator before it can be passed to the Krylov methods:

    M = LinearOperator(shape=(nx * ny, nx * ny), matvec=J1_ilu.solve)
    return M
def get_preconditioner():
    """Compute the preconditioner M"""
    diags_x = zeros((3, nx))
    diags_x[0, :] = 1 / hx / hx
    diags_x[1, :] = -2 / hx / hx
    diags_x[2, :] = 1 / hx / hx
    Lx = spdiags(diags_x, [-1, 0, 1], nx, nx)

    diags_y = zeros((3, ny))
    diags_y[0, :] = 1 / hy / hy
    diags_y[1, :] = -2 / hy / hy
    diags_y[2, :] = 1 / hy / hy
    Ly = spdiags(diags_y, [-1, 0, 1], ny, ny)

    J1 = spkron(Lx, eye(ny)) + spkron(eye(nx), Ly)

    # Now we have the matrix `J_1`. We need to find its inverse `M` --
    # however, since an approximate inverse is enough, we can use
    # the *incomplete LU* decomposition

    J1_ilu = spilu(J1)

    # This returns an object with a method .solve() that evaluates
    # the corresponding matrix-vector product. We need to wrap it into
    # a LinearOperator before it can be passed to the Krylov methods:

    M = LinearOperator(shape=(nx * ny, nx * ny), matvec=J1_ilu.solve)
    return M
Example #3
0
 def prepareJacMatrices(self):
     m = self.mesh
     matL = accumarray(m.e[:,2], m.t.shape[0]).mat.T.tolil()
     matR = accumarray(m.e[:,3], m.t.shape[0]).mat.T.tolil()
     # WL on far bc is freestream
     isFar = m.isFar(m.v[m.e[m.ieBnd,:2],:].mean(1))
     matL[m.ieBnd[isFar],:] = 0
     # average and difference
     self.matJacWL = spkron(matL, eye(4)).tocsr()
     self.matJacWR = spkron(matR, eye(4)).tocsr()
     self.matJacWE = spkron(0.5 * (matL + matR), eye(4)).tocsr()
     self.matJacdW = spkron(matR - matL, eye(4)).tocsr()
     # distribute flux matrix
     D = block_diags(1./ m.a[:,newaxis,newaxis])
     self.matJacDistFlux = spkron(D * m.matDistFlux, eye(4)).tocsr()
     # Tri to edg gradient with boundary copy
     matTriToBnd = accumarray(m.e[m.ieBnd,2], m.t.shape[0]).mat.T
     matGradTriEdg = m.matGradTriEdg + m.bcmatGradTriEdg * matTriToBnd
     # left and right gradient in cells
     edgOfTri = invertMap(m.e[:,2:])[1].reshape([-1, 3])
     avgEdgToTri = (accumarray(edgOfTri[:,0], m.e.shape[0]).mat.T + \
                    accumarray(edgOfTri[:,1], m.e.shape[0]).mat.T + \
                    accumarray(edgOfTri[:,2], m.e.shape[0]).mat.T) / 3.
     matGradTri = spkron(avgEdgToTri, eye(2)) * matGradTriEdg
     xt = m.xt(); dxt = xt[m.e[:,3],:] - xt[m.e[:,2],:]
     matL = spkron(accumarray(m.e[:,2], m.t.shape[0]).mat.T, eye(2))
     matR = spkron(accumarray(m.e[:,3], m.t.shape[0]).mat.T, eye(2))
     matJacdWL = block_diags(dxt[:,newaxis,:]) * matL * matGradTri
     matJacdWR = block_diags(dxt[:,newaxis,:]) * matR * matGradTri
     self.matJacdWL = spkron(matJacdWL, eye(4)).tocsr()
     self.matJacdWR = spkron(matJacdWR, eye(4)).tocsr()
Example #4
0
def test_wave_st_2d():
    T_end = 2.0
    geo = geometry.unit_cube(dim=1).extrude(0.0, T_end, support=(0.0,T_end))
    kv_t = bspline.make_knots(2, 0.0, T_end, 6)    # time axis
    kv   = bspline.make_knots(3, 0.0,   1.0, 8)    # space axis
    kvs = (kv_t, kv)

    M = mass(kv)
    DxDx = stiffness(kv)
    D0Dt = bsp_mixed_deriv_biform_1d(kv_t, 0, 1)
    DttDt = bsp_mixed_deriv_biform_1d(kv_t, 2, 1)
    A_ref = (spkron(DttDt, M) + spkron(D0Dt, DxDx)).tocsr()

    A = assemble(assemblers.WaveAssembler_ST2D(kvs, geo))
    assert abs(A_ref - A).max() < 1e-14
Example #5
0
 def prepareJacMatricesVisc(self):
     m = self.mesh
     # velocity gradient operator matrix
     xeBnd = m.v[m.e[m.ieBnd,:2],:].mean(1)
     isFar = m.isFar(xeBnd)
     ieFar = m.ieBnd[isFar]
     indi, indj = isFar.nonzero()[0], m.e[ieFar,3]
     shape = (isFar.size, m.t.shape[0])
     matJacUBc = csr_matrix((ones(isFar.sum()), (indi, indj)), shape)
     matGradU = m.matGradTriEdg + m.bcmatGradTriEdg * matJacUBc
     self.matGradU = spkron(matGradU, eye(2)).tocsr()
     # velocity avarage matrix
     #matL = accumarray(m.e[:,2], m.t.shape[0]).mat.T
     #matR = accumarray(m.e[:,3], m.t.shape[0]).mat.T
     self.matJacUE = spkron( m.e_map, eye(2), format='csr')
Example #6
0
 def prepareJacMatricesVisc(self):
     m = self.mesh
     # velocity gradient operator matrix
     xeBnd = m.v[m.e[m.ieBnd, :2], :].mean(1)
     isFar = m.isFar(xeBnd)
     ieFar = m.ieBnd[isFar]
     indi, indj = isFar.nonzero()[0], m.e[ieFar, 3]
     shape = (isFar.size, m.t.shape[0])
     matJacUBc = csr_matrix((ones(isFar.sum()), (indi, indj)), shape)
     matGradU = m.matGradTriEdg + m.bcmatGradTriEdg * matJacUBc
     self.matGradU = spkron(matGradU, eye(2)).tocsr()
     # velocity avarage matrix
     #matL = accumarray(m.e[:,2], m.t.shape[0]).mat.T
     #matR = accumarray(m.e[:,3], m.t.shape[0]).mat.T
     self.matJacUE = spkron(m.e_map, eye(2), format='csr')
Example #7
0
def test_heat_st_2d():
    T_end = 2.0
    geo = geometry.unit_cube(dim=1).cylinderize(0.0, T_end, support=(0.0,T_end))
    kv_t = bspline.make_knots(2, 0.0, T_end, 6)    # time axis
    kv   = bspline.make_knots(3, 0.0,   1.0, 8)    # space axis
    kvs = (kv_t, kv)

    M = mass(kv)
    M_t = mass(kv_t)
    DxDx = stiffness(kv)
    DtD0 = bsp_mixed_deriv_biform_1d(kv_t, 1, 0)
    A_ref = (spkron(DtD0, M) + spkron(M_t, DxDx)).tocsr()

    A = assemble_entries(assemblers.HeatAssembler_ST2D(kvs, geo))
    assert abs(A_ref - A).max() < 1e-14
Example #8
0
def test_canonical_op():
    N = (3, 4, 5)
    I = CanonicalOperator.eye(N)
    assert I.shape[0] == I.shape[1] == N
    X = _random_tucker(N, 2)
    Y = I.apply(X)
    assert Y.R == (2, 2, 2)
    assert np.allclose(X.asarray(), Y.asarray())
    # multiplication
    A = CanonicalOperator(
        [tuple(_random_banded(n, 1) for n in N) for k in range(3)])
    B = CanonicalOperator(
        [tuple(_random_banded(n, 1) for n in N) for k in range(2)])
    AB = A * B
    assert AB.R == 6
    assert scipy.sparse.linalg.norm(AB.asmatrix() -
                                    (A.asmatrix().dot(B.asmatrix()))) < 1e-6
    Y1 = A.apply(B.apply(X))
    Y2 = AB.apply(X)
    assert np.allclose(Y1.asarray(), Y2.asarray())
    assert np.allclose(((A @ B) @ X).asarray(), (A @ (B @ X)).asarray())
    # arithmetic
    assert np.allclose(((A + B) @ X).asarray(), (A @ X + B @ X).asarray())
    assert np.allclose(((A - B) @ X).asarray(), (A @ X - B @ X).asarray())
    assert np.allclose(((-A) @ X).asarray(), -(A @ X).asarray())
    # kron
    assert scipy.sparse.linalg.norm((A.kron(B)).asmatrix() -
                                    spkron(A.asmatrix(), B.asmatrix())) < 1e-10
def _prepare_b_jkl_mn(readout_povm, pauli_basis, pre_channel_ops, post_channel_ops, rho0):
    """
    Prepare the coefficient matrix for process tomography. This function uses sparse matrices
    for much greater efficiency. The coefficient matrix is defined as:

    .. math::

            B_{(jkl)(mn)}=\sum_{r,q}\pi_{jr}(\mathcal{R}_{k})_{rm} (\mathcal{R}_{l})_{nq} (\rho_0)_q

    where :math:`\mathcal{R}_{k}` is the transfer matrix of the quantum map corresponding to the
    k-th pre-measurement channel, while :math:`\mathcal{R}_{l}` is the transfer matrix of the l-th
    state preparation process. We also require the overlap
    between the (generalized) Pauli basis ops and the projection operators
    :math:`\pi_{jl}:=\sbraket{\Pi_j}{P_l} = \tr{\Pi_j P_l}`.

    See the grove documentation on tomography for detailed information.

    :param DiagonalPOVM readout_povm: The POVM corresponding to the readout plus classifier.
    :param OperatorBasis pauli_basis: The (generalized) Pauli basis employed in the estimation.
    :param list pre_channel_ops: The state preparation channel operators as `qutip.Qobj`
    :param list post_channel_ops: The pre-measurement (post circuit) channel operators as `qutip.Qobj`
    :param qutip.Qobj rho0: The initial state as a density matrix.
    :return: The coefficient matrix necessary to set up the binomial state tomography problem.
    :rtype: scipy.sparse.csr_matrix
    """
    c_jk_m = state_tomography._prepare_c_jk_m(readout_povm, pauli_basis, post_channel_ops)
    pre_channel_transfer_matrices = [pauli_basis.transfer_matrix(qt.to_super(ek))
                                     for ek in pre_channel_ops]
    rho0_q = pauli_basis.project_op(rho0)

    # These next lines hide some very serious (sparse-)matrix index magic,
    # basically we exploit the same index math as in `qutip.sprepost()`
    # i.e., if a matrix X is linearly mapped `X -> A.dot(X).dot(B)`
    # then this can be rewritten as
    #           `np.kron(B.T, A).dot(X.T.ravel()).reshape((B.shape[1], A.shape[0])).T`
    # The extra matrix transpose operations are necessary because numpy by default
    # uses row-major storage, whereas these operations are conventionally defined for column-major
    # storage.
    d_ln = spvstack([(rlnq * rho0_q).T for rlnq in pre_channel_transfer_matrices]).tocoo()
    b_jkl_mn = spkron(d_ln, c_jk_m).real
    return b_jkl_mn
Example #10
0
def extend_to_nd(from_small, to_small, n_prior, n_post):
    from_approx = spkron(spkron(speye(n_post), from_small), speye(n_prior))
    to_approx = spkron(spkron(speye(n_post), to_small), speye(n_prior))

    return from_approx, to_approx
Example #11
0
def eqcond(model):
    """
    Compute equilibirum of HANK model
    Written based on NYFED-DSGE's Julia-language implementation.
    """
    nstates = len(util.flatten_indices(model.endog_states))  # 406
    n_s_exp = len(util.flatten_indices(model.expected_shocks))  # 201
    n_s_exo = len(util.flatten_indices(model.exog_shocks))  # 1

    x = np.zeros(2 * nstates + n_s_exp + n_s_exo)

    # Read in parameters, settings
    niter_hours = model.settings['niter_hours'].value
    n_v = model.settings['n_jump_vars'].value
    n_g = model.settings['n_state_vars'].value
    ymarkov_combined = model.settings['ymarkov_combined'].value
    zz = model.settings['zz'].value
    a = model.settings['a'].value
    I, J = zz.shape
    amax = model.settings['amax'].value
    amin = model.settings['amin'].value
    aa = np.repeat(a.reshape(-1, 1), J, axis=1)
    A_switch = spkron(ymarkov_combined, speye(I, dtype=float, format='csc'))
    daf, dab, azdelta = aux.initialize_diff_grids(a, I, J)

    # Set up steady state parameters
    V_ss = model.steady_state['V_ss'].value
    g_ss = model.steady_state['g_ss'].value
    G_ss = model.steady_state['G_ss'].value
    w_ss = model.steady_state['w_ss'].value
    N_ss = model.steady_state['N_ss'].value
    C_ss = model.steady_state['C_ss'].value
    Y_ss = model.steady_state['Y_ss'].value
    B_ss = model.steady_state['B_ss'].value
    r_ss = model.steady_state['r_ss'].value
    rho_ss = model.steady_state['rho_ss'].value
    sig_MP = model.params['sig_MP'].value
    theta_MP = model.params['theta_MP'].value
    # sig_FP   = model.params['sig_FP'].value
    # theta_FP = model.params['theta_FP'].value
    # sig_PS   = model.params['sig_PS'].value
    # theta_PS = model.params['theta_PS'].value

    h_ss = model.steady_state['h_ss'].value.reshape(I, J, order='F')
    ceselast = model.params['ceselast'].value
    inflation_ss = model.steady_state['inflation_ss'].value
    maxhours = model.params['maxhours'].value
    govbcrule_fixnomB = model.params['govbcrule_fixnomB'].value
    priceadjust = model.params['priceadjust'].value
    taylor_inflation = model.params['taylor_inflation'].value
    taylor_outputgap = model.params['taylor_outputgap'].value
    meanlabeff = model.params['meanlabeff'].value

    # Necessary for construction of household problem functions
    labtax = model.params['labtax'].value
    coefrra = model.params['coefrra'].value
    frisch = model.params['frisch'].value
    labdisutil = model.params['labdisutil'].value

    TFP = 1.0

    def _get_residuals(x):
        #x = x.toarray().flatten()
        # Prepare steady state deviations
        V = (x[:n_v - 1] + V_ss).reshape(I, J, order='F')
        inflation = x[n_v - 1] + inflation_ss
        gg = x[n_v:n_v + n_g - 1] + g_ss[:-1]
        MP = x[n_v + n_g - 1]
        w = x[n_v + n_g] + w_ss
        hours = x[n_v + n_g + 1] + N_ss
        consumption = x[n_v + n_g + 2] + C_ss
        output = x[n_v + n_g + 3] + Y_ss
        assets = x[n_v + n_g + 4] + B_ss
        #government  = x[n_v + n_g + 5]       + G_ss

        V_dot = x[nstates:nstates + n_v - 1]
        inflation_dot = x[nstates + n_v - 1]
        g_dot = x[nstates + n_v:nstates + n_v + n_g - 1]
        mp_dot = x[nstates + n_g + n_v - 1]
        #fp_dot          = x[nstates + n_g + n_v + 5]
        #ps_dot          = x[nstates + n_g + n_v + 3]
        VEErrors = x[2 * nstates:2 * nstates + n_v - 1]
        inflation_error = x[2 * nstates + n_v - 1]
        mp_shock = x[2 * nstates + n_v]
        #fp_shock        = x[2*nstates + n_v + 1]
        #ps_shock        = x[2*nstates + n_v + 2]

        g_end = (1 - gg @ azdelta[:-1]) / azdelta[-1]
        g = np.append(gg, g_end)
        g[g < 1e-19] = 0.0

        #-----------------------------------------------------------------
        # Get equilibrium values, given steady state values
        normalized_wage = w / TFP
        profshare = (zz / meanlabeff) * ((1.0 - normalized_wage) * output)
        r_nominal = r_ss + taylor_inflation * inflation \
                    + taylor_outputgap * (np.log(output)-np.log(Y_ss)) + MP
        r = r_nominal - inflation
        lumptransfer    = labtax * w * hours - G_ss - \
                            (r_nominal - (1-govbcrule_fixnomB) * inflation) * assets

        #-----------------------------------------------------------------
        # Compute one iteration of the HJB
        ## Get flow utility, income, and labor hour functions
        util, income, labor = \
            aux.construct_household_problem_functions(V, w, coefrra, frisch, labtax, labdisutil)

        ## Initialize other variables, using V to ensure everything is a dual number
        Vaf = np.copy(V)
        Vab = np.copy(V)
        #h0 = np.array([h_ss[i, j] for i in range(I) for j in range(J)]).reshape(I, J)
        h0 = np.copy(h_ss)

        #-----------------------------------------------------------------
        # Construct Initial Difference Matrices
        #         hf = np.empty_like(V)
        #         hb = np.empty_like(V)

        Vaf[-1, :] = income(h_ss[-1, :], zz[-1, :], profshare[-1, :],
                            lumptransfer, r, amax)**(-coefrra)
        Vab[-1, :] = (V[-1, :] - V[-2, :]) / dab[-1]

        Vaf[0, :] = (V[1, :] - V[0, :]) / daf[0]
        Vab[0, :] = income(h_ss[0, :], zz[0, :], profshare[0, :], lumptransfer,
                           r, amin)**(-coefrra)

        Vaf[1:-1] = (V[2:, :] - V[1:-1, :]) / daf[0]
        Vab[1:-1] = (V[1:-1, :] - V[:-2, :]) / dab[0]

        # idx = ((i,j) for i in range(I) for j in range(J))
        # for t in idx:
        #     hf[t] = min(abs(labor(zz[t], Vaf[t])), maxhours)
        #     hb[t] = min(abs(labor(zz[t], Vab[t])), maxhours)

        hf = np.minimum(abs(labor(zz, Vaf)), maxhours)
        hb = np.minimum(abs(labor(zz, Vab)), maxhours)

        cf = Vaf**(-1 / coefrra)
        cb = Vab**(-1 / coefrra)

        #-----------------------------------------------------------------
        # Hours Iteration
        idx = ((i, j) for i in range(I) for j in range(J))
        for ih in range(niter_hours):
            for t in idx:
                if t[0] == I - 1:
                    cf[t] = income(hf[t], zz[t], profshare[t], lumptransfer, r,
                                   aa[t])
                    hf[t] = labor(zz[t], cf[t]**(-coefrra))
                    hf[t] = min(abs(hf[t]), maxhours)
                    if ih == niter_hours - 1:
                        Vaf[t] = cf[t]**(-coefrra)

                elif t[0] == 0:
                    cb[t] = income(hb[t], zz[t], profshare[t], lumptransfer, r,
                                   aa[t])
                    hb[t] = labor(zz[t], cb[t]**(-coefrra))
                    hb[t] = min(abs(hb[t]), maxhours)
                    if ih == niter_hours:
                        Vab[t] = cb[t]**(-coefrra)

            c0 = income(h0, zz, profshare, lumptransfer, r, aa)
            h0 = labor(zz, c0**(-coefrra))
            h0 = np.minimum(abs(h0.flatten()), maxhours).reshape(I, J)

        c0 = income(h0, zz, profshare, lumptransfer, r, aa)
        sf = income(hf, zz, profshare, lumptransfer, r, aa) - cf
        sb = income(hb, zz, profshare, lumptransfer, r, aa) - cb

        #-----------------------------------------------------------------
        # Upwind
        #T = sb[0,0].dtype

        Vf = (cf > 0) * (util(cf, hf) + sf * Vaf) + (cf <= 0) * (-1e12)
        Vb = (cb > 0) * (util(cb, hb) + sb * Vab) + (cb <= 0) * (-1e12)
        V0 = (c0 > 0) * util(c0, h0) + (c0 <= 0) * (-1e12)

        Iunique = (sb < 0) * (1 - (sf > 0)) + (1 - (sb < 0)) * (sf > 0)
        Iboth = (sb < 0) * (sf > 0)
        Ib = Iunique * (sb < 0) * (Vb > V0) + Iboth * (Vb == np.maximum(
            np.maximum(Vb, Vf), V0))
        If = Iunique * (sf > 0) * (Vf > V0) + Iboth * (Vf == np.maximum(
            np.maximum(Vb, Vf), V0))
        I0 = 1 - Ib - If

        h = hf * If + hb * Ib + h0 * I0
        c = cf * If + cb * Ib + c0 * I0
        s = sf * If + sb * Ib
        u = util(c, h)

        X = -Ib * sb / np.array([dab, dab]).reshape(I, J)
        Z = If * sf / np.array([daf, daf]).reshape(I, J)
        Y = -Z - X

        X[0, :] = 0.
        Z[I - 1, :] = 0.

        A = spdiag([
            X.reshape(I * J, order='F')[1:],
            Y.reshape(I * J, order='F'),
            Z.reshape(I * J, order='F')[:I * J - 1]
        ],
                   offsets=[-1, 0, 1],
                   shape=(I * J, I * J),
                   format='csc') + A_switch

        #-----------------------------------------------------------------
        # Collect/calculate Residuals
        hjb_residual = u.flatten(order='F') + A * V.flatten(order='F') \
                        + V_dot + VEErrors  - rho_ss * V.flatten(order='F')

        pc_residual  = -((r - 0) * inflation - (ceselast / priceadjust * \
                                                (w / TFP - (ceselast-1) / ceselast) + \
                                                inflation_dot - inflation_error))

        g_azdelta = g.flatten() * azdelta.flatten()
        g_intermediate = spdiag(1 / azdelta) * A.T @ g_azdelta
        g_residual = g_dot - g_intermediate[:-1]

        mp_residual = mp_dot - (-theta_MP * MP + sig_MP * mp_shock)

        realsav = sum(
            aa.flatten(order='F') * g.flatten(order='F') *
            azdelta.flatten(order='F'))
        realsav_dot = sum(
            s.flatten(order='F') * g.flatten(order='F') *
            azdelta.flatten(order='F'))
        bondmarket_residual = realsav_dot / realsav + govbcrule_fixnomB * inflation

        labmarket_residual = sum(zz.flatten(order='F') * h.flatten(order='F') \
                                 * g.flatten(order='F') * azdelta.flatten(order='F')) - hours

        consumption_residual = sum(c.flatten(order='F') * g.flatten(order='F') \
                                   * azdelta.flatten(order='F')) - consumption

        output_residual = TFP * hours - output
        #output_residual = TFP * hours - (-theta_PS * output + sig_PS * ps_shock)

        assets_residual = assets - realsav

        #government_residual = fp_dot - (-theta_FP * government + sig_FP * fp_shock)

        # Return equilibrium conditions
        return np.hstack(
            (hjb_residual, pc_residual, g_residual, mp_residual,
             bondmarket_residual, labmarket_residual, consumption_residual,
             output_residual, assets_residual))
        # return np.hstack((hjb_residual, pc_residual, g_residual,
        #                  mp_residual,
        #                  bondmarket_residual, labmarket_residual, consumption_residual,
        #                  output_residual, assets_residual, government_residual))

    derivs = jacob_mat(_get_residuals, x, nstates, h=1e-10)

    GAM1 = -derivs[:, :nstates]
    GAM0 = derivs[:, nstates:2 * nstates]
    PI = -derivs[:, 2 * nstates:2 * nstates + n_s_exp]
    PSI = -derivs[:, 2 * nstates + n_s_exp:2 * nstates + n_s_exp + n_s_exo]
    C = np.zeros(nstates)

    return GAM0, GAM1, PSI, PI, C
Example #12
0
def steadystate(model):
    # Read in parameters
    coefrra = model.params['coefrra'].value
    frisch = model.params['frisch'].value
    meanlabeff = model.params['meanlabeff'].value
    maxhours = model.params['maxhours'].value
    ceselast = model.params['ceselast'].value
    labtax = model.params['labtax'].value
    govbondtarget = model.params['govbondtarget'].value
    labdisutil = model.params['labdisutil'].value
    lumptransferpc = model.params['lumptransferpc'].value

    # Read in grids
    I = model.settings['I'].value
    J = model.settings['J'].value
    a = model.settings['a'].value
    g_z = model.settings['g_z'].value
    zz = model.settings['zz'].value
    ymarkov_combined = model.settings['ymarkov_combined'].value

    # Set necessary variables
    aa = np.repeat(a.reshape(-1, 1), J, axis=1)
    amax = np.max(a)
    amin = np.min(a)

    # Read in initial rates
    iterate_r = model.settings['iterate_r'].value
    r = model.settings['r0'].value
    rmin = model.settings['rmin'].value
    rmax = model.settings['rmax'].value
    iterate_rho = model.settings['iterate_rho'].value
    rho = model.settings['rho0'].value
    rhomin = model.settings['rhomin'].value
    rhomax = model.settings['rhomax'].value

    # Read in approximation parameters
    Ir = model.settings['Ir'].value
    maxit_HJB = model.settings['maxit_HJB'].value
    tol_HJB = model.settings['tol_HJB'].value
    d_HJB = model.settings['d_HJB'].value
    maxit_kfe = model.settings['maxit_kfe'].value
    tol_kfe = model.settings['tol_kfe'].value
    d_kfe = model.settings['d_kfe'].value
    niter_hours = model.settings['niter_hours'].value
    crit_S = model.settings['crit_S'].value

    # Initializing equilibrium objects
    labor_share_ss = (ceselast - 1) / ceselast
    w = w_ss = labor_share_ss

    # compute initial guesses at steady state values given zz, labor_share_ss, etc.
    N_ss, Y_ss, B_ss, profit_ss, profshare, lumptransfer = \
        aux.calculate_ss_equil_vars_init(zz, labor_share_ss,
                                         meanlabeff, lumptransferpc, govbondtarget)

    # Initialize matrices for finite differences
    Vaf = np.empty((I, J), dtype=np.complex64)
    Vab = np.empty((I, J), dtype=np.complex64)

    cf = np.empty((I, J), dtype=np.complex64)  # forward consumption difference
    hf = np.empty((I, J), dtype=np.complex64)  # forward hours difference
    sf = np.empty((I, J), dtype=np.complex64)  # forward saving difference
    cb = np.empty((I, J),
                  dtype=np.complex64)  # backward consumption difference
    hb = np.empty((I, J), dtype=np.complex64)  # backward hours difference
    sb = np.empty((I, J), dtype=np.complex64)  # backward saving difference
    c0 = np.empty((I, J), dtype=np.complex64)
    A = np.empty((I * J, J * J), dtype=np.complex64)

    Aswitch = spkron(ymarkov_combined, speye(I, dtype='complex64'))

    # Initialize steady state variables
    V = np.empty((I, J), dtype=np.complex64)  # value function
    u = np.empty((I, J), dtype=np.complex64)  # flow utility across state space
    s = np.empty((I, J), dtype=np.complex64)  # savings across state space
    c = np.empty((I, J), dtype=np.complex64)  # flow consumption
    h = np.empty((I, J), dtype=np.complex64)  # flow hours of labor
    h0 = np.empty((I, J), dtype=np.complex64)  # guess of what h will be

    # Creates functions for computing flow utility, income earned, and labor done given
    # CRRA + frisch elasticity style labor disutility
    util, income, labor = \
        aux.construct_household_problem_functions(V, w, coefrra, frisch, labtax, labdisutil)

    # Setting up forward/backward difference grids for a.
    daf, dab, azdelta = aux.initialize_diff_grids(a, I, J)

    for ir in range(Ir):
        c.fill(np.complex(0.))
        h.fill(np.complex(1 / 3))
        h0.fill(np.complex(1.))

        # Initial guess
        inc = income(h, zz, profshare, lumptransfer, r, aa)  # get income
        v = util(inc, h) / rho  # value function guess

        # Iterate HJB
        for ihjb in range(maxit_HJB):
            V = v
            Vaf, Vab, cf, hf, cb, hb = aux.construct_initial_diff_matrices(
                V, Vaf, Vab, income, labor, h, h0, zz, profshare, lumptransfer,
                amax, amin, coefrra, r, daf, dab, maxhours)
            # Iterative method to find consistent forward/backward/neutral
            # difference matrices for c and h
            cf, hf, cb, hb, c0, h0 = aux.hours_iteration(
                income, labor, zz, profshare, lumptransfer, aa, coefrra, r, cf,
                hf, cb, hb, c0, h0, maxhours, niter_hours)

            c0 = income(h0, zz, profshare, lumptransfer, r, aa)
            sf = income(hf, zz, profshare, lumptransfer, r, aa) - cf
            sb = income(hb, zz, profshare, lumptransfer, r, aa) - cb

            Vaf[I - 1, :] = cf[I - 1, :]**(
                -coefrra
            )  # Forward difference for value function w.r.t. wealth
            Vab[0, :] = cb[0, :]**(
                -coefrra
            )  # Backward difference for value function w.r.t. wealth

            V, A, u, h, c, s = aux.upwind(rho,
                                          V,
                                          util,
                                          Aswitch,
                                          cf,
                                          cb,
                                          c0,
                                          hf,
                                          hb,
                                          h0,
                                          sf,
                                          sb,
                                          Vaf,
                                          Vab,
                                          daf,
                                          dab,
                                          d_HJB=d_HJB)

            # Check for convergence
            Vchange = V - v
            v = V

            err_HJB = np.max(np.abs(Vchange))
            if err_HJB < tol_HJB:
                break
        # Create initial guess for g0
        g0 = np.zeros((I, J), dtype=np.complex64)
        # Assign stationary income distribution weight at a = 0, zero elsewhere
        g0[a == 0, :] = g_z
        # g_z is marginal distribution, so re-weight by some multiplier of Lebesgue measure
        g0 = g0 / azdelta.reshape(I, J)

        # Solve for distribution
        g = aux.solve_kfe(A,
                          g0,
                          spdiag(azdelta),
                          maxit_kfe=maxit_kfe,
                          tol_kfe=tol_kfe,
                          d_kfe=d_kfe)
        # Back out static conditions/steady state values given our value function and distribution
        N_ss, Y_ss, B_ss, profit_ss, profshare, lumptransfer, bond_err = \
            aux.calculate_ss_equil_vars(zz, h, g, azdelta, aa, labor_share_ss, meanlabeff,
                                        lumptransferpc, govbondtarget)

        # Check bond market for market clearing
        r, rmin, rmax, rho, rhomin, rhomax, clear_cond = \
            aux.check_bond_market_clearing(bond_err, crit_S, r, rmin, rmax, rho, rhomin, rhomax,
                                           iterate_r, iterate_rho)
        if clear_cond:
            # Set steady state values
            model.steady_state['V_ss'].value = np.real(V.flatten(order='F'))
            model.steady_state['inflation_ss'].value = 0.
            model.steady_state['g_ss'].value = np.real(g.flatten(order='F'))
            model.steady_state['r_ss'].value = r
            model.steady_state['u_ss'].value = np.real(u.flatten(order='F'))
            model.steady_state['c_ss'].value = np.real(c.flatten(order='F'))
            model.steady_state['h_ss'].value = np.real(h.flatten(order='F'))
            model.steady_state['s_ss'].value = np.real(s.flatten(order='F'))
            model.steady_state['rnom_ss'].value        = model.steady_state['r_ss'].value \
                                                         + model.steady_state['inflation_ss'].value
            model.steady_state['B_ss'].value = sum(
                model.steady_state['g_ss'].value * aa.flatten(order='F') *
                azdelta)
            model.steady_state['N_ss'].value           = np.real(sum(zz.flatten(order='F') * model.steady_state['h_ss'].value \
                                                                     * model.steady_state['g_ss'].value * azdelta))
            model.steady_state['Y_ss'].value = model.steady_state['N_ss'].value
            model.steady_state['labor_share_ss'].value = (ceselast -
                                                          1) / ceselast
            model.steady_state['w_ss'].value = model.steady_state[
                'labor_share_ss'].value
            model.steady_state['profit_ss'].value      = (1 - model.steady_state['labor_share_ss'].value) \
                                                          * model.steady_state['Y_ss'].value
            model.steady_state['C_ss'].value = sum(
                model.steady_state['c_ss'].value *
                model.steady_state['g_ss'].value * azdelta)
            model.steady_state['T_ss'].value = np.real(lumptransfer)
            model.steady_state['rho_ss'].value = rho
            model.steady_state['G_ss'].value           = labtax * model.steady_state['w_ss'].value * model.steady_state['N_ss'].value \
                                                         - model.steady_state['T_ss'].value - model.steady_state['r_ss'].value * model.steady_state['B_ss'].value

            break
    return model
Example #13
0
def slra_by_factorization(x,
                          m,
                          k,
                          PRINT=0,
                          x_0=None,
                          Omega=None,
                          N=None,
                          PCA_INIT=False):
    if Omega is None:
        # assume x is the full data vector
        x = x
        N = x.size
        M_bar = None
    else:
        x_Omega = x
        if N is None:
            N = Omega.max()
        else:
            N = N
        x = np.zeros((N, ))
        x[Omega] = x_Omega

        entries = np.zeros((N, ))
        entries[Omega] = 1.0
        M_bar = lil_matrix((N, N))
        M_bar.setdiag(entries)

    n = N - m + 1
    hankel = Hankel(m, n)

    if PCA_INIT:
        X_full = hankel.struct_from_vec(x)
        P, _, _ = svds(X_full, k)
    else:
        P, _ = np.linalg.qr(np.random.rand(m, k))

    L = None

    if M_bar is None:
        b = np.hstack((x, np.zeros((m * n, ))))
    else:
        b = np.hstack((M_bar.dot(x), np.zeros((m * n, ))))

    X = hankel.struct_from_vec(x)

    if x_0 is not None:
        X_0 = hankel.struct_from_vec(x_0)
    else:
        X_0 = None

    Pi_S_orth = speye(m * n) - hankel.Pi_S

    II_max = 1000
    I_max = 1000
    # Ishteva et al. propose to choose rho in the range (1, 1e14), but the values below work better in practice
    rho_start = 1e-5
    rho_end = 1e6
    c_rho_slow = 1.5
    c_rho_fast = 10

    rho = rho_start

    printit = 0
    II = 0

    for i in xrange(I_max):
        print "Iteration ", i, ", rho = ", rho
        for j in xrange(II_max):
            P_old = P
            if M_bar is None:
                M = vstack((hankel.S_pinv, np.sqrt(rho) * Pi_S_orth))
            else:
                M = vstack(
                    (M_bar.dot(hankel.S_pinv), np.sqrt(rho) * Pi_S_orth))

            A_L = M.dot(spkron(speye(n), P))
            L = np.reshape(lsqr(A_L, b)[0], (k, n), order='F')

            A_P = M.dot(spkron(L.T, speye(m)))
            P = np.reshape(lsqr(A_P, b)[0], (m, k), order='F')

            # Ishteva et al. propose to evaluate the change in the column space of P (such as the angle between subsequent subspaces), but it is not working well in practice
            # Instead, measure the relative difference between old and new estimate of P
            diff_P = np.linalg.norm(P - P_old, 'fro') / np.linalg.norm(
                P_old, 'fro')

            print diff_P
            if diff_P < 0.1:
                II = j
                break

        if II > 5:
            rho *= c_rho_slow
        else:
            rho *= c_rho_fast
        if rho >= rho_end:
            break
        if PRINT > 1:
            PL = np.dot(P, L)
            if X_0 is None:
                plot_matrices(1, (1, 3),
                              X,
                              "$\mathbf{X}$", (X.min(), X.max()),
                              PL,
                              "PL", (X.min(), X.max()),
                              X - PL,
                              "$\mathbf{X} - \mathbf{P}\mathbf{L}$",
                              (-X.max(), X.max()),
                              filename="/tmp/figures/matrices/slrabyF_" +
                              '{:03d}'.format(printit) + ".png",
                              visible=False)
            else:
                plot_matrices(1, (1, 4),
                              X,
                              "$\mathbf{X}$", (X.min(), X.max()),
                              PL,
                              "PL", (X.min(), X.max()),
                              X - PL,
                              "$\mathbf{X} - \mathbf{P}\mathbf{L}$",
                              (-X.max(), X.max()),
                              X_0 - PL,
                              "$\mathbf{X}_0 - \mathbf{P}\mathbf{L}$",
                              (-X.max(), X.max()),
                              filename="/tmp/figures/matrices/slrabyF_" +
                              '{:03d}'.format(printit) + ".png",
                              visible=False)
            printit += 1

    Y = np.dot(P, L)
    y = hankel.S_pinv.dot(Y.flatten('F'))
    return y