Esempio n. 1
0
    def setUp(self):
        """Set up an example from Hill's equations."""

        x_2 = Powers((2, 0, 0, 0, 0, 0))
        px2 = Powers((0, 2, 0, 0, 0, 0))
        y_2 = Powers((0, 0, 2, 0, 0, 0))
        py2 = Powers((0, 0, 0, 2, 0, 0))
        z_2 = Powers((0, 0, 0, 0, 2, 0))
        pz2 = Powers((0, 0, 0, 0, 0, 2))
        xpy = Powers((1, 0, 0, 1, 0, 0))
        ypx = Powers((0, 1, 1, 0, 0, 0))
        terms = {
            px2: 0.5,
            py2: 0.5,
            pz2: 0.5,
            xpy: -1.0,
            ypx: 1.0,
            x_2: -4.0,
            y_2: 2.0,
            z_2: 2.0
        }
        assert len(terms) == 8

        self.h_2 = Polynomial(6, terms=terms)
        self.lie = LieAlgebra(3)
        self.diag = Diagonalizer(self.lie)
        self.eq_type = 'scc'
        e = []
        e.append(+sqrt(2.0 * sqrt(7.0) + 1.0))
        e.append(-e[-1])
        e.append(complex(0.0, +sqrt(2.0 * sqrt(7.0) - 1.0)))
        e.append(-e[-1])
        e.append(complex(0.0, +2.0))
        e.append(-e[-1])
        self.eig_vals = e
Esempio n. 2
0
    def test_cf_hamilton_linear_to_quadratic_matrix(self):
        """Compare the results of (1) asking directly for the linear
        matrix for a given Hamiltonian, and (2) forming Hamilton's
        equations and then linearizing them."""

        dof = 3
        terms = {
            Powers((2, 0, 0, 0, 0, 0)): -0.3,
            Powers((1, 1, 0, 0, 0, 0)): 0.33,
            Powers((0, 1, 0, 1, 1, 0)): 7.2,
            Powers((0, 1, 0, 0, 1, 0)): 7.12,
            Powers((0, 0, 3, 0, 1, 0)): -4.0
        }
        h = Polynomial(2 * dof, terms=terms)
        alg = LieAlgebra(dof)
        diag = Diagonalizer(alg)
        lin = diag.linear_matrix(h)
        rhs = diag.hamiltons_equations_rhs(h)
        rhs_lin = tuple([alg.isograde(h_term, 1) for h_term in rhs])
        for i, pol in enumerate(rhs_lin):
            for m, c in pol.powers_and_coefficients():
                mon = alg.monomial(m, c)
                self.assertEquals(alg.grade(mon), 1)
                for j, f in enumerate(m):
                    if f == 1:
                        self.assertEquals(lin[i, j], c)
Esempio n. 3
0
    def test_cf_hamilton_linear_to_quadratic_matrix(self):

        """Compare the results of (1) asking directly for the linear
        matrix for a given Hamiltonian, and (2) forming Hamilton's
        equations and then linearizing them."""
        
        dof = 3
        terms = {Powers((2, 0, 0, 0, 0, 0)): -0.3,
                 Powers((1, 1, 0, 0, 0, 0)): 0.33,
                 Powers((0, 1, 0, 1, 1, 0)): 7.2,
                 Powers((0, 1, 0, 0, 1, 0)): 7.12,
                 Powers((0, 0, 3, 0, 1, 0)): -4.0 }
        h = Polynomial(2*dof, terms=terms)
        alg = LieAlgebra(dof)
        diag = Diagonalizer(alg)
        lin = diag.linear_matrix(h)
        rhs = diag.hamiltons_equations_rhs(h)
        rhs_lin = tuple([alg.isograde(h_term, 1) for h_term in rhs])
        for i, pol in enumerate(rhs_lin):
            for m, c in pol.powers_and_coefficients():
                mon = alg.monomial(m, c)
                self.assertEquals(alg.grade(mon), 1)
                for j, f in enumerate(m):
                    if f==1:
                        self.assertEquals(lin[i, j], c)
Esempio n. 4
0
    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.')
Esempio n. 5
0
    def test_example_skew(self):
        """Multiply the skew-symmetric matrix by a specific vector."""

        dof = 3
        lie = LieAlgebra(dof)
        diag = Diagonalizer(lie)
        J = diag.skew_symmetric_matrix()
        x = (1, 2, 3, 4, 5, 6)
        y = matrixmultiply(J, x)
        # self.assertEquals(y, (2,-1,4,-3,6,-5))
        z = y == (2, -1, 4, -3, 6, -5)
        self.assertTrue(z.all())
Esempio n. 6
0
    def test_skew_symmetric_diagonal_2x_2(self):
        """Test the basic structure of the skew-symmetric matrix."""

        dof = 3
        lie = LieAlgebra(dof)
        diag = Diagonalizer(lie)
        J = diag.skew_symmetric_matrix()
        for qi in xrange(0, dof, 2):
            pi = qi + 1
            self.assertEquals(J[qi, qi], 0.0)
            self.assertEquals(J[qi, pi], +1.0)
            self.assertEquals(J[pi, qi], -1.0)
            self.assertEquals(J[pi, pi], 0.0)
Esempio n. 7
0
    def test_example_skew(self):

        """Multiply the skew-symmetric matrix by a specific vector."""
        
        dof = 3
        lie = LieAlgebra(dof)
        diag = Diagonalizer(lie)
        J = diag.skew_symmetric_matrix()
        x = (1,2,3,4,5,6)
        y = matrixmultiply(J, x)
        # self.assertEquals(y, (2,-1,4,-3,6,-5))
        z = y == (2,-1,4,-3,6,-5)
        self.assertTrue(z.all())
Esempio n. 8
0
    def test_skew_symmetric_diagonal_2x_2(self):

        """Test the basic structure of the skew-symmetric matrix."""
        
        dof = 3
        lie = LieAlgebra(dof)
        diag = Diagonalizer(lie)
        J = diag.skew_symmetric_matrix()
        for qi in xrange(0, dof, 2):
            pi = qi+1
            self.assertEquals(J[qi,qi],  0.0)
            self.assertEquals(J[qi,pi], +1.0)
            self.assertEquals(J[pi,qi], -1.0)
            self.assertEquals(J[pi,pi],  0.0)
Esempio n. 9
0
 def test_matrix_as_polynomials(self):
     dof = 1
     mat = ((1, 2), (3, 4))
     alg = LieAlgebra(dof)
     diag = Diagonalizer(alg)
     vp = diag.matrix_as_vector_of_row_polynomials(mat)
     self.assert_(vp[0]((0.0, 0.0)) == 0.0)
     self.assert_(vp[0]((1.0, 0.0)) == 1.0)
     self.assert_(vp[0]((1.0, 1.0)) == 3.0)
     self.assert_(vp[0]((0.0, 1.0)) == 2.0)
     self.assert_(vp[1]((0.0, 0.0)) == 0.0)
     self.assert_(vp[1]((1.0, 0.0)) == 3.0)
     self.assert_(vp[1]((1.0, 1.0)) == 7.0)
     self.assert_(vp[1]((0.0, 1.0)) == 4.0)
Esempio n. 10
0
 def test_matrix_as_polynomials(self):
     dof = 1
     mat = ((1, 2), (3, 4))
     alg = LieAlgebra(dof)
     diag = Diagonalizer(alg)
     vp = diag.matrix_as_vector_of_row_polynomials(mat)
     self.assert_(vp[0]((0.0, 0.0)) == 0.0)
     self.assert_(vp[0]((1.0, 0.0)) == 1.0)
     self.assert_(vp[0]((1.0, 1.0)) == 3.0)
     self.assert_(vp[0]((0.0, 1.0)) == 2.0)
     self.assert_(vp[1]((0.0, 0.0)) == 0.0)
     self.assert_(vp[1]((1.0, 0.0)) == 3.0)
     self.assert_(vp[1]((1.0, 1.0)) == 7.0)
     self.assert_(vp[1]((0.0, 1.0)) == 4.0)
Esempio n. 11
0
    def setUp(self):

        """Set up an example from Hill's equations."""

        x_2 = Powers((2, 0, 0, 0, 0, 0))
        px2 = Powers((0, 2, 0, 0, 0, 0))
        y_2 = Powers((0, 0, 2, 0, 0, 0))
        py2 = Powers((0, 0, 0, 2, 0, 0))
        z_2 = Powers((0, 0, 0, 0, 2, 0))
        pz2 = Powers((0, 0, 0, 0, 0, 2))
        xpy = Powers((1, 0, 0, 1, 0, 0))
        ypx = Powers((0, 1, 1, 0, 0, 0))
        terms = {px2: 0.5, py2: 0.5, pz2: 0.5,
                 xpy: -1.0, ypx: 1.0,
                 x_2: -4.0, y_2: 2.0, z_2: 2.0}
        assert len(terms) == 8

        self.h_2 = Polynomial(6, terms=terms)
        self.lie = LieAlgebra(3)
        self.diag = Diagonalizer(self.lie)
        self.eq_type = 'scc'
        e = []
        e.append(+sqrt(2.0*sqrt(7.0)+1.0))
        e.append(-e[-1])
        e.append(complex(0.0, +sqrt(2.0*sqrt(7.0)-1.0)))
        e.append(-e[-1])
        e.append(complex(0.0, +2.0))
        e.append(-e[-1])
        self.eig_vals = e
Esempio n. 12
0
    def test_eigensystem(self):

        """Multiply eigenvectors and the original matrix by the
        eigenvalues in order to check the integrity of the
        eigensystem."""
        
        dof = 3
        terms = {Powers((2, 0, 0, 0, 0, 0)): -0.3,
                 Powers((1, 1, 0, 0, 0, 0)): 0.33,
                 Powers((0, 0, 1, 0, 1, 0)): 7.2,
                 Powers((0, 0, 0, 0, 0, 2)): 7.2,
                 Powers((0, 0, 0, 1, 1, 0)): 7.12 }
        g = Polynomial(2*dof, terms=terms)
        alg = LieAlgebra(dof)
        diag = Diagonalizer(alg)
        lin = diag.linear_matrix(g)
        val_vec_pairs = diag.eigenvalue_eigenvector_pairs(g)
        for p in val_vec_pairs:
            prod_s = p.vec*p.val
            prod_v = matrixmultiply(lin, p.vec)
            for x in prod_s-prod_v:
                self.assert_(abs(x)<1.0e-15)
Esempio n. 13
0
    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.')
Esempio n. 14
0
    def test_quadratic_terms(self):
        tolerance = 1.0e-15
        n = 0  #bath modes

        sb = new_random_system_bath(n,
                                    1.0,
                                    imag_harm_freq_barr,
                                    0.6,
                                    random_seed=54321)
        lie = sb.lie_algebra()
        h = sb.hamiltonian_real()

        #Sanity checks:
        assert h.degree() == 4
        assert h.n_vars() == 2 * n + 2
        assert len(h) == (3) + (2 * n) + (n)  #system+bath+coupling

        h_2 = h.homogeneous(2)
        self.assert_(h_2)  #non-zero
        diag = Diagonalizer(lie)
        eig = diag.compute_eigen_system(h_2, tolerance)
        diag.compute_diagonal_change()

        eq_type = eig.get_equilibrium_type()
        self.assertEquals(eq_type, 's')

        eigs = [pair.val for pair in eig.get_raw_eigen_value_vector_pairs()]

        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)
        comp = Complexifier(lie, eq_type)
        sub_complex_into_real = comp.calc_sub_complex_into_real()

        h_2_diag = h_2.substitute(sub_diag_into_equi)
        h_2_comp = h_2_diag.substitute(sub_complex_into_real)
        h_2_comp = h_2_comp.with_small_coeffs_removed(tolerance)
        self.assert_(lie.is_diagonal_polynomial(h_2_comp))

        h_diag = h.substitute(sub_diag_into_equi)
        h_comp = h_diag.substitute(sub_complex_into_real)
        h_comp = h_comp.with_small_coeffs_removed(tolerance)

        h_comp_2 = h_comp.homogeneous(2)
        self.assert_((h_comp_2 - h_2_comp).l1_norm() < tolerance,
                     '%s != %s' % (h_comp_2, h_2_comp))
        self.assert_(not h_comp.homogeneous(1))
    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
Esempio n. 16
0
    def test_eigensystem(self):
        """Multiply eigenvectors and the original matrix by the
        eigenvalues in order to check the integrity of the
        eigensystem."""

        dof = 3
        terms = {
            Powers((2, 0, 0, 0, 0, 0)): -0.3,
            Powers((1, 1, 0, 0, 0, 0)): 0.33,
            Powers((0, 0, 1, 0, 1, 0)): 7.2,
            Powers((0, 0, 0, 0, 0, 2)): 7.2,
            Powers((0, 0, 0, 1, 1, 0)): 7.12
        }
        g = Polynomial(2 * dof, terms=terms)
        alg = LieAlgebra(dof)
        diag = Diagonalizer(alg)
        lin = diag.linear_matrix(g)
        val_vec_pairs = diag.eigenvalue_eigenvector_pairs(g)
        for p in val_vec_pairs:
            prod_s = p.vec * p.val
            prod_v = matrixmultiply(lin, p.vec)
            for x in prod_s - prod_v:
                self.assert_(abs(x) < 1.0e-15)
Esempio n. 17
0
 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)
Esempio n. 18
0
 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)
Esempio n. 19
0
 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)
Esempio n. 20
0
 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)
Esempio n. 21
0
    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
    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
Esempio n. 23
0
def compare_normal_form(dir_name1, dir_name2, grade=4):
    def compare_matrix(dia, mat1, mat2, comment):
        print dia.matrix_norm(array(mat1, Float) - array(mat2, Float)), comment

    print "Comparing data in Normal form files upto grade %d" % (grade)
    print
    print "Reading python data"

    first = NormalFormData(dir_name1, is_xxpp_format=True, degree=grade)

    ring = PolynomialRing(first.equi_to_tham.n_vars())

    print
    print "Comparing python data with cpp files upto grade %d" % (grade)
    print "l_infinity_norm \t l1_norm \t\t polynomials"
    ringIO = PolynomialRingIO(ring)
    file_istr = open("hill_l1_18--norm_to_diag.vpol", 'r')
    pv_norm_to_diag = ringIO.read_sexp_vector_of_polynomials(file_istr)
    compare_poly_vec(first.norm_to_diag,
                     pv_norm_to_diag,
                     "norm_to_diag",
                     grade=grade - 1)
    file_istr = open("hill_l1_18--diag_to_norm.vpol", 'r')
    pv_diag_to_norm = ringIO.read_sexp_vector_of_polynomials(file_istr)
    compare_poly_vec(first.diag_to_norm,
                     pv_diag_to_norm,
                     "diag_to_norm",
                     grade=grade - 1)
    print
    print "Reading mathematica data"
    n_ints = len(first.ints_to_freq)
    # get the frequencies to find the order of the planes
    order_f = [poly((0.0, ) * n_ints) for poly in first.ints_to_freq]
    second = NormalFormData(dir_name2,
                            order_f=order_f,
                            is_xxpp_format=True,
                            degree=grade)

    from Diagonal import Diagonalizer
    lie = LieAlgebra(n_ints)
    dia = Diagonalizer(lie)
    grade_ints = grade / 2
    dia.matrix_is_symplectic(array(first.diag_to_equi, Float))
    dia.matrix_is_symplectic(array(second.diag_to_equi, Float))
    dia.matrix_is_symplectic(array(first.equi_to_diag, Float))
    dia.matrix_is_symplectic(array(second.equi_to_diag, Float))

    # For the case develloped, Hill, there is a 45deg rotation between the
    # diagonalised coordinates in each of the centre planes. Thus:
    # These matrices are different
    #compare_matrix(dia, first.diag_to_equi, second.diag_to_equi, "diag_to_equi")
    #compare_matrix(dia, first.equi_to_diag, second.equi_to_diag, "equi_to_diag")
    # We neeed to convert between the diagonal planes and back to
    # compare the nonlinear normalisation plolynomials
    # second.diag_to_first.diag = first.diag_in_terms_of_second.diag =
    fd_in_sd = dia.matrix_as_vector_of_row_polynomials(
        matrixmultiply(array(first.equi_to_diag, Float),
                       array(second.diag_to_equi, Float)))
    sd_in_fd = dia.matrix_as_vector_of_row_polynomials(
        matrixmultiply(array(second.equi_to_diag, Float),
                       array(first.diag_to_equi, Float)))

    print
    print "Comparing mathematica data with cpp files upto grade %d" % (grade -
                                                                       1)
    compare_poly_vec(pv_norm_to_diag,
                     poly_vec_substitute(
                         fd_in_sd,
                         poly_vec_substitute(
                             poly_vec_isograde(second.norm_to_diag, grade - 1),
                             sd_in_fd)),
                     "norm_to_diag",
                     grade=grade - 1)
    print "Comparing mathematica data with cpp files upto grade %d" % (grade -
                                                                       1)
    compare_poly_vec(pv_diag_to_norm,
                     poly_vec_substitute(
                         fd_in_sd,
                         poly_vec_substitute(
                             poly_vec_isograde(second.diag_to_norm, grade - 1),
                             sd_in_fd)),
                     "diag_to_norm",
                     grade=grade - 1)

    print
    print "Comparing mathematica data with python upto grade %d" % (grade)

    compare_poly(first.equi_to_tham,
                 second.equi_to_tham,
                 "equi_to_tham",
                 grade=grade)
    compare_poly_vec(first.ints_to_freq,
                     second.ints_to_freq,
                     "ints_to_freq",
                     grade=grade_ints - 1)
    ring_ints = PolynomialRing(second.ints_to_tham.n_vars())
    poly_2 = ring_ints.isograde(second.ints_to_tham, 0, up_to=grade_ints + 1)
    compare_poly(first.ints_to_tham, poly_2, "ints_to_tham")
    compare_poly_vec(first.norm_to_ints,
                     second.norm_to_ints,
                     "norm_to_ints",
                     grade=grade)

    second.diag_to_norm = poly_vec_isograde(second.diag_to_norm, grade)
    second.norm_to_diag = poly_vec_isograde(second.norm_to_diag, grade)
    compare_poly_vec(first.norm_to_diag,
                     poly_vec_substitute(
                         fd_in_sd,
                         poly_vec_substitute(second.norm_to_diag, sd_in_fd)),
                     "norm_to_diag",
                     grade=grade - 1)
    compare_poly_vec(first.diag_to_norm,
                     poly_vec_substitute(
                         fd_in_sd,
                         poly_vec_substitute(second.diag_to_norm, sd_in_fd)),
                     "diag_to_norm",
                     grade=grade - 1)
    compare_poly_vec(first.diag_to_norm,
                     second.diag_to_norm,
                     "diag_to_norm",
                     grade=grade - 1)
    compare_poly_vec(first.diag_to_norm,
                     poly_vec_substitute(
                         fd_in_sd,
                         poly_vec_substitute(second.diag_to_norm, sd_in_fd)),
                     "diag_to_norm",
                     grade=grade)
    compare_poly_vec(first.equi_to_tvec,
                     second.equi_to_tvec,
                     "equi_to_tvec",
                     grade=grade - 1)
def compare_normal_form(dir_name1, dir_name2, grade=4):
    def compare_matrix(dia, mat1, mat2, comment):
        print dia.matrix_norm(array(mat1, Float)-array(mat2, Float)), comment

    print "Comparing data in Normal form files upto grade %d" %(grade)
    print
    print "Reading python data"

    first = NormalFormData(dir_name1, is_xxpp_format=True, degree=grade)

    ring = PolynomialRing(first.equi_to_tham.n_vars())
    
    print
    print "Comparing python data with cpp files upto grade %d" %(grade)
    print "l_infinity_norm \t l1_norm \t\t polynomials"
    ringIO = PolynomialRingIO(ring)
    file_istr = open("hill_l1_18--norm_to_diag.vpol", 'r')
    pv_norm_to_diag = ringIO.read_sexp_vector_of_polynomials(file_istr)
    compare_poly_vec(first.norm_to_diag, 
                     pv_norm_to_diag, "norm_to_diag", grade=grade-1)
    file_istr = open("hill_l1_18--diag_to_norm.vpol", 'r')
    pv_diag_to_norm = ringIO.read_sexp_vector_of_polynomials(file_istr)
    compare_poly_vec(first.diag_to_norm,
                     pv_diag_to_norm, "diag_to_norm", grade=grade-1)
    print
    print "Reading mathematica data"
    n_ints = len(first.ints_to_freq)
    # get the frequencies to find the order of the planes
    order_f=[poly((0.0,)*n_ints) for poly in first.ints_to_freq]
    second = NormalFormData(dir_name2, order_f=order_f,
                            is_xxpp_format=True, degree=grade)
    
    from Diagonal import Diagonalizer
    lie = LieAlgebra(n_ints)
    dia = Diagonalizer(lie)
    grade_ints = grade / 2
    dia.matrix_is_symplectic(array(first.diag_to_equi, Float))
    dia.matrix_is_symplectic(array(second.diag_to_equi, Float))
    dia.matrix_is_symplectic(array(first.equi_to_diag, Float))
    dia.matrix_is_symplectic(array(second.equi_to_diag, Float))

    # For the case develloped, Hill, there is a 45deg rotation between the
    # diagonalised coordinates in each of the centre planes. Thus:
    # These matrices are different
    #compare_matrix(dia, first.diag_to_equi, second.diag_to_equi, "diag_to_equi")
    #compare_matrix(dia, first.equi_to_diag, second.equi_to_diag, "equi_to_diag")
    # We neeed to convert between the diagonal planes and back to
    # compare the nonlinear normalisation plolynomials
    # second.diag_to_first.diag = first.diag_in_terms_of_second.diag =
    fd_in_sd = dia.matrix_as_vector_of_row_polynomials(matrixmultiply(
        array(first.equi_to_diag, Float),array(second.diag_to_equi, Float)))
    sd_in_fd = dia.matrix_as_vector_of_row_polynomials(matrixmultiply(
        array(second.equi_to_diag, Float),array(first.diag_to_equi, Float)))

    print
    print "Comparing mathematica data with cpp files upto grade %d" %(grade-1)
    compare_poly_vec(pv_norm_to_diag,
                     poly_vec_substitute(fd_in_sd, poly_vec_substitute(
        poly_vec_isograde(second.norm_to_diag, grade-1), sd_in_fd)),
                     "norm_to_diag", grade=grade-1)
    print "Comparing mathematica data with cpp files upto grade %d" %(grade-1)
    compare_poly_vec(pv_diag_to_norm,
                     poly_vec_substitute(fd_in_sd, poly_vec_substitute(
        poly_vec_isograde(second.diag_to_norm, grade-1), sd_in_fd)),
                     "diag_to_norm", grade=grade-1)

    print
    print "Comparing mathematica data with python upto grade %d" %(grade)

    compare_poly(first.equi_to_tham, second.equi_to_tham,
                 "equi_to_tham", grade=grade)
    compare_poly_vec(first.ints_to_freq , second.ints_to_freq , "ints_to_freq",
                     grade=grade_ints-1)
    ring_ints = PolynomialRing(second.ints_to_tham.n_vars())
    poly_2 = ring_ints.isograde(second.ints_to_tham, 0, up_to=grade_ints+1)
    compare_poly(first.ints_to_tham , poly_2 , "ints_to_tham")
    compare_poly_vec(first.norm_to_ints , second.norm_to_ints ,
                     "norm_to_ints", grade=grade)

    second.diag_to_norm = poly_vec_isograde(second.diag_to_norm, grade)
    second.norm_to_diag = poly_vec_isograde(second.norm_to_diag, grade)
    compare_poly_vec(first.norm_to_diag, 
                     poly_vec_substitute(fd_in_sd, poly_vec_substitute(
        second.norm_to_diag, sd_in_fd)), "norm_to_diag", grade=grade-1)
    compare_poly_vec(first.diag_to_norm,
                     poly_vec_substitute(fd_in_sd, poly_vec_substitute(
        second.diag_to_norm, sd_in_fd)), "diag_to_norm", grade=grade-1)
    compare_poly_vec(first.diag_to_norm,
                     second.diag_to_norm,"diag_to_norm", grade=grade-1)
    compare_poly_vec(first.diag_to_norm,
                     poly_vec_substitute(fd_in_sd, poly_vec_substitute(
        second.diag_to_norm, sd_in_fd)), "diag_to_norm", grade=grade)
    compare_poly_vec(first.equi_to_tvec,
                     second.equi_to_tvec,"equi_to_tvec", grade=grade-1)
Esempio n. 25
0
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
Esempio n. 27
0
class CanonicalChange(unittest.TestCase):
    def setUp(self):
        """Set up an example from Hill's equations."""

        x_2 = Powers((2, 0, 0, 0, 0, 0))
        px2 = Powers((0, 2, 0, 0, 0, 0))
        y_2 = Powers((0, 0, 2, 0, 0, 0))
        py2 = Powers((0, 0, 0, 2, 0, 0))
        z_2 = Powers((0, 0, 0, 0, 2, 0))
        pz2 = Powers((0, 0, 0, 0, 0, 2))
        xpy = Powers((1, 0, 0, 1, 0, 0))
        ypx = Powers((0, 1, 1, 0, 0, 0))
        terms = {
            px2: 0.5,
            py2: 0.5,
            pz2: 0.5,
            xpy: -1.0,
            ypx: 1.0,
            x_2: -4.0,
            y_2: 2.0,
            z_2: 2.0
        }
        assert len(terms) == 8

        self.h_2 = Polynomial(6, terms=terms)
        self.lie = LieAlgebra(3)
        self.diag = Diagonalizer(self.lie)
        self.eq_type = 'scc'
        e = []
        e.append(+sqrt(2.0 * sqrt(7.0) + 1.0))
        e.append(-e[-1])
        e.append(complex(0.0, +sqrt(2.0 * sqrt(7.0) - 1.0)))
        e.append(-e[-1])
        e.append(complex(0.0, +2.0))
        e.append(-e[-1])
        self.eig_vals = e

    def test_basic_matrix(self):
        """This test is rather monolithic, but at least it implements
        a concrete example that we can compare with our earlier
        computations.  It also tests the mutual-inverse character of
        the equi-to-diag and diag-to-equi transformations."""

        tolerance = 5.0e-15
        eig = self.diag.compute_eigen_system(self.h_2, tolerance)
        self.diag.compute_diagonal_change()

        eq_type = eig.get_equilibrium_type()
        self.assertEquals(eq_type, self.eq_type)

        eigs = [pair.val for pair in eig.get_raw_eigen_value_vector_pairs()]
        for actual, expected in zip(eigs, self.eig_vals):
            self.assert_(
                abs(actual - expected) < tolerance, (actual, expected))

        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)
        mat_inv = LinearAlgebra.inverse(MLab.array(mat))
        sub_equi_into_diag = self.diag.matrix_as_vector_of_row_polynomials(
            mat_inv)
        h_diag_2 = self.h_2.substitute(sub_diag_into_equi)
        h_2_inv = h_diag_2.substitute(sub_equi_into_diag)
        self.assert_(h_2_inv)  #non-zero
        self.assert_(not h_2_inv.is_constant())
        self.assert_(self.lie.is_isograde(h_2_inv, 2))
        self.assert_((self.h_2 - h_2_inv).l1_norm() < 1.0e-14)
        comp = Complexifier(self.diag.get_lie_algebra(), eq_type)
        sub_complex_into_real = comp.calc_sub_complex_into_real()
        h_comp_2 = h_diag_2.substitute(sub_complex_into_real)
        h_comp_2 = h_comp_2.with_small_coeffs_removed(tolerance)
        self.assert_(self.lie.is_diagonal_polynomial(h_comp_2))
Esempio n. 28
0
class CanonicalChange(unittest.TestCase):

    def setUp(self):

        """Set up an example from Hill's equations."""

        x_2 = Powers((2, 0, 0, 0, 0, 0))
        px2 = Powers((0, 2, 0, 0, 0, 0))
        y_2 = Powers((0, 0, 2, 0, 0, 0))
        py2 = Powers((0, 0, 0, 2, 0, 0))
        z_2 = Powers((0, 0, 0, 0, 2, 0))
        pz2 = Powers((0, 0, 0, 0, 0, 2))
        xpy = Powers((1, 0, 0, 1, 0, 0))
        ypx = Powers((0, 1, 1, 0, 0, 0))
        terms = {px2: 0.5, py2: 0.5, pz2: 0.5,
                 xpy: -1.0, ypx: 1.0,
                 x_2: -4.0, y_2: 2.0, z_2: 2.0}
        assert len(terms) == 8

        self.h_2 = Polynomial(6, terms=terms)
        self.lie = LieAlgebra(3)
        self.diag = Diagonalizer(self.lie)
        self.eq_type = 'scc'
        e = []
        e.append(+sqrt(2.0*sqrt(7.0)+1.0))
        e.append(-e[-1])
        e.append(complex(0.0, +sqrt(2.0*sqrt(7.0)-1.0)))
        e.append(-e[-1])
        e.append(complex(0.0, +2.0))
        e.append(-e[-1])
        self.eig_vals = e

    def test_basic_matrix(self):

        """This test is rather monolithic, but at least it implements
        a concrete example that we can compare with our earlier
        computations.  It also tests the mutual-inverse character of
        the equi-to-diag and diag-to-equi transformations."""

        tolerance = 5.0e-15
        eig = self.diag.compute_eigen_system(self.h_2, tolerance)
        self.diag.compute_diagonal_change()

        eq_type = eig.get_equilibrium_type()
        self.assertEquals(eq_type, self.eq_type)

        eigs = [pair.val for pair in eig.get_raw_eigen_value_vector_pairs()]
        for actual, expected in zip(eigs, self.eig_vals):
            self.assert_(abs(actual-expected) < tolerance, (actual, expected))

        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)
        mat_inv = LinearAlgebra.inverse(MLab.array(mat))
        sub_equi_into_diag = self.diag.matrix_as_vector_of_row_polynomials(mat_inv)
        h_diag_2 = self.h_2.substitute(sub_diag_into_equi)
        h_2_inv = h_diag_2.substitute(sub_equi_into_diag)
        self.assert_(h_2_inv) #non-zero
        self.assert_(not h_2_inv.is_constant())
        self.assert_(self.lie.is_isograde(h_2_inv, 2))
        self.assert_((self.h_2-h_2_inv).l1_norm() < 1.0e-14)
        comp = Complexifier(self.diag.get_lie_algebra(), eq_type)
        sub_complex_into_real = comp.calc_sub_complex_into_real()
        h_comp_2 = h_diag_2.substitute(sub_complex_into_real)
        h_comp_2 = h_comp_2.with_small_coeffs_removed(tolerance)
        self.assert_(self.lie.is_diagonal_polynomial(h_comp_2))
Esempio n. 29
0
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