コード例 #1
0
    def test_smw_formula_spv(self):
        """check the use of the smw formula with sparse v

        for the inverse of A-UV with v sparse"""

        # check the branch with direct solves
        AuvInvZ = lau.app_smw_inv(self.A, umat=self.U, vmat=self.Vsp,
                                  rhsa=self.Z, Sinv=None)
        AAinvZ = self.A * AuvInvZ - np.dot(self.U, self.Vsp * AuvInvZ)
        self.assertTrue(np.allclose(AAinvZ, self.Z))

        # check the branch where A comes as LU
        alusolve = spsla.factorized(self.A)
        AuvInvZ = lau.app_smw_inv(alusolve, umat=self.U, vmat=self.Vsp,
                                  rhsa=self.Z, Sinv=None)
        AAinvZ = self.A * AuvInvZ - np.dot(self.U, self.Vsp * AuvInvZ)

        self.assertTrue(np.allclose(AAinvZ, self.Z))
コード例 #2
0
    def test_smw_formula_complex(self):
        """check the use of the smw formula

        for the inverse of A-UV"""

        # check the branch with direct solves
        apoi = self.A + 1j * self.M
        AuvInvZ = lau.app_smw_inv(apoi, umat=self.U, vmat=self.V,
                                  rhsa=self.Z, Sinv=None)
        AAinvZ = apoi * AuvInvZ - np.dot(self.U, np.dot(self.V, AuvInvZ))
        self.assertTrue(np.allclose(AAinvZ, self.Z))

        # check the branch where A comes as LU
        alusolve = spsla.factorized(apoi)
        AuvInvZ = lau.app_smw_inv(alusolve, umat=self.U, vmat=self.V,
                                  rhsa=self.Z, Sinv=None)
        AAinvZ = apoi * AuvInvZ - np.dot(self.U, np.dot(self.V, AuvInvZ))
        self.assertTrue(np.allclose(AAinvZ, self.Z))
コード例 #3
0
    def test_smw_formula_krypy(self):
        """check the smw using krypy's gmres

        """

        AuvInvZ = lau.app_smw_inv(self.A, umat=self.U, vmat=self.V,
                                  rhsa=self.Z,
                                  krylov=True, krpslvprms=self.krpslvprms)
        AAinvZ = self.A * AuvInvZ - np.dot(self.U,
                                           np.dot(self.V, AuvInvZ))

        print np.linalg.norm(AAinvZ - self.Z)

        self.assertTrue(np.allclose(AAinvZ, self.Z))
コード例 #4
0
    def test_smw_formula(self):
        """check the use of the smw formula

        for the inverse of A-UV"""

        # check the branch with direct solves
        AuvInvZ = lau.app_smw_inv(self.A,
                                  umat=self.U,
                                  vmat=self.V,
                                  rhsa=self.Z,
                                  Sinv=None)
        AAinvZ = self.A * AuvInvZ - np.dot(self.U, np.dot(self.V, AuvInvZ))
        self.assertTrue(np.allclose(AAinvZ, self.Z))

        # check the branch where A comes as LU
        alusolve = spsla.factorized(self.A)
        AuvInvZ = lau.app_smw_inv(alusolve,
                                  umat=self.U,
                                  vmat=self.V,
                                  rhsa=self.Z,
                                  Sinv=None)
        AAinvZ = self.A * AuvInvZ - np.dot(self.U, np.dot(self.V, AuvInvZ))
        self.assertTrue(np.allclose(AAinvZ, self.Z))
コード例 #5
0
    def test_smw_formula_krypy(self):
        """check the smw using krypy's gmres

        """

        AuvInvZ = lau.app_smw_inv(self.A,
                                  umat=self.U,
                                  vmat=self.V,
                                  rhsa=self.Z,
                                  krylov=True,
                                  krpslvprms=self.krpslvprms)
        AAinvZ = self.A * AuvInvZ - np.dot(self.U, np.dot(self.V, AuvInvZ))

        print np.linalg.norm(AAinvZ - self.Z)

        self.assertTrue(np.allclose(AAinvZ, self.Z))
コード例 #6
0
def solve_proj_lyap_stein(amat=None, jmat=None, wmat=None, mmat=None,
                          umat=None, vmat=None,
                          transposed=False,
                          adi_dict=dict(adi_max_steps=150,
                                        adi_newZ_reltol=1e-8),
                          nwtn_adi_dict=None, **kw):
    """ approximates the solution X to the projected lyap equation

        [A-UV].T*X*M + M.T*X*[A-UV] + J.T*Y*M + M.T*Y.T*J = -W*W.T

        J*X*M = 0    and    M.T*X*J.T = 0

    by considering the equivalent Stein eqns
    and computing the first members of the
    series converging to X

    We use the SMW formula:
    (A-UV).-1 = A.-1 + A.-1*U [ I - V A.-1 U].-1 A.-1

    for the transpose:

    (A-UV).-T = A.-T + A.-T*Vt [ I - Ut A.-T Vt ].-1 A.-T

              = (A.T - Vt Ut).-1

    see numOptAff.pdf
    """
    if nwtn_adi_dict is not None:
        adi_dict = nwtn_adi_dict
        # so we can pass the same dicts to lyap and ric solve

    if transposed:
        At, Mt = amat, mmat
    else:
        At, Mt = amat.T, mmat.T

    # TODO: compute optimal shifts
    try:
        ms = adi_dict['ms']
    except KeyError:
        ms = [-30.0, -20.0, -10.0, -5.0, -3.0, -1.0]

    if adi_dict['verbose']:
        print ('\nAdishifts: {0} ').format(ms)

    NZ = wmat.shape[0]

    def get_atmtlu(At, Mt, jmat, ms):
        """compute the LU of the projection matrix

        """
        NP = jmat.shape[0]
        sysm = sps.vstack([sps.hstack([At + ms.conjugate() * Mt, -jmat.T]),
                           sps.hstack([jmat, sps.csr_matrix((NP, NP))])],
                          format='csc')
        return spsla.factorized(sysm)

    def _app_projinvz(Z, At=None, Mt=None,
                      jmat=None, ms=None, atmtlu=None):

        if atmtlu is None:
            atmtlu = get_atmtlu(At, Mt, jmat, ms)

        NZ = Z.shape[0]

        Zp = np.zeros(Z.shape)
        zcol = np.zeros(NZ + jmat.shape[0])
        for ccol in range(Z.shape[1]):
            if sps.isspmatrix(Z):
                zcol[:NZ] = Z[:NZ, ccol].todense().flatten()
            else:
                zcol[:NZ] = Z[:NZ, ccol]
            Zp[:, ccol] = atmtlu(zcol)[:NZ]

        return Zp, atmtlu

    adi_step = 0
    rel_newZ_norm = 2
    adi_rel_newZ_norms = []

    atmtlulist = []
    for mu in ms:
        atmtlumu = get_atmtlu(At, Mt, jmat, mu)
        atmtlulist.append(atmtlumu)

    if umat is not None and vmat is not None:
        # preps to apply the smw formula
        # adding zeros to the coefficients to fit the
        # saddle point systems
        vmate = np.hstack([vmat, np.zeros((vmat.shape[0], jmat.shape[0]))])
        if sps.isspmatrix(umat):
            umate = sps.vstack([umat, sps.csr_matrix((jmat.shape[0],
                                                     umat.shape[1]))])
        else:
            umate = np.vstack([umat, np.zeros((jmat.shape[0], umat.shape[1]))])

        stinvlist = []
        for ncurmu, mu in enumerate(ms):
            stinvlist.append(lau.get_Sinv_smw(atmtlulist[ncurmu],
                                              umat=vmate.T, vmat=umate.T))

        #  Start the ADI iteration

        We = np.vstack([wmat, np.zeros((jmat.shape[0], wmat.shape[1]))])

        Z = lau.app_smw_inv(atmtlulist[0], umat=vmate.T, vmat=umate.T,
                            rhsa=np.sqrt(-2 * ms[0].real) * We,
                            Sinv=stinvlist[0])[:NZ, :]

        ufac = Z
        u_norm_sqrd = np.linalg.norm(Z) ** 2

        muind = 1
        muind = np.mod(muind, len(ms))

        while adi_step < adi_dict['adi_max_steps'] and \
                rel_newZ_norm > adi_dict['adi_newZ_reltol']:

            Ze = np.vstack([Mt*Z, np.zeros((jmat.shape[0], wmat.shape[1]))])
            Zi = lau.app_smw_inv(atmtlulist[muind], umat=vmate.T,
                                 vmat=umate.T, rhsa=Ze,
                                 Sinv=stinvlist[muind])[:NZ, :]

            Z = np.sqrt(ms[muind].real / ms[muind-1].real) *\
                (Z - (ms[muind] + ms[muind-1].conjugate()) * Zi)

            z_norm_sqrd = np.linalg.norm(Z) ** 2
            u_norm_sqrd = u_norm_sqrd + z_norm_sqrd

            ufac = np.hstack([ufac, Z])
            rel_newZ_norm = np.sqrt(z_norm_sqrd / u_norm_sqrd)
            # np.linalg.norm(Z)/np.linalg.norm(ufac)

            adi_step += 1
            muind = np.mod(muind+1, len(ms))
            adi_rel_newZ_norms.append(rel_newZ_norm)

            try:
                if adi_dict['check_lyap_res'] and np.mod(adi_step, 10) == 0:
                    sqrdprolyares = \
                        comp_proj_lyap_res_norm(Z, amat=amat, mmat=mmat,
                                                wmat=wmat, jmat=jmat,
                                                umat=umat, vmat=vmat)
                    print 'adistep ', adi_step
                    print 'cur proj lyap res: ', np.sqrt(sqrdprolyares)
                    print 'rel Z norm: \n', rel_newZ_norm
            except KeyError:
                pass  # no such option specified

        try:
            if adi_dict['verbose']:
                print ('Number of ADI steps {0} -- \n' +
                       'Relative norm of the update {1}'
                       ).format(adi_step, rel_newZ_norm)
                print 'sqrd norm of Z: {0}'.format(u_norm_sqrd)
        except KeyError:
            pass  # no verbosity specified - nothing is shown

    else:

        Z = _app_projinvz(np.sqrt(-2*ms[0].real)*wmat, jmat=jmat,
                          atmtlu=atmtlulist[0])[0]

        ufac = Z
        u_norm_sqrd = np.linalg.norm(Z) ** 2
        muind = 1
        muind = np.mod(muind, len(ms))

        while adi_step < adi_dict['adi_max_steps'] and \
                rel_newZ_norm > adi_dict['adi_newZ_reltol']:

            Zi = _app_projinvz(Mt*Z, jmat=jmat, atmtlu=atmtlulist[muind])[0]

            Z = np.sqrt(ms[muind].real / ms[muind-1].real) *\
                (Z - (ms[muind] + ms[muind-1].conjugate()) * Zi)

            ufac = np.hstack([ufac, Z])

            z_norm_sqrd = np.linalg.norm(Z) ** 2
            u_norm_sqrd = u_norm_sqrd + z_norm_sqrd

            rel_newZ_norm = np.sqrt(z_norm_sqrd / u_norm_sqrd)

            adi_step += 1
            muind = np.mod(muind+1, len(ms))
            adi_rel_newZ_norms.append(rel_newZ_norm)

        try:
            if adi_dict['verbose']:
                print ('Number of ADI steps {0} -- \n' +
                       'Relative norm of the update {1}'
                       ).format(adi_step, rel_newZ_norm)
        except KeyError:
            pass  # no verbosity specified - nothing is shown

    return dict(zfac=ufac,
                adi_rel_newZ_norms=adi_rel_newZ_norms)