def test_geodesics(): from scipy.linalg import expm alpha = np.random.randint(1, 10, (2)) * .1 beta = alpha[1] * .1 m, d = (5, 3) man = RealPositiveSemidefinite(m, d, alpha=alpha, beta=beta) X = man.rand() alf = alpha[1] / alpha[0] def calc_gamma(man, X, xi, eta): g_inv_Jst_solve_J_g_in_Jst_DJ = man.g_inv( X, man.Jst(X, man.solve_J_g_inv_Jst(X, man.D_J(X, xi, eta)))) proj_christoffel = man.proj_g_inv(X, man.christoffel_form(X, xi, eta)) return g_inv_Jst_solve_J_g_in_Jst_DJ + proj_christoffel eta = man.randvec(X) g1 = calc_gamma(man, X, eta, eta) g2 = man.christoffel_gamma(X, eta, eta) print(man._vec(g1 - g2)) egrad = man._rand_ambient() print(man.base_inner_ambient(g1, egrad)) print(man.rhess02_alt(X, eta, eta, egrad, 0)) print(man.rhess02(X, eta, eta, egrad, man.zerovec(X))) # second solution: A = X.Y.T @ eta.tY t = 2 K = eta.tY - X.Y @ (X.Y.T @ eta.tY) Yp, R = np.linalg.qr(K) x_mat = np.bmat([[2 * alf * A, -R.T], [R, zeros((d, d))]]) Yt = np.bmat([X.Y, Yp]) @ expm(t*x_mat)[:, :d] @ \ expm(t*(1-2*alf)*A) x_d_mat = x_mat[:, :d].copy() x_d_mat[:d, :] += (1 - 2 * alf) * A Ydt = np.bmat([X.Y, Yp]) @ expm(t*x_mat) @ x_d_mat @\ expm(t*(1-2*alf)*A) x_dd_mat = x_mat @ x_d_mat + x_d_mat @ ((1 - 2 * alf) * A) Yddt = np.bmat([X.Y, Yp]) @ expm(t*x_mat) @ x_dd_mat @\ expm(t*(1-2*alf)*A) sqrtP = X.evec @ np.diag(np.sqrt(X.evl)) @ X.evec.T isqrtP = X.evec @ np.diag(1 / np.sqrt(X.evl)) @ X.evec.T Pinn = t * isqrtP @ eta.tP @ isqrtP ePinn = expm(Pinn) Pt = sqrtP @ ePinn @ sqrtP Pdt = eta.tP @ isqrtP @ ePinn @ sqrtP Pddt = eta.tP @ isqrtP @ ePinn @ isqrtP @ eta.tP Xt = psd_point(np.array(Yt), np.array(Pt)) Xdt = psd_ambient(np.array(Ydt), np.array(Pdt)) Xddt = psd_ambient(np.array(Yddt), np.array(Pddt)) gcheck = Xddt + calc_gamma(man, Xt, Xdt, Xdt) print(man._vec(gcheck)) Xt1 = man.exp(X, t * eta) print((Xt1.Y - Xt.Y)) print((Xt1.P - Xt.P))
def v_func(S): # a function from the manifold # to ambient csp = sym((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 make_j_mat(man, S): codim = man.codim ret = zeros((codim, man.tdim_P + man.tdim_St)) for ii in range(ret.shape[1]): eSt = zeros(man.tdim_St) eP = zeros((man.tdim_P)) if ii < man.tdim_St: eSt[ii] = 1 else: eP[ii - man.tdim_St] = 1 ret[:, ii] = man._vec_range_J( man.J( S, psd_ambient(eSt.reshape(man.n, man.p), eP.reshape(man.p, man.p)))) return ret
def ehess(S, xi): return psd_ambient(-4 * A @ (xi.tY @ S.P + S.Y @ xi.tP), 2 * (xi.tP - xi.tY.T @ A @ S.Y - S.Y.T @ A @ xi.tY))
def egrad(S): return psd_ambient(-4 * A @ S.Y @ S.P, 2 * (S.P - S.Y.T @ A @ S.Y))
def eta_field(Sin): return man.proj( S, psd_ambient(m1 @ (Sin.Y - S.Y) @ m2, sym((m_p @ (Sin.P - S.P).reshape(-1)).reshape( d, d)))) + eeta
def omg_func(S): csp = sym((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_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 = RealPositiveSemidefinite(n, d, alpha=alpha, beta=beta) S = man.rand() aa = randn(n * d, n * d) cc = randn(d * d, d * d) icpt = man._rand_ambient() def omg_func(S): csp = sym((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 = sym((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 = sym((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 = sym((cc @ S.P.reshape(-1)).reshape(d, d)) return psd_ambient((aa @ S.Y.reshape(-1) + bb).reshape(n, d), csp + dd)