def compute_diagonalisation(nf, lie_algebra, h_er_trunc, max_degree, tolerance, system_prefix): """ Here, just go as far as we can with double precision, and dump the output files. """ nf.set_tolerance(tolerance) desired_grade = max_degree nf.desired_grade = max_degree logger.info('main computation started...') #setup: nf.h_er = nf.alg.isograde(nf.h_er, 0, desired_grade + 1) nf.confirm_equilibrium_point() #output max grade print "Set up to degree", desired_grade, #output h_er print "with hamiltonian degree", nf.h_er.degree() #diagonalize nf.diagonalize() #compute the complexification maps eq_type = nf.eig.get_equilibrium_type() nf.eq_type = eq_type com = Complexifier(lie_algebra, eq_type) nf.com = com r_from_c = com.calc_sub_complex_into_real() c_from_r = com.calc_sub_real_into_complex() nf.r_in_terms_of_c = r_from_c nf.c_in_terms_of_r = c_from_r # convert to semi classical and then output files if isinstance(nf, SemiclassicalNormalForm): nf.quantize() r_from_c = nf.r_in_terms_of_c c_from_r = nf.c_in_terms_of_r #make a polynomial ring io, poss SemiClassical lie_algebra = nf.alg ring_io = PolynomialRingIO(lie_algebra) #dump the Taylor series dump_isogrades(nf.alg, nf.h_er, max_degree, example.prefix, 'h-from-e') #output vector of polynomials for er in terms of dr er_from_dr = nf.er_in_terms_of_dr file_name = '%s--e-from-d.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, er_from_dr) file_ostr.close() #output equilibrium type print nf.eig.get_equilibrium_type() #output the complexification maps file_name = '%s--r-from-c.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, r_from_c) file_ostr.close() file_name = '%s--c-from-r.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, c_from_r) file_ostr.close()
def compute_diagonalisation(nf, lie_algebra, h_er_trunc, max_degree, tolerance, system_prefix): """ Here, just go as far as we can with double precision, and dump the output files. """ nf.set_tolerance(tolerance) desired_grade = max_degree nf.desired_grade = max_degree logger.info('main computation started...') #setup: nf.h_er = nf.alg.isograde(nf.h_er, 0, desired_grade+1) nf.confirm_equilibrium_point() #output max grade print "Set up to degree", desired_grade, #output h_er print "with hamiltonian degree", nf.h_er.degree() #diagonalize nf.diagonalize() #compute the complexification maps eq_type = nf.eig.get_equilibrium_type() nf.eq_type = eq_type com = Complexifier(lie_algebra, eq_type) nf.com = com r_from_c = com.calc_sub_complex_into_real() c_from_r = com.calc_sub_real_into_complex() nf.r_in_terms_of_c = r_from_c nf.c_in_terms_of_r = c_from_r # convert to semi classical and then output files if isinstance(nf, SemiclassicalNormalForm): nf.quantize() r_from_c = nf.r_in_terms_of_c c_from_r = nf.c_in_terms_of_r #make a polynomial ring io, poss SemiClassical lie_algebra = nf.alg ring_io = PolynomialRingIO(lie_algebra) #dump the Taylor series dump_isogrades(nf.alg, nf.h_er, max_degree, example.prefix, 'h-from-e') #output vector of polynomials for er in terms of dr er_from_dr = nf.er_in_terms_of_dr file_name = '%s--e-from-d.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, er_from_dr) file_ostr.close() #output equilibrium type print nf.eig.get_equilibrium_type() #output the complexification maps file_name = '%s--r-from-c.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, r_from_c) file_ostr.close() file_name = '%s--c-from-r.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, c_from_r) file_ostr.close()
def test_saddle(self): lie = LieAlgebra(1) diag = Diagonalizer(lie) q = lie.q p = lie.p orig = q(0)*p(0) eq_type = 's' comp = Complexifier(lie, eq_type) r2c = comp.calc_sub_complex_into_real() c2r = comp.calc_sub_real_into_complex() comp = orig.substitute(r2c) real = comp.substitute(c2r) diff = orig-real for m, c in diff.powers_and_coefficients(): self.assert_(abs(c)<1.0e-15)
def test_saddle(self): lie = LieAlgebra(1) diag = Diagonalizer(lie) q = lie.q p = lie.p orig = q(0) * p(0) eq_type = 's' comp = Complexifier(lie, eq_type) r2c = comp.calc_sub_complex_into_real() c2r = comp.calc_sub_real_into_complex() comp = orig.substitute(r2c) real = comp.substitute(c2r) diff = orig - real for m, c in diff.powers_and_coefficients(): self.assert_(abs(c) < 1.0e-15)
def test_mutual_inverses(self): lie = LieAlgebra(6) diag = Diagonalizer(lie) pol = lie.zero() for i in xrange(6): pol += lie.q(i) pol += lie.p(i) eq_type = 'scccsc' comp = Complexifier(lie, eq_type) sub_c_into_r = comp.calc_sub_complex_into_real() sub_r_into_c = comp.calc_sub_real_into_complex() pol_c = pol.substitute(sub_c_into_r) pol_r = pol_c.substitute(sub_r_into_c) self.assert_(len(pol_r) == len(pol)) for i in xrange(6): self.assert_((pol_r-pol).l_infinity_norm() < 1.0e-15) self.assert_((pol_r-pol).l_infinity_norm() < 1.0e-15)
def test_mutual_inverses(self): lie = LieAlgebra(6) diag = Diagonalizer(lie) pol = lie.zero() for i in xrange(6): pol += lie.q(i) pol += lie.p(i) eq_type = 'scccsc' comp = Complexifier(lie, eq_type) sub_c_into_r = comp.calc_sub_complex_into_real() sub_r_into_c = comp.calc_sub_real_into_complex() pol_c = pol.substitute(sub_c_into_r) pol_r = pol_c.substitute(sub_r_into_c) self.assert_(len(pol_r) == len(pol)) for i in xrange(6): self.assert_((pol_r - pol).l_infinity_norm() < 1.0e-15) self.assert_((pol_r - pol).l_infinity_norm() < 1.0e-15)
def test_centre_saddle(self): lie = LieAlgebra(2) diag = Diagonalizer(lie) q = lie.q p = lie.p cent = (0.5*q(0)**2)+(0.5*p(0)**2) sadd = (1.0*q(1))*(1.0*p(1)) orig = cent + sadd self.assertEquals(len(orig), 3) eq_type = 'cs' comp = Complexifier(lie, eq_type) r2c = comp.calc_sub_complex_into_real() c2r = comp.calc_sub_real_into_complex() comp = orig.substitute(r2c) self.assertEquals(len(comp), 2) real = comp.substitute(c2r) diff = orig-real for m, c in diff.powers_and_coefficients(): self.assert_(abs(c)<1.0e-15)
def test_centre_saddle(self): lie = LieAlgebra(2) diag = Diagonalizer(lie) q = lie.q p = lie.p cent = (0.5 * q(0)**2) + (0.5 * p(0)**2) sadd = (1.0 * q(1)) * (1.0 * p(1)) orig = cent + sadd self.assertEquals(len(orig), 3) eq_type = 'cs' comp = Complexifier(lie, eq_type) r2c = comp.calc_sub_complex_into_real() c2r = comp.calc_sub_real_into_complex() comp = orig.substitute(r2c) self.assertEquals(len(comp), 2) real = comp.substitute(c2r) diff = orig - real for m, c in diff.powers_and_coefficients(): self.assert_(abs(c) < 1.0e-15)
def compute_diagonalisation(lie_algebra, h_er_trunc, max_degree, tolerance, system_prefix): """ Here, just go as far as we can with double precision, and dump the output files. """ nf = NormalForm(lie_algebra, h_er_trunc) nf.set_tolerance(tolerance) desired_grade = max_degree nf.desired_grade = max_degree logger.info('main computation started...') #setup: nf.h_er = nf.alg.isograde(nf.h_er, 0, desired_grade+1) nf.confirm_equilibrium_point() #output max grade print desired_grade #output h_er print nf.h_er #diagonalize nf.diagonalize() #make a polynomial ring io ring_io = PolynomialRingIO(lie_algebra) #output vector of polynomials for er in terms of dr er_from_dr = nf.er_in_terms_of_dr file_name = '%s--e-from-d.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, er_from_dr) file_ostr.close() #output equilibrium type print nf.eig.get_equilibrium_type() #compute the complexification maps eq_type = nf.eig.get_equilibrium_type() com = Complexifier(lie_algebra, eq_type) r_from_c = com.calc_sub_complex_into_real() c_from_r = com.calc_sub_real_into_complex() #output the complexification maps file_name = '%s--r-from-c.vpol' % system_prefix file_ostr = open(file_name, 'w') ring_io.write_sexp_vector_of_polynomials(file_ostr, r_from_c) file_ostr.close()
def test_centre(self): lie = LieAlgebra(1) diag = Diagonalizer(lie) q = lie.q p = lie.p orig = (0.5 * q(0)**2) + (0.5 * p(0)**2) self.assertEquals(len(orig), 2) eq_type = 'c' comp = Complexifier(lie, eq_type) r2c = comp.calc_sub_complex_into_real() c2r = comp.calc_sub_real_into_complex() comp = orig.substitute(r2c) self.assertEquals(len(comp), 1) for m, c in comp.powers_and_coefficients(): self.assert_(c.real == 0.0) self.assert_(m[0] == 1) self.assert_(m[1] == 1) real = comp.substitute(c2r) diff = orig - real for m, c in diff.powers_and_coefficients(): self.assert_(abs(c) < 1.0e-15)
def test_centre(self): lie = LieAlgebra(1) diag = Diagonalizer(lie) q = lie.q p = lie.p orig = (0.5*q(0)**2)+(0.5*p(0)**2) self.assertEquals(len(orig), 2) eq_type = 'c' comp = Complexifier(lie, eq_type) r2c = comp.calc_sub_complex_into_real() c2r = comp.calc_sub_real_into_complex() comp = orig.substitute(r2c) self.assertEquals(len(comp), 1) for m, c in comp.powers_and_coefficients(): self.assert_(c.real == 0.0) self.assert_(m[0] == 1) self.assert_(m[1] == 1) real = comp.substitute(c2r) diff = orig-real for m, c in diff.powers_and_coefficients(): self.assert_(abs(c)<1.0e-15)
def diagonalize(self, dof, h): tolerance = 5.0e-15 lie = self.alg diag = Diagonalizer(lie) eig = diag.compute_eigen_system(h, tolerance=tolerance) diag.compute_diagonal_change() mat = diag.get_matrix_diag_to_equi() assert diag.matrix_is_symplectic(mat) sub_diag_into_equi = diag.matrix_as_vector_of_row_polynomials(mat) h_diag = h.substitute(sub_diag_into_equi) eq_type = eig.get_equilibrium_type() comp = Complexifier(lie, eq_type) self.sub_c_into_r = comp.calc_sub_complex_into_real() self.sub_r_into_c = comp.calc_sub_real_into_complex() h_comp = h_diag.substitute(self.sub_c_into_r) h_comp = h_comp.with_small_coeffs_removed(tolerance) self.assert_(lie.is_diagonal_polynomial(h_comp.homogeneous(2))) return h_comp
class SemiclassicalNormalForm(NormalForm): def __init__(self, classical_lie_algebra, h_er): NormalForm.__init__(self, classical_lie_algebra, h_er) def quantize(self): cla_to_sem = ClassicalToSemiclassical(self.get_lie_algebra()) #keep classical versions self.alg_classical = self.alg self.com_classical = self.com self.c_in_terms_of_r_classical = self.c_in_terms_of_r self.r_in_terms_of_c_classical = self.r_in_terms_of_c # if we have h_dc convert it if hasattr(self,"h_dc"): self.h_dc_classical = self.h_dc self.h_dc = cla_to_sem(self.h_dc) #make semiclassical versions self.alg = cla_to_sem.semi_classical_algebra() n_vars = self.alg.n_vars() self.com = Complexifier(self.alg, self.eq_type) self.r_in_terms_of_c = self.com.calc_sub_complex_into_real() self.c_in_terms_of_r = self.com.calc_sub_real_into_complex() #make polys for use by cplusplus self.h_er_classical = self.h_er self.h_er = cla_to_sem(self.h_er) self.er_in_terms_of_dr_classical = self.er_in_terms_of_dr er_in_terms_of_dr = [] for i in xrange(len(self.er_in_terms_of_dr)): er_in_terms_of_dr.append(cla_to_sem(self.er_in_terms_of_dr[i])) er_in_terms_of_dr.append(Polynomial.Polynomial.CoordinateMonomial(n_vars,n_vars-1)) self.er_in_terms_of_dr = er_in_terms_of_dr def perform_all_computations(self, desired_grade): """ Overrides classical normal form. """ logger.info('main computation started...') #flags for extra computations: do_check_generating_function_invariant = False do_check_diag_transforms_to_norm = False do_compute_complex_diag_vs_norm = False do_check_diag_vs_norm_using_conversion = False #setup: self.desired_grade = desired_grade self.h_er = self.alg.isograde(self.h_er, 0, desired_grade+1) self.confirm_equilibrium_point() #main steps: self.diagonalize() self.complexify() self.quantize() self.normalize() #the following need semiclassical real-complex relations... self.normalize_real() #self.extract_integrals() #optional computations: #if do_check_generating_function_invariant: # self.check_generating_function_invariant() #if do_check_diag_transforms_to_norm: # self.check_diag_transforms_to_norm() #if do_compute_complex_diag_vs_norm: # self.compute_diag_to_norm() # self.compute_norm_to_diag() #coordinate change maps: #self.compute_diag_to_norm_real_using_w_real() #self.compute_norm_to_diag_real_using_w_real() #optional computations: #if do_check_diag_vs_norm_using_conversion: # self.compute_diag_to_norm_real_using_conversion() # self.compute_norm_to_diag_real_using_conversion() logger.info('...main computation done.')
class NormalForm: def __init__(self, lie_algebra, h_er): logger.info('Initializing...') self.alg = lie_algebra self.h_er = h_er logger.info('...done initializing.') def get_lie_algebra(self): return self.alg def set_tolerance(self, tolerance): self.tolerance = tolerance def confirm_equilibrium_point(self): logger.info('Confirming equilibrium point...') alg = self.alg #logger.info('Real Equilibrium Hamiltonian (terms up to grade') #logger.info(truncated_poly(self.alg, self.h_er)) logger.info('Equilibrium Hamiltonian has %d terms'%self.h_er.n_terms()) gra = alg.grade(self.h_er) if alg.isograde(self.h_er, 0): logger.error('WARNING! constant term on input Hamiltonian removed') logger.error('size %s', alg.isograde(self.h_er, 0).l_infinity_norm()) self.h_er = alg.isograde(self.h_er, 1, alg.grade(self.h_er)+1) if alg.isograde(self.h_er, 1): logger.error('WARNING! linear term on input Hamiltonian removed') logger.error('size %s', alg.isograde(self.h_er, 1).l_infinity_norm()) self.h_er = alg.isograde(self.h_er, 2, alg.grade(self.h_er)+1) assert not alg.isograde(self.h_er, 0, 2) assert gra == alg.grade(self.h_er) logger.info('WARNING! Removing small coefficients of size <=%s'%tol_equi_real_coeffs) self.h_er = self.h_er.with_small_coeffs_removed(tol_equi_real_coeffs) logger.info('Real Equilibrium Hamiltonian has %d terms'%self.h_er.n_terms()) logger.info('...done confirming equilibrium point.') def diagonalize(self): logger.info('Diagonalizing...') self.dia = Diagonalizer(self.alg) logger.info('Equilibrium Hamiltonian has %d terms'%self.h_er.n_terms()) logger.info('Computing the eigensystem...') self.eig = self.dia.compute_eigen_system(self.h_er, self.tolerance) logger.info('...done computing the eigensystem.') logger.info('Computing the diagonal change...') self.dia.compute_diagonal_change() logger.info('...done computing the diagonal change.') logger.info('Measuring error in symplectic identities...') mat = self.dia.get_matrix_diag_to_equi() assert self.dia.matrix_is_symplectic(mat) logger.info('...done measuring error in symplectic identities.') logger.info('Converting the matrix into vec<poly> representation...') er_in_terms_of_dr = self.dia.matrix_as_vector_of_row_polynomials(mat) self.er_in_terms_of_dr = er_in_terms_of_dr logger.info('... done converting the matrix into vec<poly> repn.') logger.info('Applying diagonalizing change to equilibrium H...') self.h_dr = self.h_er.substitute(er_in_terms_of_dr) logger.info('...done applying diagonalizing change to equilibrium H.') del er_in_terms_of_dr logger.info('Real diagonal Hamiltonian has %d terms'%self.h_dr.n_terms()) err = self.h_dr.imag().l_infinity_norm() logger.info('Size of imaginary part: %s', err) assert err < tol_diag_real_imag_part logger.info('WARNING! Removing imaginary terms') self.h_dr = self.h_dr.real() logger.info('Real diagonal Hamiltonian has %d terms'%self.h_dr.n_terms()) logger.info('WARNING! Removing small coefficients of size <=%s'%tol_diag_real_coeffs) self.h_dr = self.h_dr.with_small_coeffs_removed(tol_diag_real_coeffs) logger.info('Real diagonal Hamiltonian has %d terms'%self.h_dr.n_terms()) #logger.info('Real Diagonal Hamiltonian (terms up to gra 3)') #logger.info(truncated_poly(self.alg, self.h_dr)) logger.info('Quadratic part') logger.info(truncated_poly(self.alg, self.alg.isograde(self.h_dr, 2))) logger.info('Terms in quadratic part %d'%(self.alg.isograde(self.h_dr, 2).n_terms())) logger.info('...done diagonalizing.') def complexify(self): logger.info('Complexifying...') self.eq_type = self.eig.get_equilibrium_type() logger.info('Equilibrium type %s'%self.eq_type) logger.info('Terms in real diagonal %d'%self.h_dr.n_terms()) self.com = Complexifier(self.alg, self.eq_type) self.r_in_terms_of_c = self.com.calc_sub_complex_into_real() self.c_in_terms_of_r = self.com.calc_sub_real_into_complex() logger.info('Performing complex substitution...') self.h_dc = self.h_dr.substitute(self.r_in_terms_of_c) logger.info('Terms in complex diagonal %d'%self.h_dc.n_terms()) logger.info('Removing small coefficients...') self.h_dc = self.h_dc.with_small_coeffs_removed(self.tolerance) logger.info('Terms in complex diagonal %d'%self.h_dc.n_terms()) h_dc_2 = self.alg.isograde(self.h_dc, 2) off_diag = h_dc_2 - self.alg.diagonal_part_of_polynomial(h_dc_2) err = off_diag.l_infinity_norm() logger.info('Size of off-diagonal part of quadratic part of diagonal h: %s', err) assert err < tol_diag_comp_off_diag_part logger.info('Removing off-diagonal part') self.h_dc -= off_diag del off_diag logger.info('Terms in complex diagonal %d'%self.h_dc.n_terms()) h_dc_2 = self.alg.isograde(self.h_dc, 2) logger.info('Quadratic part') logger.info(self.alg.display(h_dc_2)) assert (self.alg.is_diagonal_polynomial(h_dc_2)) del h_dc_2 self.eig_vals = self.eig.get_eigen_values_in_plus_minus_pairs() logger.info('Complex diagonal Hamiltonian has %d terms'%self.h_dc.n_terms()) logger.info('...done complexifying.') def cvec2r_to_rvec2r(self, p): """ @param p: a polynomial map from a vector of complex coordinates to a real scalar. @return: a polynomial map from the real version of the coordinates to the real scalar. """ return p.substitute(self.c_in_terms_of_r) def cvec2cvec_to_rvec2rvec(self, vp): """ @param vp: vector of polynomial maps from vector of complex coordinates to a complex coordinate. @return: vector of polynomial maps from vector of reals to real. """ cvec_in_rvec = [] for i in xrange(len(vp)): cvec_in_rvec.append(vp[i].substitute(self.c_in_terms_of_r)) cvec_in_cvec = [] for r_in_c_i in self.r_in_terms_of_c: cvec_in_cvec.append(r_in_c_i.substitute(cvec_in_rvec)) return cvec_in_cvec def normalize(self): logger.info('Normalizing...') steps = self.desired_grade-1 #1+h_dc.grade()-2 self.w_c_list = [] self.h_nc_list = [] self.h_nc_dict = {} self.h_nc = self.alg.zero() self.w_c = self.alg.zero() h_dc_2 = self.alg.isograde(self.h_dc, 2) state = (self.h_nc_dict, self.w_c_list, -1) tri = LieTriangle.LieTriangle(self.alg, h_dc_2, state) # # note that, in the following, h_term is _NOT_ h_i for the # Deprit triangle; it is (h_i)/factorial(i) and this is # taken care of _WITHIN_ the triangle procedure. # for step in xrange(0, steps + 1): h_term = self.alg.isograde(self.h_dc, step + 2) k_term, w_term = tri.compute_normal_form_and_generating_function(h_term) logger.info('Resulting normal form terms:') logger.info(truncated_poly(self.alg, k_term)) self.h_nc += k_term self.w_c += w_term logger.info('Complex normal form:') logger.info(truncated_poly(self.alg, self.h_nc)) self.iso_nf = tri.get_isograde_list_handler() #h_nc_new = tri.compute_lie_transform_given_generating_function([], steps) #logger.info('Normalized using computed generating function:') #logger.info(self.alg.display(h_nc_new)) def check_generating_function_invariant(self): logger.info('confirming generating function invariant...') grade = self.alg.grade #1+self.h_dc.grade()-3 #check steps = self.desired_grade-2 logger.info('surely we can use independent no. steps in coord change,') logger.info('than we did in the nf computation? CARE!!!') logger.info('the generating function is only invariant with correct steps.') cc = CoordinateChange(self.alg, self.w_c_list) res1 = [] cc.express_norm_in_diag(self.w_c, res1, {}, steps) res2 = [] cc.express_diag_in_norm(self.w_c, res2, {}, steps) iso_cc = cc.get_isograde_list_handler() for res in [res1, res2]: w_c_new = iso_cc.list_to_poly(res) logger.info('Grade %d to %d', grade(self.w_c), grade(w_c_new)) gra = min((grade(self.w_c), grade(w_c_new))) err = self.alg.isograde((w_c_new-self.w_c), 0, gra+1).l_infinity_norm() logger.info('Change in like-grade part of generating function: %s', err) assert err < tol_comp_generator_through_lie_triangle del cc del res1 del res2 del iso_cc del w_c_new def check_diag_transforms_to_norm(self): logger.info('confirming that diagonal Hamiltonian transforms to normal...') grade = self.alg.grade steps = self.desired_grade-2 #1+self.h_dc.grade()-3 cc = CoordinateChange(self.alg, self.w_c_list) iso_cc = cc.get_isograde_list_handler() res1 = [] cc.express_norm_in_diag(self.h_nc, res1, {}, steps) h_dc_new = iso_cc.list_to_poly(res1) gra = min((grade(self.h_dc), grade(h_dc_new))) err = self.alg.isograde(self.h_dc-h_dc_new, 0, gra+1).l_infinity_norm() logger.info('Error expressing H_{nc} in x_{dc}') logger.info('Grade %d to %d', grade(self.h_dc), grade(h_dc_new)) logger.info(err) logger.info('confirming that normal Hamiltonian transforms to diagonal...') res2 = [] cc.express_diag_in_norm(self.h_dc, res2, {}, steps) h_nc_new = iso_cc.list_to_poly(res2) gra = min((grade(self.h_nc), grade(h_nc_new))) err = self.alg.isograde(self.h_nc-h_nc_new, 0, gra+1).l_infinity_norm() logger.info('Error expressing H_{dc} in x_{nc}') logger.info('Grade %d to %d', grade(self.h_nc), grade(h_nc_new)) logger.info(err) del cc del iso_cc del h_dc_new del h_nc_new del res1 del res2 def normalize_real(self): logger.info('computing real normalization...') self.h_nr = self.h_nc.substitute(self.c_in_terms_of_r) err = self.h_nr.imag().l_infinity_norm() tol_norm_real_imag_part = (1.0 + self.h_nr.l_infinity_norm()) * 1.0e-10 logger.info('l infinity norm of real normal form imaginary part: %s', err) assert err < tol_norm_real_imag_part self.h_nr = self.h_nr.real() logger.info('Real normal form:') logger.info(truncated_poly(self.alg, self.h_nr)) self.w_r_list = [p.substitute(self.c_in_terms_of_r) for p in self.w_c_list] #self.w_r = self.iso_nf.list_to_poly(self.w_r_list) def extract_integrals(self): logger.info('extracting the integrals...') int_ext = IntegralExtractor(self.alg) int_ext.set_complex_normal_hamiltonian(self.h_nc) int_ext.find_lost_simple_integrals_and_non_simple_integral() logger.info('Lost integrals:') logger.info(int_ext._lost_integrals) assert ((not int_ext._lost_integrals), int_ext._lost_integrals) logger.info('Real simple part:') logger.info((self.cvec2r_to_rvec2r(int_ext._simple_part))) logger.info('Real non-simple part:') logger.info((self.cvec2r_to_rvec2r(int_ext._non_simple_integral))) int_ext.list_the_simple_integrals() logger.info('Kept integrals:') logger.info(int_ext._kept_integrals) int_ext.express_simple_part_as_polynomial_over_all_integrals() logger.info('Simple part in terms of integrals:') logger.info((int_ext._simple_in_integrals)) int_ext.express_both_parts_as_polynomial_over_all_integrals() logger.info('Total in terms of integrals') logger.info((int_ext._total_in_integrals)) int_ext.express_all_integrals_in_normal_form_coords() logger.info('Complex Integrals in complex normal form coords:') logger.info((int_ext._integrals_in_coords)) logger.info('Complex Integrals in real normal form coords:') ic_in_nr = [self.cvec2r_to_rvec2r(int_i) for int_i in int_ext._integrals_in_coords] logger.info(ic_in_nr) #convert simple part in terms of complex integrals, #to simple part in terms of real integrals. def simple_int_is_saddle(real_integral): return len(real_integral) == 1 def simple_int_is_centre(real_integral): return len(real_integral) == 2 comp_ints_in_real_ints = [] real_integrals = [] n_integrals = len(int_ext._integrals_in_coords) ring_ints = PolynomialRing(n_integrals) for i, integral in zip(int_ext._kept_integrals, int_ext._integrals_in_coords): # This is the complex integral in real coordinates real_integral = integral.substitute(self.c_in_terms_of_r) mon = ring_ints.coordinate_monomial(i) if simple_int_is_centre(real_integral): # Note that a centre real integral = i * complex integral comp_ints_in_real_ints.append((-1.0J)*mon) real_integrals.append((1.0J)*real_integral) logger.info('centre') elif simple_int_is_saddle(real_integral): comp_ints_in_real_ints.append(mon) real_integrals.append(real_integral) logger.info('saddle') else: assert 0, 'Simple integral, neither saddle nor centre!' h_ir = int_ext._simple_in_integrals.substitute(comp_ints_in_real_ints) logger.info('Simple part in terms of the real simple integrals:') logger.info(h_ir) logger.info('Real integrals in real nf coords:') logger.info(real_integrals) #we should check this by converting the simple part to real h_ir_check = self.cvec2r_to_rvec2r(int_ext._simple_part) err = (h_ir_check-h_ir.substitute(real_integrals)).l_infinity_norm() logger.info('Error in composite of real integrals and real simple part') logger.info(err) self.h_ir = h_ir self.real_integrals = real_integrals def compute_diag_to_norm(self): logger.info('computing coordinate changes...') steps = self.desired_grade-2 #1+self.h_dc.grade()-3 #check! res = [] for s in xrange(self.alg.n_vars()): #do we request a coordinate change in h-bar??? logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [0,]*(self.alg.n_vars()) sp[s] = 1 #use complex nf logger.info('COMPLEX component of x_{nc} expressed IN x_{dc} (diag TO norm):') x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_c_list) cc.express_norm_in_diag(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1+1)) iso_cc = cc.get_isograde_list_handler() #for i, polc in enumerate(x_i_list): #logger.info(truncated_poly(self.alg, iso_cc.inner_taylor_to_poly(polc, i))) poly = iso_cc.list_to_poly(x_i_list) res.append(poly) self.nc_in_dc = res def compute_diag_to_norm_real_using_w_real(self): logger.info('computing real coordinate changes using real generator...') steps = self.desired_grade-2 #self.h_dc.grade()-2 #check! res = [] for s in xrange(self.alg.n_vars()): logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [0,]*(self.alg.n_vars()) sp[s] = 1 #use real nf logger.info('REAL component of x_{nr} expressed IN x_{dc} (diag TO norm):') x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_r_list) cc.express_norm_in_diag(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1+1)) iso_cc = cc.get_isograde_list_handler() for i, polc in enumerate(x_i_list): err = polc.imag().l_infinity_norm() logger.info('l_infinity_norm of imaginary part: %s', err) tol_norm_real_imag_part = (1.0 + self.w_r_list[i].l_infinity_norm()) * 1.0e-10 assert err < tol_norm_real_imag_part #logger.info(truncated_poly(self.alg, iso_cc.inner_taylor_to_poly(polc.real(), i))) poly = iso_cc.list_to_poly(x_i_list) res.append(poly.real()) self.nr_in_dr_via_wr = res def compute_diag_to_norm_real_using_conversion(self): logger.info('computing real coordinate changes using real conversion...') res = self.cvec2cvec_to_rvec2rvec(self.nc_in_dc) self.nr_in_dr_via_nc_in_dc = res logger.info('ERRORS in real generator vs. conversion:') for m0, m1 in zip(self.nr_in_dr_via_nc_in_dc, self.nr_in_dr_via_wr): err = (m1-m0).l_infinity_norm() logger.info(err) def compute_norm_to_diag(self): logger.info('computing inverse coordinate changes...') steps = self.desired_grade-2 #1+self.h_dc.grade()-3 #check! res = [] for s in xrange(self.alg.n_vars()): logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [0,]*(self.alg.n_vars()) sp[s] = 1 #use complex nf logger.info('COMPLEX component of x_{dc} expressed IN x_{nc} (norm TO diag):') x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_c_list) cc.express_diag_in_norm(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1+1)) iso_cc = cc.get_isograde_list_handler() #for i, polc in enumerate(x_i_list): #logger.info(truncated_poly(self.alg, iso_cc.inner_taylor_to_poly(polc, i))) poly = iso_cc.list_to_poly(x_i_list) res.append(poly) self.dc_in_nc = res def compute_norm_to_diag_real_using_w_real(self): logger.info('computing real inverse coordinate change using real generator...') steps = self.desired_grade-2 #self.h_dc.grade()-2 #check! res = [] for s in xrange(self.alg.n_vars()): logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [0,]*(self.alg.n_vars()) sp[s] = 1 #use real nf logger.info('REAL component of x_{dc} expressed IN x_{nr} (norm TO diag):') x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_r_list) cc.express_diag_in_norm(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1+1)) iso_cc = cc.get_isograde_list_handler() for i, polc in enumerate(x_i_list): err = polc.imag().l_infinity_norm() logger.info('l_infinity_norm of imaginary part: %s', err) tol_norm_real_imag_part = (1.0 + self.w_r_list[i].l_infinity_norm()) * 1.0e-10 assert err < tol_norm_real_imag_part poly = iso_cc.list_to_poly(x_i_list) res.append(poly.real()) self.dr_in_nr_via_wr = res def compute_norm_to_diag_real_using_conversion(self): logger.info('computing real inverse coordinate changes using real conversion...') res = self.cvec2cvec_to_rvec2rvec(self.dc_in_nc) self.nr_in_dr_via_nc_in_dc = res logger.info('ERRORS in real generator vs. conversion:') for m0, m1 in zip(self.nr_in_dr_via_nc_in_dc, self.dr_in_nr_via_wr): err = (m1-m0).l_infinity_norm() logger.info(err) def perform_all_computations(self, desired_grade): logger.info('main computation started...') #flags for extra computations: do_check_generating_function_invariant = False do_check_diag_transforms_to_norm = False do_compute_complex_diag_vs_norm = False do_check_diag_vs_norm_using_conversion = False #setup: self.desired_grade = desired_grade self.h_er = self.alg.isograde(self.h_er, 0, desired_grade+1) self.confirm_equilibrium_point() #main steps: self.diagonalize() self.complexify() self.normalize() self.normalize_real() self.extract_integrals() #optional computations: if do_check_generating_function_invariant: self.check_generating_function_invariant() if do_check_diag_transforms_to_norm: self.check_diag_transforms_to_norm() if do_compute_complex_diag_vs_norm: self.compute_diag_to_norm() self.compute_norm_to_diag() #coordinate change maps: self.compute_diag_to_norm_real_using_w_real() self.compute_norm_to_diag_real_using_w_real() #optional computations: if do_check_diag_vs_norm_using_conversion: self.compute_diag_to_norm_real_using_conversion() self.compute_norm_to_diag_real_using_conversion() logger.info('...main computation done.') #h_nr_check = self.h_dr.substitute(self.dr_in_nr_via_wr) #print "(self.h_dr.substitute(self.dr_in_nr_via_wr)-self.h_nr).l_infinity_norm()\n", h_nr_check.l_infinity_norm(), self.h_nr.l_infinity_norm(), (h_nr_check-self.h_nr).l_infinity_norm(), "\n", h_nr_check.l1_norm(), self.h_nr.l1_norm(), (h_nr_check-self.h_nr).l1_norm() #h_dr_check = self.h_nr.substitute(self.nr_in_dr_via_wr) #print "(self.h_nr.substitute(self.nr_in_dr_via_wr)-self.h_dr).l_infinity_norm()\n", h_dr_check.l_infinity_norm(), self.h_dr.l_infinity_norm(), (h_dr_check-self.h_dr).l_infinity_norm(), "\n", h_dr_check.l1_norm(), self.h_dr.l1_norm(), (h_dr_check-self.h_dr).l1_norm() #print "truncated to degree 5" #print self.alg.isograde(h_dr_check-self.h_dr, 1, up_to=5).l1_norm() #print self.alg.isograde(h_nr_check-self.h_nr, 1, up_to=5).l1_norm() self.write_out_integrals() self.write_out_transforms() def write_out_transforms(self): #write out in Mathematica xxpp format is_xxpp_format = True write_file_mat("diag_to_equi.mat", self.dia.matrix_diag_to_equi) write_file_mat("equi_to_diag.mat", self.dia.get_matrix_equi_to_diag()) write_file_vec_polynomials("norm_to_diag.vec", self.dr_in_nr_via_wr, is_xxpp_format) write_file_vec_polynomials("diag_to_norm.vec", self.nr_in_dr_via_wr, is_xxpp_format) write_file_vec_polynomials("norm_to_ints.vec", self.real_integrals, is_xxpp_format) write_file_polynomial("equi_to_tham.pol", self.h_er, is_xxpp_format) def write_out_integrals(self): #write out in Mathematica xxpp format is_xxpp_format = True # equi_to_tvec is J.Hessian hess = [] for i in xrange(self.h_er.n_vars()): hess.append(self.h_er.diff(i)) e2tv = [ poly.substitute(hess) for poly in self.dia.matrix_as_vector_of_row_polynomials(self.dia.skew_symmetric_matrix())] write_file_vec_polynomials("equi_to_tvec.vec",e2tv,is_xxpp_format) #These are dim dof, is_xxpp_format doesn't apply i2f = [] for i in xrange(self.h_ir.n_vars()): i2f.append(self.h_ir.diff(i)) write_file_vec_polynomials("ints_to_freq.vec", i2f, False) file_ostr = open("ints_to_tham.pol", 'w') write_ascii_polynomial(file_ostr, self.h_ir.real(), False) file_ostr.close() logger.info('...done')
class NormalForm: def __init__(self, lie_algebra, h_er): logger.info('Initializing...') self.alg = lie_algebra self.h_er = h_er logger.info('...done initializing.') def get_lie_algebra(self): return self.alg def set_tolerance(self, tolerance): self.tolerance = tolerance def confirm_equilibrium_point(self): logger.info('Confirming equilibrium point...') alg = self.alg #logger.info('Real Equilibrium Hamiltonian (terms up to grade') #logger.info(truncated_poly(self.alg, self.h_er)) logger.info('Equilibrium Hamiltonian has %d terms' % self.h_er.n_terms()) gra = alg.grade(self.h_er) if alg.isograde(self.h_er, 0): logger.error('WARNING! constant term on input Hamiltonian removed') logger.error('size %s', alg.isograde(self.h_er, 0).l_infinity_norm()) self.h_er = alg.isograde(self.h_er, 1, alg.grade(self.h_er) + 1) if alg.isograde(self.h_er, 1): logger.error('WARNING! linear term on input Hamiltonian removed') logger.error('size %s', alg.isograde(self.h_er, 1).l_infinity_norm()) self.h_er = alg.isograde(self.h_er, 2, alg.grade(self.h_er) + 1) assert not alg.isograde(self.h_er, 0, 2) assert gra == alg.grade(self.h_er) logger.info('WARNING! Removing small coefficients of size <=%s' % tol_equi_real_coeffs) self.h_er = self.h_er.with_small_coeffs_removed(tol_equi_real_coeffs) logger.info('Real Equilibrium Hamiltonian has %d terms' % self.h_er.n_terms()) logger.info('...done confirming equilibrium point.') def diagonalize(self): logger.info('Diagonalizing...') self.dia = Diagonalizer(self.alg) logger.info('Equilibrium Hamiltonian has %d terms' % self.h_er.n_terms()) logger.info('Computing the eigensystem...') self.eig = self.dia.compute_eigen_system(self.h_er, self.tolerance) logger.info('...done computing the eigensystem.') logger.info('Computing the diagonal change...') self.dia.compute_diagonal_change() logger.info('...done computing the diagonal change.') logger.info('Measuring error in symplectic identities...') mat = self.dia.get_matrix_diag_to_equi() assert self.dia.matrix_is_symplectic(mat) logger.info('...done measuring error in symplectic identities.') logger.info('Converting the matrix into vec<poly> representation...') er_in_terms_of_dr = self.dia.matrix_as_vector_of_row_polynomials(mat) self.er_in_terms_of_dr = er_in_terms_of_dr logger.info('... done converting the matrix into vec<poly> repn.') logger.info('Applying diagonalizing change to equilibrium H...') self.h_dr = self.h_er.substitute(er_in_terms_of_dr) logger.info('...done applying diagonalizing change to equilibrium H.') del er_in_terms_of_dr logger.info('Real diagonal Hamiltonian has %d terms' % self.h_dr.n_terms()) err = self.h_dr.imag().l_infinity_norm() logger.info('Size of imaginary part: %s', err) assert err < tol_diag_real_imag_part logger.info('WARNING! Removing imaginary terms') self.h_dr = self.h_dr.real() logger.info('Real diagonal Hamiltonian has %d terms' % self.h_dr.n_terms()) logger.info('WARNING! Removing small coefficients of size <=%s' % tol_diag_real_coeffs) self.h_dr = self.h_dr.with_small_coeffs_removed(tol_diag_real_coeffs) logger.info('Real diagonal Hamiltonian has %d terms' % self.h_dr.n_terms()) #logger.info('Real Diagonal Hamiltonian (terms up to gra 3)') #logger.info(truncated_poly(self.alg, self.h_dr)) logger.info('Quadratic part') logger.info(truncated_poly(self.alg, self.alg.isograde(self.h_dr, 2))) logger.info('Terms in quadratic part %d' % (self.alg.isograde(self.h_dr, 2).n_terms())) logger.info('...done diagonalizing.') def complexify(self): logger.info('Complexifying...') self.eq_type = self.eig.get_equilibrium_type() logger.info('Equilibrium type %s' % self.eq_type) logger.info('Terms in real diagonal %d' % self.h_dr.n_terms()) self.com = Complexifier(self.alg, self.eq_type) self.r_in_terms_of_c = self.com.calc_sub_complex_into_real() self.c_in_terms_of_r = self.com.calc_sub_real_into_complex() logger.info('Performing complex substitution...') self.h_dc = self.h_dr.substitute(self.r_in_terms_of_c) logger.info('Terms in complex diagonal %d' % self.h_dc.n_terms()) logger.info('Removing small coefficients...') self.h_dc = self.h_dc.with_small_coeffs_removed(self.tolerance) logger.info('Terms in complex diagonal %d' % self.h_dc.n_terms()) h_dc_2 = self.alg.isograde(self.h_dc, 2) off_diag = h_dc_2 - self.alg.diagonal_part_of_polynomial(h_dc_2) err = off_diag.l_infinity_norm() logger.info( 'Size of off-diagonal part of quadratic part of diagonal h: %s', err) assert err < tol_diag_comp_off_diag_part logger.info('Removing off-diagonal part') self.h_dc -= off_diag del off_diag logger.info('Terms in complex diagonal %d' % self.h_dc.n_terms()) h_dc_2 = self.alg.isograde(self.h_dc, 2) logger.info('Quadratic part') logger.info(self.alg.display(h_dc_2)) assert (self.alg.is_diagonal_polynomial(h_dc_2)) del h_dc_2 self.eig_vals = self.eig.get_eigen_values_in_plus_minus_pairs() logger.info('Complex diagonal Hamiltonian has %d terms' % self.h_dc.n_terms()) logger.info('...done complexifying.') def cvec2r_to_rvec2r(self, p): """ @param p: a polynomial map from a vector of complex coordinates to a real scalar. @return: a polynomial map from the real version of the coordinates to the real scalar. """ return p.substitute(self.c_in_terms_of_r) def cvec2cvec_to_rvec2rvec(self, vp): """ @param vp: vector of polynomial maps from vector of complex coordinates to a complex coordinate. @return: vector of polynomial maps from vector of reals to real. """ cvec_in_rvec = [] for i in xrange(len(vp)): cvec_in_rvec.append(vp[i].substitute(self.c_in_terms_of_r)) cvec_in_cvec = [] for r_in_c_i in self.r_in_terms_of_c: cvec_in_cvec.append(r_in_c_i.substitute(cvec_in_rvec)) return cvec_in_cvec def normalize(self): logger.info('Normalizing...') steps = self.desired_grade - 1 #1+h_dc.grade()-2 self.w_c_list = [] self.h_nc_list = [] self.h_nc_dict = {} self.h_nc = self.alg.zero() self.w_c = self.alg.zero() h_dc_2 = self.alg.isograde(self.h_dc, 2) state = (self.h_nc_dict, self.w_c_list, -1) tri = LieTriangle.LieTriangle(self.alg, h_dc_2, state) # # note that, in the following, h_term is _NOT_ h_i for the # Deprit triangle; it is (h_i)/factorial(i) and this is # taken care of _WITHIN_ the triangle procedure. # for step in xrange(0, steps + 1): h_term = self.alg.isograde(self.h_dc, step + 2) k_term, w_term = tri.compute_normal_form_and_generating_function( h_term) logger.info('Resulting normal form terms:') logger.info(truncated_poly(self.alg, k_term)) self.h_nc += k_term self.w_c += w_term logger.info('Complex normal form:') logger.info(truncated_poly(self.alg, self.h_nc)) self.iso_nf = tri.get_isograde_list_handler() #h_nc_new = tri.compute_lie_transform_given_generating_function([], steps) #logger.info('Normalized using computed generating function:') #logger.info(self.alg.display(h_nc_new)) def check_generating_function_invariant(self): logger.info('confirming generating function invariant...') grade = self.alg.grade #1+self.h_dc.grade()-3 #check steps = self.desired_grade - 2 logger.info('surely we can use independent no. steps in coord change,') logger.info('than we did in the nf computation? CARE!!!') logger.info( 'the generating function is only invariant with correct steps.') cc = CoordinateChange(self.alg, self.w_c_list) res1 = [] cc.express_norm_in_diag(self.w_c, res1, {}, steps) res2 = [] cc.express_diag_in_norm(self.w_c, res2, {}, steps) iso_cc = cc.get_isograde_list_handler() for res in [res1, res2]: w_c_new = iso_cc.list_to_poly(res) logger.info('Grade %d to %d', grade(self.w_c), grade(w_c_new)) gra = min((grade(self.w_c), grade(w_c_new))) err = self.alg.isograde((w_c_new - self.w_c), 0, gra + 1).l_infinity_norm() logger.info('Change in like-grade part of generating function: %s', err) assert err < tol_comp_generator_through_lie_triangle del cc del res1 del res2 del iso_cc del w_c_new def check_diag_transforms_to_norm(self): logger.info( 'confirming that diagonal Hamiltonian transforms to normal...') grade = self.alg.grade steps = self.desired_grade - 2 #1+self.h_dc.grade()-3 cc = CoordinateChange(self.alg, self.w_c_list) iso_cc = cc.get_isograde_list_handler() res1 = [] cc.express_norm_in_diag(self.h_nc, res1, {}, steps) h_dc_new = iso_cc.list_to_poly(res1) gra = min((grade(self.h_dc), grade(h_dc_new))) err = self.alg.isograde(self.h_dc - h_dc_new, 0, gra + 1).l_infinity_norm() logger.info('Error expressing H_{nc} in x_{dc}') logger.info('Grade %d to %d', grade(self.h_dc), grade(h_dc_new)) logger.info(err) logger.info( 'confirming that normal Hamiltonian transforms to diagonal...') res2 = [] cc.express_diag_in_norm(self.h_dc, res2, {}, steps) h_nc_new = iso_cc.list_to_poly(res2) gra = min((grade(self.h_nc), grade(h_nc_new))) err = self.alg.isograde(self.h_nc - h_nc_new, 0, gra + 1).l_infinity_norm() logger.info('Error expressing H_{dc} in x_{nc}') logger.info('Grade %d to %d', grade(self.h_nc), grade(h_nc_new)) logger.info(err) del cc del iso_cc del h_dc_new del h_nc_new del res1 del res2 def normalize_real(self): logger.info('computing real normalization...') self.h_nr = self.h_nc.substitute(self.c_in_terms_of_r) err = self.h_nr.imag().l_infinity_norm() tol_norm_real_imag_part = (1.0 + self.h_nr.l_infinity_norm()) * 1.0e-10 logger.info('l infinity norm of real normal form imaginary part: %s', err) assert err < tol_norm_real_imag_part self.h_nr = self.h_nr.real() logger.info('Real normal form:') logger.info(truncated_poly(self.alg, self.h_nr)) self.w_r_list = [ p.substitute(self.c_in_terms_of_r) for p in self.w_c_list ] #self.w_r = self.iso_nf.list_to_poly(self.w_r_list) def extract_integrals(self): logger.info('extracting the integrals...') int_ext = IntegralExtractor(self.alg) int_ext.set_complex_normal_hamiltonian(self.h_nc) int_ext.find_lost_simple_integrals_and_non_simple_integral() logger.info('Lost integrals:') logger.info(int_ext._lost_integrals) assert ((not int_ext._lost_integrals), int_ext._lost_integrals) logger.info('Real simple part:') logger.info((self.cvec2r_to_rvec2r(int_ext._simple_part))) logger.info('Real non-simple part:') logger.info((self.cvec2r_to_rvec2r(int_ext._non_simple_integral))) int_ext.list_the_simple_integrals() logger.info('Kept integrals:') logger.info(int_ext._kept_integrals) int_ext.express_simple_part_as_polynomial_over_all_integrals() logger.info('Simple part in terms of integrals:') logger.info((int_ext._simple_in_integrals)) int_ext.express_both_parts_as_polynomial_over_all_integrals() logger.info('Total in terms of integrals') logger.info((int_ext._total_in_integrals)) int_ext.express_all_integrals_in_normal_form_coords() logger.info('Complex Integrals in complex normal form coords:') logger.info((int_ext._integrals_in_coords)) logger.info('Complex Integrals in real normal form coords:') ic_in_nr = [ self.cvec2r_to_rvec2r(int_i) for int_i in int_ext._integrals_in_coords ] logger.info(ic_in_nr) #convert simple part in terms of complex integrals, #to simple part in terms of real integrals. def simple_int_is_saddle(real_integral): return len(real_integral) == 1 def simple_int_is_centre(real_integral): return len(real_integral) == 2 comp_ints_in_real_ints = [] real_integrals = [] n_integrals = len(int_ext._integrals_in_coords) ring_ints = PolynomialRing(n_integrals) for i, integral in zip(int_ext._kept_integrals, int_ext._integrals_in_coords): # This is the complex integral in real coordinates real_integral = integral.substitute(self.c_in_terms_of_r) mon = ring_ints.coordinate_monomial(i) if simple_int_is_centre(real_integral): # Note that a centre real integral = i * complex integral comp_ints_in_real_ints.append((-1.0J) * mon) real_integrals.append((1.0J) * real_integral) logger.info('centre') elif simple_int_is_saddle(real_integral): comp_ints_in_real_ints.append(mon) real_integrals.append(real_integral) logger.info('saddle') else: assert 0, 'Simple integral, neither saddle nor centre!' h_ir = int_ext._simple_in_integrals.substitute(comp_ints_in_real_ints) logger.info('Simple part in terms of the real simple integrals:') logger.info(h_ir) logger.info('Real integrals in real nf coords:') logger.info(real_integrals) #we should check this by converting the simple part to real h_ir_check = self.cvec2r_to_rvec2r(int_ext._simple_part) err = (h_ir_check - h_ir.substitute(real_integrals)).l_infinity_norm() logger.info( 'Error in composite of real integrals and real simple part') logger.info(err) self.h_ir = h_ir self.real_integrals = real_integrals def compute_diag_to_norm(self): logger.info('computing coordinate changes...') steps = self.desired_grade - 2 #1+self.h_dc.grade()-3 #check! res = [] for s in xrange(self.alg.n_vars()): #do we request a coordinate change in h-bar??? logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [ 0, ] * (self.alg.n_vars()) sp[s] = 1 #use complex nf logger.info( 'COMPLEX component of x_{nc} expressed IN x_{dc} (diag TO norm):' ) x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_c_list) cc.express_norm_in_diag(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1 + 1)) iso_cc = cc.get_isograde_list_handler() #for i, polc in enumerate(x_i_list): #logger.info(truncated_poly(self.alg, iso_cc.inner_taylor_to_poly(polc, i))) poly = iso_cc.list_to_poly(x_i_list) res.append(poly) self.nc_in_dc = res def compute_diag_to_norm_real_using_w_real(self): logger.info( 'computing real coordinate changes using real generator...') steps = self.desired_grade - 2 #self.h_dc.grade()-2 #check! res = [] for s in xrange(self.alg.n_vars()): logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [ 0, ] * (self.alg.n_vars()) sp[s] = 1 #use real nf logger.info( 'REAL component of x_{nr} expressed IN x_{dc} (diag TO norm):') x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_r_list) cc.express_norm_in_diag(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1 + 1)) iso_cc = cc.get_isograde_list_handler() for i, polc in enumerate(x_i_list): err = polc.imag().l_infinity_norm() logger.info('l_infinity_norm of imaginary part: %s', err) tol_norm_real_imag_part = ( 1.0 + self.w_r_list[i].l_infinity_norm()) * 1.0e-10 assert err < tol_norm_real_imag_part #logger.info(truncated_poly(self.alg, iso_cc.inner_taylor_to_poly(polc.real(), i))) poly = iso_cc.list_to_poly(x_i_list) res.append(poly.real()) self.nr_in_dr_via_wr = res def compute_diag_to_norm_real_using_conversion(self): logger.info( 'computing real coordinate changes using real conversion...') res = self.cvec2cvec_to_rvec2rvec(self.nc_in_dc) self.nr_in_dr_via_nc_in_dc = res logger.info('ERRORS in real generator vs. conversion:') for m0, m1 in zip(self.nr_in_dr_via_nc_in_dc, self.nr_in_dr_via_wr): err = (m1 - m0).l_infinity_norm() logger.info(err) def compute_norm_to_diag(self): logger.info('computing inverse coordinate changes...') steps = self.desired_grade - 2 #1+self.h_dc.grade()-3 #check! res = [] for s in xrange(self.alg.n_vars()): logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [ 0, ] * (self.alg.n_vars()) sp[s] = 1 #use complex nf logger.info( 'COMPLEX component of x_{dc} expressed IN x_{nc} (norm TO diag):' ) x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_c_list) cc.express_diag_in_norm(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1 + 1)) iso_cc = cc.get_isograde_list_handler() #for i, polc in enumerate(x_i_list): #logger.info(truncated_poly(self.alg, iso_cc.inner_taylor_to_poly(polc, i))) poly = iso_cc.list_to_poly(x_i_list) res.append(poly) self.dc_in_nc = res def compute_norm_to_diag_real_using_w_real(self): logger.info( 'computing real inverse coordinate change using real generator...') steps = self.desired_grade - 2 #self.h_dc.grade()-2 #check! res = [] for s in xrange(self.alg.n_vars()): logger.info('complex coord change, component %d of %d', s, self.alg.n_vars()) xs = self.alg.coordinate_monomial(s) sp = [ 0, ] * (self.alg.n_vars()) sp[s] = 1 #use real nf logger.info( 'REAL component of x_{dc} expressed IN x_{nr} (norm TO diag):') x_i_list = [] x_ij_dict = {} cc = CoordinateChange(self.alg, self.w_r_list) cc.express_diag_in_norm(xs, x_i_list, x_ij_dict, steps) #near-identity? assert (len(x_i_list[0]) == 1) assert (x_i_list[0][Powers(tuple(sp))] == 1.0) for gra_minus_1, pol in enumerate(x_i_list): gra = self.alg.grade(pol) assert ((gra == 0) or (gra == gra_minus_1 + 1)) iso_cc = cc.get_isograde_list_handler() for i, polc in enumerate(x_i_list): err = polc.imag().l_infinity_norm() logger.info('l_infinity_norm of imaginary part: %s', err) tol_norm_real_imag_part = ( 1.0 + self.w_r_list[i].l_infinity_norm()) * 1.0e-10 assert err < tol_norm_real_imag_part poly = iso_cc.list_to_poly(x_i_list) res.append(poly.real()) self.dr_in_nr_via_wr = res def compute_norm_to_diag_real_using_conversion(self): logger.info( 'computing real inverse coordinate changes using real conversion...' ) res = self.cvec2cvec_to_rvec2rvec(self.dc_in_nc) self.nr_in_dr_via_nc_in_dc = res logger.info('ERRORS in real generator vs. conversion:') for m0, m1 in zip(self.nr_in_dr_via_nc_in_dc, self.dr_in_nr_via_wr): err = (m1 - m0).l_infinity_norm() logger.info(err) def perform_all_computations(self, desired_grade): logger.info('main computation started...') #flags for extra computations: do_check_generating_function_invariant = False do_check_diag_transforms_to_norm = False do_compute_complex_diag_vs_norm = False do_check_diag_vs_norm_using_conversion = False #setup: self.desired_grade = desired_grade self.h_er = self.alg.isograde(self.h_er, 0, desired_grade + 1) self.confirm_equilibrium_point() #main steps: self.diagonalize() self.complexify() self.normalize() self.normalize_real() self.extract_integrals() #optional computations: if do_check_generating_function_invariant: self.check_generating_function_invariant() if do_check_diag_transforms_to_norm: self.check_diag_transforms_to_norm() if do_compute_complex_diag_vs_norm: self.compute_diag_to_norm() self.compute_norm_to_diag() #coordinate change maps: self.compute_diag_to_norm_real_using_w_real() self.compute_norm_to_diag_real_using_w_real() #optional computations: if do_check_diag_vs_norm_using_conversion: self.compute_diag_to_norm_real_using_conversion() self.compute_norm_to_diag_real_using_conversion() logger.info('...main computation done.') #h_nr_check = self.h_dr.substitute(self.dr_in_nr_via_wr) #print "(self.h_dr.substitute(self.dr_in_nr_via_wr)-self.h_nr).l_infinity_norm()\n", h_nr_check.l_infinity_norm(), self.h_nr.l_infinity_norm(), (h_nr_check-self.h_nr).l_infinity_norm(), "\n", h_nr_check.l1_norm(), self.h_nr.l1_norm(), (h_nr_check-self.h_nr).l1_norm() #h_dr_check = self.h_nr.substitute(self.nr_in_dr_via_wr) #print "(self.h_nr.substitute(self.nr_in_dr_via_wr)-self.h_dr).l_infinity_norm()\n", h_dr_check.l_infinity_norm(), self.h_dr.l_infinity_norm(), (h_dr_check-self.h_dr).l_infinity_norm(), "\n", h_dr_check.l1_norm(), self.h_dr.l1_norm(), (h_dr_check-self.h_dr).l1_norm() #print "truncated to degree 5" #print self.alg.isograde(h_dr_check-self.h_dr, 1, up_to=5).l1_norm() #print self.alg.isograde(h_nr_check-self.h_nr, 1, up_to=5).l1_norm() self.write_out_integrals() self.write_out_transforms() def write_out_transforms(self): #write out in Mathematica xxpp format is_xxpp_format = True write_file_mat("diag_to_equi.mat", self.dia.matrix_diag_to_equi) write_file_mat("equi_to_diag.mat", self.dia.get_matrix_equi_to_diag()) write_file_vec_polynomials("norm_to_diag.vec", self.dr_in_nr_via_wr, is_xxpp_format) write_file_vec_polynomials("diag_to_norm.vec", self.nr_in_dr_via_wr, is_xxpp_format) write_file_vec_polynomials("norm_to_ints.vec", self.real_integrals, is_xxpp_format) write_file_polynomial("equi_to_tham.pol", self.h_er, is_xxpp_format) def write_out_integrals(self): #write out in Mathematica xxpp format is_xxpp_format = True # equi_to_tvec is J.Hessian hess = [] for i in xrange(self.h_er.n_vars()): hess.append(self.h_er.diff(i)) e2tv = [ poly.substitute(hess) for poly in self.dia.matrix_as_vector_of_row_polynomials( self.dia.skew_symmetric_matrix()) ] write_file_vec_polynomials("equi_to_tvec.vec", e2tv, is_xxpp_format) #These are dim dof, is_xxpp_format doesn't apply i2f = [] for i in xrange(self.h_ir.n_vars()): i2f.append(self.h_ir.diff(i)) write_file_vec_polynomials("ints_to_freq.vec", i2f, False) file_ostr = open("ints_to_tham.pol", 'w') write_ascii_polynomial(file_ostr, self.h_ir.real(), False) file_ostr.close() logger.info('...done')
class Hill: def __init__(self, max_grade): dof = 3 self.alg = LieAlgebra(dof) self.h = self.alg.isograde(self.hill_about_l1(), 0, max_grade + 1) self.h_dc = self.diagonalize(self.alg, self.h) self.h_dr = self.h_dc.substitute(self.sub_r_into_c) self.k_dc = self.normalize_to_grade(max_grade) self.k_dr = self.k_dc.substitute(self.sub_r_into_c) def hill_about_l1(self): #print 'reading hill hamiltonian for test...' in_name = '../../test/ma-files/hill_l1_18_equi_to_tham.pol' in_file = open(in_name, 'r') h = read_ascii_polynomial(in_file, is_xxpp_format=1) in_file.close() #print 'done' terms = { Powers((2, 0, 0, 0, 0, 0)): -4.0, #x^2 Powers((0, 0, 2, 0, 0, 0)): +2.0, #y^2 Powers((0, 0, 0, 0, 2, 0)): +2.0, #z^2 Powers((0, 2, 0, 0, 0, 0)): +0.5, #px^2 Powers((0, 0, 0, 2, 0, 0)): +0.5, #py^2 Powers((0, 0, 0, 0, 0, 2)): +0.5, #pz^2 Powers((1, 0, 0, 1, 0, 0)): -1.0, #xpy Powers((0, 1, 1, 0, 0, 0)): +1.0 } #ypx assert len(terms) == 8 h_2 = self.alg.polynomial(terms) assert (h_2 == self.alg.isograde(h, 2)) return h def diagonalize(self, dof, h): tolerance = 5.0e-15 self.diag = Diagonalizer(self.alg) self.eig = self.diag.compute_eigen_system(h, tolerance) self.diag.compute_diagonal_change() mat = self.diag.get_matrix_diag_to_equi() assert self.diag.matrix_is_symplectic(mat) sub_diag_into_equi = self.diag.matrix_as_vector_of_row_polynomials(mat) h_diag = h.substitute(sub_diag_into_equi) self.eq_type = self.eig.get_equilibrium_type() self.comp = Complexifier(self.alg, self.eq_type) self.sub_c_into_r = self.comp.calc_sub_complex_into_real() self.sub_r_into_c = self.comp.calc_sub_real_into_complex() h_comp = h_diag.substitute(self.sub_c_into_r) h_comp = h_comp.with_small_coeffs_removed(tolerance) assert (self.alg.is_diagonal_polynomial(self.alg.isograde(h_comp, 2))) return h_comp def normalize_to_grade(self, max_grade): steps = max_grade h_dc = self.alg.isograde(self.h_dc, 2, max_grade + 1) h_dc_2 = self.alg.isograde(h_dc, 2) k_comp = self.alg.zero() w_comp = self.alg.zero() #the following is not very efficient for separating grades! h_list = [self.alg.isograde(h_dc, i + 2) for i in xrange(0, steps + 1)] nf = LieTriangle(self.alg, h_dc_2) for i in xrange(0, steps + 1): h_term = h_list[i] k_term, w_term = nf.compute_normal_form_and_generating_function( h_term) k_comp += k_term w_comp += w_term #print k_comp k_real = k_comp.substitute(self.sub_r_into_c) assert (k_real.imag().l_infinity_norm() < 1.0e-14) k_real = k_real.real() return k_comp
class Hill: def __init__(self, max_grade): dof = 3 self.alg = LieAlgebra(dof) self.h = self.alg.isograde(self.hill_about_l1(), 0, max_grade+1) self.h_dc = self.diagonalize(self.alg, self.h) self.h_dr = self.h_dc.substitute(self.sub_r_into_c) self.k_dc = self.normalize_to_grade(max_grade) self.k_dr = self.k_dc.substitute(self.sub_r_into_c) def hill_about_l1(self): #print 'reading hill hamiltonian for test...' in_name = '../../test/ma-files/hill_l1_18_equi_to_tham.pol' in_file = open(in_name, 'r') h = read_ascii_polynomial(in_file, is_xxpp_format=1) in_file.close() #print 'done' terms = {Powers((2, 0, 0, 0, 0, 0)): -4.0, #x^2 Powers((0, 0, 2, 0, 0, 0)): +2.0, #y^2 Powers((0, 0, 0, 0, 2, 0)): +2.0, #z^2 Powers((0, 2, 0, 0, 0, 0)): +0.5, #px^2 Powers((0, 0, 0, 2, 0, 0)): +0.5, #py^2 Powers((0, 0, 0, 0, 0, 2)): +0.5, #pz^2 Powers((1, 0, 0, 1, 0, 0)): -1.0, #xpy Powers((0, 1, 1, 0, 0, 0)): +1.0} #ypx assert len(terms) == 8 h_2 = self.alg.polynomial(terms) assert (h_2 == self.alg.isograde(h, 2)) return h def diagonalize(self, dof, h): tolerance = 5.0e-15 self.diag = Diagonalizer(self.alg) self.eig = self.diag.compute_eigen_system(h, tolerance) self.diag.compute_diagonal_change() mat = self.diag.get_matrix_diag_to_equi() assert self.diag.matrix_is_symplectic(mat) sub_diag_into_equi = self.diag.matrix_as_vector_of_row_polynomials(mat) h_diag = h.substitute(sub_diag_into_equi) self.eq_type = self.eig.get_equilibrium_type() self.comp = Complexifier(self.alg, self.eq_type) self.sub_c_into_r = self.comp.calc_sub_complex_into_real() self.sub_r_into_c = self.comp.calc_sub_real_into_complex() h_comp = h_diag.substitute(self.sub_c_into_r) h_comp = h_comp.with_small_coeffs_removed(tolerance) assert (self.alg.is_diagonal_polynomial(self.alg.isograde(h_comp, 2))) return h_comp def normalize_to_grade(self, max_grade): steps = max_grade h_dc = self.alg.isograde(self.h_dc, 2, max_grade+1) h_dc_2 = self.alg.isograde(h_dc, 2) k_comp = self.alg.zero() w_comp = self.alg.zero() #the following is not very efficient for separating grades! h_list = [self.alg.isograde(h_dc, i + 2) for i in xrange(0, steps + 1)] nf = LieTriangle(self.alg, h_dc_2) for i in xrange(0, steps + 1): h_term = h_list[i] k_term, w_term = nf.compute_normal_form_and_generating_function(h_term) k_comp += k_term w_comp += w_term #print k_comp k_real = k_comp.substitute(self.sub_r_into_c) assert (k_real.imag().l_infinity_norm() < 1.0e-14) k_real = k_real.real() return k_comp