# HG changeset patch
# User William Stein <wstein@gmail.com>
# Date 1245366201 25200
# Node ID af576e286a2d22f549c464fa8f5e5f4efbe519f2
# Parent  f52bf8765eac2a248830d8bf4cf4fe76e98fac7d
trac #5882 --  implement general package for finitely generated not-necessarily free R-modules (flattened)
* * *
referee patch: reST fixes for 5882
* * *
trac 5882--final referee followup patch
* * *
davidloeffler's patch
* * *
trac 5882 -- address all comments on full referee report.
* * *
reconcile davidloeffler's new patch with was's new patch

diff -r f52bf8765eac -r af576e286a2d doc/en/reference/modules.rst
--- a/doc/en/reference/modules.rst	Wed Jul 01 07:28:17 2009 -0700
+++ b/doc/en/reference/modules.rst	Thu Jun 18 16:03:21 2009 -0700
@@ -17,4 +17,7 @@
    sage/modules/free_module_morphism
    
    sage/modules/matrix_morphism
-   
\ No newline at end of file
+
+   sage/modules/fg_pid/fgp_module
+   sage/modules/fg_pid/fgp_element
+   sage/modules/fg_pid/fgp_morphism
diff -r f52bf8765eac -r af576e286a2d sage/categories/category.py
--- a/sage/categories/category.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/categories/category.py	Thu Jun 18 16:03:21 2009 -0700
@@ -171,7 +171,7 @@
         return set([])
 
     def category(self):
-        return Objects()
+        return Sets()
 
 def is_Category(x):
     """
diff -r f52bf8765eac -r af576e286a2d sage/categories/homset.py
--- a/sage/categories/homset.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/categories/homset.py	Thu Jun 18 16:03:21 2009 -0700
@@ -281,7 +281,7 @@
             from sage.categories.homset import Hom
             return CallMorphism(Hom(S, self))
         else:
-            return parent.Parent._generic_convert_map(self, S)
+            return Parent._generic_convert_map(self, S)
 
     def homset_category(self): 
         """ 
diff -r f52bf8765eac -r af576e286a2d sage/matrix/matrix_integer_dense.pyx
--- a/sage/matrix/matrix_integer_dense.pyx	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/matrix/matrix_integer_dense.pyx	Thu Jun 18 16:03:21 2009 -0700
@@ -1475,9 +1475,6 @@
             sage: A.echelon_form()
             [1 0]
             [0 2]
-        
-        ::
-        
             sage: A = MatrixSpace(ZZ,5)(range(25))
             sage: A.echelon_form()
             [  5   0  -5 -10 -15]
@@ -1485,6 +1482,19 @@
             [  0   0   0   0   0]
             [  0   0   0   0   0]
             [  0   0   0   0   0]
+
+        Getting a transformation matrix in the nonsquare case::
+
+            sage: A = matrix(ZZ,5,3,[1..15])
+            sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)
+            sage: H
+            [1 2 3]
+            [0 3 6]
+            sage: U
+            [  0   0   0   4  -3]
+            [  0   0   0  13 -10]
+            sage: U*A == H
+            True
         
         TESTS: Make sure the zero matrices are handled correctly::
         
@@ -1574,6 +1584,10 @@
             if transformation:
                 return self, self
             return self
+
+        key = 'hnf-%s-%s'%(include_zero_rows,transformation)
+        ans = self.fetch(key)
+        if ans is not None: return ans
         
         cdef Py_ssize_t nr, nc, n, i, j
         nr = self._nrows
@@ -1599,9 +1613,11 @@
         if algorithm == "padic":
             import matrix_integer_dense_hnf
             if transformation:
+                H_m, U, pivots = matrix_integer_dense_hnf.hnf_with_transformation(self, proof=proof)
                 if not include_zero_rows:
-                    raise ValueError, "if you get the transformation matrix you must include zero rows"
-                H_m, U, pivots = matrix_integer_dense_hnf.hnf_with_transformation(self, proof=proof)
+                    r = H_m.rank()
+                    H_m = H_m[:r]
+                    U = U[:r]
             else:
                 H_m, pivots = matrix_integer_dense_hnf.hnf(self,
                                    include_zero_rows=include_zero_rows, proof=proof)
@@ -1682,10 +1698,14 @@
 
         H_m.cache('in_echelon_form', True)
 
+        
         if transformation:
-            return H_m, U
-        else:
-            return H_m
+            U.set_immutable()
+            ans = H_m, U
+        else:
+            ans = H_m
+        self.cache(key, ans)
+        return ans
 
     def saturation(self, p=0, proof=None, max_dets=5):
         r"""
diff -r f52bf8765eac -r af576e286a2d sage/matrix/matrix_rational_dense.pyx
--- a/sage/matrix/matrix_rational_dense.pyx	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/matrix/matrix_rational_dense.pyx	Thu Jun 18 16:03:21 2009 -0700
@@ -2455,7 +2455,7 @@
             3
         """
         if self._nrows != self._ncols:
-            raise ArithmeticError, "self must be a square matrix"
+            raise ArithmeticError, "incompatible matrix dimensions"
         cdef PariInstance P = sage.libs.pari.gen.pari
         _sig_on
         cdef GEN d = det0(pari_GEN(self), flag)
diff -r f52bf8765eac -r af576e286a2d sage/modular/abvar/abvar.py
--- a/sage/modular/abvar/abvar.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/modular/abvar/abvar.py	Thu Jun 18 16:03:21 2009 -0700
@@ -3575,7 +3575,7 @@
             Abelian subvariety of dimension 1 of J0(33)
             sage: A.lattice()
             Free module of degree 6 and rank 2 over Integer Ring
-            Echelon basis matrix:
+            User basis matrix:
             [ 1  0  0 -1  0  0]
             [ 0  0  1  0  1 -1]        
             sage: type(A)
diff -r f52bf8765eac -r af576e286a2d sage/modular/modsym/ambient.py
--- a/sage/modular/modsym/ambient.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/modular/modsym/ambient.py	Thu Jun 18 16:03:21 2009 -0700
@@ -1959,10 +1959,9 @@
         if check:
             if not free_module.is_FreeModule(M):
                 V = self.free_module()
-                if isinstance(M, (list,tuple)):
-                    M = V.span([V(x.element()) for x in M])
-                else:
-                    M = V.span(M)
+                if not isinstance(M, (list,tuple)):
+                    M = M.gens()
+                M = V.span([V(x.element()) for x in M])
         return subspace.ModularSymbolsSubspace(self, M, dual_free_module=dual_free_module, check=check)
 
     def twisted_winding_element(self, i, eps):
diff -r f52bf8765eac -r af576e286a2d sage/modules/fg_pid/__init__.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sage/modules/fg_pid/__init__.py	Thu Jun 18 16:03:21 2009 -0700
@@ -0,0 +1,1 @@
+
diff -r f52bf8765eac -r af576e286a2d sage/modules/fg_pid/fgp_element.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sage/modules/fg_pid/fgp_element.py	Thu Jun 18 16:03:21 2009 -0700
@@ -0,0 +1,331 @@
+r"""
+Elements of finitely generated modules over a PID.
+
+AUTHOR:
+    - William Stein, 2009
+"""
+
+####################################################################################
+#       Copyright (C) 2009 William Stein <wstein@gmail.com>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+####################################################################################
+
+from sage.structure.element import ModuleElement
+
+class FGP_Element(ModuleElement):
+    """
+    An element of a finitely generated module over a PID.
+
+    INPUT:
+    
+    - ``parent`` -- parent module M
+    
+    - ``x`` -- element of M.V()
+    
+    - ``check`` -- (default: True) if True, verify that x in M.V()
+    
+    EXAMPLES::
+
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+        sage: Q = V/W
+        sage: x = Q(V.0-V.1); x
+        (0, 3)
+        sage: type(x)
+        <class 'sage.modules.fg_pid.fgp_element.FGP_Element'>
+        sage: x is Q(x)
+        True
+        sage: x.parent() is Q
+        True
+
+    TESTS::
+    
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+        sage: loads(dumps(Q.0)) == Q.0
+        True
+    """
+    def __init__(self, parent, x, check=True):
+        """
+        INPUT:
+        
+        - ``parent`` -- parent module M
+            
+        - ``x`` -- element of M.V()
+            
+        - ``check`` -- (default: True) if True, verify that x in M.V()
+            
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: x = Q(V.0-V.1); type(x)
+            <class 'sage.modules.fg_pid.fgp_element.FGP_Element'>
+
+        For full documentation, see :class:`FGP_Element`.
+        """
+        if check:
+            if isinstance(x, FGP_Element): x = x.lift()
+            if x.parent() is not parent.V():
+                x = parent.V()(x)
+        ModuleElement.__init__(self, parent)
+        self._x = x
+        
+    def lift(self):
+        """
+        Lift self to an element of V, where the parent of self is the quotient module V/W.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.0
+            (1, 0)
+            sage: Q.1
+            (0, 1)
+            sage: Q.0.lift()
+            (0, 0, 1)
+            sage: Q.1.lift()
+            (0, 2, 0)
+            sage: x = Q(V.0); x
+            (0, 4)
+            sage: x.lift()
+            (1/2, 0, 0)
+            sage: x == 4*Q.1
+            True
+            sage: x.lift().parent() == V
+            True
+
+        A silly version of the integers modulo 100::
+        
+            sage: A = (ZZ^1)/span([[100]], ZZ); A
+            Finitely generated module V/W over Integer Ring with invariants (100)
+            sage: x = A([5]); x
+            (5)
+            sage: v = x.lift(); v
+            (5)
+            sage: v.parent()
+            Ambient free module of rank 1 over the principal ideal domain Integer Ring
+        """
+        return self._x
+        
+
+    def __neg__(self):
+        """
+        EXAMPLES::
+
+            sage: V1 = ZZ^2; W1 = V1.span([[1,2],[3,4]]); A1 = V1/W1; A1
+            Finitely generated module V/W over Integer Ring with invariants (2)
+            sage: -A1.0
+            (1)
+            sage: -A1.0 == A1.0           # order 2
+            True
+        """
+        return self.parent()._element_class()(self.parent(), self._x.__neg__())
+
+
+    def _add_(self, other):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0; x
+            (1, 0)
+            sage: y = Q.1; y
+            (0, 1)
+            sage: x + y                        # indirect doctest
+            (1, 1)
+            sage: x + x + x + x
+            (0, 0)
+            sage: x + 0
+            (1, 0)
+            sage: 0 + x
+            (1, 0)
+
+        We test canonical coercion from V and W.
+
+            sage: Q.0 + V.0
+            (1, 4)
+            sage: V.0 + Q.0
+            (1, 4)
+            sage: W.0 + Q.0
+            (1, 0)
+            sage: W.0 + Q.0 == Q.0
+            True
+        """
+        return self.parent()._element_class()(self.parent(), self._x + other._x)
+        
+    def _sub_(self, other):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0; x
+            (1, 0)
+            sage: y = Q.1; y
+            (0, 1)
+            sage: x - y                                # indirect doctest
+            (1, 11)
+            sage: x - x
+            (0, 0)
+        """
+        return self.parent()._element_class()(self.parent(), self._x - other._x)
+
+    def _r_action(self, s):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0; x
+            (1, 0)
+            sage: 2*x                            # indirect doctest
+            (2, 0)
+            sage: 4*x
+            (0, 0)
+        """
+        return self.parent()._element_class()(self.parent(), self._x._rmul_(s))
+
+    def _l_action(self, s):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0; x
+            (1, 0)
+            sage: x*2                          # indirect doctest
+            (2, 0)
+            sage: x*4
+            (0, 0)
+        """
+        return self.parent()._element_class()(self.parent(), self._x._lmul_(s))
+
+    def _repr_(self):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q(V.1)._repr_()
+            '(0, 1)'
+        """
+        return self.vector().__repr__()
+
+    def __getitem__(self, *args):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0 + 3*Q.1; x
+            (1, 3)
+            sage: x[0]
+            1
+            sage: x[1]
+            3
+            sage: x[-1]
+            3
+        """
+        return self.vector().__getitem__(*args)
+
+    def vector(self):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0 + 3*Q.1; x
+            (1, 3)
+            sage: x.vector()
+            (1, 3)
+            sage: tuple(x)
+            (1, 3)
+            sage: list(x)
+            [1, 3]
+            sage: x.vector().parent()
+            Ambient free module of rank 2 over the principal ideal domain Integer Ring
+        """
+        try: return self.__vector
+        except AttributeError:
+            self.__vector = self.parent().coordinate_vector(self, reduce=True)
+            return self.__vector
+
+
+    def __cmp__(self, right):
+        """
+        Compare self and right.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: x = Q.0; x
+            (1, 0)
+            sage: y = Q.1; y
+            (0, 1)
+            sage: x == y
+            False
+            sage: x == x
+            True
+            sage: x + x == 2*x
+            True
+        """
+        return cmp(self.vector(), right.vector())
+
+    def additive_order(self):
+        """
+        Return the additive order of this element.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.0.additive_order()
+            4
+            sage: Q.1.additive_order()
+            12
+            sage: (Q.0+Q.1).additive_order()
+            12
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (12, 0)
+            sage: Q.0.additive_order()
+            12
+            sage: type(Q.0.additive_order())
+            <type 'sage.rings.integer.Integer'>
+            sage: Q.1.additive_order()
+            +Infinity
+        """
+        Q = self.parent()
+        I = Q.invariants()
+        v = self.vector()
+
+        from sage.rings.all import infinity, lcm, Mod, Integer
+        n = Integer(1)
+        for i, a in enumerate(I):
+            if a == 0:
+                if v[i] != 0:
+                    return infinity
+            else:
+                n = lcm(n, Mod(v[i],a).additive_order())
+        return n
diff -r f52bf8765eac -r af576e286a2d sage/modules/fg_pid/fgp_module.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sage/modules/fg_pid/fgp_module.py	Thu Jun 18 16:03:21 2009 -0700
@@ -0,0 +1,1534 @@
+r"""
+Finitely generated modules over a PID.
+
+You can use Sage to compute with finitely generated modules (FGM's)
+over a principal ideal domain R presented as a quotient V/W, where V
+and W are free.
+
+NOTE: Currently this is only enabled over R=ZZ, since it has not been
+tested and debugged over more general PIDs.  All algorithms make sense
+whenever there is a Hermite form implementation.  In theory the
+obstruction to extending the implementation is only that one has to
+decide how elements print.  If you're annoyed that by this, fix things
+and post a patch!
+
+We represent M=V/W as a pair (V,W) with W contained in V, and we
+internally represent elements of M non-cannonically as elements x of
+V.  We also fix independent generators g[i] for M in V, and when we
+print out elements of V we print their coordinates with respect to the
+g[i]; over `\ZZ` this is canonical, since each coefficient is reduce
+modulo the additive order of g[i]. To obtain the vector in V
+corresponding to x in M, use x.lift().
+
+Morphisms between finitely generated R modules are well supported.
+You create a homomorphism by simply giving the images of generators of
+M0 in M1.  Given a morphism phi:M0-->M1, you can compute the image of
+phi, the kernel of phi, and using y=phi.lift(x) you can lift an
+elements x in M1 to an element y in M0, if such a y exists.
+
+TECHNICAL NOTE: For efficiency, we introduce a notion of optimized
+representation for quotient modules.  The optimized representation of
+M=V/W is the quotient V'/W' where V' has as basis lifts of the
+generators g[i] for M.  We internally store a morphism from M0=V0/W0
+to M1=V1/W1 by giving a morphism from the optimized represention V0'
+of M0 to V1 that sends W0 into W1.
+
+
+
+The following TUTORIAL illustrates several of the above points.
+
+First we create free modules V0 and W0 and the quotient module M0.
+Notice that everything works fine even though V0 and W0 are not
+contained inside `\ZZ^n`, which is extremely convenient. ::
+
+    sage: V0 = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W0 = V0.span([V0.0+2*V0.1, 9*V0.0+2*V0.1, 4*V0.2])
+    sage: M0 = V0/W0; M0
+    Finitely generated module V/W over Integer Ring with invariants (4, 16)
+
+The invariants are computed using the Smith normal form algorithm, and
+determine the structure of this finitely generated module.
+
+You can get the V and W used in constructing the quotient module using
+V() and W() methods::
+
+    sage: M0.V()
+    Free module of degree 3 and rank 3 over Integer Ring
+    Echelon basis matrix:
+    [1/2   0   0]
+    [  0   2   0]
+    [  0   0   1]
+    sage: M0.W()
+    Free module of degree 3 and rank 3 over Integer Ring
+    Echelon basis matrix:
+    [1/2   4   0]
+    [  0  32   0]
+    [  0   0   4]
+
+We note that the optimized representation of M0, mentioned above in
+the technical note has a V that need not be equal to V0, in general. ::
+
+    sage: M0.optimized()[0].V()
+    Free module of degree 3 and rank 2 over Integer Ring
+    User basis matrix:
+    [0 0 1]
+    [0 2 0]
+
+Create elements of M0 either by coercing in elements of V0, getting
+generators, or coercing in a list or tuple or coercing in 0.  Coercing
+in a list or tuple takes the corresponding linear combination of the
+generators of M0. ::
+
+    sage: M0(V0.0)
+    (0, 14)
+    sage: M0(V0.0 + W0.0)  # no difference modulo W0
+    (0, 14)
+    sage: M0([3,20])      
+    (3, 4)
+    sage: 3*M0.0 + 20*M0.1
+    (3, 4)
+
+We make an element of M0 by taking a difference of two generators, and
+lift it.  We also illustrate making an element from a list, which
+coerces to V0, then take the equivalence class modulo W0. ::
+
+    sage: x = M0.0 - M0.1; x
+    (1, 15)
+    sage: x.lift()
+    (0, -2, 1)
+    sage: M0(vector([1/2,0,0]))
+    (0, 14)
+    sage: x.additive_order()
+    16
+
+
+Similarly, we construct V1 and W1, and the quotient M1, in a completely different
+2-dimensional ambient space. ::
+
+    sage: V1 = span([[1/2,0],[3/2,2]],ZZ); W1 = V1.span([2*V1.0, 3*V1.1])
+    sage: M1 = V1/W1; M1
+    Finitely generated module V/W over Integer Ring with invariants (6)
+
+We create the homomorphism from M0 to M1 that sends both generators of
+M0 to 3 times the generator of M1.  This is well defined since 3 times
+the generator has order 2. ::
+
+    sage: f = M0.hom([3*M1.0, 3*M1.0]); f
+    Morphism from module over Integer Ring with invariants (4, 16) to module with invariants (6,) that sends the generators to [(3), (3)]
+
+We evaluate the homomorphsm on our element x of the domain, and on the
+first generator of the domain.  We also evaluate at an element of V0,
+which is coerced into M0. ::
+
+    sage: f(x)
+    (0)
+    sage: f(M0.0)
+    (3)
+    sage: f(V0.1)
+    (3)
+
+Here we illustrate lifting an element of the image of f, i.e., finding
+an element of M0 that maps to a given element of M1::
+
+    sage: y = f.lift(3*M1.0); y
+    (0, 13)
+    sage: f(y)
+    (3)
+
+We compute the kernel of f, i.e., the submodule of elements of M0 that
+map to 0.  Note that the kernel is not explicitly represented as a
+submodule, but as another quotient V/W where V is contained in V0.
+You can explicitly coerce elements of the kernel into M0 though. ::
+
+    sage: K = f.kernel(); K
+    Finitely generated module V/W over Integer Ring with invariants (2, 16)
+
+    sage: M0(K.0)
+    (2, 0)
+    sage: M0(K.1)
+    (3, 1)
+    sage: f(M0(K.0))
+    (0)
+    sage: f(M0(K.1))
+    (0)
+
+We compute the image of f. ::
+
+    sage: f.image()
+    Finitely generated module V/W over Integer Ring with invariants (2)
+
+Notice how the elements of the image are written as (0) and (1),
+despite the image being naturally a submodule of M1, which has
+elements (0), (1), (2), (3), (4), (5).  However, below we coerce the
+element (1) of the image into the codomain, and get (3)::
+
+    sage: list(f.image())
+    [(0), (1)]
+    sage: list(M1)
+    [(0), (1), (2), (3), (4), (5)]
+    sage: x = f.image().0; x
+    (1)
+    sage: M1(x)
+    (3)
+
+
+
+AUTHOR:
+- William Stein, 2009
+"""
+
+####################################################################################
+#       Copyright (C) 2009 William Stein <wstein@gmail.com>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+####################################################################################
+
+from sage.modules.module import Module
+from sage.modules.free_module import is_FreeModule
+from sage.structure.sequence import Sequence
+from fgp_element  import FGP_Element
+from fgp_morphism import FGP_Morphism, FGP_Homset
+from sage.rings.all import Integer, ZZ, lcm
+from sage.misc.cachefunc import cached_method
+
+import weakref
+_fgp_module = weakref.WeakValueDictionary()
+
+# This adds extra maybe-not-necessary checks in the code, but could
+# slow things down.  It can impact what happens in more than just this
+# file.
+DEBUG=True
+
+def FGP_Module(V, W, check=True):
+    """
+    INPUT:
+
+    - ``V`` -- a free R-module
+
+    - ``W`` -- a free R-submodule of V
+
+    - ``check`` -- bool (default: True); if True, more checks on
+                   correctness are performed; in particular, we check
+                   the data types of V and W, and that W is a
+                   submodule of V with the same base ring.
+
+    OUTPUT:
+
+    - the quotient V/W as a finitely generated R-module
+    
+
+    EXAMPLES::
+    
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+        sage: import sage.modules.fg_pid.fgp_module
+        sage: Q = sage.modules.fg_pid.fgp_module.FGP_Module(V, W)
+        sage: type(Q)
+        <class 'sage.modules.fg_pid.fgp_module.FGP_Module_class'>
+        sage: Q is sage.modules.fg_pid.fgp_module.FGP_Module(V, W, check=False)
+        True
+    """
+    key = (V,V.basis_matrix(),W,W.basis_matrix())
+    try:
+        return _fgp_module[key]
+    except KeyError: pass
+    M = FGP_Module_class(V, W, check=check)
+    _fgp_module[key] = M
+    return M
+
+def is_FGP_Module(x):
+    """
+    Return true of x is an FGP module, i.e., a finitely generated
+    module over a PID represented as a quotient of finitely generated
+    free modules over a PID.
+    
+    EXAMPLES::
+    
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+        sage: sage.modules.fg_pid.fgp_module.is_FGP_Module(V)
+        False
+        sage: sage.modules.fg_pid.fgp_module.is_FGP_Module(Q)
+        True
+    """
+    return isinstance(x, FGP_Module_class)
+
+class FGP_Module_class(Module):
+    """
+    A finitely generated module over a PID presented as a quotient V/W.
+
+    INPUT:
+
+    - ``V`` -- an R-module
+
+    - ``W`` -- an R-submodule of V
+
+    - ``check`` -- bool (default: True)
+        
+    EXAMPLES::
+        
+        sage: A = (ZZ^1)/span([[100]], ZZ); A
+        Finitely generated module V/W over Integer Ring with invariants (100)
+        sage: A.V()
+        Ambient free module of rank 1 over the principal ideal domain Integer Ring
+        sage: A.W()
+        Free module of degree 1 and rank 1 over Integer Ring
+        Echelon basis matrix:
+        [100]
+
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+        sage: Q = V/W; Q
+        Finitely generated module V/W over Integer Ring with invariants (4, 12)
+        sage: type(Q)
+        <class 'sage.modules.fg_pid.fgp_module.FGP_Module_class'>
+    """
+    def __init__(self, V, W, check=True):
+        """
+        INPUT:
+
+        - ``V`` -- an R-module
+
+        - ``W`` -- an R-submodule of V
+
+        - ``check`` -- bool (default: True); if True, more checks on
+                   correctness are performed; in particular, we check
+                   the data types of V and W, and that W is a
+                   submodule of V with the same base ring.
+        
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: type(Q)
+            <class 'sage.modules.fg_pid.fgp_module.FGP_Module_class'>
+        """
+        if check:
+            if not is_FreeModule(V):
+                raise TypeError, "V must be a FreeModule"
+            if not is_FreeModule(W):
+                raise TypeError, "W must be a FreeModule"
+            if not W.is_submodule(V):
+                raise ValueError, "W must be a submodule of V"
+            if V.base_ring() != W.base_ring():
+                raise ValueError, "W and V must have the same base ring"
+        self._W = W
+        self._V = V
+        self._populate_coercion_lists_(element_constructor = self._element_class(),
+                                       coerce_list = [V, W])
+
+    def _subquotient_class(self):
+        r"""
+        Return a constructor for subquotients of this module. This should be
+        overridden in derived classes. The object returned need not actually be
+        a class, as in the example below -- it may be any callable object
+        accepting 3 arguments `V`, `W`, and `check`.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q._subquotient_class()
+            <function FGP_Module at ...>
+        """
+
+        return FGP_Module
+
+    def _element_class(self):
+        r"""
+        Return the class to be used for creating elements of this module.
+        (This should be overridden in derived classes.)
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q._element_class()
+            <class 'sage.modules.fg_pid.fgp_element.FGP_Element'>
+        """
+        return FGP_Element
+
+    def _coerce_map_from_(self, S):
+        """
+        Return true if S canonically coerces to self.
+        
+        EXAMPLES::
+
+            sage: V = span([[5, -1/2]],ZZ); W = span([[20,-2]],ZZ); Q = V/W; phi=Q.hom([2*Q.0])
+            sage: Q._coerce_map_from_(ZZ)
+            False
+            sage: Q._coerce_map_from_(phi.kernel())
+            True
+            sage: Q._coerce_map_from_(Q)
+            True
+            sage: Q._coerce_map_from_(phi.image())
+            True
+            sage: Q._coerce_map_from_(V/V.zero_submodule())
+            True
+            sage: Q._coerce_map_from_(V/V)
+            False
+            sage: Q._coerce_map_from_(ZZ^2)
+            False
+
+        Of course, `V` canonically coerces to `Q`, as does twice `V`:
+        
+            sage: Q._coerce_map_from_(V)
+            True
+            sage: Q._coerce_map_from_(V.scale(2))
+            True
+        """
+        if is_FGP_Module(S):
+            return S.has_canonical_map_to(self)
+        return bool(self._V._coerce_map_from_(S))
+
+    def _repr_(self):
+        """
+        Return string representation of this module.
+        
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: (V/W)._repr_()
+            'Finitely generated module V/W over Integer Ring with invariants (4, 12)'
+        """
+        I = str(self.invariants()).replace(',)',')')
+        return "Finitely generated module V/W over %s with invariants %s"%(self.base_ring(), I)
+
+    def __div__(self, other):
+        """
+        Return the quotient self/other, where other must be a
+        submodule of self.
+
+        EXAMPLES::
+        
+            sage: V = span([[5, -1/2]],ZZ); W = span([[20,-2]],ZZ); Q = V/W; phi=Q.hom([2*Q.0])
+            sage: Q
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: Q/phi.kernel()
+            Finitely generated module V/W over Integer Ring with invariants (2)
+            sage: Q/Q
+            Finitely generated module V/W over Integer Ring with invariants ()
+        """
+        if not is_FGP_Module(other):
+            if is_FreeModule(other):
+                other = other / other.zero_submodule()
+            else:
+                raise TypeError, "other must be an FGP module"
+        if not other.is_submodule(self):
+            raise ValueError, "other must be a submodule of self"
+        return self._subquotient_class()(self._V, other._V+self._W)
+
+    def __eq__(self, other):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q == Q
+            True
+            sage: loads(dumps(Q)) == Q
+            True
+            sage: Q == V
+            False
+            sage: Q == V/V.zero_submodule()
+            False
+        """
+        if not is_FGP_Module(other):
+            return False
+        return self._V == other._V and self._W == other._W
+    
+    def __call__(self, x, check=True):
+        """
+        INPUT:
+        
+        - ``x`` -- a vector, an fgp module element, or a list or tuple:
+            
+               - list or tuple: take the corresponding linear combination of
+                 the generators of self.
+
+               - vector: coerce vector into V and define the
+                 corresponding element of V/W
+
+               - fgp module element: lift to element of ambient vector
+                 space and try to put into V.  If x is in self already,
+                 just return x.
+
+        - `check` -- bool (default: True)
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: x = Q(V.0-V.1); x
+            (0, 3)
+            sage: type(x)
+            <class 'sage.modules.fg_pid.fgp_element.FGP_Element'>
+            sage: x is Q(x)
+            True
+            sage: x.parent() is Q
+            True
+        """
+        if hasattr(x,'parent') and x.parent() is self:
+            return x
+        if isinstance(x, (list,tuple)):
+            try:
+                x = self.optimized()[0].V().linear_combination_of_basis(x)
+            except ValueError, msg:
+                raise TypeError, msg
+        elif isinstance(x, FGP_Element):
+            x = x.lift()
+        return self._element_class()(self, self._V(x), check=check)
+
+
+    def linear_combination_of_smith_form_gens(self, x):
+        r"""
+        Compute a linear combination of the optimised generators of this module
+        as returned by :meth:`.smith_form_gens`.
+
+        EXAMPLE::
+
+            sage: X = ZZ**2 / span([[3,0],[0,2]], ZZ)
+            sage: X.linear_combination_of_smith_form_gens([1])
+            (1)
+
+        """
+        try:
+            x = self.optimized()[0].V().linear_combination_of_basis(x)
+        except ValueError, msg:
+            raise TypeError, msg
+        return self._element_class()(self, self._V(x), check=False)
+
+    def __contains__(self, x):
+        """
+        Return true if x is contained in self.
+
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.0 in Q
+            True
+            sage: 0 in Q
+            True
+            sage: vector([1,2,3/7]) in Q
+            False
+            sage: vector([1,2,3]) in Q
+            True
+            sage: Q.0 - Q.1 in Q
+            True
+        """
+        if hasattr(x, 'parent') and x.parent() == self:
+            return True
+        try:
+            self(x)
+            return True
+        except TypeError:
+            return False
+
+    def submodule(self, x):
+        """
+        Return the submodule defined by x.
+
+        INPUT:
+
+        - ``x`` -- list, tuple, or FGP module 
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.gens()
+            ((1, 0), (0, 1))
+
+        We create submodules generated by a list or tuple of elements::
+            
+            sage: Q.submodule([Q.0])
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: Q.submodule([Q.1])
+            Finitely generated module V/W over Integer Ring with invariants (12)
+            sage: Q.submodule((Q.0, Q.0 + 3*Q.1))
+            Finitely generated module V/W over Integer Ring with invariants (4, 4)
+
+        A submodule defined by a submodule::
+        
+            sage: A = Q.submodule((Q.0, Q.0 + 3*Q.1)); A
+            Finitely generated module V/W over Integer Ring with invariants (4, 4)
+            sage: Q.submodule(A)
+            Finitely generated module V/W over Integer Ring with invariants (4, 4)
+
+        Inclusion is checked::
+        
+            sage: A.submodule(Q)
+            Traceback (most recent call last):
+            ...
+            ValueError: x.V() must be contained in self's V.
+        """
+        if is_FGP_Module(x):
+            if not x._W.is_submodule(self._W):
+                raise ValueError, "x.W() must be contained in self's W."
+            
+            V = x._V
+            if not V.is_submodule(self._V):
+                raise ValueError, "x.V() must be contained in self's V."
+
+            return x
+
+        if not isinstance(x, (list, tuple)):
+            raise TypeError, "x must be a list, tuple, or FGP module"
+        
+        x = Sequence(x)
+        if is_FGP_Module(x.universe()):
+            # TODO: possibly inefficient in some cases
+            x = [self(v).lift() for v in x]
+        V = self._V.submodule(x) + self._W
+        return self._subquotient_class()(V, self._W)
+
+    def has_canonical_map_to(self, A):
+        """
+        Return True if self has a canonical map to A, relative to the
+        given presentation of A. This means that A is a finitely
+        generated quotient module, self.V() is a submodule of A.V()
+        and self.W() is a submodule of A.W(), i.e., that there is a
+        natural map induced by inclusion of the V's. Note that we do
+        *not* require that this natural map be injective; for this use
+        :meth:`is_submodule`.
+
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: A = Q.submodule((Q.0, Q.0 + 3*Q.1)); A
+            Finitely generated module V/W over Integer Ring with invariants (4, 4)
+            sage: A.has_canonical_map_to(Q)
+            True
+            sage: Q.has_canonical_map_to(A)
+            False
+
+        """
+        if not is_FGP_Module(A):
+            return False
+        if self.cardinality() == 0 and self.base_ring() == A.base_ring():
+            return True
+        return self.V().is_submodule(A.V()) and self.W().is_submodule(A.W())
+
+    def is_submodule(self, A):
+        """
+        Return True if self is a submodule of A.  More precisely, this returns True if
+        if ``self.V()`` is a submodule of ``A.V()``, with ``self.W()`` equal to ``A.W()``. 
+
+        Compare :meth:`.has_canonical_map_to`.
+
+        EXAMPLES::
+        
+            sage: V = ZZ^2; W = V.span([[1,2]]); W2 = W.scale(2)
+            sage: A = V/W; B = W/W2
+            sage: B.is_submodule(A)
+            False
+            sage: A = V/W2; B = W/W2
+            sage: B.is_submodule(A)
+            True
+        
+        This example illustrates that this command works in a subtle cases.::
+
+            sage: A = ZZ^1
+            sage: Q3 = A / A.span([[3]])
+            sage: Q6 = A / A.span([[6]])
+            sage: Q6.is_submodule(Q3)
+            False
+            sage: Q6.has_canonical_map_to(Q3)
+            True
+            sage: Q = A.span([[2]]) / A.span([[6]])
+            sage: Q.is_submodule(Q6)
+            True
+        """
+        if not self.has_canonical_map_to(A):
+            return False
+        
+        return self.V().is_submodule(A.V()) and self.W() == A.W()
+        
+    def V(self): 
+        """
+        If this module was constructed as a quotient V/W, returns V.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.V()
+            Free module of degree 3 and rank 3 over Integer Ring
+            Echelon basis matrix:
+            [1/2   0   0]
+            [  0   1   0]
+            [  0   0   1]
+
+        """
+        return self._V
+
+    def cover(self):
+        """
+        If this module was constructed as V/W, returns the cover module V.  This is the same as self.V().
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.V()
+            Free module of degree 3 and rank 3 over Integer Ring
+            Echelon basis matrix:
+            [1/2   0   0]
+            [  0   1   0]
+            [  0   0   1]
+        """
+        return self.V()
+    
+    def W(self): 
+        """
+        If this module was constructed as a quotient V/W, returns W.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.W()
+            Free module of degree 3 and rank 3 over Integer Ring
+            Echelon basis matrix:
+            [1/2   8   0]
+            [  0  12   0]
+            [  0   0   4]
+        """
+        return self._W
+    
+    def relations(self):
+        """
+        If this module was constructed as V/W, returns the relations module V. This is the same as self.W().
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.relations()
+            Free module of degree 3 and rank 3 over Integer Ring
+            Echelon basis matrix:
+            [1/2   8   0]
+            [  0  12   0]
+            [  0   0   4]
+        """
+        return self.W()
+
+    @cached_method
+    def _relative_matrix(self):
+        """
+        V has a fixed choice of basis, and W has a fixed choice of
+        basis, and both V and W are free R-modules.  Since W is
+        contained in V, we can write each basis element of W as an
+        R-linear combination of the basis for V.  This function
+        returns that matrix over R, where each row corresponds to a
+        basis element of W.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q._relative_matrix()
+            [ 1  8  0]
+            [ 0 12  0]
+            [ 0  0  4]
+        """
+        V = self._V
+        W = self._W
+        A = V.coordinate_module(W).basis_matrix().change_ring(self.base_ring())
+        return A
+        
+    @cached_method
+    def _smith_form(self):
+        """
+        Return matrices S, U, and V such that S = U*R*V, and S is in
+        Smith normal form, and R is the relative matrix that defines
+        self (see :meth:`._relative_matrix`).
+        
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q._smith_form()
+            ([ 1  0  0]
+            [ 0  4  0]
+            [ 0  0 12], [1 0 0]
+            [0 0 1]
+            [0 1 0], [ 1  0 -8]
+            [ 0  0  1]
+            [ 0  1  0])
+        """
+        return self._relative_matrix().smith_form()
+        
+    def base_ring(self): 
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.base_ring()
+            Integer Ring
+        """
+        return self._V.base_ring()
+        
+    @cached_method
+    def invariants(self, include_ones=False):
+        """
+        Return the diagonal entries of the smith form of the relative
+        matrix that defines self (see :meth:`._relative_matrix`)
+        padded with zeros, excluding 1's by default.   Thus if v is the
+        list of integers returned, then self is abstractly isomorphic to
+        the product of cyclic groups `Z/nZ` where `n` is in `v`.
+        
+        INPUT:
+        
+            - ``include_ones`` -- bool (default: False); if True, also
+              include 1's in the output list.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.invariants()
+            (4, 12)
+
+        An example with 1 and 0 rows::
+        
+            sage: V = ZZ^3; W = V.span([[1,2,0],[0,1,0], [0,2,0]]); Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (0)
+            sage: Q.invariants()
+            (0,)
+            sage: Q.invariants(include_ones=True)
+            (1, 1, 0)
+            
+        """
+        D,_,_ = self._smith_form()
+        
+        v = [D[i,i] for i in range(D.nrows())] + [Integer(0)]*(D.ncols()-D.nrows())
+        w = tuple([x for x in v if x != 1])
+        v = tuple(v)
+        self.invariants.set_cache(v, True)
+        self.invariants.set_cache(w, False)
+        return self.invariants(include_ones)
+        
+    def gens(self):
+        """
+        Returns tuple of elements `g_0,...,g_n` of self such that the module generated by
+        the gi is isomorphic to the direct sum of R/ei*R, where ei are the
+        invariants of self and R is the base ring.
+
+        Note that these are not generally uniquely determined, and depending on
+        how Smith normal form is implemented for the base ring, they may not
+        even be deterministic.
+
+        This can safely be overridden in all derived classes.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.gens()
+            ((1, 0), (0, 1))
+            sage: Q.0
+            (1, 0)
+        """
+        return self.smith_form_gens()
+
+    @cached_method
+    def smith_form_gens(self):
+        """
+        Return a set of generators for self which are in Smith normal form. 
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.smith_form_gens()
+            ((1, 0), (0, 1))
+            sage: [x.lift() for x in Q.smith_form_gens()]
+            [(0, 0, 1), (0, 1, 0)]
+        """
+        # Get the rightmost transformation in the Smith form
+        _, _, X = self._smith_form()
+        # Invert it to get a matrix whose rows (in terms of the basis for V)
+        # are the gi (including 1 invariants).
+        Y = X**(-1)  
+        # Get the basis matrix for V
+        B = self._V.basis_matrix()
+        # Multiply to express the gi in terms of the ambient vector space.
+        Z = Y*B
+        # Make gens out of the rows of Z that correspond to non-1 invariants.
+        v = self.invariants(include_ones=True)
+        non1 = [i for i in range(Z.nrows()) if v[i] != 1]
+        Z = Z.matrix_from_rows(non1)
+        self._gens = tuple([self(z, check=DEBUG) for z in Z.rows()])
+        return self._gens
+
+    def coordinate_vector(self, x, reduce=False):
+        """
+        Return coordinates of x with respect to the optimized
+        representation of self.
+        
+        INPUT:
+
+        - ``x`` -- element of self
+            
+        - ``reduce`` -- (default: False); if True, reduce
+          coefficients modulo invariants; this is
+          ignored if the base ring isn't ZZ.
+
+        OUTPUT:
+
+        - ``tuple`` of elements of base ring
+           
+        EXAMPLES::
+
+            sage: V = span([[1/4,0,0],[3/4,4,2],[0,0,2]],ZZ); W = V.span([4*V.0+12*V.1])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 0, 0)
+            sage: Q.coordinate_vector(-Q.0)
+            (-1, 0, 0)
+            sage: Q.coordinate_vector(-Q.0, reduce=True)
+            (3, 0, 0)
+
+        If x isn't in self, it is coerced in::
+        
+            sage: Q.coordinate_vector(V.0)
+            (1, 0, -3)
+            sage: Q.coordinate_vector(Q(V.0))
+            (1, 0, -3)
+
+
+        TESTS::
+        
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.coordinate_vector(Q.0 - Q.1)
+            (1, -1)
+
+            sage: O, X = Q.optimized()
+            sage: O.V()
+            Free module of degree 3 and rank 2 over Integer Ring
+            User basis matrix:
+            [0 0 1]
+            [0 2 0]
+            sage: phi = Q.hom([Q.0, 4*Q.1])
+            sage: x = Q(V.0); x
+            (0, 4)
+            sage: Q.coordinate_vector(x, reduce=True)
+            (0, 4)
+            sage: Q.coordinate_vector(-x, reduce=False)
+            (0, -4)
+            sage: x == 4*Q.1
+            True
+            sage: x = Q(V.1); x
+            (0, 1)
+            sage: Q.coordinate_vector(x)
+            (0, 1)
+            sage: x == Q.1
+            True
+            sage: x = Q(V.2); x
+            (1, 0)
+            sage: Q.coordinate_vector(x)
+            (1, 0)
+            sage: x == Q.0
+            True
+        """
+        try: T = self.__T
+        except AttributeError:
+            self.optimized() # computes T as side effect -- see the "optimized" method.
+            T = self.__T
+
+        x = self(x)
+            
+        c = self._V.coordinate_vector(x.lift())
+        b = (c*T).change_ring(self.base_ring())
+        if reduce and self.base_ring() == ZZ:
+
+            I = self.invariants()
+            return b.parent()([b[i] if I[i] == 0 else b[i] % I[i]   for i in range(len(I))])
+
+        else:
+            # Don't know (or not requested) canonical way to reduce
+            # each entry yet, or how to compute invariants.
+            return b
+            
+    def gen(self, i):
+        """
+        Return the i-th generator of self.
+
+        INPUT:
+
+        - ``i`` -- integer
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.gen(0)
+            (1, 0)
+            sage: Q.gen(1)
+            (0, 1)
+            sage: Q.gen(2)
+            Traceback (most recent call last):
+            ...
+            ValueError: Generator 2 not defined
+            sage: Q.gen(-1)
+            Traceback (most recent call last):
+            ...
+            ValueError: Generator -1 not defined
+        """
+        v = self.gens()
+        if i < 0 or i >= len(v):
+            raise ValueError, "Generator %s not defined"%i
+        return v[i]
+
+    def smith_form_gen(self, i):
+        """
+        Return the i-th generator of self. A private name (so we can freely
+        override gen() in derived classes).
+
+        INPUT:
+
+        - ``i`` -- integer
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.smith_form_gen(0)
+            (1, 0)
+            sage: Q.smith_form_gen(1)
+            (0, 1)
+        """
+        v = self.smith_form_gens()
+        if i < 0 or i >= len(v):
+            raise ValueError, "Smith form generator %s not defined"%i
+        return v[i]
+        
+    def optimized(self):
+        """
+        Return a module isomorphic to this one, but with V replaced by
+        a submodule of V such that the generators of self all lift
+        trivially to generators of V.  Replace W by the intersection
+        of V and W. This has the advantage that V has small dimension
+        and any homomorphism from self trivially extends to a
+        homomorphism from V.
+
+        OUTPUT:
+
+        - ``Q`` -- an optimized quotient V0/W0 with V0 a submodule of V
+          such that phi: V0/W0 --> V/W is an isomorphism
+
+        - ``Z`` -- matrix such that if x is in self.V() and
+          c gives the coordinates of x in terms of the
+          basis for self.V(), then c*Z is in V0
+          and c*Z maps to x via phi above.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: O, X = Q.optimized(); O
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: O.V()
+            Free module of degree 3 and rank 2 over Integer Ring
+            User basis matrix:
+            [0 0 1]
+            [0 1 0]
+            sage: O.W()
+            Free module of degree 3 and rank 2 over Integer Ring
+            Echelon basis matrix:
+            [ 0 12  0]
+            [ 0  0  4]
+            sage: X
+            [0 4 0]
+            [0 1 0]
+            [0 0 1]
+            sage: OV = O.V()
+            sage: Q(OV([0,-8,0])) == V.0
+            True
+            sage: Q(OV([0,1,0])) == V.1
+            True
+            sage: Q(OV([0,0,1])) == V.2
+            True
+        """
+        try:
+            if self.__optimized is True:
+                return self, None
+            return self.__optimized
+        except AttributeError: pass
+        V = self._V.span_of_basis([x.lift() for x in self.smith_form_gens()])
+        M = self._subquotient_class()(V, self._W.intersection(V))
+        # Compute matrix T of linear transformation from self._V to V.
+        # This matrix T gives each basis element of self._V in terms
+        # of our new optimized V, modulo the W's.
+        A = V.basis_matrix().stack(self._W.basis_matrix())
+        B, d = A._clear_denom()
+        H, U = B.hermite_form(transformation=True)
+        Y = H.solve_left(d*self._V.basis_matrix())
+        T = Y * U.matrix_from_columns(range(V.rank()))
+        self.__T = T
+
+        # Finally we multiply by V.basis_matrix() so X gives vectors
+        # in the ambient space instead of coefficients of linear
+        # combinations of the basis for V.
+        X = T * V.basis_matrix()
+
+        self.__optimized = M, X
+        return M, X
+      
+
+    def hom(self, im_gens, codomain=None, check=True):
+        """
+        Homomorphism defined by giving the images of ``self.gens()`` in some
+        fixed fg R-module. 
+        
+        .. note ::
+        
+            We do not assume that the generators given by ``self.gens()`` are
+            the same as the Smith form generators, since this may not be true
+            for a general derived class. 
+        
+        INPUTS:
+
+        - ``im_gens`` -- a list of the images of ``self.gens()`` in some
+          R-module
+
+            
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: phi = Q.hom([3*Q.1, Q.0])
+            sage: phi
+            Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(0, 3), (1, 0)]            
+            sage: phi(Q.0)
+            (0, 3)
+            sage: phi(Q.1)
+            (1, 0)
+            sage: Q.0 == phi(Q.1)
+            True
+
+        This example illustrates creating a morphism to a free module.
+        The free module is turned into an FGP module (i.e., quotient
+        V/W with W=0), and the morphism is constructed::
+
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (2, 0, 0)
+            sage: phi = Q.hom([0,V.0,V.1]); phi
+            Morphism from module over Integer Ring with invariants (2, 0, 0) to module with invariants (0, 0, 0) that sends the generators to [(0, 0, 0), (0, 0, 1), (0, 1, 0)]
+            sage: phi.domain()
+            Finitely generated module V/W over Integer Ring with invariants (2, 0, 0)
+            sage: phi.codomain()
+            Finitely generated module V/W over Integer Ring with invariants (0, 0, 0)
+            sage: phi(Q.0)
+            (0, 0, 0)
+            sage: phi(Q.1)
+            (0, 0, 1)
+            sage: phi(Q.2) == V.1
+            True
+
+        Constructing two zero maps from the zero module::
+
+            sage: A = (ZZ^2)/(ZZ^2); A
+            Finitely generated module V/W over Integer Ring with invariants ()
+            sage: A.hom([])
+            Morphism from module over Integer Ring with invariants () to module with invariants () that sends the generators to []
+            sage: A.hom([]).codomain() is A
+            True
+            sage: B = (ZZ^3)/(ZZ^3)
+            sage: A.hom([],codomain=B)
+            Morphism from module over Integer Ring with invariants () to module with invariants () that sends the generators to []
+            sage: phi = A.hom([],codomain=B); phi
+            Morphism from module over Integer Ring with invariants () to module with invariants () that sends the generators to []
+            sage: phi(A(0))
+            ()
+            sage: phi(A(0)) == B(0)
+            True
+
+
+        A degenerate case::
+
+            sage: A = (ZZ^2)/(ZZ^2)
+            sage: phi = A.hom([]); phi
+            Morphism from module over Integer Ring with invariants () to module with invariants () that sends the generators to []
+            sage: phi(A(0))
+            ()
+
+        The code checks that the morphism is valid.  In the example
+        below we try to send a generator of order 2 to an element of
+        order 14::
+
+            sage: V = span([[1/14,3/14],[0,1/2]],ZZ); W = ZZ^2
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (2, 14)
+            sage: Q([1,11]).additive_order()
+            14
+            sage: f = Q.hom([Q([1,11]), Q([1,3])]); f
+            Traceback (most recent call last):
+            ...
+            ValueError: phi must send optimized submodule of M.W() into N.W()
+
+        """
+        if len(im_gens) == 0:
+            # 0 map
+            N = self if codomain is None else codomain
+        else:
+            if codomain is None:
+                im_gens = Sequence(im_gens)
+                N = im_gens.universe()
+            else:
+                N = codomain
+                im_gens = Sequence(im_gens, universe=N)
+            
+        if is_FreeModule(N):
+            # If im_smith_gens aren't in an R-module, but are in a Free-module,
+            # then we quotient out by the 0 submodule and get an R-module.
+            N = FGP_Module(N, N.zero_submodule(), check=DEBUG)
+            im_gens = Sequence(im_gens, universe=N)
+
+        if len(im_gens) == 0:
+            VO = self.optimized()[0].V()
+            H = VO.Hom(N.V())
+            return FGP_Morphism(self.Hom(N), H(0), check=DEBUG)
+ 
+        if self.gens() == self.smith_form_gens():
+            return self._hom_from_smith(im_gens, check)
+        else:
+            return self._hom_general(im_gens, check)
+
+
+    def _hom_general(self, im_gens, check=True):
+        """
+        Homomorphism defined by giving the images of ``self.gens()`` in some
+        fixed fg R-module. We do not assume that the generators given by
+        ``self.gens()`` are the same as the Smith form generators, since this
+        may not be true for a general derived class.
+    
+        INPUT:
+
+        - ``im_gens`` - a Sequence object giving the images of ``self.gens()``,
+          whose universe is some fixed fg R-module
+
+        EXAMPLE::
+
+            sage: class SillyModule(sage.modules.fg_pid.fgp_module.FGP_Module_class):
+            ...       def gens(self):
+            ...           return tuple(flatten([[x,x] for x in self.smith_form_gens()]))
+            sage: A = SillyModule(ZZ**1, span([[3]], ZZ))
+            sage: A.gen(0)
+            (1)
+            sage: A.gen(1)
+            (1)
+            sage: B = ZZ**1 / span([[3]], ZZ)
+            sage: A.hom([B.0, 2*B.0], B)
+            Traceback (most recent call last):
+            ...
+            ValueError: Images do not determine a valid homomorphism
+            sage: A.hom([B.0, B.0], B)
+            Morphism from module over Integer Ring with invariants (3,) to module with invariants (3,) that sends the generators to [(1), (1)]
+
+        """
+        m = self.ngens()
+        A = ZZ**m
+        q = A.hom([x.lift() for x in self.gens()], self.V())
+        B = q.inverse_image(self.W())
+        N = im_gens.universe()
+        r = A.hom([x.lift() for x in im_gens], N.V())
+        if check:
+            if not r(B).is_submodule(N.W()):
+                raise ValueError, "Images do not determine a valid homomorphism"
+        smith_images = Sequence([N(r(q.lift(x.lift()))) for x in self.smith_form_gens()])
+        return self._hom_from_smith(smith_images, check=DEBUG)
+
+    def _hom_from_smith(self, im_smith_gens, check=True):
+        """
+        Homomorphism defined by giving the images of the Smith-form generators
+        of self in some fixed fg R-module.
+
+        INPUTS:
+
+        - ``im_gens`` -- a Sequence object giving the images of the Smith-form
+          generators of self, whose universe is some fixed fg R-module
+
+        EXAMPLE::
+
+            sage: class SillyModule(sage.modules.fg_pid.fgp_module.FGP_Module_class):
+            ...       def gens(self):
+            ...           return tuple(flatten([[x,x] for x in self.smith_form_gens()]))
+            sage: A = SillyModule(ZZ**1, span([[3]], ZZ))
+            sage: A.gen(0)
+            (1)
+            sage: A.gen(1)
+            (1)
+            sage: B = ZZ**1 / span([[3]], ZZ)
+            sage: A._hom_from_smith(Sequence([B.0]), B)
+            Morphism from module over Integer Ring with invariants (3,) to module with invariants (3,) that sends the generators to [(1), (1)]
+        """
+        if len(im_smith_gens) != len(self.smith_form_gens()):
+            raise ValueError, "im_gens must have length the same as self.smith_form_gens()"
+
+       # replace self by representation in which smith-gens g_i are a basis for V.
+        M, _ = self.optimized()
+        # Define morphism from M to N
+        f = M.V().hom([x.lift() for x in im_smith_gens]) 
+        N = im_smith_gens.universe()
+        homspace = self.Hom(N)
+        phi = FGP_Morphism(homspace, f, check=DEBUG)
+        return phi
+
+    def Hom(self, N):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([V.0+2*V.1, 9*V.0+2*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.Hom(Q)
+            Set of Morphisms from Finitely generated module V/W over Integer Ring with invariants (4, 16) to Finitely generated module V/W over Integer Ring with invariants (4, 16) in Category of ring modules over Integer Ring
+            sage: M = V/V.zero_submodule()
+            sage: M.Hom(Q)
+            Set of Morphisms from Finitely generated module V/W over Integer Ring with invariants (0, 0, 0) to Finitely generated module V/W over Integer Ring with invariants (4, 16) in Category of ring modules over Integer Ring
+        """
+        return FGP_Homset(self, N)
+
+    def random_element(self, *args, **kwds):
+        """
+        Create a random element of self=V/W, by creating a random element of V and
+        reducing it modulo W.
+
+        All arguments are passed onto the random_element method of V.
+
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: Q.random_element()
+            (1, 10)
+        """
+        
+        return self(self._V.random_element(*args, **kwds))
+
+    def cardinality(self):
+        """
+        Return the cardinality of this module as a set.
+        
+        EXAMPLES::
+
+            sage: V = ZZ^2; W = V.span([[1,2],[3,4]]); A = V/W; A
+            Finitely generated module V/W over Integer Ring with invariants (2)
+            sage: A.cardinality()
+            2
+            sage: V = ZZ^2; W = V.span([[1,2]]); A = V/W; A
+            Finitely generated module V/W over Integer Ring with invariants (0)
+            sage: A.cardinality()
+            +Infinity
+        """
+        try: return self.__cardinality
+        except AttributeError: pass
+        from sage.rings.all import infinity
+        if self.base_ring() != ZZ:
+            raise NotImplementedError, "only implemented over ZZ"
+        v = self.invariants()
+        from sage.misc.all import prod
+        c = infinity if 0 in v else prod(v)
+        self.__cardinality = c
+        return c
+
+    def __iter__(self):
+        """
+        Return iterator over all elements of self. 
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([V.0+2*V.1, 4*V.0+2*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (2, 12)
+            sage: z = list(V/W)
+            sage: print z
+            [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (0, 11), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (1, 11)]
+            sage: len(z)
+            24
+        """
+        if self.base_ring() != ZZ:
+            raise NotImplementedError, "only implemented over ZZ"
+        v = self.invariants()
+        if 0 in v:
+            raise NotImplementedError, "currently self must be finite to iterate over"
+        B = self.optimized()[0].V().basis_matrix()
+        V = self.base_ring()**B.nrows()
+        from sage.misc.mrange import cartesian_product_iterator
+        for a in cartesian_product_iterator([range(k) for k in v]):
+            b = V(a) * B
+            yield self(b)
+        
+    def is_finite(self):
+        """
+        Return True if self is finite and False otherwise.
+
+        EXAMPLES::
+        
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([V.0+2*V.1, 9*V.0+2*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 16)
+            sage: Q.is_finite()
+            True
+            sage: Q = V/V.zero_submodule(); Q
+            Finitely generated module V/W over Integer Ring with invariants (0, 0, 0)
+            sage: Q.is_finite()
+            False
+        """
+        return 0 not in self.invariants()
+
+    def annihilator(self):
+        """
+        Return the ideal of the base ring that annihilates self. This
+        is precisely the ideal generated by the LCM of the invariants
+        of self if self is finite, and is 0 otherwise.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([V.0+2*V.1, 9*V.0+2*V.1, 4*V.2])
+            sage: Q = V/W; Q.annihilator()
+            Principal ideal (16) of Integer Ring
+            sage: Q.annihilator().gen()
+            16
+            
+            sage: Q = V/V.span([V.0]); Q
+            Finitely generated module V/W over Integer Ring with invariants (0, 0)
+            sage: Q.annihilator()
+            Principal ideal (0) of Integer Ring
+        """
+        if not self.is_finite():
+            g = 0
+        else:
+            g = reduce(lcm, self.invariants())
+        return self.base_ring().ideal(g)
+
+    def ngens(self):
+        r"""
+        Return the number of generators of self.
+
+        (Note for developers: This is just the length of :meth:`.gens`, rather
+        than of the minimal set of generators as returned by
+        :meth:`.smith_form_gens`; these are the same in the
+        :class:`~sage.modules.fg_pid.fgp_module.FGP_Module_class`, but not
+        necessarily in derived classes.)
+
+        EXAMPLES::
+
+            sage: A = (ZZ**2) / span([[4,0],[0,3]], ZZ)
+            sage: A.ngens()
+            1
+           
+        This works (but please don't do it in production code!) ::
+
+            sage: A.gens = lambda: [1,2,"Barcelona!"]
+            sage: A.ngens()
+            3
+        """
+        return len(self.gens())
+
+    def __hash__(self):
+        r"""
+        Calculate a hash for self.
+
+        EXAMPLES::
+
+            sage: A = (ZZ**2) / span([[4,0],[0,3]], ZZ)
+            sage: hash(A)
+            1328975982 # 32-bit
+
+        """
+        return hash( (self.V(), self.W()) )
+
+##############################################################
+# Useful for testing
+##############################################################
+
+def random_fgp_module(n, R=ZZ, finite=False):
+    """
+    Return a random FGP module inside a rank n free module over R.
+
+    INPUT:
+    
+    - ``n`` -- nonnegative integer
+
+    - ``R`` -- base ring (default: ZZ)
+
+    - ``finite`` -- bool (default: True); if True, make the random module finite.
+
+    EXAMPLES::
+    
+        sage: import sage.modules.fg_pid.fgp_module as fgp
+        sage: fgp.random_fgp_module(4)
+        Finitely generated module V/W over Integer Ring with invariants (4)
+    """
+    K = R.fraction_field()
+    V = K**n
+    i = ZZ.random_element(max(n,1))
+    A = V.span([V.random_element() for _ in range(i)], R)
+    if not finite:
+        i = ZZ.random_element(i+1)
+    while True:
+        B = A.span([A.random_element() for _ in range(i)], R)
+        #Q = A/B
+        Q = FGP_Module_class(A,B,check=DEBUG)
+        if not finite or Q.is_finite():
+            return Q
+    
+def random_fgp_morphism_0(*args, **kwds):
+    """
+    Construct a random fgp module using random_fgp_module,
+    then construct a random morphism that sends each generator
+    to a random multiple of itself.  Inputs are the same
+    as to random_fgp_module.
+
+    EXAMPLES::
+
+        sage: import sage.modules.fg_pid.fgp_module as fgp
+        sage: fgp.random_fgp_morphism_0(4)
+        Morphism from module over Integer Ring with invariants (4,) to module with invariants (4,) that sends the generators to [(0)]
+    
+    """
+    A = random_fgp_module(*args, **kwds)
+    return A.hom([ZZ.random_element()*g for g in A.smith_form_gens()])
+
+def test_morphism_0(*args, **kwds):
+    """
+    EXAMPLES::
+    
+        sage: import sage.modules.fg_pid.fgp_module as fgp
+        sage: s = 0  # we set a seed so results clearly and easly reproducible across runs.
+        sage: set_random_seed(s); v = [fgp.test_morphism_0(1) for _ in range(30)]
+        sage: set_random_seed(s); v = [fgp.test_morphism_0(2) for _ in range(30)]
+        sage: set_random_seed(s); v = [fgp.test_morphism_0(3) for _ in range(10)]
+        sage: set_random_seed(s); v = [fgp.test_morphism_0(i) for i in range(1,20)] 
+        sage: set_random_seed(s); v = [fgp.test_morphism_0(4) for _ in range(50)]    # long
+    """
+    phi = random_fgp_morphism_0(*args, **kwds)
+    K = phi.kernel()
+    I = phi.image()
+    from sage.misc.all import prod
+    if prod(K.invariants()):
+        assert prod(phi.domain().invariants()) % prod(K.invariants()) == 0
+    assert I.is_submodule(phi.codomain())
+    if len(I.smith_form_gens()) > 0:
+        x = phi.lift(I.smith_form_gen(0))
+        assert phi(x) == I.smith_form_gen(0)
+        
+    
diff -r f52bf8765eac -r af576e286a2d sage/modules/fg_pid/fgp_morphism.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sage/modules/fg_pid/fgp_morphism.py	Thu Jun 18 16:03:21 2009 -0700
@@ -0,0 +1,524 @@
+r"""
+Morphisms between finitely generated modules over a PID.
+
+AUTHOR:
+- William Stein, 2009
+"""
+
+####################################################################################
+#       Copyright (C) 2009 William Stein <wstein@gmail.com>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+####################################################################################
+
+from sage.categories.all import Morphism, is_Morphism
+
+import fgp_module
+
+class FGP_Morphism(Morphism):
+    """
+    A morphism between finitely generated modules over a PID.
+
+    EXAMPLES:
+
+    An endomorphism::
+    
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+        sage: Q = V/W; Q
+        Finitely generated module V/W over Integer Ring with invariants (4, 12)
+        sage: phi = Q.hom([Q.0+3*Q.1, -Q.1]); phi
+        Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(1, 3), (0, 11)]
+        sage: phi(Q.0) == Q.0 + 3*Q.1
+        True
+        sage: phi(Q.1) == -Q.1
+        True
+
+    A morphism between different modules V1/W1 ---> V2/W2 in
+    different ambient spaces::
+
+        sage: V1 = ZZ^2; W1 = V1.span([[1,2],[3,4]]); A1 = V1/W1
+        sage: V2 = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W2 = V2.span([2*V2.0+4*V2.1, 9*V2.0+12*V2.1, 4*V2.2]); A2=V2/W2
+        sage: A1
+        Finitely generated module V/W over Integer Ring with invariants (2)
+        sage: A2
+        Finitely generated module V/W over Integer Ring with invariants (4, 12)
+        sage: phi = A1.hom([2*A2.0])
+        sage: phi(A1.0)
+        (2, 0)
+        sage: 2*A2.0
+        (2, 0)
+        sage: phi(2*A1.0)
+        (0, 0)
+
+    TESTS::
+
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+        sage: phi = Q.hom([Q.0,Q.0 + 2*Q.1])
+        sage: loads(dumps(phi)) == phi
+        True
+    """
+    def __init__(self, parent, phi, check=True):
+        """
+        A morphism between finitely generated modules over a PID.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: phi = Q.hom([Q.0+3*Q.1, -Q.1]); phi
+            Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(1, 3), (0, 11)]
+            sage: phi(Q.0) == Q.0 + 3*Q.1
+            True
+            sage: phi(Q.1) == -Q.1
+            True
+
+        For full documentation, see :class:`FGP_Morphism`.
+        """
+        Morphism.__init__(self, parent)
+        M = parent.domain()
+        N = parent.codomain()
+        if isinstance(phi, FGP_Morphism):
+            if check:
+                if phi.parent() != parent:
+                    raise TypeError
+            phi = phi._phi
+            check = False # no need
+            
+        # input: phi is a morphism from MO = M.optimized().V() to N.V()
+        # that sends MO.W() to N.W()
+        if check:
+            if not is_Morphism(phi) and M == N:
+                A = M.optimized()[0].V()
+                B = N.V()
+                s = M.base_ring()(phi) * B.coordinate_module(A).basis_matrix()
+                phi = A.Hom(B)(s)
+                
+            MO, _ = M.optimized()
+            if phi.domain() != MO.V():
+                raise ValueError, "domain of phi must be the covering module for the optimized covering module of the domain"
+            if phi.codomain() != N.V():
+                raise ValueError, "codomain of phi must be the covering module the codomain."
+            # check that MO.W() gets sent into N.W()
+            # todo (optimize): this is slow:
+            for x in MO.W().basis():
+                if phi(x) not in N.W():
+                    raise ValueError, "phi must send optimized submodule of M.W() into N.W()"
+        self._phi = phi
+        
+    def _repr_(self):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: phi = Q.hom([Q.0+3*Q.1, -Q.1])
+            sage: phi._repr_()
+            'Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(1, 3), (0, 11)]'
+        """
+        return "Morphism from module over %s with invariants %s to module with invariants %s that sends the generators to %s"%(
+            self.domain().base_ring(), self.domain().invariants(), self.codomain().invariants(),
+            list(self.im_gens()))
+
+    def im_gens(self):
+        """
+        Return tuple of the images of the generators of the domain
+        under this morphism.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+            sage: phi = Q.hom([Q.0,Q.0 + 2*Q.1])
+            sage: phi.im_gens()
+            ((1, 0), (1, 2))
+            sage: phi.im_gens() is phi.im_gens()
+            True
+        """
+        try: return self.__im_gens
+        except AttributeError: pass
+        self.__im_gens = tuple([self(x) for x in self.domain().gens()])
+        return self.__im_gens
+
+    def __cmp__(self, right):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+            sage: phi = Q.hom([Q.0,Q.0 + 2*Q.1])
+            sage: phi.im_gens()
+            ((1, 0), (1, 2))
+            sage: phi.im_gens() is phi.im_gens()
+            True
+            sage: phi == phi
+            True
+            sage: psi = Q.hom([Q.0,Q.0 - 2*Q.1])
+            sage: phi == psi
+            False
+            sage: psi = Q.hom([Q.0,Q.0 - 2*Q.1])
+            sage: cmp(phi,psi)
+            -1
+            sage: cmp(psi,phi)
+            1
+            sage: psi = Q.hom([Q.0,Q.0 + 2*Q.1])
+            sage: phi == psi
+            True
+        """
+        if not isinstance(right, FGP_Morphism):
+            raise TypeError
+        a = (self.domain(), self.codomain())
+        b = (right.domain(), right.codomain())
+        c = cmp(a,b)
+        if c: return c
+        return cmp(self.im_gens(), right.im_gens())
+
+    def __add__(self, right):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q=V/W; phi = Q.hom([2*Q.0, Q.1]); phi
+            Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(2, 0), (0, 1)]
+            sage: phi + phi
+            Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(0, 0), (0, 2)]
+        """
+        if not isinstance(right, FGP_Morphism):  # todo: implement using coercion model
+            right = self.parent()(right)
+        return FGP_Morphism(self.parent(), self._phi + right._phi, check=fgp_module.DEBUG)
+
+    def __sub__(self, right):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q=V/W; phi = Q.hom([2*Q.0, Q.1])
+            sage: phi - phi
+            Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(0, 0), (0, 0)]
+        """
+        if not isinstance(right, FGP_Morphism):  # todo: implement using coercion model
+            right = self.parent()(right)
+        return FGP_Morphism(self.parent(), self._phi - right._phi, check=fgp_module.DEBUG)
+
+    def __neg__(self):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q=V/W; phi = Q.hom([2*Q.0, Q.1])
+            sage: -phi
+            Morphism from module over Integer Ring with invariants (4, 12) to module with invariants (4, 12) that sends the generators to [(2, 0), (0, 11)]
+        """
+        return FGP_Morphism(self.parent(), self._phi.__neg__(), check=fgp_module.DEBUG)
+
+    def __call__(self, x):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W
+            sage: phi = Q.hom([Q.0+3*Q.1, -Q.1]);
+            sage: phi(Q.0) == Q.0 + 3*Q.1
+            True
+
+        We compute the image of some submodules of the domain::
+
+            sage: phi(Q)
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: phi(Q.submodule([Q.0]))
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: phi(Q.submodule([Q.1]))
+            Finitely generated module V/W over Integer Ring with invariants (12)
+            sage: phi(W/W)
+            Finitely generated module V/W over Integer Ring with invariants ()
+
+        We try to evaluate on a module that is not a submodule of the domain, which raises a ValueError::
+
+            sage: phi(V/W.scale(2))
+            Traceback (most recent call last):
+            ...
+            ValueError: x must be a submodule or element of the domain
+
+        We evaluate on an element of the domain that is not in the V
+        for the optimized representation of the domain::
+
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: O, X = Q.optimized()
+            sage: O.V()
+            Free module of degree 3 and rank 2 over Integer Ring
+            User basis matrix:
+            [0 0 1]
+            [0 2 0]
+            sage: phi = Q.hom([Q.0, 4*Q.1])
+            sage: x = Q(V.0); x
+            (0, 4)
+            sage: x == 4*Q.1
+            True
+            sage: x in O.V()
+            False
+            sage: phi(x)
+            (0, 4)
+            sage: phi(4*Q.1)
+            (0, 4)
+            sage: phi(4*Q.1) == phi(x)
+            True
+        """
+        from fgp_module import is_FGP_Module
+        if is_FGP_Module(x):
+            if not x.is_submodule(self.domain()):
+                raise ValueError, "x must be a submodule or element of the domain"
+            # perhaps can be optimized with a matrix multiply; but note
+            # the subtlety of optimized representations.
+            return self.codomain().submodule([self(y) for y in x.smith_form_gens()])
+        else:
+            C = self.codomain()
+            D = self.domain()
+            O, X = D.optimized()
+            x = D(x)
+            if O is D:
+                x = x.lift()
+            else:
+                # Now we have to transform x so that it is in the optimized representation.
+                x = D.V().coordinate_vector(x.lift()) * X
+            return C(self._phi(x))
+        
+    def kernel(self):
+        """
+        Compute the kernel of this homomorphism.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.hom([0, Q.1]).kernel()
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: A = Q.hom([Q.0, 0]).kernel(); A
+            Finitely generated module V/W over Integer Ring with invariants (12)
+            sage: Q.1 in A
+            True
+            sage: phi = Q.hom([Q.0-3*Q.1, Q.0+Q.1])
+            sage: A = phi.kernel(); A
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: phi(A)
+            Finitely generated module V/W over Integer Ring with invariants ()
+        """
+        # The kernel is just got by taking the inverse image of the submodule W
+        # of the codomain quotient object.
+        V = self._phi.inverse_image(self.codomain().W())
+        D = self.domain()
+        V = D.W() + V
+        return D._subquotient_class()(V, D.W(), check=fgp_module.DEBUG)
+        
+    def inverse_image(self, A):
+        """
+        Given a submodule A of the codomain of this morphism, return
+        the inverse image of A under this morphism.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: phi = Q.hom([0, Q.1])
+            sage: phi.inverse_image(Q.submodule([]))
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: phi.kernel()
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: phi.inverse_image(phi.codomain())
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+
+            sage: phi.inverse_image(Q.submodule([Q.0]))
+            Finitely generated module V/W over Integer Ring with invariants (4)
+            sage: phi.inverse_image(Q.submodule([Q.1]))
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+
+            sage: phi.inverse_image(ZZ^3)
+            Traceback (most recent call last):
+            ...
+            TypeError: A must be a finitely generated quotient module
+            sage: phi.inverse_image(ZZ^3 / W.scale(2))
+            Traceback (most recent call last):
+            ...
+            ValueError: A must be a submodule of the codomain
+        """
+        from fgp_module import is_FGP_Module
+        if not is_FGP_Module(A):
+            raise TypeError, "A must be a finitely generated quotient module"
+        if not A.is_submodule(self.codomain()):
+            raise ValueError, "A must be a submodule of the codomain"
+        V = self._phi.inverse_image(A.V())
+        D = self.domain()
+        V = D.W() + V
+        return D._subquotient_class()(V, D.W(), check=fgp_module.DEBUG)
+
+    def image(self):
+        """
+        Compute the image of this homomorphism.
+        
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q = V/W; Q
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.hom([Q.0+3*Q.1, -Q.1]).image()
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+            sage: Q.hom([3*Q.1, Q.1]).image()
+            Finitely generated module V/W over Integer Ring with invariants (12)
+        """
+        V = self._phi.image() + self.codomain().W()
+        W = V.intersection(self.codomain().W())
+        return self.codomain()._subquotient_class()(V, W, check=fgp_module.DEBUG)    
+        
+    def lift(self, x):
+        """
+        Given an element x in the codomain of self, if possible find an
+        element y in the domain such that self(y) == x.  Raise a ValueError
+        if no such y exists.
+
+        INPUT:
+
+        - ``x`` -- element of the codomain of self.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2])
+            sage: Q=V/W; phi = Q.hom([2*Q.0, Q.1])
+            sage: phi.lift(Q.1)
+            (0, 1)
+            sage: phi.lift(Q.0)
+            Traceback (most recent call last):
+            ...
+            ValueError: no lift of element to domain
+            sage: phi.lift(2*Q.0)
+            (1, 0)
+            sage: phi.lift(2*Q.0+Q.1)
+            (1, 1)
+            sage: V = span([[5, -1/2]],ZZ); W = span([[20,-2]],ZZ); Q = V/W; phi=Q.hom([2*Q.0])
+            sage: x = phi.image().0; phi(phi.lift(x)) == x
+            True
+
+        """
+        x = self.codomain()(x)
+
+        # We view self as a map V/W --> V'/W', where V/W is the
+        # optimized representation (which is fine to work with since
+        # there is a lift to the optimized representation if and only
+        # if there is a lift to the non-optimized representation).
+        CD = self.codomain()
+        A = self._phi.matrix()
+        try:
+            H, U = self.__lift_data
+        except AttributeError:
+            # Get the matrix of self: V --> V' wrt the basis for V and V'.
+
+            # Stack it on top of the basis for W'.
+            Wp = CD.V().coordinate_module(CD.W()).basis_matrix()
+            B = A.stack(Wp)
+
+            # Compute Hermite form of C with transformation
+            H, U = B.hermite_form(transformation=True)
+            self.__lift_data = H, U
+            
+        # write x in terms of the basis for V.
+        w = CD.V().coordinate_vector(x.lift())
+        
+        # Solve z*H = w.
+        try:
+            z = H.solve_left(w)[0]  # [0] to get first solution vector
+            if z.denominator() != 1:
+                raise ValueError
+        except ValueError:
+            raise ValueError, "no lift of element to domain"
+
+        # Write back in terms of rows of B, and delete rows not corresponding to A,
+        # since those coresponding to relations
+        v = (z*U)[:A.nrows()]
+
+        # Take the linear combination that v defines.
+        y = v*self.domain().optimized()[0].V().basis_matrix()
+
+        # Return the finitely generated module element defined by y.
+        y = self.domain()(y)
+        assert self(y) == x, "bug in phi.lift()"
+        return y
+
+from sage.categories.homset import Homset
+
+import weakref
+_fgp_homset = weakref.WeakValueDictionary()
+def FGP_Homset(X, Y):
+    """
+    EXAMPLES::
+
+        sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+        sage: Q.Hom(Q)           # indirect doctest
+        Set of Morphisms from Finitely generated module V/W over Integer Ring with invariants (4, 12) to Finitely generated module V/W over Integer Ring with invariants (4, 12) in Category of ring modules over Integer Ring
+        sage: Q.Hom(Q) is Q.Hom(Q)
+        True
+        sage: type(Q.Hom(Q))
+        <class 'sage.modules.fg_pid.fgp_morphism.FGP_Homset_class'>
+    """
+    key = (X,Y)
+    try: return _fgp_homset[key]
+    except KeyError: pass
+    H = FGP_Homset_class(X, Y)
+    _fgp_homset[key] = H
+    return H
+        
+    
+class FGP_Homset_class(Homset):
+    def __init__(self, X, Y):
+        """
+        EXAMPLES::
+        
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+            sage: type(Q.Hom(Q))
+            <class 'sage.modules.fg_pid.fgp_morphism.FGP_Homset_class'>
+        """
+        Homset.__init__(self, X, Y)
+        self._populate_coercion_lists_(element_constructor = FGP_Morphism,
+                                       coerce_list = [])
+
+    def _coerce_map_from_(self, S):
+        """
+        EXAMPLES::
+
+            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
+            sage: phi = Q.hom([Q.0,Q.0 + 2*Q.1]);  psi = loads(dumps(phi))
+            sage: phi.parent()._coerce_map_from_(psi.parent())
+            True
+            sage: phi.parent()._coerce_map_from_(Q.Hom(ZZ^3))
+            False
+        """
+        # We define this so that morphisms in equal parents canonically coerce,
+        # since otherwise, e.g., the dumps(loads(...)) doctest above would fail.
+        if isinstance(S, FGP_Homset_class) and S == self:
+            return True
+        if self.is_endomorphism_set():
+            R = self.domain().base_ring()
+            return R == S or bool(R._coerce_map_from_(S))
+        return False
+
+    def __call__(self, x):
+        """
+        Convert x into an fgp morphism.
+
+        EXAMPLES::
+
+            sage: V = span([[1/2,0,0],[3/2,2,1],[0,0,1]],ZZ); W = V.span([V.0+2*V.1, 9*V.0+2*V.1, 4*V.2])
+            sage: Q = V/W; H = Q.Hom(Q)
+            sage: H(3)
+            Morphism from module over Integer Ring with invariants (4, 16) to module with invariants (4, 16) that sends the generators to [(3, 0), (0, 3)]
+        """
+        return FGP_Morphism(self, x)
+
diff -r f52bf8765eac -r af576e286a2d sage/modules/free_module.py
--- a/sage/modules/free_module.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/modules/free_module.py	Thu Jun 18 16:03:21 2009 -0700
@@ -693,7 +693,7 @@
         
             sage: V = VectorSpace(QQ,2)
             sage: V._an_element_impl()
-            (2, 3)
+            (1, 0)
             sage: U = V.submodule([[1,0]])
             sage: U._an_element_impl()
             (1, 0)
@@ -702,17 +702,9 @@
             (0, 0)
         """
         try:
-            return self([k+2 for k in range(self.__rank)])
-        except TypeError:
-            pass
-
-        try:
             return self.gen(0)
         except ValueError:
-            #No generators
-            pass
-
-        return self(0)
+            return self(0)
 
     def element_class(self):
         """
@@ -773,7 +765,7 @@
             sage: N((0,0,0,1))
             Traceback (most recent call last):
             ...
-            ValueError: element (= (0, 0, 0, 1)) is not in free module
+            TypeError: element (= (0, 0, 0, 1)) is not in free module
         
         Beware that using check=False can create invalid results::
         
@@ -811,9 +803,13 @@
             if isinstance(self, FreeModule_ambient):
                 return self._element_class(self, x, coerce, copy)
             try:
-                self.coordinates(x)
+                c = self.coordinates(x)
+                R = self.base_ring()
+                for d in c:
+                    if d not in R:
+                        raise ArithmeticError
             except ArithmeticError:
-                raise ValueError, "element (= %s) is not in free module"%(x,)
+                raise TypeError, "element (= %s) is not in free module"%(x,)
         return self._element_class(self, x, coerce, copy)
 
     def is_submodule(self, other):
@@ -1311,7 +1307,7 @@
             sage: W = (ZZ^3).span([[1/2,4,2]])
             sage: V.coordinate_module(W)
             Free module of degree 2 and rank 1 over Integer Ring
-            Echelon basis matrix:
+            User basis matrix:
             [1 4]
             sage: V.0 + 4*V.1
             (1/2, 4, 2)
@@ -1324,7 +1320,7 @@
             sage: W = (ZZ^3).span([[1/4,2,1]])
             sage: V.coordinate_module(W)
             Free module of degree 2 and rank 1 over Integer Ring
-            Echelon basis matrix:
+            User basis matrix:
             [1/2   2]        
         
         The following more elaborate example illustrates using this
@@ -1345,7 +1341,7 @@
             [ 0  0  3  0 -3  2 -1  2 -1 -4  2 -1 -2  1  2  0  0 -1  1]
             sage: K.coordinate_module(L)
             Free module of degree 8 and rank 2 over Integer Ring
-            Echelon basis matrix:
+            User basis matrix:
             [ 1  1  1 -1  1 -1  0  0]
             [ 0  3  2 -1  2 -1 -1 -2]
             sage: K.coordinate_module(L).basis_matrix() * K.basis_matrix()
@@ -1354,15 +1350,12 @@
         """
         if not is_FreeModule(V):
             raise ValueError, "V must be a free module"
-        #if self.base_ring() != V.base_ring():
-        #    raise ValueError, "self and V must have the same base ring"
         A = self.basis_matrix()
         A = A.matrix_from_columns(A.pivots()).transpose()
         B = V.basis_matrix()
         B = B.matrix_from_columns(self.basis_matrix().pivots()).transpose()
         S = A.solve_right(B).transpose()
-        return S.row_module(self.base_ring())
-        
+        return (self.base_ring()**S.ncols()).span_of_basis(S.rows())
 
     def degree(self):
         """
@@ -1702,12 +1695,9 @@
         """
         rand = current_randstate().python_random().random
         R = self.base_ring()
-        v = self(0)
         prob = float(prob)
-        for i in range(self.rank()):
-            if rand() <= prob:
-                v += self.gen(i) * R.random_element(**kwds)
-        return v
+        c = [0 if rand() > prob else R.random_element(**kwds) for _ in range(self.rank())]
+        return self.linear_combination_of_basis(c)
 
     def rank(self):
         """
@@ -1858,9 +1848,9 @@
         K = magma(self.base_ring())
         if not self._inner_product_is_dot_product():
             M = magma(self.inner_product_matrix())
-            return "RSpace(%s,%s,%s)"%(K.name(), self.__rank, M._ref())
-        else:
-            return "RSpace(%s,%s)"%(K.name(), self.__rank)
+            return "RSpace(%s,%s,%s)"%(K.name(), self.rank(), M._ref())
+        else:
+            return "RSpace(%s,%s)"%(K.name(), self.rank())
 
     def _macaulay2_(self, macaulay2=None):
         r"""
@@ -2754,6 +2744,55 @@
         """
         return FreeModule_submodule_with_basis_field(self.ambient_vector_space(), basis, check=check)        
 
+    def quotient(self, sub, check=True):
+        """
+        Return the quotient of self by the given submodule sub.
+        
+        INPUT:
+
+        -  ``sub`` - a submodule of self, or something that can
+           be turned into one via self.submodule(sub).
+        
+        -  ``check`` - (default: True) whether or not to check
+           that sub is a submodule.
+        
+        
+        EXAMPLES::
+        
+            sage: A = ZZ^3; V = A.span([[1,2,3], [4,5,6]])
+            sage: Q = V.quotient( [V.0 + V.1] ); Q
+            Finitely generated module V/W over Integer Ring with invariants (0)
+        """
+        # Calling is_subspace may be way too slow and repeat work done below.
+        # It will be very desirable to somehow do this step better. 
+        if check and (not is_FreeModule(sub) or not sub.is_submodule(self)):
+            try:
+                sub = self.submodule(sub)
+            except (TypeError, ArithmeticError):
+                raise ArithmeticError, "sub must be a subspace of self"
+        if self.base_ring() == sage.rings.integer_ring.ZZ:
+            from fg_pid.fgp_module import FGP_Module
+            return FGP_Module(self, sub, check=False)
+        else:
+            raise NotImplementedError, "quotients of modules over rings other than fields or ZZ is not fully implemented"
+
+    def __div__(self, sub, check=True):
+        """
+        Return the quotient of self by the given submodule sub.
+        
+        This just calls self.quotient(sub, check).
+        
+        EXAMPLES::
+            
+            sage: V1 = ZZ^2; W1 = V1.span([[1,2],[3,4]])
+            sage: V1/W1
+            Finitely generated module V/W over Integer Ring with invariants (2)
+            sage: V2 = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W2 = V2.span([2*V2.0+4*V2.1, 9*V2.0+12*V2.1, 4*V2.2])
+            sage: V2/W2
+            Finitely generated module V/W over Integer Ring with invariants (4, 12)
+        """
+        return self.quotient(sub, check)
+
 class FreeModule_generic_field(FreeModule_generic_pid):
     """
     Base class for all free modules over fields.
@@ -3343,7 +3382,6 @@
         """
         return self.submodule([], check=False, already_echelonized=True)
 
-    # This has to wait until we have non-abstract quotients.
     def __div__(self, sub, check=True):
         """
         Return the quotient of self by the given subspace sub.
@@ -3399,9 +3437,18 @@
             [1 1 1]
             sage: Q(V.0 + V.1)
             (0)
-        """
-        # Calling is_subspace may be way too slow and repeat work done below.
-        # It will be very desirable to somehow do this step better. 
+
+        We illustrate the the base rings must be the same::
+
+            sage: (QQ^2)/(ZZ^2)
+            Traceback (most recent call last):
+            ...
+            ValueError: base rings must be the same
+        """
+        # Calling is_submodule may be way too slow and repeat work done below.
+        # It will be very desirable to somehow do this step better.
+        if is_FreeModule(sub) and self.base_ring() != sub.base_ring():
+            raise ValueError, "base rings must be the same"
         if check and (not is_FreeModule(sub) or not sub.is_subspace(self)):
             try:
                 sub = self.subspace(sub)
@@ -4490,6 +4537,7 @@
                           coerce=False, copy=True) for x in basis]
         except TypeError:
             C = element_class(R.fraction_field(), self.is_sparse())
+            self._element_class = C
             w = [C(self, x.list(),
                           coerce=False, copy=True) for x in basis]
         self.__basis = basis_seq(self, w)
@@ -5333,7 +5381,8 @@
             sage: V.linear_combination_of_basis([1,1])
             (1, 5, 9)
         """
-        return self(self.basis_matrix().linear_combination_of_rows(v))
+        return self(self.basis_matrix().linear_combination_of_rows(v),
+                    check=False, copy=False, coerce=False)
 
 
 class FreeModule_submodule_pid(FreeModule_submodule_with_basis_pid):
diff -r f52bf8765eac -r af576e286a2d sage/modules/free_module_morphism.py
--- a/sage/modules/free_module_morphism.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/modules/free_module_morphism.py	Thu Jun 18 16:03:21 2009 -0700
@@ -1,7 +1,37 @@
 """
-Morphisms of free modules
+Morphisms of free modules.
+
+AUTHOR:
+    - William Stein
+
+TESTS::
+
+    sage: V = ZZ^2; f = V.hom([V.1,-2*V.0])
+    sage: loads(dumps(f))
+    Free module morphism defined by the matrix
+    [ 0  1]
+    [-2  0]
+    Domain: Ambient free module of rank 2 over the principal ideal domain ...
+    Codomain: Ambient free module of rank 2 over the principal ideal domain ...
+    sage: loads(dumps(f)) == f
+    True
 """
 
+####################################################################################
+#       Copyright (C) 2009 William Stein <wstein@gmail.com>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+####################################################################################
+
 # A matrix morphism is a morphism that is defined by multiplication by a
 # matrix.  Elements of domain must either have a method "vector()" that
 # returns a vector that the defining matrix can hit from the left, or
@@ -15,18 +45,32 @@
 import free_module_homspace
 
 def is_FreeModuleMorphism(x):
+    """
+    EXAMPLES::
+    
+        sage: V = ZZ^2; f = V.hom([V.1,-2*V.0])
+        sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(f)
+        True
+        sage: sage.modules.free_module_morphism.is_FreeModuleMorphism(0)
+        False
+    """
     return isinstance(x, FreeModuleMorphism)
 
 class FreeModuleMorphism(matrix_morphism.MatrixMorphism):
     def __init__(self, parent, A):
         """
         INPUT:
+
+            -  ``parent`` - a homspace in a (sub) category of free modules
+
+            -  ``A`` - matrix
         
+        EXAMPLES::
         
-        -  ``parent`` - a homspace in a (sub) category of free
-           modules
-        
-        -  ``A`` - matrix
+            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
+            sage: phi = V.hom(matrix(QQ,3,[1..9]))
+            sage: type(phi)
+            <class 'sage.modules.free_module_morphism.FreeModuleMorphism'>
         """
         if not free_module_homspace.is_FreeModuleHomspace(parent):
             raise TypeError, "parent (=%s) must be a free module hom space"%parent
@@ -34,12 +78,268 @@
             A = A.matrix()
         A = parent._matrix_space()(A)
         matrix_morphism.MatrixMorphism.__init__(self, parent, A)
+
+    def __call__(self, x):
+        """
+        Evaluate this matrix morphism at x, which is either an element
+        that can be coerced into the domain or a submodule of the domain.
+
+        EXAMPLES::
+
+            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
+            sage: phi = V.hom(matrix(QQ,3,[1..9]))
+
+        We compute the image of some elements::
+
+            sage: phi(V.0)
+            (1, 2, 3)
+            sage: phi(V.1)
+            (4, 5, 6)
+            sage: phi(V.0  - 1/4*V.1)
+            (0, 3/4, 3/2)
+
+        We compute the image of a *subspace*::
+
+            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
+            sage: phi = V.hom(matrix(QQ,3,[1..9]))
+            sage: phi.rank()
+            2
+            sage: phi(V)
+            Vector space of degree 3 and dimension 2 over Rational Field
+            Basis matrix:
+            [ 1  0 -1]
+            [ 0  1  2]
+
+        We restrict phi to W and compute the image of an element::
         
-    def __repr__(self):
+            sage: psi = phi.restrict_domain(W)
+            sage: psi(W.0) == phi(W.0)
+            True
+            sage: psi(W.1) == phi(W.1)
+            True
+
+        We compute the image of a submodule of a ZZ-module embedded in
+        a rational vector space::
+        
+            sage: V = QQ^3; W = V.span_of_basis([[2,2,3],[-1,2,5/3]], ZZ)
+            sage: phi = W.hom([W.0, W.0-W.1]); phi
+            Free module morphism defined by the matrix
+            [ 1  0]
+            [ 1 -1]...
+            sage: phi(span([2*W.1],ZZ))
+            Free module of degree 3 and rank 1 over Integer Ring
+            Echelon basis matrix:
+            [  6   0 8/3]
+            sage: phi(2*W.1)
+            (6, 0, 8/3)
+        """
+        if free_module.is_FreeModule(x):
+            V = self.domain().submodule(x)
+            return self.restrict_domain(V).image()
+        return matrix_morphism.MatrixMorphism.__call__(self, x)
+        
+    def _repr_(self):
+        """
+        Return string representation of this morphism of free modules.
+        
+        EXAMPLES::
+        
+            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
+            sage: phi = V.hom(matrix(QQ,3,[1..9]))
+            sage: phi._repr_()        
+            'Free module morphism defined by the matrix\n[1 2 3]\n[4 5 6]\n[7 8 9]\nDomain: Vector space of dimension 3 over Rational Field\nCodomain: Vector space of dimension 3 over Rational Field'
+        """
         if max(self.matrix().nrows(),self.matrix().ncols()) > 5:
             mat = "(not printing %s x %s matrix)"%(self.matrix().nrows(), self.matrix().ncols())
         else:
             mat = str(self.matrix())
         return "Free module morphism defined by the matrix\n%s\nDomain: %s\nCodomain: %s"%(\
             mat, misc.strunc(self.domain()), misc.strunc(self.codomain()))
+
+    def change_ring(self, R):
+        """
+        Change the ring over which this morphism is defined.  This changes the ring of the
+        domain, codomain, and underlying matrix.
+        
+        EXAMPLES::
+
+            sage: V0 = span([[0,0,1],[0,2,0]],ZZ); V1 = span([[1/2,0],[0,2]],ZZ); W = span([[1,0],[0,6]],ZZ)
+            sage: h = V0.hom([-3*V1.0-3*V1.1, -3*V1.0-3*V1.1])
+            sage: h.base_ring()
+            Integer Ring
+            sage: h
+            Free module morphism defined by the matrix
+            [-3 -3]
+            [-3 -3]...
+            sage: h.change_ring(QQ).base_ring()
+            Rational Field
+            sage: f = h.change_ring(QQ); f
+            Free module morphism defined by the matrix
+            [-3 -3]
+            [-3 -3]
+            Domain: Vector space of degree 3 and dimension 2 over Rational Field
+            Basis ...
+            Codomain: Vector space of degree 2 and dimension 2 over Rational Field
+            Basis ...
+            sage: f = h.change_ring(GF(7)); f
+            Free module morphism defined by the matrix
+            [4 4]
+            [4 4]
+            Domain: Vector space of degree 3 and dimension 2 over Finite Field of ...
+            Codomain: Vector space of degree 2 and dimension 2 over Finite Field of ...
+        """
+        D = self.domain().change_ring(R)
+        C = self.codomain().change_ring(R)
+        A = self.matrix().change_ring(R)
+        return D.hom(A, C)
                 
+    def inverse_image(self, V):
+        """
+        Given a submodule V of the codomain of self, return the
+        inverse image of V under self, i.e., the biggest submodule of
+        the domain of self that maps into V.
+
+        EXAMPLES:
+
+        We test computing inverse images over a field::
+        
+            sage: V = QQ^3; W = span([[1,2,3],[-1,2,5/3]], QQ)
+            sage: phi = V.hom(matrix(QQ,3,[1..9]))
+            sage: phi.rank()
+            2
+            sage: I = phi.inverse_image(W); I
+            Vector space of degree 3 and dimension 2 over Rational Field
+            Basis matrix:
+            [   1    0    0]
+            [   0    1 -1/2]
+            sage: phi(I.0) in W
+            True
+            sage: phi(I.1) in W
+            True
+            sage: W = phi.image()
+            sage: phi.inverse_image(W) == V
+            True
+
+        We test computing inverse images between two spaces embedded in different
+        ambient spaces.::
+
+            sage: V0 = span([[0,0,1],[0,2,0]],ZZ); V1 = span([[1/2,0],[0,2]],ZZ); W = span([[1,0],[0,6]],ZZ)
+            sage: h = V0.hom([-3*V1.0-3*V1.1, -3*V1.0-3*V1.1])
+            sage: h.inverse_image(W)
+            Free module of degree 3 and rank 2 over Integer Ring
+            Echelon basis matrix:
+            [0 2 1]
+            [0 0 2]
+            sage: h(h.inverse_image(W)).is_submodule(W)
+            True
+            sage: h(h.inverse_image(W)).index_in(W)
+            +Infinity
+            sage: h(h.inverse_image(W))
+            Free module of degree 2 and rank 1 over Integer Ring
+            Echelon basis matrix:
+            [ 3 12]
+
+
+        We test computing inverse images over the integers::
+
+            sage: V = QQ^3; W = V.span_of_basis([[2,2,3],[-1,2,5/3]], ZZ)
+            sage: phi = W.hom([W.0, W.0-W.1])
+            sage: Z = W.span([2*W.1]); Z
+            Free module of degree 3 and rank 1 over Integer Ring
+            Echelon basis matrix:
+            [    2    -4 -10/3]
+            sage: Y = phi.inverse_image(Z); Y
+            Free module of degree 3 and rank 1 over Integer Ring
+            Echelon basis matrix:
+            [  6   0 8/3]
+            sage: phi(Y) == Z
+            True
+        """
+        if self.rank() == 0:
+            # Special case -- if this is the 0 map, then the only possibility
+            # for the inverse image is that it is the whole domain.
+            return self.domain()
+        
+        R = self.base_ring()
+        A = self.matrix()
+
+        # Replace the module V that we are going to pullback by a
+        # submodule that is contained in the image of self, since our
+        # plan is to lift all generators of V.
+        V = self.image().intersection(V)
+        # Write V in terms of the basis for the codomain.
+        V = self.codomain().coordinate_module(V)
+        B = V.basis_matrix()
+
+        # Compute the kernel, which is contained in the inverse image. 
+        K = self.kernel()
+        
+        if R.is_field():
+            # By solving, find lifts of each of the basis elements of V.
+            # Each row of C gives a linear combination of the basis for the domain
+            # that maps to one of the basis elements V.
+            C = A.solve_left(B)
+
+        else:
+            if not hasattr(A, 'hermite_form'):
+                raise NotImplementedError, "base ring (%s) must have hermite_form algorithm in order to compute inverse image"%R
+
+            # 1. Compute H such that U*A = H = hnf(A) without zero
+            # rows. What this "does" is find a basis for the image of
+            # A and explicitly represents each element in this basis
+            # as the image of some element of the domain (the rows of
+            # U give these elements of the domain).
+            H, U = A.hermite_form(transformation=True,include_zero_rows=False)
+            
+            # 2. Next we find the unique solution to the equation
+            #    Y*H = B.  This writes each basis element of V in
+            # terms of our image basis found in the previous step.
+            Y = H.solve_left(B)
+            
+            # 3. Multiply Y by U then takes those same linear combinations
+            # from step 2 above and lifts them to coefficients that define
+            # linear combinations of the basis for the domain. 
+            C = Y*U
+
+        # Finally take the linear combinations of the basis for the
+        # domain defined by C. Together with the kernel K, this spans
+        # the inverse image of V.
+        if self.domain().is_ambient():
+            L = C.row_module(R)
+        else:
+            L = (C*self.domain().basis_matrix()).row_module(R)
+            
+        return K + L
+        
+    def lift(self, x):
+        r"""
+        Given an element of the image, return an element of the codomain that maps onto it.
+        
+        EXAMPLE::
+
+            sage: X = QQ**2
+            sage: V = X.span([[2, 0], [0, 8]], ZZ)
+            sage: W = (QQ**1).span([[1/6]], ZZ)
+            sage: f = V.hom([W([1/3]), W([1/2])], W)
+            sage: f.lift([1/3])
+            (8, -16)
+            sage: f.lift([1/2])
+            (12, -24)
+            sage: f.lift([1/6])
+            (4, -8)
+            sage: f.lift([1/12])
+            Traceback (most recent call last):
+            ...
+            TypeError: element (= [1/12]) is not in free module
+
+        """
+        from free_module_element import vector
+        x = self.codomain()(x)
+        A = self.matrix()
+        H, U = A.hermite_form(transformation=True,include_zero_rows=False)
+        Y = H.solve_left(vector(self.codomain().coordinates(x)))
+        C = Y*U
+        t = self.domain().linear_combination_of_basis(C.row(0))
+        assert self(t) == x
+        return t
+        
diff -r f52bf8765eac -r af576e286a2d sage/modules/matrix_morphism.py
--- a/sage/modules/matrix_morphism.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/modules/matrix_morphism.py	Thu Jun 18 16:03:21 2009 -0700
@@ -413,7 +413,8 @@
                             cr=True, check=False)
         else:
             B = D.basis_matrix()
-            return Sequence([D.submodule((V.basis_matrix() * B).row_space(),
+            R = D.base_ring()
+            return Sequence([D.submodule((V.basis_matrix() * B).row_module(R),
                                          check=False) for V, _ in E],
                             cr=True, check=False)
 
@@ -475,7 +476,7 @@
             # This is a matrix multiply:  we take the linear combinations of the basis for
             # D given by the elements of the basis for V.
             B = V.basis_matrix() * D.basis_matrix()
-            V = B.row_space()
+            V = B.row_module(D.base_ring())
         return self.domain().submodule(V, check=False)
 
     def image(self):
@@ -520,7 +521,7 @@
             # This is a matrix multiply:  we take the linear combinations of the basis for
             # D given by the elements of the basis for V.
             B = V.basis_matrix() * D.basis_matrix()
-            V = B.row_space(self.domain().base_ring())        
+            V = B.row_module(self.domain().base_ring())        
         return self.codomain().submodule(V, check=False)
         
     def matrix(self):
@@ -573,8 +574,16 @@
             Free module morphism defined by the matrix
             [0 2]...
         """
+        D = self.domain()
+        if hasattr(D, 'coordinate_module'):
+            # We only have to do this in case the module supports
+            # alternative basis.  Some modules do, some modules don't.
+            V = D.coordinate_module(sub)
+        else:
+            V = sub.free_module()
+        A = self.matrix().restrict_domain(V)
         H = sub.Hom(self.codomain())
-        return H(self.matrix().restrict_domain(sub))
+        return H(A)
 
     def restrict_codomain(self, sub):
         """
@@ -600,9 +609,52 @@
             Domain: Ambient free module of rank 2 over the principal ideal domain ...
             Codomain: Free module of degree 2 and rank 1 over Integer Ring
             Echelon ...
+
+        An example in which the codomain equals the full ambient space, but
+        with a different basis::
+
+            sage: V = QQ^2
+            sage: W = V.span_of_basis([[1,2],[3,4]])
+            sage: phi = V.hom(matrix(QQ,2,[1,0,2,0]),W)
+            sage: phi.matrix()
+            [1 0]
+            [2 0]
+            sage: phi(V.0)
+            (1, 2)
+            sage: phi(V.1)
+            (2, 4)
+            sage: X = V.span([[1,2]]); X
+            Vector space of degree 2 and dimension 1 over Rational Field
+            Basis matrix:
+            [1 2]
+            sage: phi(V.0) in X
+            True
+            sage: phi(V.1) in X
+            True
+            sage: psi = phi.restrict_codomain(X); psi
+            Free module morphism defined by the matrix
+            [1]
+            [2]
+            Domain: Vector space of dimension 2 over Rational Field
+            Codomain: Vector space of degree 2 and dimension 1 over Rational Field
+            Basis ...
+            sage: psi(V.0)
+            (1, 2)
+            sage: psi(V.1)
+            (2, 4)
+            sage: psi(V.0).parent() is X
+            True
         """
         H = self.domain().Hom(sub)
-        return H(self.matrix().restrict_codomain(sub.free_module()))
+        C = self.codomain()
+        if hasattr(C, 'coordinate_module'):
+            # We only have to do this in case the module supports
+            # alternative basis.  Some modules do, some modules don't.
+            V = C.coordinate_module(sub)
+        else:
+            V = sub.free_module()
+        return H(self.matrix().restrict_codomain(V))
+
 
     def restrict(self, sub):
         """
@@ -620,10 +672,42 @@
             Echelon ...
             Codomain: Free module of degree 2 and rank 1 over Integer Ring
             Echelon ...
+
+            sage: V = (QQ^2).span_of_basis([[1,2],[3,4]])
+            sage: phi = V.hom([V.0+V.1, 2*V.1])
+            sage: phi(V.1) == 2*V.1
+            True
+            sage: W = span([V.1])
+            sage: phi(W)
+            Vector space of degree 2 and dimension 1 over Rational Field
+            Basis matrix:
+            [  1 4/3]
+            sage: psi = phi.restrict(W); psi
+            Free module morphism defined by the matrix
+            [2]
+            Domain: Vector space of degree 2 and dimension 1 over Rational Field
+            Basis ...
+            Codomain: Vector space of degree 2 and dimension 1 over Rational Field
+            Basis ...
+            sage: psi.domain() == W
+            True
+            sage: psi(W.0) == 2*W.0
+            True
         """
         if not self.is_endomorphism():
             raise ArithmeticError, "matrix morphism must be an endomorphism"
-        A = self.matrix().restrict(sub.free_module())
+        D = self.domain()
+        C = self.codomain()
+        if D is not C and (D.basis() != C.basis()):
+            # Tricky case when two bases for same space
+            return self.restrict_domain(sub).restrict_codomain(sub)
+        if hasattr(D, 'coordinate_module'):
+            # We only have to do this in case the module supports
+            # alternative basis.  Some modules do, some modules don't.
+            V = D.coordinate_module(sub)
+        else:
+            V = sub.free_module()
+        A = self.matrix().restrict(V)
         H = sage.categories.homset.End(sub, self.domain().category())
         return H(A)
         
@@ -688,13 +772,14 @@
 
     def _repr_(self):
         """
-        Return string representation of this morphism (this is for
-        some reason currently not used at all).
+        Return string representation of this morphism (this gets overloaded in the derived class).
 
         EXAMPLES::
 
             sage: V = ZZ^2; phi = V.hom([3*V.0, 2*V.1])
             sage: phi._repr_()
+            'Free module morphism defined by the matrix\n[3 0]\n[0 2]\nDomain: Ambient free module of rank 2 over the principal ideal domain ...\nCodomain: Ambient free module of rank 2 over the principal ideal domain ...'
+            sage: sage.modules.matrix_morphism.MatrixMorphism._repr_(phi)
             'Morphism defined by the matrix\n[3 0]\n[0 2]'
         """
         if max(self.matrix().nrows(),self.matrix().ncols()) > 5:
@@ -703,4 +788,3 @@
         else:
             mat = str(self.matrix())
         return "Morphism defined by the matrix\n%s"%mat
-
diff -r f52bf8765eac -r af576e286a2d sage/modules/quotient_module.py
--- a/sage/modules/quotient_module.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/modules/quotient_module.py	Thu Jun 18 16:03:21 2009 -0700
@@ -1,8 +1,21 @@
-###############################################################################
+r"""
+Quotients of finite rank free modules over a field.
+"""
+
+####################################################################################
+#       Copyright (C) 2009 William Stein <wstein@gmail.com>
 #
-# A quotient of a free module over a field.
+#  Distributed under the terms of the GNU General Public License (GPL)
 #
-###############################################################################
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+####################################################################################
 
 from free_module import FreeModule_ambient_field
 
@@ -111,7 +124,6 @@
             sage: Q._repr_()
             'Vector space quotient V/W of dimension 1 over Finite Field in a of size 3^2 where\nV: Vector space of degree 3 and dimension 2 over Finite Field in a of size 3^2\nUser basis matrix:\n[1 0 a]\n[a a 1]\nW: Vector space of degree 3 and dimension 1 over Finite Field in a of size 3^2\nBasis matrix:\n[    1     1 a + 2]'
         """
-        pi = self.__quo_map
         return "%s space quotient V/W of dimension %s over %s where\nV: %s\nW: %s"%(
             "Sparse vector" if self.is_sparse() else "Vector",
             self.dimension(), self.base_ring(),
@@ -306,7 +318,7 @@
     
     def V(self):
         """
-        Given this quotient space $Q = V/W$, return V.
+        Given this quotient space $Q = V/W$, return $V$.
 
         EXAMPLES:
             sage: M = QQ^10 / [range(10), range(2,12)]
@@ -315,3 +327,27 @@
         """
         return self.__domain
 
+    def cover(self):
+        """
+        Given this quotient space $Q = V/W$, return $V$.  This is the same as self.V().
+
+        EXAMPLES:
+            sage: M = QQ^10 / [range(10), range(2,12)]
+            sage: M.cover()
+            Vector space of dimension 10 over Rational Field
+        """
+        return self.V()
+
+    def relations(self):
+        """
+        Given this quotient space $Q = V/W$, return $W$.  This is the same as self.W().
+
+        EXAMPLES:
+            sage: M = QQ^10 / [range(10), range(2,12)]
+            sage: M.relations()
+            Vector space of degree 10 and dimension 2 over Rational Field
+            Basis matrix:
+            [ 1  0 -1 -2 -3 -4 -5 -6 -7 -8]
+            [ 0  1  2  3  4  5  6  7  8  9]
+        """
+        return self.W()
diff -r f52bf8765eac -r af576e286a2d sage/rings/number_field/order.py
--- a/sage/rings/number_field/order.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/sage/rings/number_field/order.py	Thu Jun 18 16:03:21 2009 -0700
@@ -1793,7 +1793,7 @@
             # Then we move everything into that field, where
             # W does define an order.
             while True:
-                z = W.random_element()
+                z = V.random_element()
                 alpha = from_V(z)
                 if alpha.minpoly().degree() == W.rank():
                     break
diff -r f52bf8765eac -r af576e286a2d setup.py
--- a/setup.py	Wed Jul 01 07:28:17 2009 -0700
+++ b/setup.py	Thu Jun 18 16:03:21 2009 -0700
@@ -801,6 +801,7 @@
                      'sage.misc',
                      
                      'sage.modules',
+                     'sage.modules.fg_pid',
                      
                      'sage.modular',
                      'sage.modular.arithgroup',
