def test_projection(man, Y): print("test projection") N = 10 ret = np.zeros(N) for i in range(N): U = man._rand_ambient() Upr = man.proj(Y, U) ret[i] = check_zero(man._vec_range_J(man.J(Y, Upr))) # print(ret) if check_zero(ret) > 1e-9: print("not all works") else: print("All good") print("test randvec") ret_pr = np.zeros(N) for i in range(N): XX = man.rand() H = man.randvec(XX) U = man._rand_ambient() Upr = man.proj(XX, U) ret_pr[i] = man.inner(XX, U, H) - man.inner(XX, Upr, H) ret[i] = (check_zero(XX.T.conjugate() @ H + H.T.conjugate() @ XX)) print(ret) if check_zero(ret) > 1e-9: print("not all works") else: print("All good") print("check inner of projection = inner of original") print(ret_pr) if check_zero(ret_pr) > 1e-9: print("not all works") else: print("All good")
def test_N_proj(): alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 1)[0] * .02 n = 10 d = 6 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S = man.rand() """ def proj_range_alt(man, S, U): # projection. U is in ambient # return one in tangent al1 = man.alpha[1] beta = man.beta YTU = [email protected] D0 = sym(U.tP + [email protected] - S.P@YTU) D = _extended_lyapunov(al1, beta, S.P, D0, S.evl, S.evec) return psd_ambient( beta*S.Y@(S.Pinv@[email protected]) + U.tY - S.Y@([email protected]), al1*D) """ U = man.randvec(S) Upr1 = super(ComplexPositiveSemidefinite, man).proj(S, U) Upr2 = man.proj(S, U) Upr3 = man.proj_range_alt(S, U) print(check_zero(Upr1.tP - Upr2.tP)) print(check_zero(Upr1.tY - Upr2.tY)) print(check_zero(Upr1.tY - Upr3.tY)) print(check_zero(Upr1.tP - Upr3.tP))
def test_vectorize(): from ManNullRange.manifolds.tools import cvech, cunvech, cvecah, cunvecah p = 10 mat = crandn(p, p) mat += mat.T.conjugate() v = cvech(mat) mat2 = cunvech(v) print(check_zero(mat - mat2)) # check inner product: for i in range(p * p): v = zeros(p * p) v[i] = 1 h = cunvech(v) assert (np.abs(trace(h @ h.T.conjugate()).real - 1) < 1e-10) # now do skew mat = crandn(p, p) mat -= mat.T.conjugate() v = cvecah(mat) mat2 = cunvecah(v) print(check_zero(mat - mat2)) for i in range(p * p): v = zeros(p * p) v[i] = 1 h = cunvecah(v) assert (np.abs(trace(h @ h.T.conjugate()).real - 1) < 1e-10)
def test_covariance_deriv(): # now test full: # do covariant derivatives # check that it works, preseving everything dvec = np.array([10, 3, 2, 3]) p = dvec.shape[0] - 1 alpha = randint(1, 10, (p, p + 1)) * .1 man = ComplexFlag(dvec, alpha=alpha) n = man.n d = man.d Y = man.rand() slp = np.random.randn(n * d) aa = np.random.randn(n * d, n * d) def omg_func(Y): return (aa @ Y.reshape(-1) + slp).reshape(n, d) xi = man.randvec(Y) egrad = omg_func(Y) ehess = (aa @ xi.reshape(-1)).reshape(n, d) val1 = man.ehess2rhess(Y, egrad, ehess, xi) def rgrad_func(W): return man.proj_g_inv(W, omg_func(W)) if False: d_xi_rgrad = num_deriv(man, Y, xi, rgrad_func) rgrad = man.proj_g_inv(Y, egrad) fourth = man.christoffel_form(Y, xi, rgrad) val1c = man.proj(Y, d_xi_rgrad) + man.proj_g_inv(Y, fourth) if False: first = ehess a = man.J(Y, man.g_inv(Y, egrad)) rgrad = man.proj_g_inv(Y, egrad) second = -man.D_g(Y, xi, man.g_inv(Y, egrad)) aout = man.solve_J_g_inv_Jst(Y, a) third = -man.proj(Y, man.D_g_inv_Jst(Y, xi, aout)) fourth = man.christoffel_form(Y, xi, rgrad) val1a = man.proj_g_inv(Y, first + second + fourth) + third d_xi_rgrad = num_deriv(man, Y, xi, rgrad_func) rgrad = man.proj_g_inv(Y, egrad) fourth = man.christoffel_form(Y, xi, rgrad) val1b = man.proj(Y, d_xi_rgrad) + man.proj_g_inv(Y, fourth) print(check_zero(val1 - val1b)) # nabla_v_xi, dxi, cxxi # val2a, _, _ = calc_covar_numeric(man, Y, xi, omg_func) val2, _, _ = calc_covar_numeric(man, Y, xi, rgrad_func) # val2_p = project(prj, val2) val2_p = man.proj(Y, val2) # print(val1) # print(val2_p) print(check_zero(val1 - val2_p))
def test_covariance_deriv(): # now test full: # do covariant derivatives # check that it works, preseving everything n, d = (5, 3) A = make_sym_pos(n) B = make_sym_pos(d) man = RealStiefelWoodbury(n, d, A=A, B=B) Y = man.rand() slp = np.random.randn(n * d) aa = np.random.randn(n * d, n * d) def omg_func(Y): return (aa @ Y.reshape(-1) + slp).reshape(n, d) xi = man.randvec(Y) egrad = omg_func(Y) ehess = (aa @ xi.reshape(-1)).reshape(n, d) val1 = man.ehess2rhess(Y, egrad, ehess, xi) if False: val1a = man.ehess2rhess_alt(Y, egrad, ehess, xi) print(check_zero(val1 - val1a)) def rgrad_func(W): return man.proj_g_inv(W, omg_func(W)) if False: first = ehess a = man.J(Y, man.g_inv(Y, egrad)) rgrad = man.proj_g_inv(Y, egrad) second = -man.D_g(Y, xi, man.g_inv(Y, egrad)) aout = man.solve_J_g_inv_Jst(Y, a) third = -man.proj(Y, man.D_g_inv_Jst(Y, xi, aout)) fourth = man.christoffel_form(Y, xi, rgrad) val1a = man.proj_g_inv(Y, first + second + fourth) + third d_xi_rgrad = num_deriv(man, Y, xi, rgrad_func) rgrad = man.proj_g_inv(Y, egrad) fourth = man.christoffel_form(Y, xi, rgrad) val1b = man.proj(Y, d_xi_rgrad) + man.proj_g_inv(Y, fourth) print(check_zero(val1 - val1b)) # nabla_v_xi, dxi, cxxi val2a, _, _ = calc_covar_numeric(man, Y, xi, omg_func) val2, _, _ = calc_covar_numeric(man, Y, xi, rgrad_func) # val2_p = project(prj, val2) val2_p = man.proj(Y, val2) # print(val1) # print(val2_p) print(val1 - val2_p)
def testN(man, X): m, n, p = (man.m, man.n, man.p) B = crandn(m-p, p) C = crandn(n-p, p) D = crandn(p, p) ee = N(man, X, B, C, D) print(check_zero(stU(X, ee))) print(check_zero(stV(X, ee))) print(check_zero(symP(X, ee))) print(check_zero(Hz(man, X, ee))) nmat = make_N_mat(man, X) ee2 = man._unvec(nmat @ np.concatenate( [cvec(B), cvec(C), cvec(D)])) print(check_zero(man._vec(ee - ee2)))
def testN(man, X): m, n, p = (man.m, man.n, man.p) B = randn(m - p, p) C = randn(n - p, p) D = randn(p, p) ee = N(man, X, B, C, D) print(check_zero(stU(X, ee))) print(check_zero(stV(X, ee))) print(check_zero(symP(X, ee))) print(check_zero(Hz(man, X, ee))) nmat = make_N_mat(man, X) ee2 = man._unvec(nmat @ np.concatenate( [B.reshape(-1), C.reshape(-1), D.reshape(-1)])) print(check_zero(man._vec(ee - ee2)))
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))
def testNTgN(man, X): m, n, p = (man.m, man.n, man.p) B0 = randn(m - p, p) C0 = randn(n - p, p) D0 = randn(p, p) out1 = NTgN @ np.concatenate( [B0.reshape(-1), C0.reshape(-1), D0.reshape(-1)]) out2a = NTgN_opt(X, B0, C0, D0) out2 = np.concatenate( [out2a[0].reshape(-1), out2a[1].reshape(-1), out2a[2].reshape(-1)]) 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))
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 diff_i_j(i, j): U = zeros_like(Y) U[ii, jj] = 1 ju = man.J(Y, U) asum = 0 gdc = man._g_idx for r, s in ju: br, er = gdc[r] if r == s: asum += check_zero(ju[r, r] - alpha[r - 1, r] * Y[:, br:er].T.conjugate() @ U[:, br:er]) else: bs, es = gdc[s] asum += check_zero(ju[r, s] - Y[:, br:er].T.conjugate() @ U[:, bs:es] - U[:, br:er].T.conjugate() @ Y[:, bs:es]) return asum / len(ju)
def solve_dist_with_man(man, A, X0, maxiter, check_deriv=False): import pymanopt from pymanopt import Problem from pymanopt.solvers import TrustRegions @pymanopt.function.Callable def cost(S): """ if not(S.P.dtype == np.float): raise(ValueError("Non real")) """ diff = (A - S.Y @ S.P @ S.Y.T.conjugate()) val = trace(diff @ diff.T.conjugate()).real # print('val=%f' % val) return val @pymanopt.function.Callable def egrad(S): return psd_ambient(-4 * A @ S.Y @ S.P, 2 * (S.P - S.Y.T.conjugate() @ A @ S.Y)) @pymanopt.function.Callable def ehess(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)) if check_deriv: xi = man.randvec(X0) dlt = 1e-7 S1 = psd_point(X0.Y + dlt * xi.tY, X0.P + dlt * xi.tP) print((cost(S1) - cost(X0)) / dlt) print(man.base_inner_ambient(egrad(X0), xi)) h1 = egrad(S1) - egrad(X0) h1 = psd_ambient(h1.tY / dlt, h1.tP / dlt) h2 = ehess(X0, xi) print(check_zero(h1.tY - h2.tY) + check_zero(h1.tP - h2.tP)) return prob = Problem(man, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=maxiter, use_rand=False) opt = solver.solve(prob, x=X0, Delta_bar=250) return opt
def test_Jst(man, S, jmat): print("test JST") for ii in range(10): a = man._rand_range_J() avec = man._vec_range_J(a) jtout = jmat.T @ avec jtout2 = man._vec(man.Jst(S, a)) # print(np.where(np.abs(jtout - jtout2) > 1e-9)) diff = check_zero(jtout - jtout2) print(diff)
def test_Jst(man, Y, jmat): print("test JST") for ii in range(10): a = man._rand_range_J() avec = man._vec_range_J(a) jtout = man._unvec(jmat.T.conjugate() @ avec) jtout2 = man.Jst(Y, a) # print(np.where(np.abs(jtout - jtout2) > 1e-9)) diff = check_zero(jtout - jtout2) print(diff)
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 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) dvec = np.array([10, 3, 2, 3]) p = dvec.shape[0]-1 alpha = randint(1, 10, (p, p+1)) * .1 man = RealFlag(dvec, alpha=alpha) n = man.n d = man.d slp = randn(n*d) Y0 = man.rand() slpxi = randn(n*d) aa = randn(n*d, n*d) aaxi = randn(n*d, n*d) def v_func(Y): return man.proj(Y, (aa @ (Y-Y0).reshape(-1) + slp).reshape(n, d)) YY = Y0.copy() xi = man.proj(YY, slpxi.reshape(n, d)) nabla_xi_v, dv, cxv = calc_covar_numeric( man, YY, xi, v_func) def xi_func(Y): return man.proj(Y, (aaxi @ (Y-Y0).reshape(-1) + slpxi).reshape(n, d)) vv = v_func(YY) nabla_v_xi, dxi, cxxi = calc_covar_numeric( man, YY, vv, xi_func) diff = nabla_xi_v - nabla_v_xi # print(diff) # now do Lie bracket: dlt = 1e-7 YnewXi = YY + dlt * xi Ynewvv = YY + dlt * vv vnewxi = v_func(YnewXi) xnewv = xi_func(Ynewvv) dxiv = (vnewxi - vv)/dlt dvxi = (xnewv - xi)/dlt diff2 = man.proj(YY, dxiv-dvxi) print(check_zero(diff - diff2))
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_projection(man, X): print("test projection") NN = 10 ret = np.zeros(NN) for i in range(NN): omg = man._rand_ambient() Upr = man.proj(X, omg) ret[i] = check_zero( np.concatenate([ stU(X, Upr).reshape(-1), stV(X, Upr).reshape(-1), symP(X, Upr).reshape(-1), Hz(man, X, Upr).reshape(-1) ])) print(ret) if check_zero(ret) > 1e-8: print("not all works") else: print("All good") print("test randvec") ret_pr = np.zeros(NN) for i in range(NN): XX = man.rand() H = man.randvec(XX) Ue = man._rand_ambient() Upr = man.proj(XX, Ue) ret_pr[i] = man.inner(XX, Ue, H) - man.inner(XX, Upr, H) ret[i] = check_zero(stU(XX, H)) + check_zero(stV(XX, H)) +\ check_zero(symP(XX, H)) + check_zero(Hz(man, XX, H)) print(ret) if check_zero(ret) > 1e-9: print("not all works") else: print("All good") print("check inner of projection = inner of original") print(ret_pr) if check_zero(ret_pr) > 1e-8: print("not all works") else: print("All good")
def test_lyapunov(): alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 1)[0] * .02 n = 5 d = 3 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S = man.rand() P = S.P B = crandn(d, d) alpha1 = alpha[1] def L(X, P): Piv = la.inv(P) return (alpha1 - 2 * beta) * X + beta * (P @ X @ Piv + Piv @ X @ P) X = extended_lyapunov(alpha1, beta, P, B) # L(X, P) print(check_zero(B - L(X, P)))
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 = (5, 3) A = make_sym_pos(n) B = make_sym_pos(d) man = RealStiefelWoodbury(n, d, A=A, B=B) slp = randn(n * d) Y0 = man.rand() slpxi = randn(n * d) aa = randn(n * d, n * d) aaxi = randn(n * d, n * d) def v_func(Y): return man.proj(Y, (aa @ (Y - Y0).reshape(-1) + slp).reshape(n, d)) YY = Y0.copy() xi = man.proj(YY, slpxi.reshape(n, d)) nabla_xi_v, dv, cxv = calc_covar_numeric(man, YY, xi, v_func) def xi_func(Y): return man.proj(Y, (aaxi @ (Y - Y0).reshape(-1) + slpxi).reshape(n, d)) vv = v_func(YY) nabla_v_xi, dxi, cxxi = calc_covar_numeric(man, YY, vv, xi_func) diff = nabla_xi_v - nabla_v_xi print(diff) # now do Lie bracket: dlt = 1e-7 YnewXi = YY + dlt * xi Ynewvv = YY + dlt * vv vnewxi = v_func(YnewXi) xnewv = xi_func(Ynewvv) dxiv = (vnewxi - vv) / dlt dvxi = (xnewv - xi) / dlt diff2 = man.proj(YY, dxiv - dvxi) print(check_zero(diff - diff2))
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 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_all_projections(): alpha = randint(1, 10, 2) * .1 beta = randint(1, 10, 1)[0] * .02 n = 5 d = 3 man = ComplexPositiveSemidefinite(n, d, alpha=alpha, beta=beta) print(man) S = man.rand() test_inner(man, S) test_J(man, S) # now check metric, Jst etc # check Jst: vectorize the operator J then compare Jst with jmat.T jmat = make_j_mat(man, S) test_Jst(man, S, jmat) ginv_mat = make_g_inv_mat(man, S) ee = man._rand_ambient() g1 = man._unvec(ginv_mat @ man._vec(ee)) print(check_zero(man.g_inv(S, ee).tP - g1.tP)) print(check_zero(man.g_inv(S, ee).tY - g1.tY)) # test g_inv_Jst for ii in range(10): a = man._rand_range_J() avec = man._vec_range_J(a) jtout = ginv_mat @ jmat.T @ avec jtout2 = man._vec(man.g_inv_Jst(S, a)) diff = check_zero(jtout - jtout2) print(diff) # test projection test_projection(man, S) # now diff projection for i in range(1): e = man._rand_ambient() S1 = man.rand() xi = man.randvec(S1) dlt = 1e-7 S2 = psd_point(S1.Y + dlt * xi.tY, S1.P + dlt * xi.tP) # S = psd_point(S1.Y, S1.P) d1P = (man.proj(S2, e).tP - man.proj(S1, e).tP) / dlt d1Y = (man.proj(S2, e).tY - man.proj(S1, e).tY) / dlt d2 = man.D_proj(S1, xi, e) print(check_zero(d1P - d2.tP) + check_zero(d1Y - d2.tY)) for i in range(10): a = man._rand_range_J() eta = man._rand_ambient() print(man.base_inner_ambient(eta, man.Jst(S, a))) print((trace((eta.tP.T.conjugate() - eta.tP) @ a['P'] + (man.alpha[1] * eta.tY.T.conjugate() @ S.Y + man.beta * (S.Pinv @ eta.tP.T.conjugate() - eta.tP.T.conjugate() @ S.Pinv)) @ a['YP'])).real) print((trace(2 * eta.tP.T.conjugate() @ a['P']) + trace( (man.alpha[1] * eta.tY.T.conjugate() @ S.Y + man.beta * (S.Pinv @ eta.tP.T.conjugate() - eta.tP.T.conjugate() @ S.Pinv)) @ a['YP'])).real) print((trace( eta.tP.T.conjugate() @ (2 * a['P'] + man.beta * (a['YP'] @ S.Pinv - S.Pinv @ a['YP']))) + trace(eta.tY.T.conjugate() @ (man.alpha[1] * S.Y @ a['YP'])) ).real) print(man.base_inner_E_J(man.J(S, eta), a)) print(( trace((eta.tP - eta.tP.T.conjugate()).T.conjugate() @ a['P'] + (man.alpha[1] * S.Y.T.conjugate() @ eta.tY + man.beta * (eta.tP @ S.Pinv - S.Pinv @ eta.tP)).T.conjugate() @ a['YP'] )).real) for i in range(10): a = man._rand_range_J() beta = man.beta alf = man.alpha anew1 = man.J(S, man.g_inv_Jst(S, a)) anew = {} saYP = a['YP'] + a['YP'].T.conjugate() anew['P'] = 4 / beta * S.P @ a['P'] @ S.P + S.P @ saYP - saYP @ S.P anew['YP'] = alf[1] * a['YP'] + beta * ( ((2 / man.beta) * S.P @ a['P'] @ S.P + S.P @ a['YP'] - a['YP'] @ S.P) @ S.Pinv - S.Pinv @ ( (2 / man.beta) * S.P @ a['P'] @ S.P + S.P @ a['YP'] - a['YP'] @ S.P)) anew['YP'] = alf[1] * a['YP'] + ( (2 * S.P @ a['P'] + beta * S.P @ a['YP'] @ S.Pinv - beta * a['YP']) - (2 * a['P'] @ S.P + beta * a['YP'] - beta * S.Pinv @ a['YP'] @ S.P)) anew['YP'] = (alf[1] - 2 * beta) * a['YP'] + ( (2 * S.P @ a['P'] + beta * S.P @ a['YP'] @ S.Pinv) - (2 * a['P'] @ S.P - beta * S.Pinv @ a['YP'] @ S.P)) anew['YP'] = (alf[1] - 2 * beta) * a['YP'] + ( (2 * S.P @ a['P'] - 2 * a['P'] @ S.P + beta * S.P @ a['YP'] @ S.Pinv + beta * S.Pinv @ a['YP'] @ S.P)) print(check_zero(man._vec_range_J(anew1) - man._vec_range_J(anew))) for i in range(10): a = man._rand_range_J() b1 = man.J(S, man.g_inv_Jst(S, a)) b2 = man.J_g_inv_Jst(S, a) print(check_zero(man._vec_range_J(b1) - man._vec_range_J(b2))) a1 = man.solve_J_g_inv_Jst(S, b1) print(check_zero(man._vec_range_J(a) - man._vec_range_J(a1))) for ii in range(10): E = man._rand_ambient() a2 = man.J_g_inv(S, E) a1 = man.J(S, man.g_inv(S, E)) print(check_zero(man._vec_range_J(a1) - man._vec_range_J(a2))) for i in range(20): Uran = man._rand_ambient() Upr = man.proj(S, man.g_inv(S, Uran)) Upr2 = man.proj_g_inv(S, Uran) print(check_zero(man._vec(Upr) - man._vec(Upr2))) for ii in range(10): a = man._rand_range_J() xi = man.randvec(S) jtout2 = man.Jst(S, a) dlt = 1e-7 Snew = psd_point(S.Y + dlt * xi.tY, S.P + dlt * xi.tP) jtout2a = man.Jst(Snew, a) d1 = (jtout2a - jtout2).scalar_mul(1 / dlt) d2 = man.D_Jst(S, xi, a) print(check_zero(man._vec(d2) - man._vec(d1))) for ii in range(10): S1 = man.rand() eta = man._rand_ambient() xi = man.randvec(S1) a1 = man.J(S1, eta) dlt = 1e-8 Snew = psd_point(S1.Y + dlt * xi.tY, S1.P + dlt * xi.tP) a2 = man.J(Snew, eta) d1 = { 'P': (a2['P'] - a1['P']) / dlt, 'YP': (a2['YP'] - a1['YP']) / dlt } d2 = man.D_J(S1, xi, eta) print(check_zero(man._vec_range_J(d2) - man._vec_range_J(d1))) # derives metrics for ii in range(10): S1 = man.rand() xi = man.randvec(S1) omg1 = man._rand_ambient() omg2 = man._rand_ambient() dlt = 1e-7 S2 = psd_point(S1.Y + dlt * xi.tY, S1.P + dlt * xi.tP) p1 = man.inner(S1, omg1, omg2) p2 = man.inner(S2, omg1, omg2) der1 = (p2 - p1) / dlt der2 = man.base_inner_ambient(man.D_g(S1, xi, omg2), omg1) print(der1 - der2) if np.abs(der1 - der2) > 1e-4: print(der1, der2) break # cross term for christofel for i in range(10): S1 = man.rand() xi = man.randvec(S1) eta1 = man.randvec(S1) eta2 = man.randvec(S1) dr1 = man.D_g(S1, xi, eta1) x12 = man.contract_D_g(S1, eta1, eta2) p1 = man.base_inner_ambient(dr1, eta2) p2 = man.base_inner_ambient(x12, xi) print(p1, p2, p1 - p2) # now test christofel: # two things: symmetric on vector fields # and christofel relation # in the case metric for i in range(10): S1 = man.rand() xi = man.randvec(S1) eta1 = man.randvec(S1) eta2 = man.randvec(S1) p1 = man.proj_g_inv(S1, man.christoffel_form(S1, xi, eta1)) p2 = man.proj_g_inv(S1, man.christoffel_form(S1, eta1, xi)) print(check_zero(man._vec(p1) - man._vec(p2))) v1 = man.base_inner_ambient(man.christoffel_form(S1, eta1, eta2), xi) v2 = man.base_inner_ambient(man.D_g(S1, eta1, eta2), xi) v3 = man.base_inner_ambient(man.D_g(S1, eta2, eta1), xi) v4 = man.base_inner_ambient(man.D_g(S1, xi, eta1), eta2) print(v1, 0.5 * (v2 + v3 - v4), v1 - 0.5 * (v2 + v3 - v4))
def test_rhess_02(): 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() # simple function. Distance to a given matrix # || S - A||_F^2 Basically SVD A = crandn(m, n) def f(S): diff = (A - S.U @ S.P @ S.V.T.conj()) return rtrace(diff @ diff.T.conj()) def df(S): return fr_ambient(-2*A @ S.V @ S.P, -2*A.T.conj() @ S.U @S.P, 2*(S.P-S.U.T.conj() @ A @ S.V)) def ehess_vec(S, xi): return fr_ambient(-2*A @ (xi.tV @ S.P + S.V @ xi.tP), -2*A.T.conj() @ (xi.tU @S.P + [email protected]), 2*(xi.tP - xi.tU.T.conj()@[email protected] - S.U.T.conj()@[email protected])) def ehess_form(S, xi, eta): ev = ehess_vec(S, xi) return rtrace(ev.tU.T.conj() @ eta.tU) +\ rtrace(ev.tV.T.conj() @ eta.tV) +\ rtrace(ev.tP.T.conj() @ eta.tP) xxi = man.randvec(S) dlt = 1e-8 Snew = fr_point( S.U+dlt*xxi.tU, S.V+dlt*xxi.tV, S.P + dlt*xxi.tP) d1 = (f(Snew) - f(S))/dlt d2 = df(S) print(d1 - man.base_inner_ambient(d2, xxi)) dv1 = (df(Snew) - df(S)).scalar_mul(1/dlt) dv2 = ehess_vec(S, xxi) print(man._vec(dv1-dv2)) eeta = man.randvec(S) d1 = man.base_inner_ambient((df(Snew) - df(S)), eeta) / dlt ehess_val = ehess_form(S, xxi, eeta) 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. mU1 = crandn(m, m) mV1 = crandn(n, n) m2 = crandn(p, p) m_p = crandn(p*p, p*p) 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 # 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.conj()) 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(S, rhessvec, eta1) print(man.inner(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(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 = fr_point( S.U + dlt*xi1.tU, S.V + dlt*xi1.tV, 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_all_projections(): dvec = np.array([10, 3, 2, 3]) p = dvec.shape[0] - 1 alpha = randint(1, 10, (p, p + 1)) * .1 man = ComplexFlag(dvec, alpha=alpha) Y = man.rand() U = man._rand_ambient() Upr = man.proj(Y, U) test_inner(man, Y) test_J(man, Y) # now check metric, Jst etc # check Jst: vectorize the operator J then compare Jst with jmat.T.conjugate() jmat = make_j_mat(man, Y) test_Jst(man, Y, jmat) ginv_mat = make_g_inv_mat(man, Y) # test g_inv_Jst for ii in range(10): a = man._rand_range_J() avec = man._vec_range_J(a) jtout = man._unvec(ginv_mat @ jmat.T @ avec) jtout2 = man.g_inv_Jst(Y, a) diff = check_zero(jtout - jtout2) print(diff) # test projection test_projection(man, Y) for i in range(20): Uran = man._rand_ambient() Upr = man.proj(Y, man.g_inv(Y, Uran)) Upr2 = man.proj_g_inv(Y, Uran) print(check_zero(Upr - Upr2)) for ii in range(10): a = man._rand_range_J() xi = man._rand_ambient() jtout2 = man.Jst(Y, a) dlt = 1e-7 Ynew = Y + dlt * xi jtout2a = man.Jst(Ynew, a) d1 = (jtout2a - jtout2) / dlt d2 = man.D_Jst(Y, xi, a) print(check_zero(d2 - d1)) for ii in range(10): Y = man.rand() eta = man._rand_ambient() xi = man.randvec(Y) a1 = man.J(Y, eta) dlt = 1e-7 Ynew = Y + dlt * xi a2 = man.J(Ynew, eta) d1 = (man._vec_range_J(a2) - man._vec_range_J(a1)) / dlt d2 = man._vec_range_J(man.D_J(Y, xi, eta)) print(check_zero(d2 - d1)) for ii in range(10): a = man._rand_range_J() xi = man._rand_ambient() jtout2 = man.g_inv_Jst(Y, a) dlt = 1e-7 Ynew = Y + dlt * xi jtout2a = man.g_inv_Jst(Ynew, a) d1 = (jtout2a - jtout2) / dlt d2 = man.D_g_inv_Jst(Y, xi, a) print(check_zero(d2 - d1)) for ii in range(10): arand = man._rand_range_J() a2 = man.solve_J_g_inv_Jst(Y, arand) a1 = man.J(Y, man.g_inv_Jst(Y, a2)) print(check_zero(man._vec_range_J(a1) - man._vec_range_J(arand))) # derives for ii in range(10): Y1 = man.rand() xi = man.randvec(Y1) omg1 = man._rand_ambient() omg2 = man._rand_ambient() dlt = 1e-7 Y2 = Y1 + dlt * xi p1 = man.inner(Y1, omg1, omg2) p2 = man.inner(Y2, omg1, omg2) der1 = (p2 - p1) / dlt der2 = man.base_inner_ambient(man.D_g(Y1, xi, omg2), omg1) print(check_zero(der1 - der2)) # cross term for christofel for i in range(10): Y1 = man.rand() xi = man.randvec(Y1) omg1 = man._rand_ambient() omg2 = man._rand_ambient() dr1 = man.D_g(Y1, xi, omg1) x12 = man.contract_D_g(Y1, omg1, omg2) p1 = trace(dr1 @ omg2.T.conjugate()).real p2 = trace(x12 @ xi.T.conjugate()).real print(p1, p2, p1 - p2) # now test christofel: # two things: symmetric on vector fields # and christofel relation # in the case metric for i in range(10): Y1 = man.rand() xi = man.randvec(Y1) eta1 = man.randvec(Y1) eta2 = man.randvec(Y1) p1 = man.proj_g_inv(Y1, man.christoffel_form(Y1, xi, eta1)) p2 = man.proj_g_inv(Y1, man.christoffel_form(Y1, eta1, xi)) print(check_zero(p1 - p2)) v1 = man.base_inner_ambient(man.christoffel_form(Y1, eta1, eta2), xi) v2 = man.base_inner_ambient(man.D_g(Y1, eta1, eta2), xi) v3 = man.base_inner_ambient(man.D_g(Y1, eta2, eta1), xi) v4 = man.base_inner_ambient(man.D_g(Y1, xi, eta1), eta2) print(v1, 0.5 * (v2 + v3 - v4), v1 - 0.5 * (v2 + v3 - v4)) """
def test_rhess_02(): np.random.seed(0) dvec = np.array([10, 3, 2, 3]) p = dvec.shape[0] - 1 alpha = randint(1, 10, (p, p + 1)) * .1 man = ComplexFlag(dvec, alpha=alpha) n = man.n d = man.d Y = man.rand() UU = {} p = alpha.shape[0] VV = {} gidx = man._g_idx for rr in range(p): UU[rr] = make_sym_pos(n) VV[rr] = crandn(n, dvec[rr + 1]) def f(Y): ss = 0 for rr in range(p): br, er = gidx[rr + 1] wr = Y[:, br:er] ss += trace(UU[rr] @ wr @ wr.T.conjugate()).real return ss def df(W): ret = np.zeros_like(W) for rr in range(p): br, er = gidx[rr + 1] wr = W[:, br:er] ret[:, br:er] += 2 * UU[rr] @ wr return ret def ehess_form(W, xi, eta): ss = 0 for rr in range(p): br, er = gidx[rr + 1] ss += 2 * trace( UU[rr] @ xi[:, br:er] @ eta[:, br:er].T.conjugate()).real return ss def ehess_vec(W, xi): ret = np.zeros_like(W) for rr in range(p): br, er = gidx[rr + 1] ret[:, br:er] += 2 * UU[rr] @ xi[:, br:er] return ret xxi = crandn(n, d) dlt = 1e-8 Ynew = Y + dlt * xxi d1 = (f(Ynew) - f(Y)) / dlt d2 = df(Y) print(d1 - trace(d2 @ xxi.T.conjugate()).real) eeta = crandn(n, d) d1 = trace((df(Ynew) - df(Y)) @ eeta.T.conjugate()).real / dlt ehess_val = ehess_form(Y, xxi, eeta) # ehess_val2 = ehess_form(Y, eeta, xxi) dv2 = ehess_vec(Y, xxi) print(trace(dv2 @ eeta.T.conjugate()).real) 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) def eta_field(Yin): return m1 @ (Yin - Y) @ m2 + eeta # xietaf: should go to ehess(xi, eta) + df(Y) @ etafield) xietaf = trace( df(Ynew) @ eta_field(Ynew).T.conjugate() - df(Y) @ eta_field(Y).T.conjugate()).real / dlt # appy eta_func to f: should go to tr(m1 @ xxi @ m2 @ df(Y).T.conjugate()) Dxietaf = trace( (eta_field(Ynew) - eta_field(Y)) @ df(Y).T.conjugate()).real / 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(Y, xxi) eta1 = man.proj(Y, eeta) egvec = df(Y) ehvec = ehess_vec(Y, xi1) rhessvec = man.ehess2rhess(Y, egvec, ehvec, xi1) # check it numerically: def rgrad_func(Y): return man.proj_g_inv(Y, df(Y)) val2, _, _ = calc_covar_numeric(man, Y, xi1, rgrad_func) val2_p = man.proj(Y, val2) # print(rhessvec) # print(val2_p) print(check_zero(rhessvec - val2_p)) rhessval = man.inner(Y, rhessvec, eta1) print(man.inner(Y, val2, eta1)) print(rhessval) # check symmetric: ehvec_e = ehess_vec(Y, eta1) ehess_valp = ehess_form(Y, xi1, eta1) rhessvec_e = man.ehess2rhess(Y, egvec, ehvec_e, eta1) rhessval_e = man.inner(Y, rhessvec_e, xi1) rhessval_e1 = man.rhess02(Y, xi1, eta1, egvec, ehess_valp) # rhessval_e2 = man.rhess02_alt(Y, xi1, eta1, egvec, # trace([email protected]()).real) # print(rhessval_e, rhessval_e1, rhessval_e2) print(rhessval_e, rhessval_e1, rhessval_e - rhessval_e1) print('rhessval_e %f ' % 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(Y): return man.proj(Y, eta_field(Y)) print(check_zero(eta1 - eta_proj(Y))) e1 = man.inner(Y, man.proj_g_inv(Y, df(Y)), eta_proj(Y)) e1a = trace(df(Y) @ eta_proj(Y).T.conjugate()).real print(e1, e1a, e1 - e1a) Ynew = Y + xi1 * dlt e2 = man.inner(Ynew, man.proj_g_inv(Ynew, df(Ynew)), eta_proj(Ynew)) e2a = trace(df(Ynew) @ eta_proj(Ynew).T.conjugate()).real print(e2, e2a, e2 - e2a) first = (e2 - e1) / dlt first1 = trace( df(Ynew) @ eta_proj(Ynew).T.conjugate() - df(Y) @ eta_proj(Y).T.conjugate()).real / dlt print(first - first1) val3, _, _ = calc_covar_numeric(man, Y, xi1, eta_proj) second = man.inner(Y, man.proj_g_inv(Y, df(Y)), man.proj(Y, val3)) second2 = man.inner(Y, man.proj_g_inv(Y, df(Y)), val3) print(second, second2, second - second2) print('same as rhess_val %f' % (first - second))
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 optim_test(): from pymanopt import Problem from pymanopt.solvers import TrustRegions from pymanopt.function import Callable n = 300 # problem Tr(AXBX^T) for i in range(1): dvec = np.array([0, 5, 4, 10]) dvec[0] = n - dvec[1:].sum() d = dvec[1:].sum() alpha = randint(1, 10, 2) * .1 D = randint(1, 10, n) * 0.02 + 1 OO = random_orthogonal(n) A = OO @ np.diag(D) @ OO.T.conjugate() B = make_sym_pos(d) p = dvec.shape[0] - 1 alpha = randint(1, 10, (p, p + 1)) * .1 alpha0 = randint(1, 10, (p)) # alpha0 = randint(1, 2, (p)) alpha = make_simple_alpha(alpha0, 0) man = ComplexFlag(dvec, alpha) @Callable def cost(X): return trace(A @ X @ B @ X.T.conjugate()).real @Callable def egrad(X): return 2 * A @ X @ B @Callable def ehess(X, H): return 2 * A @ H @ B X = man.rand() if False: xi = man.randvec(X) d1 = num_deriv(man, X, xi, cost) d2 = trace(egrad(X) @ xi.T.conjugate()).real print(check_zero(d1 - d2)) prob = Problem(man, cost, egrad=egrad) XInit = man.rand() prob = Problem(man, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=100) opt = solver.solve(prob, x=XInit, Delta_bar=250) print(cost(opt)) alpha0 = randint(1, 2, (p)) alpha1 = make_simple_alpha(alpha0, 0) man1 = ComplexFlag(dvec, alpha=alpha1) prob = Problem(man1, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=100) opt = solver.solve(prob, x=XInit, Delta_bar=250) alpha0 = randint(1, 2, (p)) alpha2 = make_simple_alpha(alpha0, -1) man1 = ComplexFlag(dvec, alpha=alpha2) prob = Problem(man1, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=100) opt = solver.solve(prob, x=XInit, Delta_bar=250)
def optim_test3(): from pymanopt import Problem from pymanopt.solvers import TrustRegions from pymanopt.function import Callable n = 1000 # problem Tr(AXBX^T) for i in range(1): # Stiefel manifold dvec = np.array([0, 50]) dvec[0] = n - dvec[1:].sum() d = dvec[1:].sum() p = dvec.shape[0] - 1 alpha = randint(1, 10, (p, p + 1)) * .1 alpha0 = randint(1, 10, (p)) # alpha0 = randint(1, 2, (p)) alpha = make_simple_alpha(alpha0, 0) B = np.diag(np.concatenate([randint(1, 10, d), np.zeros(n - d)])) D = randint(1, 10, n) * 0.02 + 1 OO = random_orthogonal(n) A = OO @ np.diag(D) @ OO.T man = ComplexFlag(dvec, alpha) cf = 10 B2 = B @ B @Callable def cost(X): return cf * trace( B @ X @ st(X) @ B2 @ X @ st(X) @ B) +\ trace(st(X) @ A @ X) @Callable def egrad(X): R = cf * 4 * B2 @ X @ st(X) @ B2 @ X + 2 * A @ X return R @Callable def ehess(X, H): return 4*cf*B2 @ H @ st(X) @ B2 @ X +\ 4*cf*B2 @ X @ st(H) @ B2 @ X +\ 4*cf*B2 @ X @ st(X) @ B2 @ H + 2*A @ H if False: X = man.rand() xi = man.randvec(X) d1 = num_deriv(man, X, xi, cost) d2 = trace(egrad(X) @ st(xi)).real print(check_zero(d1 - d2)) d3 = num_deriv(man, X, xi, egrad) d4 = ehess(X, xi) print(check_zero(d3 - d4)) XInit = man.rand() prob = Problem(man, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=100) opt = solver.solve(prob, x=XInit, Delta_bar=2500) print(cost(opt)) if False: # print(opt) # double check: # print(cost(opt)) min_val = 1e190 # min_X = None for i in range(100): Xi = man.rand() c = cost(Xi) if c < min_val: # min_X = Xi min_val = c if i % 1000 == 0: print('i=%d min=%f' % (i, min_val)) print(min_val) alpha0 = randint(1, 2, (p)) alpha1 = make_simple_alpha(alpha0, 0) man1 = ComplexFlag(dvec, alpha=alpha1) prob = Problem(man1, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=100) opt = solver.solve(prob, x=XInit, Delta_bar=250) alpha0 = randint(1, 2, (p)) alpha2 = make_simple_alpha(alpha0, -1) man1 = ComplexFlag(dvec, alpha=alpha2) # man1 = RealStiefel(n, d, alpha=np.array([1, 1])) prob = Problem(man1, cost, egrad=egrad, ehess=ehess) solver = TrustRegions(maxtime=100000, maxiter=100) opt = solver.solve(prob, x=XInit, Delta_bar=250)
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)))