def symmetrize_periods(Pa, Pb, tol=1e-4): r"""Returns symmetric a- and b-periods `Pa_symm` and `Pb_symm`, as well as the corresponding symplectic operator `Gamma` such that `Gamma [Pa \\ Pb] = [Pa_symm \\ Pb_symm]`. Parameters ---------- Pa : complex matrix Pb : complex matrix The a- and b-periods, respectively, of a genus `g` Riemann surface. tol : double (Default: 1e-4) Tolerance used to verify integrality of intermediate matrices. Dependent on precision of period matrices. Returns ------- Gamma : integer matrix The symplectic transformation operator. Pa : complex matrix Pb : complex matrix Symmetric a- and b-periods, respectively, of a genus `g` Riemann surface. Notes ----- The algorithm described in Kalla, Klein actually operates on the transposes of the a- and b-period matrices. """ # coerce from numpy, if necessary if isinstance(Pa, numpy.ndarray): Pa = Matrix(CDF, numpy.ascontiguousarray(Pa)) if isinstance(Pb, numpy.ndarray): Pb = Matrix(CDF, numpy.ascontiguousarray(Pb)) # use the transposes of the period matrices and coerce to Sage matrices Pa = Pa.T Pb = Pb.T # use above functions to obtain topological type matrix g, g = Pa.dimensions() R = involution_matrix(Pa, Pb, tol=tol) S = integer_kernel_basis(R) N1 = N1_matrix(Pa, Pb, S, tol=tol) H, Q = symmetric_block_diagonalize(N1) Gamma = symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=tol) # compute the corresponding symmetric periods stacked_periods = zero_matrix(CDF, 2 * g, g) stacked_periods[:g, :] = Pa stacked_periods[g:, :] = Pb stacked_symmetric_periods = Gamma * stacked_periods Pa_symm = stacked_symmetric_periods[:g, :] Pb_symm = stacked_symmetric_periods[g:, :] # transpose results back Pa_symm = Pa_symm.T Pb_symm = Pb_symm.T return Pa_symm, Pb_symm
def symmetrize_periods(Pa, Pb, tol=1e-4): r"""Returns symmetric a- and b-periods `Pa_symm` and `Pb_symm`, as well as the corresponding symplectic operator `Gamma` such that `Gamma [Pa \\ Pb] = [Pa_symm \\ Pb_symm]`. Parameters ---------- Pa : complex matrix Pb : complex matrix The a- and b-periods, respectively, of a genus `g` Riemann surface. tol : double (Default: 1e-4) Tolerance used to verify integrality of intermediate matrices. Dependent on precision of period matrices. Returns ------- Gamma : integer matrix The symplectic transformation operator. Pa : complex matrix Pb : complex matrix Symmetric a- and b-periods, respectively, of a genus `g` Riemann surface. Notes ----- The algorithm described in Kalla, Klein actually operates on the transposes of the a- and b-period matrices. """ # coerce from numpy, if necessary if isinstance(Pa, numpy.ndarray): Pa = Matrix(CDF, numpy.ascontiguousarray(Pa)) if isinstance(Pb, numpy.ndarray): Pb = Matrix(CDF, numpy.ascontiguousarray(Pb)) # use the transposes of the period matrices and coerce to Sage matrices Pa = Pa.T Pb = Pb.T # use above functions to obtain topological type matrix g,g = Pa.dimensions() R = involution_matrix(Pa, Pb, tol=tol) S = integer_kernel_basis(R) N1 = N1_matrix(Pa, Pb, S, tol=tol) H,Q = symmetric_block_diagonalize(N1) Gamma = symmetric_transformation_matrix(Pa, Pb, S, H, Q, tol=tol) # compute the corresponding symmetric periods stacked_periods = zero_matrix(CDF, 2*g, g) stacked_periods[:g,:] = Pa stacked_periods[g:,:] = Pb stacked_symmetric_periods = Gamma*stacked_periods Pa_symm = stacked_symmetric_periods[:g,:] Pb_symm = stacked_symmetric_periods[g:,:] # transpose results back Pa_symm = Pa_symm.T Pb_symm = Pb_symm.T return Pa_symm, Pb_symm
def coeff_reduce(C, B, SB, Detail=0, debug=False): """B is a list of lists of rationals holding an invertible dxd matrix C is a list of lists of rationals holding an nxd matrix C*B remains invariant SB = Sturm bound: the first SB rows of C should span the whole row space over Z Computes invertible U and returns (C', B') = (C*U, U^(-1)*B), so that the entries of C' are integers and 'small' """ t0 = time.time() if Detail > 1: print("Before LLL, coefficients:\n{}".format(C)) # convert to actual matrices: d = len(B) nan = len(C) B = Matrix(B) C = Matrix(C) if debug: print("B has size {}".format(B.dimensions())) #print("B={}".format(B)) print("C has size {}".format(C.dimensions())) #print("C={}".format(C)) CB = C * B # Make integral: C1, den = C._clear_denom() B1 = B / den t1 = time.time() if Detail: print("Cleared denominator = {} in {:0.3f}".format(den, t1 - t0)) # Make primitive: if debug: print("C1 is in {}".format(C1.parent())) #print("C1 = {}".format(C1)) C1 = pari(C1) # if debug: # print("B1={} in {}".format(B1, B1.parent())) B1 = pari(B1) V1V2S = C1.matsnf(1) t2 = time.time() V2 = V1V2S[1] S = pari_row_slice(nan - d + 1, nan)(V1V2S[2]) if Detail: print("Computed Smith form in {:0.3f}".format(t2 - t1)) if debug: print("About to invert matrix of size {}".format(V2.matsize())) C1 *= V2 B1 = V2**(-1) * B1 if debug: assert CB == C1 * B1 scales = [S[i, i] for i in range(d)] if not all(s == 1 for s in scales): if Detail: print("scale factors {}".format(scales)) C1 *= S**(-1) B1 = S * B1 if debug: assert CB == C1 * B1 # LLL-reduce U = C1.qflll() t3 = time.time() if Detail: print("LLL done in {:0.3f}".format(t3 - t2)) if debug: assert U.matdet() in [1, -1] C1 *= U B1 = U**(-1) * B1 if debug: assert CB == C1 * B1 print("found Bred, Cred") # Convert back to lists of lists Cred = [ci.list() for ci in C1.mattranspose()] Bred = [bi.list() for bi in B1.mattranspose()] if Detail > 1: print("After LLL, coefficients:\n{}\nbasis={}".format(Cred, Bred)) return Cred, Bred