Ticket #9502: trac_9502_basis_parent_bug_in_FreeModule.patch

File trac_9502_basis_parent_bug_in_FreeModule.patch, 9.3 KB (added by novoselt, 13 years ago)
  • sage/modules/free_module.py

    # HG changeset patch
    # User Andrey Novoseltsev <novoselt@gmail.com>
    # Date 1279179043 21600
    # Node ID 107b5400a52384feccc640b7d38efa66e092abd1
    # Parent  92183851e6cf5a384c5a2842a7295437643f12ff
    Trac 9502: Echelonized bases of submodules with user bases had wrong parents.
    
    diff -r 92183851e6cf -r 107b5400a523 sage/modules/free_module.py
    a b  
    176176import sage.rings.infinity
    177177import sage.rings.integer
    178178import sage.structure.parent_gens as gens
     179from sage.categories.principal_ideal_domains import PrincipalIdealDomains
    179180from sage.misc.randstate import current_randstate
    180181from sage.structure.sequence import Sequence
    181182
     
    19421943            sage: FreeModule(PolynomialRing(GF(7),'x'), 2)
    19431944            Ambient free module of rank 2 over the principal ideal domain Univariate Polynomial Ring in x over Finite Field of size 7
    19441945        """
    1945         if not isinstance(base_ring, principal_ideal_domain.PrincipalIdealDomain):
    1946             raise TypeError, "The base_ring must be a principal ideal domain."
    1947         FreeModule_generic.__init__(self, base_ring, rank, degree, sparse)
     1946        # The first check should go away once everything is categorized...
     1947        if (not isinstance(base_ring,
     1948                           principal_ideal_domain.PrincipalIdealDomain)
     1949            and base_ring not in PrincipalIdealDomains()):
     1950            raise TypeError("The base_ring must be a principal ideal domain.")
     1951        super(FreeModule_generic_pid, self).__init__(base_ring, rank, degree,
     1952                                                     sparse)
    19481953
    19491954    def scale(self, other):
    19501955        """
     
    45344539###############################################################################
    45354540
    45364541class FreeModule_submodule_with_basis_pid(FreeModule_generic_pid):
    4537     """
    4538     An `R`-submodule of `K^n` with distinguished basis,
    4539     where `K` is the fraction field of a principal ideal domain
    4540     `R`.
    4541     """
    4542     def __init__(self, ambient, basis, check=True,
     4542    r"""
     4543    Construct a submodule of a free module over PID with a distiguished basis.
     4544
     4545    INPUT:
     4546
     4547    - ``ambient`` -- ambient free module over a principal ideal domain `R`,
     4548      i.e. `R^n`;
     4549
     4550    - ``basis`` -- list of elements of `K^n`, where `K` is the fraction field
     4551      of `R`. These elements must be linearly independent and will be used as
     4552      the default basis of the constructed submodule;
     4553
     4554    - ``check`` -- (default: ``True``) if ``False``, correctness of the input
     4555      will not be checked and type conversion may be omitted, use with care;
     4556
     4557    - ``echelonize`` -- (default:``False``) if ``True``, ``basis`` will be
     4558      echelonized and the result will be used as the default basis of the
     4559      constructed submodule;
     4560
     4561    - `` echelonized_basis`` -- (default: ``None``) if not ``None``, must be
     4562      the echelonized basis spanning the same submodule as ``basis``;
     4563
     4564    - ``already_echelonized`` -- (default: ``False``) if ``True``, ``basis``
     4565      must be already given in the echelonized form.
     4566
     4567    OUTPUT:
     4568
     4569    - `R`-submodule of `K^n` with the user-specified ``basis``.
     4570
     4571    EXAMPLES::
     4572
     4573        sage: M = ZZ^3
     4574        sage: W = M.span_of_basis([[1,2,3],[4,5,6]]); W
     4575        Free module of degree 3 and rank 2 over Integer Ring
     4576        User basis matrix:
     4577        [1 2 3]
     4578        [4 5 6]
     4579
     4580    Now we create a submodule of the ambient vector space, rather than
     4581    ``M`` itself::
     4582
     4583        sage: W = M.span_of_basis([[1,2,3/2],[4,5,6]]); W
     4584        Free module of degree 3 and rank 2 over Integer Ring
     4585        User basis matrix:
     4586        [  1   2 3/2]
     4587        [  4   5   6]
     4588    """
     4589   
     4590    def __init__(self, ambient, basis, check=True,
    45434591        echelonize=False, echelonized_basis=None, already_echelonized=False):
    4544         """
    4545         Create a free module with basis over a PID.
    4546        
    4547         EXAMPLES::
    4548        
    4549             sage: M = ZZ^3
    4550             sage: W = M.span_of_basis([[1,2,3],[4,5,6]]); W
     4592        r"""
     4593        See :class:`FreeModule_submodule_with_basis_pid` for documentation.
     4594
     4595        TESTS::
     4596
     4597            sage: M = ZZ^3
     4598            sage: W = M.span_of_basis([[1,2,3],[4,5,6]])
     4599            sage: TestSuite(W).run()
     4600
     4601        We test that the issue at Trac #9502 is solved::
     4602
     4603            sage: parent(W.basis()[0])
    45514604            Free module of degree 3 and rank 2 over Integer Ring
    45524605            User basis matrix:
    45534606            [1 2 3]
    45544607            [4 5 6]
    4555        
    4556         ::
    4557        
    4558             sage: W = M.span_of_basis([[1,2,3/2],[4,5,6]]); W
    4559             Free module of degree 3 and rank 2 over Integer Ring
    4560             User basis matrix:
    4561             [  1   2 3/2]
    4562             [  4   5   6]
     4608            sage: parent(W.echelonized_basis()[0])
     4609            Free module of degree 3 and rank 2 over Integer Ring
     4610            User basis matrix:
     4611            [1 2 3]
     4612            [4 5 6]
    45634613        """
    45644614        if not isinstance(ambient, FreeModule_ambient_pid):
    4565             raise TypeError, "ambient (=%s) must be ambient."%ambient
     4615            raise TypeError("ambient (=%s) must be ambient." % ambient)
     4616        self.__ambient_module = ambient
    45664617        if not isinstance(basis, (list, tuple)):
    4567             raise TypeError, "basis (=%s) must be a list"%basis
     4618            raise TypeError("basis (=%s) must be a list" % basis)
    45684619        basis = list(basis) # make it a list rather than a tuple
    45694620        if check:
    4570             V = ambient.vector_space()
    4571             basis = [V(x) for x in basis]
    4572            
    4573         self.__ambient_module = ambient
    4574        
    4575         if check:
    45764621            V = ambient.ambient_vector_space()
    45774622            for i in range(len(basis)):
    45784623                x = basis[i]
    4579                 if not (x in V):
     4624                if x not in V:
    45804625                    try:
    45814626                        basis[i] = V(x)
    45824627                    except TypeError:
    4583                         raise TypeError, "each element of basis must be in the ambient vector space"
    4584         R = ambient.base_ring()
    4585 
     4628                        raise TypeError("each element of basis must be in "
     4629                                        "the ambient vector space")
    45864630        if echelonize and not already_echelonized:
    45874631            basis = self._echelonized_basis(ambient, basis)
    4588        
    4589         FreeModule_generic.__init__(self, R, rank=len(basis), degree=ambient.degree(), sparse=ambient.is_sparse())
    4590 
     4632        R = ambient.base_ring()
     4633        # The following is WRONG - we should call __init__ of
     4634        # FreeModule_generic_pid. However, it leads to a bunch of errors.
     4635        FreeModule_generic.__init__(self, R,
     4636                                    rank=len(basis), degree=ambient.degree(),
     4637                                    sparse=ambient.is_sparse())
    45914638        C = self.element_class()
    45924639        try:
    4593             w = [C(self, x.list(),
    4594                           coerce=False, copy=True) for x in basis]
     4640            w = [C(self, x.list(), coerce=False, copy=True) for x in basis]
    45954641        except TypeError:
    45964642            C = element_class(R.fraction_field(), self.is_sparse())
    45974643            self._element_class = C
    4598             w = [C(self, x.list(),
    4599                           coerce=False, copy=True) for x in basis]
     4644            w = [C(self, x.list(), coerce=False, copy=True) for x in basis]
    46004645        self.__basis = basis_seq(self, w)
    46014646
    4602         if echelonized_basis != None:
    4603            
    4604             self.__echelonized_basis = basis_seq(self, echelonized_basis)
    4605            
    4606         else:
    4607            
    4608             if echelonize or already_echelonized:
    4609                 self.__echelonized_basis = self.__basis   
    4610             else:
    4611                 w = self._echelonized_basis(ambient, basis)
    4612                 self.__echelonized_basis = basis_seq(self, w)
    4613 
     4647        if echelonize or already_echelonized:
     4648            self.__echelonized_basis = self.__basis
     4649        else:
     4650            if echelonized_basis is None:
     4651                echelonized_basis = self._echelonized_basis(ambient, basis)
     4652            w = [C(self, x.list(), coerce=False, copy=True)
     4653                 for x in echelonized_basis]
     4654            self.__echelonized_basis = basis_seq(self, w)
    46144655        if check and len(basis) != len(self.__echelonized_basis):
    4615             raise ValueError, "The given basis vectors must be linearly independent."
     4656            raise ValueError("The given basis vectors must be linearly "
     4657                             "independent.")
    46164658           
    46174659    def __hash__(self):
    46184660        """
  • sage/symbolic/ring.pyx

    diff -r 92183851e6cf -r 107b5400a523 sage/symbolic/ring.pyx
    a b  
    3131from sage.structure.element cimport RingElement, Element
    3232from sage.structure.parent_base import ParentWithBase
    3333from sage.rings.ring cimport CommutativeRing
     34from sage.categories.all import Fields
    3435from sage.categories.morphism cimport Morphism
    35 
    3636from sage.rings.all import RR, CC
    3737           
    3838pynac_symbol_registry = {}
     
    5050            sage: sage.symbolic.ring.SymbolicRing()
    5151            Symbolic Ring
    5252        """
    53         ParentWithBase.__init__(self, self)
     53        ParentWithBase.__init__(self, self, category=Fields())
    5454        self._populate_coercion_lists_(convert_method_name='_symbolic_')
    5555
    5656    def __reduce__(self):