def optim_test(): n, d = (1000, 50) # n, d = (10, 3) # simple function. Distance to a given matrix # || S - A||_F^2 Y0, _ = np.linalg.qr(crandn(n, d)) P0 = np.diag(randint(1, 1000, d) * .001) A00 = Y0 @ P0 @ Y0.T.conjugate() A0 = hsym(A00) A = (hsym(crandn(n, n)) * 1e-2 + A0) alpha = np.array([1, 1]) print("alpha %s" % str(alpha)) beta = alpha[1] * .1 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) XInit = man.rand() opt_pre = solve_dist_with_man(man, A, X0=XInit, maxiter=20) beta = alpha[1] * 1 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) opt_mid = solve_dist_with_man(man, A, X0=opt_pre, maxiter=20) # opt_mid = opt_pre beta = alpha[1] * 30 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) opt = solve_dist_with_man(man, A, X0=opt_mid, maxiter=500) opt_mat = opt.Y @ opt.P @ opt.Y.T.conjugate() if False: print(A0) print(opt_mat) print(np.max(np.abs(A0 - opt_mat)))
def test_christ_flat(): """now test that christofel preserve metrics: on the flat space d_xi <v M v> = 2 <v M nabla_xi v> v = proj(W) @ (aa W + b) """ alpha = randint(1, 10, 2) * .1 gamma = randint(1, 10, 2) * .1 beta = randint(1, 10, 2)[0] * .1 m = 4 n = 5 p = 3 man = ComplexFixedRank(m, n, p, alpha=alpha, beta=beta, gamma=gamma) S = man.rand() xi = man.randvec(S) aaU = crandn(m*p, m*p) bbU = crandn(m*p) aaV = crandn(n*p, n*p) bbV = crandn(n*p) cc = crandn(p*p, p*p) dd = hsym(crandn(p, p)) def v_func_flat(S): # a function from the manifold # to ambient csp = hsym((cc @ S.P.reshape(-1)).reshape(p, p)) return fr_ambient( (aaU @ S.U.reshape(-1) + bbU).reshape(m, p), (aaV @ S.V.reshape(-1) + bbV).reshape(n, p), csp + dd) vv = v_func_flat(S) # vv is not horizontal dlt = 1e-7 Snew = fr_point( S.U + dlt * xi.tU, S.V + dlt * xi.tV, S.P + dlt * xi.tP) vnew = v_func_flat(Snew) val = man.inner(S, vv) valnew = man.inner(Snew, vnew) d1 = (valnew - val)/dlt dv = (vnew - vv).scalar_mul(1/dlt) nabla_xi_v = dv + man.g_inv( S, man.christoffel_form(S, xi, vv)) # not equal bc vv is not horizontal: nabla_xi_va = dv + man.g_inv( S, super(ComplexFixedRank, man).christoffel_form(S, xi, vv)) print(check_zero(man._vec(nabla_xi_v) - man._vec(nabla_xi_va))) d2 = man.inner(S, vv, nabla_xi_v) print(d1) print(2*d2)
def get_D2(omg): UTomg = X.U.T.conj()@omg.tU VTomg = X.V.T.conj()@omg.tV Piv = X.Pinv D2 = hsym([email protected]@X.Pinv + 1/(al[1]+gm[1])*( al[1]*(Piv@UTomg - UTomg@Piv) + gm[1]*(Piv@VTomg - VTomg@Piv))) return D2
def NTgN_opt(X, B, C, D): Piv = X.Pinv Dp, Dm = hsym(D), ahsym(D) Dp_ = (1/bt-2/(al[1]+gm[1]))*Piv@Dp@Piv + 1/(al[1]+gm[1])*( [email protected]@[email protected]@X.Pinv) Dm_ = al[1]*gm[1]*(al[1]+gm[1])*Dm return al[0]*B, gm[0]*C, Dp_ + Dm_
def v_func_flat(S): # a function from the manifold # to ambient csp = hsym((cc @ S.P.reshape(-1)).reshape(p, p)) return fr_ambient( (aaU @ S.U.reshape(-1) + bbU).reshape(m, p), (aaV @ S.V.reshape(-1) + bbV).reshape(n, p), csp + dd)
def xi_func(S): csp_xi = hsym((cc_xi @ (S.P-S0.P).reshape(-1)).reshape(p, p)) xi_amb = fr_ambient( (aa_xiU @ (S.U-S0.U).reshape(-1) + inct_xi.tU.reshape(-1)).reshape(m, p), (aa_xiV @ (S.V-S0.V).reshape(-1) + inct_xi.tV.reshape(-1)).reshape(n, p), csp_xi + inct_xi.tP) return man.proj(S, xi_amb)
def v_func(S): # a function from the manifold # to ambient csp = hsym((cc @ (S.P-S0.P).reshape(-1)).reshape(p, p)) return man.proj(S, fr_ambient( (aaU @ (S.U-S0.U).reshape(-1) + intcU).reshape(m, p), (aaV @ (S.V-S0.V).reshape(-1) + intcV).reshape(n, p), csp + p_intc))
def v_func(S): # a function from the manifold # to ambient csp = hsym((cc @ (S.P - S0.P).reshape(-1)).reshape(d, d)) return man.proj( S, psd_ambient((aa @ (S.Y - S0.Y).reshape(-1) + intc).reshape(n, d), csp + p_intc))
def test_chris_vectorfields(): # now test that it works on embedded metrics # we test that D_xi (eta g eta) = 2(eta g nabla_xi eta) n, d = (20, 3) alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 1)[0] * .1 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S0 = man.rand() aa = crandn(n * d, n * d) intc = crandn(n * d) cc = crandn(d * d, d * d) p_intc = hsym(crandn(d, d)) inct_xi = man._rand_ambient() aa_xi = crandn(n * d, n * d) cc_xi = crandn(d * d, d * d) def v_func(S): # a function from the manifold # to ambient csp = hsym((cc @ (S.P - S0.P).reshape(-1)).reshape(d, d)) return man.proj( S, psd_ambient((aa @ (S.Y - S0.Y).reshape(-1) + intc).reshape(n, d), csp + p_intc)) SS = psd_point(S0.Y, S0.P) xi = man.proj(SS, inct_xi) nabla_xi_v, dv, cxv = calc_covar_numeric(man, SS, xi, v_func) def xi_func(S): csp_xi = hsym((cc_xi @ (S.P - S0.P).reshape(-1)).reshape(d, d)) xi_amb = psd_ambient((aa_xi @ (S.Y - S0.Y).reshape(-1) + inct_xi.tY.reshape(-1)).reshape(n, d), csp_xi + inct_xi.tP) return man.proj(S, xi_amb) vv = v_func(SS) nabla_v_xi, dxi, cxxi = calc_covar_numeric(man, SS, vv, xi_func) diff = nabla_xi_v - nabla_v_xi print(diff.tY, diff.tP) # now do Lie bracket: dlt = 1e-7 SnewXi = psd_point(SS.Y + dlt * xi.tY, SS.P + dlt * xi.tP) Snewvv = psd_point(SS.Y + dlt * vv.tY, SS.P + dlt * vv.tP) vnewxi = v_func(SnewXi) xnewv = xi_func(Snewvv) dxiv = (vnewxi - vv).scalar_mul(1 / dlt) dvxi = (xnewv - xi).scalar_mul(1 / dlt) diff2 = man.proj(SS, dxiv - dvxi) print(check_zero(man._vec(diff) - man._vec(diff2)))
def N(man, X, B, C, D): al, bt, gm = (man.alpha, man.beta, man.gamma) U, V, Piv = (X.U, X.V, X.Pinv) Dm = ahsym(D) Dp = hsym(D) bkPivDp = Piv @ Dp - Dp @ Piv U0 = null_space(X._U.T.conj()) V0 = null_space(X._V.T.conj()) U0B = U0 @ B V0C = V0 @ C return fr_ambient( U @ (-gm[1]*Dm + 1/(al[1]+gm[1])*bkPivDp)+U0B, V @(al[1]*Dm + 1/(al[1]+gm[1])*bkPivDp)+V0C, 1/bt*Dp)
def test_christ_flat(): """now test that christofel preserve metrics: on the flat space d_xi <v M v> = 2 <v M nabla_xi v> v = proj(W) @ (aa W + b) """ alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 2)[0] * .1 n = 20 d = 3 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S = man.rand() xi = man.randvec(S) xi = man.randvec(S) aa = crandn(n * d, n * d) bb = crandn(n * d) cc = crandn(d * d, d * d) dd = hsym(crandn(d, d)) def v_func_flat(S): # a function from the manifold # to ambient csp = hsym((cc @ S.P.reshape(-1)).reshape(d, d)) return psd_ambient((aa @ S.Y.reshape(-1) + bb).reshape(n, d), csp + dd) vv = v_func_flat(S) dlt = 1e-7 Snew = psd_point(S.Y + dlt * xi.tY, S.P + dlt * xi.tP) vnew = v_func_flat(Snew) val = man.inner_product_amb(S, vv) valnew = man.inner_product_amb(Snew, vnew) d1 = (valnew - val) / dlt dv = (vnew - vv).scalar_mul(1 / dlt) nabla_xi_v = dv + man.g_inv(S, man.christoffel_form(S, xi, vv)) nabla_xi_va = dv + man.g_inv( S, super(ComplexPositiveSemidefinite, man).christoffel_form(S, xi, vv)) print(check_zero(man._vec(nabla_xi_v) - man._vec(nabla_xi_va))) d2 = man.inner(S, vv, nabla_xi_v) print(d1) print(2 * d2)
def test_covariance_deriv(): # now test full: # do covariant derivatives # check that it works, preseving everything n, d = (5, 3) alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 2)[0] * .01 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S = man.rand() aa = crandn(n * d, n * d) cc = crandn(d * d, d * d) icpt = man._rand_ambient() def omg_func(S): csp = hsym((cc @ S.P.reshape(-1)).reshape(d, d)) return psd_ambient( (aa @ S.Y.reshape(-1) + icpt.tY.reshape(-1)).reshape(n, d), csp + icpt.tP) xi = man.randvec(S) egrad = omg_func(S) ecsp = hsym((cc @ xi.tP.reshape(-1)).reshape(d, d)) ehess = psd_ambient((aa @ xi.tY.reshape(-1)).reshape(n, d), ecsp) val1 = man.ehess2rhess(S, egrad, ehess, xi) def rgrad_func(W): return man.proj_g_inv(W, omg_func(W)) if False: first = ehess a = man.J_g_inv(S, egrad) rgrad = man.proj_g_inv(S, egrad) second = man.D_g(S, xi, man.g_inv(S, egrad)).scalar_mul(-1) aout = man.solve_J_g_inv_Jst(S, a) third = man.proj(S, man.D_g_inv_Jst(S, xi, aout)).scalar_mul(-1) fourth = man.christoffel_form(S, xi, rgrad) val1a1 = man.proj_g_inv(S, first + second + fourth) + third print(check_zero(man._vec(val1 - val1a1))) elif True: d_xi_rgrad = num_deriv_amb(man, S, xi, rgrad_func) rgrad = man.proj_g_inv(S, egrad) fourth = man.christoffel_form(S, xi, rgrad) val1a = man.proj(S, d_xi_rgrad) + man.proj_g_inv(S, fourth) print(check_zero(man._vec(val1 - val1a))) # nabla_v_xi, dxi, cxxi val2a, _, _ = calc_covar_numeric(man, S, xi, omg_func) val2, _, _ = calc_covar_numeric(man, S, xi, rgrad_func) # val2_p = project(prj, val2) val2_p = man.proj(S, val2) # print(val1) # print(val2_p) print(check_zero(man._vec(val1) - man._vec(val2_p))) if True: H = xi valrangeA_ = ehess + man.g(S, man.D_proj( S, H, man.g_inv(S, egrad))) - man.D_g( S, H, man.g_inv(S, egrad)) +\ man.christoffel_form(S, H, man.proj_g_inv(S, egrad)) valrangeB = man.proj_g_inv(S, valrangeA_) valrange = man.ehess2rhess_alt(S, egrad, ehess, xi) print(check_zero(man._vec(valrange) - man._vec(val2_p))) print(check_zero(man._vec(valrange) - man._vec(val1))) print(check_zero(man._vec(valrange) - man._vec(valrangeB)))
def xi_func(S): csp_xi = hsym((cc_xi @ (S.P - S0.P).reshape(-1)).reshape(d, d)) xi_amb = psd_ambient((aa_xi @ (S.Y - S0.Y).reshape(-1) + inct_xi.tY.reshape(-1)).reshape(n, d), csp_xi + inct_xi.tP) return man.proj(S, xi_amb)
def v_func_flat(S): # a function from the manifold # to ambient csp = hsym((cc @ S.P.reshape(-1)).reshape(d, d)) return psd_ambient((aa @ S.Y.reshape(-1) + bb).reshape(n, d), csp + dd)
def eta_field(Sin): return man.proj(S, fr_ambient( mU1 @ (Sin.U - S.U) @ m2, mV1 @ (Sin.V - S.V) @ m2, hsym((m_p @ (Sin.P - S.P).reshape(-1)).reshape(p, p)))) + eeta
def solveNTgN(X, Bo, Co, Do): Dp, Dm = hsym(Do), ahsym(Do) Dm_ = 1/(al[1]*gm[1]*(al[1]+gm[1]))*Dm Dp_ = complex_extended_lyapunov(1/bt, 1/(al[1]+gm[1]), X.P, X.P@[email protected]) return 1/al[0]*Bo, 1/gm[0]*Co, Dp_ + Dm_
def eta_field(Sin): return man.proj( S, psd_ambient(m1 @ (Sin.Y - S.Y) @ m2, hsym((m_p @ (Sin.P - S.P).reshape(-1)).reshape( d, d)))) + eeta
def omg_func(S): csp = hsym((cc @ S.P.reshape(-1)).reshape(d, d)) return psd_ambient( (aa @ S.Y.reshape(-1) + icpt.tY.reshape(-1)).reshape(n, d), csp + icpt.tP)
def test_chris_vectorfields(): # now test that it works on embedded metrics # we test that D_xi (eta g eta) = 2(eta g nabla_xi eta) alpha = randint(1, 10, 2) * .1 gamma = randint(1, 10, 2) * .1 beta = randint(1, 10, 2)[0] * .1 m = 4 n = 5 p = 3 man = ComplexFixedRank(m, n, p, alpha=alpha, beta=beta, gamma=gamma) S0 = man.rand() aaU = crandn(m*p, m*p) intcU = crandn(m*p) aaV = crandn(n*p, n*p) intcV = crandn(n*p) cc = crandn(p*p, p*p) p_intc = hsym(crandn(p, p)) inct_xi = man._rand_ambient() aa_xiU = crandn(m*p, m*p) aa_xiV = crandn(n*p, n*p) cc_xi = crandn(p*p, p*p) def v_func(S): # a function from the manifold # to ambient csp = hsym((cc @ (S.P-S0.P).reshape(-1)).reshape(p, p)) return man.proj(S, fr_ambient( (aaU @ (S.U-S0.U).reshape(-1) + intcU).reshape(m, p), (aaV @ (S.V-S0.V).reshape(-1) + intcV).reshape(n, p), csp + p_intc)) SS = fr_point(S0.U, S0.V, S0.P) xi = man.proj(SS, inct_xi) nabla_xi_v, dv, cxv = calc_covar_numeric( man, SS, xi, v_func) def xi_func(S): csp_xi = hsym((cc_xi @ (S.P-S0.P).reshape(-1)).reshape(p, p)) xi_amb = fr_ambient( (aa_xiU @ (S.U-S0.U).reshape(-1) + inct_xi.tU.reshape(-1)).reshape(m, p), (aa_xiV @ (S.V-S0.V).reshape(-1) + inct_xi.tV.reshape(-1)).reshape(n, p), csp_xi + inct_xi.tP) return man.proj(S, xi_amb) vv = v_func(SS) nabla_v_xi, dxi, cxxi = calc_covar_numeric( man, SS, vv, xi_func) diff = nabla_xi_v - nabla_v_xi print(diff.tU, diff.tV, diff.tP) # now do Lie bracket: dlt = 1e-7 SnewXi = fr_point(SS.U+dlt*xi.tU, SS.V+dlt*xi.tV, SS.P+dlt*xi.tP) Snewvv = fr_point(SS.U+dlt*vv.tU, SS.V+dlt*vv.tV, SS.P+dlt*vv.tP) vnewxi = v_func(SnewXi) xnewv = xi_func(Snewvv) dxiv = (vnewxi - vv).scalar_mul(1/dlt) dvxi = (xnewv - xi).scalar_mul(1/dlt) diff2 = man.proj(SS, dxiv-dvxi) print(check_zero(man._vec(diff) - man._vec(diff2)))
def test_rhess_02(): n, d = (50, 3) alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 2)[0] * .1 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S = man.rand() # simple function. Distance to a given matrix # || S - A||_F^2 A = hsym(crandn(n, n)) def f(S): diff = (A - S.Y @ S.P @ S.Y.T.conjugate()) return trace(diff @ diff.T.conjugate()) def df(S): return psd_ambient(-4 * A @ S.Y @ S.P, 2 * (S.P - S.Y.T.conjugate() @ A @ S.Y)) def ehess_form(S, xi, eta): return ( trace(-4 * A @ (xi.tY @ S.P + S.Y @ xi.tP) @ eta.tY.T.conjugate()) + 2 * trace( (xi.tP - xi.tY.T.conjugate() @ A @ S.Y - S.Y.T.conjugate() @ A @ xi.tY) @ eta.tP.T.conjugate())).real def ehess_vec(S, xi): return psd_ambient( -4 * A @ (xi.tY @ S.P + S.Y @ xi.tP), 2 * (xi.tP - xi.tY.T.conjugate() @ A @ S.Y - S.Y.T.conjugate() @ A @ xi.tY)) xxi = man.randvec(S) dlt = 1e-8 Snew = psd_point(S.Y + dlt * xxi.tY, S.P + dlt * xxi.tP) d1 = (f(Snew) - f(S)) / dlt d2 = df(S) print(d1 - man.base_inner_ambient(d2, xxi)) eeta = man.randvec(S) d1 = man.base_inner_ambient((df(Snew) - df(S)), eeta) / dlt ehess_val = ehess_form(S, xxi, eeta) dv2 = ehess_vec(S, xxi) print(man.base_inner_ambient(dv2, eeta)) print(d1, ehess_val, d1 - ehess_val) # now check the formula: ehess = xi (eta_func(f)) - <D_xi eta, df(Y)> # promote eta to a vector field. m1 = crandn(n, n) m2 = crandn(d, d) m_p = crandn(d * d, d * d) def eta_field(Sin): return man.proj( S, psd_ambient(m1 @ (Sin.Y - S.Y) @ m2, hsym((m_p @ (Sin.P - S.P).reshape(-1)).reshape( d, d)))) + eeta # xietaf: should go to ehess(xi, eta) + df(Y) @ etafield) xietaf = (man.base_inner_ambient(df(Snew), eta_field(Snew)) - man.base_inner_ambient(df(S), eta_field(S))) / dlt # appy eta_func to f: should go to tr(m1 @ xxi @ m2 @ df(Y).T) Dxietaf = man.base_inner_ambient( (eta_field(Snew) - eta_field(S)), df(S)) / dlt # this is ehess. should be same as d1 or ehess_val print(xietaf - Dxietaf) print(xietaf - Dxietaf - ehess_val) # now check: rhess. Need to make sure xi, eta in the tangent space. # first compare this with numerical differentiation xi1 = man.proj(S, xxi) eta1 = man.proj(S, eeta) egvec = df(S) ehvec = ehess_vec(S, xi1) rhessvec = man.ehess2rhess(S, egvec, ehvec, xi1) # check it numerically: def rgrad_func(Y): return man.proj_g_inv(Y, df(Y)) # val2a, _, _ = calc_covar_numeric_raw(man, W, xi1, df) val2, _, _ = calc_covar_numeric(man, S, xi1, rgrad_func) val2_p = man.proj(S, val2) # print(rhessvec) # print(val2_p) print(man._vec(rhessvec - val2_p)) rhessval = man.inner_product_amb(S, rhessvec, eta1) print(man.inner_product_amb(S, val2, eta1)) print(rhessval) # check symmetric: ehvec_e = ehess_vec(S, eta1) rhessvec_e = man.ehess2rhess(S, egvec, ehvec_e, eta1) rhessval_e = man.inner_product_amb(S, rhessvec_e, xi1) print(rhessval_e) # the above computed inner_prod(Nabla_xi Pi * df, eta) # in the following check. Extend eta1 to eta_proj # (Pi Nabla_hat Pi g_inv df, g eta) # = D_xi (Pi g_inv df, g eta) - (Pi g_inv df g Pi Nabla_hat eta) def eta_proj(S): return man.proj(S, eta_field(S)) print(check_zero(man._vec(eta1 - eta_proj(S)))) e1 = man.inner(S, man.proj_g_inv(S, df(S)), eta_proj(S)) e1a = man.base_inner_ambient(df(S), eta_proj(S)) print(e1, e1a, e1 - e1a) Snew = psd_point(S.Y + dlt * xi1.tY, S.P + dlt * xi1.tP) e2 = man.inner(Snew, man.proj_g_inv(Snew, df(Snew)), eta_proj(Snew)) e2a = man.base_inner_ambient(df(Snew), eta_proj(Snew)) print(e2, e2a, e2 - e2a) first = (e2 - e1) / dlt first1 = (man.base_inner_ambient(df(Snew), eta_proj(Snew)) - man.base_inner_ambient(df(S), eta_proj(S))) / dlt print(first - first1) val3, _, _ = calc_covar_numeric(man, S, xi1, eta_proj) second = man.inner(S, man.proj_g_inv(S, df(S)), man.proj(S, val3)) second2 = man.inner(S, man.proj_g_inv(S, df(S)), val3) print(second, second2, second - second2) print('same as rhess_val %f' % (first - second))
def test_covariance_deriv(): # now test full: # do covariant derivatives alpha = randint(1, 10, 2) * .1 gamma = randint(1, 10, 2) * .1 beta = randint(1, 10, 2)[0] * .1 m = 4 n = 5 p = 3 man = ComplexFixedRank(m, n, p, alpha=alpha, beta=beta, gamma=gamma) S = man.rand() aaU = crandn(m*p, m*p) aaV = crandn(n*p, n*p) cc = crandn(p*p, p*p) icpt = man._rand_ambient() def omg_func(S): csp = hsym((cc @ S.P.reshape(-1)).reshape(p, p)) return fr_ambient( (aaU @ S.U.reshape(-1) + icpt.tU.reshape(-1)).reshape(m, p), (aaV @ S.V.reshape(-1) + icpt.tV.reshape(-1)).reshape(n, p), csp + icpt.tP) xi = man.randvec(S) egrad = omg_func(S) ecsp = hsym((cc @ xi.tP.reshape(-1)).reshape(p, p)) ehess = fr_ambient( (aaU @ xi.tU.reshape(-1)).reshape(m, p), (aaV @ xi.tV.reshape(-1)).reshape(n, p), ecsp) val1 = man.ehess2rhess(S, egrad, ehess, xi) def rgrad_func(W): return man.proj_g_inv(W, omg_func(W)) if False: first = ehess a = man.J_g_inv(S, egrad) rgrad = man.proj_g_inv(S, egrad) second = man.D_g( S, xi, man.g_inv(S, egrad)).scalar_mul(-1) aout = man.solve_J_g_inv_Jst(S, a) third = man.proj(S, man.D_g_inv_Jst(S, xi, aout)).scalar_mul(-1) fourth = man.christoffel_form(S, xi, rgrad) val1a1 = man.proj_g_inv(S, first + second + fourth) + third print(check_zero(man._vec(val1-val1a1))) elif True: d_xi_rgrad = num_deriv_amb(man, S, xi, rgrad_func) rgrad = man.proj_g_inv(S, egrad) fourth = man.christoffel_form(S, xi, rgrad) val1a = man.proj(S, d_xi_rgrad) + man.proj_g_inv(S, fourth) print(check_zero(man._vec(val1-val1a))) # nabla_v_xi, dxi, cxxi val2a, _, _ = calc_covar_numeric(man, S, xi, omg_func) val2, _, _ = calc_covar_numeric(man, S, xi, rgrad_func) # val2_p = project(prj, val2) val2_p = man.proj(S, val2) # print(val1) # print(val2_p) print(check_zero(man._vec(val1)-man._vec(val2_p))) if True: H = xi valrangeA_ = ehess + man.g(S, man.D_proj( S, H, man.g_inv(S, egrad))) - man.D_g( S, H, man.g_inv(S, egrad)) +\ man.christoffel_form(S, H, man.proj_g_inv(S, egrad)) valrangeB = man.proj_g_inv(S, valrangeA_) valrange = man.ehess2rhess(S, egrad, ehess, xi) print(check_zero(man._vec(valrange)-man._vec(val2_p))) print(check_zero(man._vec(valrange)-man._vec(val1))) print(check_zero(man._vec(valrange)-man._vec(valrangeB)))
def omg_func(S): csp = hsym((cc @ S.P.reshape(-1)).reshape(p, p)) return fr_ambient( (aaU @ S.U.reshape(-1) + icpt.tU.reshape(-1)).reshape(m, p), (aaV @ S.V.reshape(-1) + icpt.tV.reshape(-1)).reshape(n, p), csp + icpt.tP)
def test_J(man, X): from scipy.linalg import null_space al = man.alpha bt = man.beta gm = man.gamma p = man.p # U, V, P, Piv = (X.U, X.V, X.P, X.Pinv) jjmat = np.zeros((8*p*p, man.tdim)) # this map is not full onto - but just check tangent maps to zero for i in range(man.tdim): Ux = zeros(man.tdim) Ux[i] = 1 omg = man._unvec(Ux) jjmat[:, i] = np.concatenate( [cvec(stU(X, omg)), cvec(stV(X, omg)), cvec(symP(X, omg)), cvec(Hz(man, X, omg))]) # nsp = null_space(jjmat) # prj = nsp @ la.solve(nsp.T.conj() @ nsp, nsp.T.conj()) omg = man._rand_ambient() eta = man.proj(X, omg) def rand_vertical(): oo = crandn(man.p, man.p) oo = oo - oo.T.conj() return fr_ambient( X.U @ oo, X.V @ oo, -oo @ X.P + X.P @oo) vv = rand_vertical() print(man.inner(X, vv, eta)) nmat = make_N_mat(man, X) gmat = make_g_mat(man, X) NTgN = nmat.T @ gmat @ nmat bcd = nmat.T @ gmat @ man._vec(omg) m, n, p = (man.m, man.n, man.p) B = cunvec(bcd[:2*(m-p)*p], (m-p, p)) C = cunvec(bcd[2*(m-p)*p:2*(m+n-2*p)*p], (n-p, p)) D = cunvec(bcd[2*(m+n-2*p)*p:], (p, p)) Dp = hsym(D) Dm = ahsym(D) Dm2 = al[1]*gm[1]*ahsym(X.V.T.conj()@omg.tV - X.U.T.conj()@omg.tU) pprint(Dm - Dm2) U0 = null_space(X._U.T.conj()) V0 = null_space(X._V.T.conj()) B2 = al[0]*U0.T.conj()@omg.tU pprint(B-B2) C2 = gm[0]*V0.T.conj()@omg.tV pprint(C-C2) Dmsolve = Dm2/(al[1]+gm[1])/al[1]/gm[1] pprint(Dmsolve - (1/(al[1]+gm[1]))*( ahsym(X.V.T.conj()@omg.tV - X.U.T.conj()@omg.tU))) Dpsolve = complex_extended_lyapunov(1/bt, 1/(al[1]+gm[1]), X.P, X.P@[email protected]) Drecv = (1/bt-2/(al[1]+gm[1]))*X.Pinv@[email protected] + 1/(al[1]+gm[1])*( [email protected]@[email protected]@X.Pinv) pprint(Drecv - Dp) def get_D2(omg): UTomg = X.U.T.conj()@omg.tU VTomg = X.V.T.conj()@omg.tV Piv = X.Pinv D2 = hsym([email protected]@X.Pinv + 1/(al[1]+gm[1])*( al[1]*(Piv@UTomg - UTomg@Piv) + gm[1]*(Piv@VTomg - VTomg@Piv))) return D2 Dp2 = get_D2(omg) print(check_zero(Dp - Dp2)) def NTgN_opt(X, B, C, D): Piv = X.Pinv Dp, Dm = hsym(D), ahsym(D) Dp_ = (1/bt-2/(al[1]+gm[1]))*Piv@Dp@Piv + 1/(al[1]+gm[1])*( [email protected]@[email protected]@X.Pinv) Dm_ = al[1]*gm[1]*(al[1]+gm[1])*Dm return al[0]*B, gm[0]*C, Dp_ + Dm_ def solveNTgN(X, Bo, Co, Do): Dp, Dm = hsym(Do), ahsym(Do) Dm_ = 1/(al[1]*gm[1]*(al[1]+gm[1]))*Dm Dp_ = complex_extended_lyapunov(1/bt, 1/(al[1]+gm[1]), X.P, X.P@[email protected]) return 1/al[0]*Bo, 1/gm[0]*Co, Dp_ + Dm_ def testNTgN(man, X): m, n, p = (man.m, man.n, man.p) B0 = crandn(m-p, p) C0 = crandn(n-p, p) D0 = crandn(p, p) out1 = NTgN @ np.concatenate( [cvec(B0), cvec(C0), cvec(D0)]) out2a = NTgN_opt(X, B0, C0, D0) out2 = np.concatenate( [cvec(out2a[0]), cvec(out2a[1]), cvec(out2a[2])]) print(check_zero(out1-out2)) out2b = solveNTgN(X, *out2a) print(check_zero(out2b[2]-D0)) print(check_zero(out2b[1]-C0)) print(check_zero(out2b[0]-B0)) Bs, Cs, Ds = solveNTgN(X, B, C, D) # the formulas Using the orthogonal complements of U and V # Dsm = ahsym(Ds) # Dsp = hsym(Ds) Bf = U0.T.conj() @ omg.tU Cf = V0.T.conj() @ omg.tV print(check_zero(Bf-Bs)) print(check_zero(Cf-Cs)) Dfm = 1/(al[1]+gm[1])*ahsym(X.V.T.conj()@omg.tV - X.U.T.conj()@omg.tU) UTomg = X.U.T.conj()@omg.tU VTomg = X.V.T.conj()@omg.tV Dfp = complex_extended_lyapunov( 1/bt, 1/(al[1]+gm[1]), X.P, hsym(omg.tP + 1/(al[1]+gm[1])*( al[1]*([email protected] - X.P@UTomg) + gm[1]*([email protected] - X.P@VTomg))), X.evl, X.evec) ee1 = N(man, X, Bf, Cf, Dfp+Dfm) print(check_zero(Ds - Dfm - Dfp)) print(check_zero(man._vec(ee1-eta)))