def test_comp_frobnorm_factored_difference(self): """check the computation of the frobenius norm """ U = self.U Z = self.Z # test the branch that returns only the difference my_frob_zmu = lau.comp_sqfnrm_factrd_diff(U, Z) frob_zmu = np.linalg.norm(np.dot(U, U.T) - np.dot(Z, Z.T), 'fro') self.assertTrue(np.allclose(frob_zmu * frob_zmu, my_frob_zmu)) # test the branch that returns difference, norm z1, norm z2 my_frob_zmu, norm_u, norm_z = \ lau.comp_sqfnrm_factrd_diff(U, Z, ret_sing_norms=True) frob_zmu = np.linalg.norm(np.dot(U, U.T) - np.dot(Z, Z.T), 'fro') frob_u = np.linalg.norm(np.dot(U, U.T)) frob_z = np.linalg.norm(np.dot(Z, Z.T)) self.assertTrue(np.allclose(frob_zmu * frob_zmu, my_frob_zmu)) self.assertTrue(np.allclose(norm_u, frob_u ** 2)) self.assertTrue(np.allclose(norm_z, frob_z ** 2))
def test_comp_frobnorm_factored_difference(self): """check the computation of the frobenius norm """ U = self.U Z = self.Z # test the branch that returns only the difference my_frob_zmu = lau.comp_sqfnrm_factrd_diff(U, Z) frob_zmu = np.linalg.norm(np.dot(U, U.T) - np.dot(Z, Z.T), 'fro') self.assertTrue(np.allclose(frob_zmu * frob_zmu, my_frob_zmu)) # test the branch that returns difference, norm z1, norm z2 my_frob_zmu, norm_u, norm_z = \ lau.comp_sqfnrm_factrd_diff(U, Z, ret_sing_norms=True) frob_zmu = np.linalg.norm(np.dot(U, U.T) - np.dot(Z, Z.T), 'fro') frob_u = np.linalg.norm(np.dot(U, U.T)) frob_z = np.linalg.norm(np.dot(Z, Z.T)) self.assertTrue(np.allclose(frob_zmu * frob_zmu, my_frob_zmu)) self.assertTrue(np.allclose(norm_u, frob_u**2)) self.assertTrue(np.allclose(norm_z, frob_z**2))
def test_compress_algric_Z(self): Z = pru.proj_alg_ric_newtonadi(mmat=self.M, amat=self.F, jmat=self.J, bmat=self.bmat, wmat=self.W, z0=self.bmat, nwtn_adi_dict= self.nwtn_adi_dict)['zfac'] Zred = pru.compress_Zsvd(Z, thresh=self.comprthresh) print '\ncompressing Z from {0} to {1} columns:'.\ format(Z.shape[1], Zred.shape[1]) difn, zzn, zzrn = \ lau.comp_sqfnrm_factrd_diff(Z, Zred, ret_sing_norms=True) print '\n || ZZ - ZZred||_F || / ||ZZ|| = {0}\n'.\ format(np.sqrt(difn/zzn)) vec = np.random.randn(Z.shape[0], 1) print '||(ZZ_red - ZZ )*testvec|| / ||ZZ*testvec|| = {0}'.\ format(np.linalg.norm(np.dot(Z, np.dot(Z.T, vec)) - np.dot(Zred, np.dot(Zred.T, vec))) / np.linalg.norm(np.dot(Zred, np.dot(Zred.T, vec)))) self.assertTrue(True)
def test_compress_algric_Z(self): Z = pru.proj_alg_ric_newtonadi( mmat=self.M, amat=self.F, jmat=self.J, bmat=self.bmat, wmat=self.W, z0=self.bmat, nwtn_adi_dict=self.nwtn_adi_dict)['zfac'] Zred = pru.compress_Zsvd(Z, thresh=self.comprthresh) print '\ncompressing Z from {0} to {1} columns:'.\ format(Z.shape[1], Zred.shape[1]) difn, zzn, zzrn = \ lau.comp_sqfnrm_factrd_diff(Z, Zred, ret_sing_norms=True) print '\n || ZZ - ZZred||_F || / ||ZZ|| = {0}\n'.\ format(np.sqrt(difn/zzn)) vec = np.random.randn(Z.shape[0], 1) print '||(ZZ_red - ZZ )*testvec|| / ||ZZ*testvec|| = {0}'.\ format(np.linalg.norm(np.dot(Z, np.dot(Z.T, vec)) - np.dot(Zred, np.dot(Zred.T, vec))) / np.linalg.norm(np.dot(Zred, np.dot(Zred.T, vec)))) self.assertTrue(True)
def proj_alg_ric_newtonadi(mmat=None, amat=None, jmat=None, bmat=None, wmat=None, z0=None, mtxoldb=None, transposed=False, nwtn_adi_dict=dict(adi_max_steps=150, adi_newZ_reltol=1e-5, nwtn_max_steps=14, nwtn_upd_reltol=1e-8), **kw): """ solve the projected algebraic ricc via newton adi `M.T*X*A + A.T*X*M - M.T*X*B*B.T*X*M + J(Y) = -WW.T` `JXM = 0 and M.TXJ.T = 0` If `mtxb` is given, (e.g. as the feedback computed in a previous step of a Newton iteration), the coefficient matrix with feedback `A.T <- A.T - mtxb*b` is considered """ if transposed: mt, at = mmat, amat else: mt, at = mmat.T, amat.T loctransposed = True if sps.isspmatrix(wmat): wmat = np.array(wmat.todense()) znc = z0 nwtn_stp, upd_fnorm, upd_fnorm_n = 0, None, None nwtn_upd_fnorms = [] # import pdb # pdb.set_trace() while nwtn_stp < nwtn_adi_dict['nwtn_max_steps']: if znc is None: # i.e., if z0 was None rhsadi = wmat mtxbt = None else: mtxb = mt * np.dot(znc, lau.mm_dnssps(znc.T, bmat)) mtxbt = mtxb.T rhsadi = np.hstack([mtxb, wmat]) # to avoid a dense matrix we use the smw formula # to compute (A-UV).-T # for the factorization mTxg.T = tb * mTxtb.T = U*V # and we add the previous feedback: if mtxoldb is not None: mtxbt = mtxbt + mtxoldb.T znn = solve_proj_lyap_stein(amat=at, mmat=mt, jmat=jmat, wmat=rhsadi, umat=bmat, vmat=mtxbt, transposed=loctransposed, nwtn_adi_dict=nwtn_adi_dict)['zfac'] if nwtn_adi_dict['full_upd_norm_check']: if znc is None: # there was no initial guess znc = 0*znn upd_fnorm = lau.comp_sqfnrm_factrd_diff(znn, znc) upd_fnorm = np.sqrt(np.abs(upd_fnorm)) else: if znc is None: # there was no initial guess znc = 0*znn vec = np.random.randn(znn.shape[0], 1) vecn1 = comp_diff_zzv(znn, znc, vec) vec = np.random.randn(znn.shape[0], 1) vecn2 = comp_diff_zzv(znn, znc, vec) vec = np.random.randn(znn.shape[0], 1) # to make the estimate relative vecn3 = np.linalg.norm(np.dot(znn, np.dot(znn.T, vec))) if (vecn2 + vecn1)/vecn3 < 8e-9: upd_fnorm, nzn, nzc = lau.\ comp_sqfnrm_factrd_diff(znn, znc, ret_sing_norms=True) upd_fnorm_n = np.sqrt(np.abs(upd_fnorm) / np.abs(nzn)) nwtn_upd_fnorms.append(upd_fnorm_n) try: if np.allclose(upd_fnorm_n, upd_fnorm): print 'no more change in the norm of the update... break' break except TypeError: pass if nwtn_adi_dict['full_upd_norm_check']: upd_fnorm = upd_fnorm_n elif (vecn2 + vecn1)/vecn3 < 8e-9: upd_fnorm = upd_fnorm_n try: if nwtn_adi_dict['verbose']: print ('Newton ADI step: {1} -- ' + 'rel f norm of update: {0}').format(upd_fnorm, nwtn_stp + 1) if not nwtn_adi_dict['full_upd_norm_check']: print ('btw, we decided whether to compute the actual ' + 'norm on the base of estimates:') print '|| upd * vec || / || vec || = {0}'.format(vecn2) print '||Z*vec|| = {0}'.format(vecn3) except KeyError: pass # no verbosity specified - nothing is shown znc = znn nwtn_stp += 1 if (upd_fnorm is not None and upd_fnorm < nwtn_adi_dict['nwtn_upd_reltol']): break return dict(zfac=znn, nwtn_upd_fnorms=nwtn_upd_fnorms)