def calc_stiefel(): # Y is a matrix point eta = matrices('eta') Y = stiefels('Y') a = sm.sym_symb('a') al0, al1 = scalars('al0 al1') # scalars are symmetric sm.g_symms.update((al0, al1)) def J(Y, eta): return mat_spfy(t(Y) * eta + t(eta) * Y).doit() def J_adj(Y, a): dY = symbols('dY', commutative=False) return xtrace(trace(mat_spfy(J(Y, dY) * a)), dY) def g(Y, eta): return al0*eta+(al1-al0)*Y*t(Y)*eta def g_inv(Y, eta): return mat_spfy(1/al0*eta + (1/al1-1/al0)*Y*t(Y)*eta) J_giv_J_adj = J(Y, g_inv(Y, J_adj(Y, a))) print(J_giv_J_adj) def proj(Y, omg): jo = mat_spfy(J(Y, omg)) ifactor = al1/Integer(4) return omg - mat_spfy( g_inv(Y, mat_spfy(J_adj(Y, ifactor*jo)))) def r_gradient(Y, omg): return mat_spfy( proj(Y, mat_spfy(g_inv(Y, omg)))) print(r_gradient(Y, eta)) xi, phi = matrices('xi phi') trilinear = mat_spfy(trace(DDR(g(Y, eta), Y, phi) * t(xi))) xcross = xtrace(trilinear, phi) K = (Integer(1)/Integer(2))*(DDR(g(Y, eta), Y, xi) + DDR(g(Y, xi), Y, eta) - xcross) def d_proj(Y, xi, omg): e = matrices('e') r = mat_spfy(proj(Y, e)) expr = DDR(r, Y, xi) return expr.xreplace({e: omg}) dp_xi_eta = d_proj(Y, xi, eta) prK = simplify_stiefel_tangent(proj(Y, g_inv(Y, K)), Y, (xi, eta)) Gamma = mat_spfy( simplify_stiefel_tangent(prK - dp_xi_eta, Y, (xi, eta))) print("This is the Christoffel function:") pprint(Gamma) fY, fYY = matrices('fY fYY') rhess02 = trace(mat_spfy(t(eta)*fYY*xi-Gamma * t(fY))) rhess11_bf_gr = xtrace(rhess02, eta) print("This is the Riemannian Hessian Vector Product:") pprint(rhess11_bf_gr)
def NT(Y, P, omg_Y, omg_P): nB, nD = matrices('nB nD') ipt = mat_spfy(base_ambient_inner(*N(Y, P, nB, nD), omg_Y, omg_P)) ntB = mat_spfy(xtrace(ipt, nB)) ntD1 = mat_spfy(xtrace(ipt, nD)) ntD = mat_spfy(Integer(1) / Integer(2) * (ntD1 + t(ntD1))) return ntB, ntD
def calc_psd_range(): # in this method, the ambient is still # R(n times p) + Symmetric(p) # Horizontal is still # al1*t(Y)*omg_Y + bt*omg_P*inv(R*R) - bt*inv(R*R)*omg_P) # manifold is on pair (Y, P) # Use pair B, D. B size n*(n-p), D size p(p+1)/2 # Use the embedding # omg_Y = bt(Y*(inv(P)*D - D*inv(P)) # omg_P = al1*D # so need to set up a new variable Y_0 and relation YY_0=0 Y, Y0 = stiefels('Y Y0') sm.g_cstiefels[Y] = Y0 sm.g_cstiefels[Y0] = Y B, eta_Y, eta_P = matrices('B eta_Y eta_P') P, D = sym_symb('P D') al0, al1, bt = scalars('al0 al1 bt') def g(Y, P, omg_Y, omg_P): return al0 * omg_Y + (al1 - al0) * Y * t(Y) * omg_Y, bt * inv( P) * omg_P * inv(P) def ginv(Y, P, omg_Y, omg_P): return 1 / al0 * omg_Y + ( 1 / al1 - 1 / al0) * Y * t(Y) * omg_Y, 1 / bt * P * omg_P * P # check that ginv \circ g is id e1, e2 = ginv(Y, P, *(g(Y, P, eta_Y, eta_P))) e1 = mat_spfy(e1) e2 = mat_spfy(e2) print(e1, e2) def base_ambient_inner(omg_Y, omg_P, xi_Y, xi_P): return mat_spfy( trace(mat_spfy(omg_Y * t(xi_Y))) + trace(mat_spfy(omg_P * t(xi_P)))) def ambient_inner(Y, P, omg_Y, omg_P, xi_Y, xi_P): return mat_spfy( trace( mat_spfy((al0 * omg_Y + (al1 - al0) * Y * t(Y) * omg_Y) * t(xi_Y))) + trace(mat_spfy(bt * inv(P) * omg_P * inv(P) * t(xi_P)))) def EN_inner(Y, P, Ba, Da, Bb, Db): return trace(mat_spfy(Da * Db) + mat_spfy(Ba * t(Bb))) qat = asym_symb('qat') ipr = ambient_inner(Y, P, eta_Y, eta_P, Y * qat, P * qat - qat * P) dqat = mat_spfy(xtrace(ipr, qat)) print(dqat) def N(Y, P, B, D): N_Y = mat_spfy(bt * Y * (inv(P) * D - D * inv(P))) + Y0 * B N_P = mat_spfy(al1 * D) return N_Y, N_P def NT(Y, P, omg_Y, omg_P): nB, nD = matrices('nB nD') ipt = mat_spfy(base_ambient_inner(*N(Y, P, nB, nD), omg_Y, omg_P)) ntB = mat_spfy(xtrace(ipt, nB)) ntD1 = mat_spfy(xtrace(ipt, nD)) ntD = mat_spfy(Integer(1) / Integer(2) * (ntD1 + t(ntD1))) return ntB, ntD # check that image of N is horizontal: print( mat_spfy( xtrace( mat_spfy( ambient_inner(Y, P, *N(Y, P, B, D), Y * qat, P * qat - qat * P)), qat))) NTe_B, NTe_D = NT(Y, P, eta_Y, eta_P) mdict = {'bt': r'\beta', 'al': r'\alpha'} print(latex_map(mat_latex(NTe_B), mdict)) print(latex_map(mat_latex(NTe_D), mdict)) gN = g(Y, P, *N(Y, P, B, D)) gN_B = mat_spfy(gN[0]) gN_D = mat_spfy(gN[1]) print(latex_map(mat_latex(gN_B), mdict)) print(latex_map(mat_latex(gN_D), mdict)) NTgN_B, NTgN_D = NT(Y, P, *gN) print(latex_map(mat_latex(NTgN_B), mdict)) print(latex_map(mat_latex(NTgN_D), mdict)) NTg_B, NTg_D = NT(Y, P, *g(Y, P, eta_Y, eta_P)) print(latex_map(mat_latex(NTg_B), mdict)) # print(latex_map(sp.latex(NTgN_P), mdict)) print(latex_map(mat_latex(NTg_D), mdict)) def sym(x): return mat_spfy(Integer(1) / Integer(2) * (x + t(x))) xi_Y, xi_P, phi_Y, phi_P = matrices('xi_Y xi_P phi_Y phi_P') gYPeta = g(Y, P, eta_Y, eta_P) Dgxieta_Y = DDR(gYPeta[0], Y, xi_Y) Dgxieta_P = DDR(gYPeta[1], P, xi_P) gYPxi = g(Y, P, xi_Y, xi_P) Dgetaxi_Y = DDR(gYPxi[0], Y, eta_Y) Dgetaxi_P = DDR(gYPxi[1], P, eta_P) Dgxiphi_Y = DDR(gYPxi[0], Y, phi_Y) Dgxiphi_P = DDR(gYPxi[1], P, phi_P) tr3 = mat_spfy(base_ambient_inner(Y, P, Dgxiphi_Y, Dgxiphi_P, eta_Y, eta_P)) xcross_Y = xtrace(tr3, phi_Y) xcross_P = xtrace(tr3, phi_P) K_Y = (Integer(1) / Integer(2)) * (Dgxieta_Y + Dgetaxi_Y - xcross_Y) K_P = (Integer(1) / Integer(2)) * (Dgxieta_P + Dgetaxi_P - xcross_P) pprint(K_Y) pprint(K_P)
def JT(Y, P, a_P, a_YP): dY, dP = matrices('dY dP') ipt = mat_spfy(EJ_inner(Y, P, *J(Y, P, dY, dP), a_P, a_YP)) jty = mat_spfy(xtrace(ipt, dY)) jtp = mat_spfy(xtrace(ipt, dP)) return jty, jtp
def calc_psd(): # manifold is on pair (Y, P) Y = stiefels('Y') P = sym_symb('P') a_P = asym_symb('a_P') a_YP, eta_Y, eta_P = matrices('a_YP eta_Y eta_P') al0, al1, bt = scalars('al0 al1 bt') def g(Y, P, omg_Y, omg_P): return al0 * omg_Y + (al1 - al0) * Y * t(Y) * omg_Y, bt * inv( P) * omg_P * inv(P) def ginv(Y, P, omg_Y, omg_P): return 1 / al0 * omg_Y + ( 1 / al1 - 1 / al0) * Y * t(Y) * omg_Y, 1 / bt * P * omg_P * P # check that ginv \circ g is id e1, e2 = ginv(Y, P, *(g(Y, P, eta_Y, eta_P))) e1 = mat_spfy(e1) e2 = mat_spfy(e2) print(e1, e2) def ambient_inner(Y, P, omg_Y, omg_P, xi_Y, xi_P): return mat_spfy( trace( mat_spfy((al0 * omg_Y + (al1 - al0) * Y * t(Y) * omg_Y) * t(xi_Y))) + trace(mat_spfy(bt * inv(P) * omg_P * inv(P) * t(xi_P)))) def base_ambient_inner(Y, P, omg_Y, omg_P, xi_Y, xi_P): return mat_spfy( trace(mat_spfy(omg_Y * t(xi_Y))) + trace(mat_spfy(omg_P * t(xi_P)))) def EJ_inner(Y, P, a_P, a_YP, b_P, b_YP): return trace(mat_spfy(-a_P * b_P) + mat_spfy(a_YP * t(b_YP))) qat = matrices('qat') ipr = ambient_inner(Y, P, eta_Y, eta_P, Y * qat, P * qat - qat * P) dqat = mat_spfy(xtrace(ipr, qat)) print(dqat) def J(Y, P, omg_Y, omg_P): J_P = mat_spfy(omg_P - t(omg_P)) J_YP = mat_spfy(al1 * t(Y) * omg_Y + bt * omg_P * inv(P) - bt * inv(P) * omg_P) return J_P, J_YP def JT(Y, P, a_P, a_YP): dY, dP = matrices('dY dP') ipt = mat_spfy(EJ_inner(Y, P, *J(Y, P, dY, dP), a_P, a_YP)) jty = mat_spfy(xtrace(ipt, dY)) jtp = mat_spfy(xtrace(ipt, dP)) return jty, jtp JTa_Y, JTa_P = JT(Y, P, a_P, a_YP) ginvJT = ginv(Y, P, JTa_Y, JTa_P) ginvJT_Y = mat_spfy(ginvJT[0]) ginvJT_P = mat_spfy(ginvJT[1]) pprint(ginvJT_Y) pprint(ginvJT_P) Jginv_P, Jginv_YP = J(Y, P, *ginv(Y, P, eta_Y, eta_P)) pprint(Jginv_P) pprint(Jginv_YP) b_P, b_YP = J(Y, P, *ginvJT) pprint(b_P) pprint(b_YP) # even part of a_YP aYPev = sym(a_YP) exp1 = bt * (Integer(1) / Integer(2) * b_P - P * aYPev + aYPev * P) exp1 = mat_spfy(exp1) pprint(exp1) print('check the formula for even part of a_YP recover b_YP') exp1 = al1 * aYPev + bt / 2 * (b_P * inv(P) - inv(P) * b_P) - sym(b_YP) pprint(mat_spfy(exp1)) aYPodd = mat_spfy(a_YP - aYPev) exp2 = (al1-2*bt)*aYPodd + bt*P*aYPodd*inv(P) + bt*inv(P)*aYPodd*P -\ Integer(1)/Integer(2)*(b_YP-t(b_YP)) # this is the equation to solve a_YPodd print('this is the equation to solve a_YPodd') pprint(exp2) def even_solve(Y, P, b_P, b_YP): return Integer(1)/al1*sym(b_YP) +\ bt/(Integer(2)*al1)*(inv(P)*b_P - b_P*inv(P)) print(mat_spfy(even_solve(Y, P, b_P, b_YP))) xi_Y, xi_P, phi_Y, phi_P = matrices('xi_Y xi_P phi_Y phi_P') gYPeta = g(Y, P, eta_Y, eta_P) Dgxieta_Y = DDR(gYPeta[0], Y, xi_Y) Dgxieta_P = DDR(gYPeta[1], P, xi_P) gYPxi = g(Y, P, xi_Y, xi_P) Dgetaxi_Y = DDR(gYPxi[0], Y, eta_Y) Dgetaxi_P = DDR(gYPxi[1], P, eta_P) Dgxiphi_Y = DDR(gYPeta[0], Y, phi_Y) Dgxiphi_P = DDR(gYPeta[1], P, phi_P) tr3 = mat_spfy(base_ambient_inner(Y, P, Dgxiphi_Y, Dgxiphi_P, xi_Y, xi_P)) xcross_Y = xtrace(tr3, phi_Y) xcross_P = xtrace(tr3, phi_P) K_Y = (Integer(1) / Integer(2)) * (Dgxieta_Y + Dgetaxi_Y - xcross_Y) K_P = (Integer(1) / Integer(2)) * (Dgxieta_P + Dgetaxi_P - xcross_P) K_Y = simplify_stiefel_tangent(K_Y, Y, (eta_Y, xi_Y)) K_P = simplify_pd_tangent(K_P, P, (eta_P, xi_P)) pprint(K_Y) pprint(K_P) giKY, giKP = ginv(Y, P, K_Y, K_P) giKY1 = simplify_stiefel_tangent(giKY, Y, (eta_Y, xi_Y)) giKP1 = simplify_pd_tangent(giKP, P, (eta_P, xi_P)) jK1 = J(Y, P, giKY1, giKP1) jKP = simplify_pd_tangent(jK1[0], P, (eta_P, xi_P)) jKY = simplify_stiefel_tangent(jK1[1], Y, (eta_Y, xi_Y)) jKY1 = simplify_pd_tangent(jKY, P, (eta_P, xi_P)) pprint(jKP) pprint(jKY1) def DJ(Y, P, xi_Y, xi_P, eta_Y, eta_P): expr_P, expr_YP = J(Y, P, eta_Y, eta_P) der_P = DDR(expr_P, Y, xi_Y) + DDR(expr_P, P, xi_P) der_YP = DDR(expr_YP, Y, xi_Y) + DDR(expr_YP, P, xi_P) return mat_spfy(der_P), mat_spfy(der_YP) pprint(DJ(Y, P, xi_Y, xi_P, eta_Y, eta_P))
def d_proj(Y, xi, omg): e = matrices('e') r = mat_spfy(proj(Y, e)) expr = DDR(r, Y, xi) return expr.xreplace({e: omg})
def calc_pd(): """ For positive definite matrices Y is a matrix point, a positive definite matrix eta is an ambient point, same size with Y not necessarily symmetric or invertible b is a point in E_J. b is antisymmetric """ # eta is an ambient Y = sm.sym_symb('Y') eta = matrices('eta') b = sm.asym_symb('b') def J(Y, eta): return eta - t(eta) def J_adj(Y, a): dY = symbols('dY', commutative=False) return xtrace(trace(mat_spfy(J(Y, dY) * a)), dY) def g(Y, eta): return inv(Y)*eta*inv(Y) def g_inv(Y, eta): return Y*eta*Y J_g_inv_J_adj = J(Y, g_inv(Y, J_adj(Y, b))) pprint(J_g_inv_J_adj) def solve_JginvJadj(Y, a): return Integer(-1)/Integer(4)*inv(Y)*a*inv(Y) def proj(Y, omg): jo = mat_spfy(J(Y, omg)) cJinvjo = solve_JginvJadj(Y, jo) return mat_spfy(omg - mat_spfy( g_inv(Y, mat_spfy(J_adj(Y, cJinvjo))))) def r_gradient(Y, omg): return mat_spfy( proj(Y, mat_spfy(g_inv(Y, omg)))) print(proj(Y, eta)) print(r_gradient(Y, eta)) xi, phi = matrices('xi phi') xcross = xtrace(mat_spfy(trace(DDR(g(Y, eta), Y, phi) * t(xi))), phi) K = (Integer(1)/Integer(2))*( DDR(g(Y, eta), Y, xi) + DDR(g(Y, xi), Y, eta) - xcross) def d_proj(Y, xi, omg): e = matrices('e') r = mat_spfy(proj(Y, e)) expr = DDR(r, Y, xi) return expr.xreplace({e: omg}) dp_xi_eta = d_proj(Y, xi, eta) prK = simplify_pd_tangent(proj(Y, mat_spfy(g_inv(Y, K))), Y, (xi, eta)) Gamma = mat_spfy( simplify_pd_tangent(-dp_xi_eta+prK, Y, (xi, eta))) print("This is the Christoffel function:") pprint(Gamma) fY, fYY = matrices('fY fYY') rhess02 = trace(mat_spfy(t(eta)*fYY*xi-Gamma * t(fY))) rhess11_bf_gr = xtrace(rhess02, eta) print("This is the Riemannian Hessian Vector Product:") pprint(r_gradient(Y, rhess11_bf_gr))