Example #1
0
    def level_ideal(self):
        """
        Determines the level of the quadratic form (over R), which is the
        smallest ideal N of R such that N * (the matrix of 2*Q)^(-1) is
        in R with diagonal in 2*R.
        (Caveat: This always returns the principal ideal when working over a field!)

        WARNING:  THIS ONLY WORKS OVER A PID RING OF INTEGERS FOR NOW!
              (Waiting for Sage fractional ideal support.)

        EXAMPLES::

            sage: Q = QuadraticForm(ZZ, 2, range(1,4))
            sage: Q.level_ideal()
            Principal ideal (8) of Integer Ring

        ::

            sage: Q1 = QuadraticForm(QQ, 2, range(1,4))
            sage: Q1.level_ideal()
            Principal ideal (1) of Rational Field

        ::

            sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
            sage: Q.level_ideal()
            Principal ideal (420) of Integer Ring

        """
        ##############################################################
        ## To do this properly, the level should be the inverse of the
        ## fractional ideal (over R) generated by the entries whose
        ## denominators we take above. =)
        ##############################################################

        return ideal(self.base_ring()(self.level()))
Example #2
0
    def level(self):
        r"""
        Determines the level of the quadratic form over a PID, which is a
        generator for the smallest ideal `N` of `R` such that N * (the matrix of
        2*Q)^(-1) is in R with diagonal in 2*R.

        Over `\ZZ` this returns a non-negative number.

        (Caveat: This always returns the unit ideal when working over a field!)

        EXAMPLES::

            sage: Q = QuadraticForm(ZZ, 2, range(1,4))
            sage: Q.level()
            8

            sage: Q1 = QuadraticForm(QQ, 2, range(1,4))
            sage: Q1.level()      # random
            UserWarning: Warning -- The level of a quadratic form over a field is always 1.  Do you really want to do this?!?
            1

            sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
            sage: Q.level()
            420

        """
        ## Try to return the cached level
        try:
            return self.__level
        except AttributeError:

            ## Check that the base ring is a PID
            if not is_PrincipalIdealDomain(self.base_ring()):
                raise TypeError("Oops!  The level (as a number) is only defined over a Principal Ideal Domain.  Try using level_ideal().")


            ## Warn the user if the form is defined over a field!
            if self.base_ring().is_field():
                warn("Warning -- The level of a quadratic form over a field is always 1.  Do you really want to do this?!?")
                #raise RuntimeError, "Warning -- The level of a quadratic form over a field is always 1.  Do you really want to do this?!?"


            ## Check invertibility and find the inverse
            try:
                mat_inv = self.matrix()**(-1)
            except ZeroDivisionError:
                raise TypeError("Oops!  The quadratic form is degenerate (i.e. det = 0). =(")

            ## Compute the level
            inv_denoms = []
            for i in range(self.dim()):
                for j in range(i, self.dim()):
                    if (i == j):
                        inv_denoms += [denominator(mat_inv[i,j] / 2)]
                    else:
                        inv_denoms += [denominator(mat_inv[i,j])]
            lvl = LCM(inv_denoms)
            lvl = ideal(self.base_ring()(lvl)).gen()
            ##############################################################
            ## To do this properly, the level should be the inverse of the
            ## fractional ideal (over R) generated by the entries whose
            ## denominators we take above. =)
            ##############################################################

            ## Normalize the result over ZZ
            if self.base_ring() == IntegerRing():
                lvl = abs(lvl)

            ## Cache and return the level
            self.__level = lvl
            return lvl