
    sgU                         d Z ddlmZmZmZmZmZ ddlmZ  G d d      Z	 G d de	      Z
 G d d	e
      Z G d
 de
      Zd Zy)a   
Computations with homomorphisms of modules and rings.

This module implements classes for representing homomorphisms of rings and
their modules. Instead of instantiating the classes directly, you should use
the function ``homomorphism(from, to, matrix)`` to create homomorphism objects.
    )Module
FreeModuleQuotientModule	SubModuleSubQuotientModule)CoercionFailedc                       e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd ZeZd Zd Zd Zd Zd Zd Zd Zd Z d Z!y) ModuleHomomorphisma"  
    Abstract base class for module homomoprhisms. Do not instantiate.

    Instead, use the ``homomorphism`` function:

    >>> from sympy import QQ
    >>> from sympy.abc import x
    >>> from sympy.polys.agca import homomorphism

    >>> F = QQ.old_poly_ring(x).free_module(2)
    >>> homomorphism(F, F, [[1, 0], [0, 1]])
    Matrix([
    [1, 0], : QQ[x]**2 -> QQ[x]**2
    [0, 1]])

    Attributes:

    - ring - the ring over which we are considering modules
    - domain - the domain module
    - codomain - the codomain module
    - _ker - cached kernel
    - _img - cached image

    Non-implemented methods:

    - _kernel
    - _image
    - _restrict_domain
    - _restrict_codomain
    - _quotient_domain
    - _quotient_codomain
    - _apply
    - _mul_scalar
    - _compose
    - _add
    c                 *   t        |t              st        d|z        t        |t              st        d|z        |j                  |j                  k7  rt	        d|d|      || _        || _        |j                  | _        d | _        d | _        y )NzSource must be a module, got %szTarget must be a module, got %sz0Source and codomain must be over same ring, got z != )	
isinstancer   	TypeErrorring
ValueErrordomaincodomain_ker_img)selfr   r   s      Q/var/www/html/venv/lib/python3.12/site-packages/sympy/polys/agca/homomorphisms.py__init__zModuleHomomorphism.__init__8   s    &&)=FGG(F+=HII;;(--'/5xA B B KK			    c                 \    | j                   | j                         | _         | j                   S )a  
        Compute the kernel of ``self``.

        That is, if ``self`` is the homomorphism `\phi: M \to N`, then compute
        `ker(\phi) = \{x \in M | \phi(x) = 0\}`.  This is a submodule of `M`.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> homomorphism(F, F, [[1, 0], [x, 0]]).kernel()
        <[x, -1]>
        )r   _kernelr   s    r   kernelzModuleHomomorphism.kernelF   s%    $ 99DIyyr   c                 \    | j                   | j                         | _         | j                   S )a  
        Compute the image of ``self``.

        That is, if ``self`` is the homomorphism `\phi: M \to N`, then compute
        `im(\phi) = \{\phi(x) | x \in M \}`.  This is a submodule of `N`.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> homomorphism(F, F, [[1, 0], [x, 0]]).image() == F.submodule([1, 0])
        True
        )r   _imager   s    r   imagezModuleHomomorphism.image\   s%    $ 99DIyyr   c                     t         )zCompute the kernel of ``self``.NotImplementedErrorr   s    r   r   zModuleHomomorphism._kernelr       !!r   c                     t         )zCompute the image of ``self``.r    r   s    r   r   zModuleHomomorphism._imagev   r"   r   c                     t         z%Implementation of domain restriction.r    r   sms     r   _restrict_domainz#ModuleHomomorphism._restrict_domainz   r"   r   c                     t         z'Implementation of codomain restriction.r    r&   s     r   _restrict_codomainz%ModuleHomomorphism._restrict_codomain~   r"   r   c                     t         z"Implementation of domain quotient.r    r&   s     r   _quotient_domainz#ModuleHomomorphism._quotient_domain   r"   r   c                     t         z$Implementation of codomain quotient.r    r&   s     r   _quotient_codomainz%ModuleHomomorphism._quotient_codomain   r"   r   c                     | j                   j                  |      st        d| j                   d|      || j                   k(  r| S | j                  |      S )a?  
        Return ``self``, with the domain restricted to ``sm``.

        Here ``sm`` has to be a submodule of ``self.domain``.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h
        Matrix([
        [1, x], : QQ[x]**2 -> QQ[x]**2
        [0, 0]])
        >>> h.restrict_domain(F.submodule([1, 0]))
        Matrix([
        [1, x], : <[1, 0]> -> QQ[x]**2
        [0, 0]])

        This is the same as just composing on the right with the submodule
        inclusion:

        >>> h * F.submodule([1, 0]).inclusion_hom()
        Matrix([
        [1, x], : <[1, 0]> -> QQ[x]**2
        [0, 0]])
        zsm must be a submodule of , got )r   is_submoduler   r(   r&   s     r   restrict_domainz"ModuleHomomorphism.restrict_domain   sT    @ {{''+ $R1 2 2K$$R((r   c                     |j                  | j                               st        d| j                         d|      || j                  k(  r| S | j	                  |      S )a  
        Return ``self``, with codomain restricted to to ``sm``.

        Here ``sm`` has to be a submodule of ``self.codomain`` containing the
        image.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h
        Matrix([
        [1, x], : QQ[x]**2 -> QQ[x]**2
        [0, 0]])
        >>> h.restrict_codomain(F.submodule([1, 0]))
        Matrix([
        [1, x], : QQ[x]**2 -> <[1, 0]>
        [0, 0]])
        z
the image  must contain sm, got )r4   r   r   r   r+   r&   s     r   restrict_codomainz$ModuleHomomorphism.restrict_codomain   sU    2 tzz|, $

b2 3 3K&&r**r   c                     | j                         j                  |      st        d| j                         d|      |j                         r| S | j	                  |      S )am  
        Return ``self`` with domain replaced by ``domain/sm``.

        Here ``sm`` must be a submodule of ``self.kernel()``.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h
        Matrix([
        [1, x], : QQ[x]**2 -> QQ[x]**2
        [0, 0]])
        >>> h.quotient_domain(F.submodule([-x, 1]))
        Matrix([
        [1, x], : QQ[x]**2/<[-x, 1]> -> QQ[x]**2
        [0, 0]])
        zkernel r7   )r   r4   r   is_zeror.   r&   s     r   quotient_domainz"ModuleHomomorphism.quotient_domain   sT    0 {{}))"-"kkmR1 2 2::<K$$R((r   c                     | j                   j                  |      st        d| j                   d|      |j                         r| S | j	                  |      S )a:  
        Return ``self`` with codomain replaced by ``codomain/sm``.

        Here ``sm`` must be a submodule of ``self.codomain``.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h
        Matrix([
        [1, x], : QQ[x]**2 -> QQ[x]**2
        [0, 0]])
        >>> h.quotient_codomain(F.submodule([1, 1]))
        Matrix([
        [1, x], : QQ[x]**2 -> QQ[x]**2/<[1, 1]>
        [0, 0]])

        This is the same as composing with the quotient map on the left:

        >>> (F/[(1, 1)]).quotient_hom() * h
        Matrix([
        [1, x], : QQ[x]**2 -> QQ[x]**2/<[1, 1]>
        [0, 0]])
        z#sm must be a submodule of codomain r3   )r   r4   r   r:   r1   r&   s     r   quotient_codomainz$ModuleHomomorphism.quotient_codomain   sP    > }}))"- $r3 4 4::<K&&r**r   c                     t         )zApply ``self`` to ``elem``.r    r   elems     r   _applyzModuleHomomorphism._apply  r"   r   c                     | j                   j                  | j                  | j                  j                  |                  S N)r   convertrA   r   r?   s     r   __call__zModuleHomomorphism.__call__  s/    }}$$T[[1D1DT1J%KLLr   c                     t         )a	  
        Compose ``self`` with ``oth``, that is, return the homomorphism
        obtained by first applying then ``self``, then ``oth``.

        (This method is private since in this syntax, it is non-obvious which
        homomorphism is executed first.)
        r    r   oths     r   _composezModuleHomomorphism._compose  s
     "!r   c                     t         )z8Scalar multiplication. ``c`` is guaranteed in self.ring.r    )r   cs     r   _mul_scalarzModuleHomomorphism._mul_scalar'  r"   r   c                     t         )zv
        Homomorphism addition.
        ``oth`` is guaranteed to be a homomorphism with same domain/codomain.
        r    rG   s     r   _addzModuleHomomorphism._add+  s
    
 "!r   c                     t        |t              sy|j                  | j                  k(  xr |j                  | j                  k(  S )zEHelper to check that oth is a homomorphism with same domain/codomain.F)r   r
   r   r   rG   s     r   
_check_homzModuleHomomorphism._check_hom2  s5    #12zzT[[(JS\\T]]-JJr   c                     t        |t              r*| j                  |j                  k(  r|j	                  |       S 	 | j                  | j                  j                  |            S # t        $ r	 t        cY S w xY wrC   )
r   r
   r   r   rI   rL   r   rD   r   NotImplementedrG   s     r   __mul__zModuleHomomorphism.__mul__8  se    c-.4;;#,,3N<<%%	"##DII$5$5c$:;; 	"!!	"s   )A& &A87A8c                     	 | j                  d| j                  j                  |      z        S # t        $ r	 t        cY S w xY w)N   )rL   r   rD   r   rR   rG   s     r   __truediv__zModuleHomomorphism.__truediv__C  sA    	"##Adii&7&7&<$<== 	"!!	"s   ,/ A Ac                 R    | j                  |      r| j                  |      S t        S rC   )rP   rN   rR   rG   s     r   __add__zModuleHomomorphism.__add__I  s"    ??399S>!r   c                     | j                  |      r9| j                  |j                  | j                  j	                  d                  S t
        S )N)rP   rN   rL   r   rD   rR   rG   s     r   __sub__zModuleHomomorphism.__sub__N  s;    ??399S__TYY->->r-BCDDr   c                 >    | j                         j                         S )a  
        Return True if ``self`` is injective.

        That is, check if the elements of the domain are mapped to the same
        codomain element.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h.is_injective()
        False
        >>> h.quotient_domain(h.kernel()).is_injective()
        True
        )r   r:   r   s    r   is_injectivezModuleHomomorphism.is_injectiveS  s    * {{}$$&&r   c                 <    | j                         | j                  k(  S )a  
        Return True if ``self`` is surjective.

        That is, check if every element of the codomain has at least one
        preimage.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h.is_surjective()
        False
        >>> h.restrict_codomain(h.image()).is_surjective()
        True
        )r   r   r   s    r   is_surjectivez ModuleHomomorphism.is_surjectivej  s    * zz|t}},,r   c                 F    | j                         xr | j                         S )a~  
        Return True if ``self`` is an isomorphism.

        That is, check if every element of the codomain has precisely one
        preimage. Equivalently, ``self`` is both injective and surjective.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h = h.restrict_codomain(h.image())
        >>> h.is_isomorphism()
        False
        >>> h.quotient_domain(h.kernel()).is_isomorphism()
        True
        )r]   r_   r   s    r   is_isomorphismz!ModuleHomomorphism.is_isomorphism  s!    ,   ";t'9'9';;r   c                 >    | j                         j                         S )aN  
        Return True if ``self`` is a zero morphism.

        That is, check if every element of the domain is mapped to zero
        under self.

        Examples
        ========

        >>> from sympy import QQ
        >>> from sympy.abc import x
        >>> from sympy.polys.agca import homomorphism

        >>> F = QQ.old_poly_ring(x).free_module(2)
        >>> h = homomorphism(F, F, [[1, 0], [x, 0]])
        >>> h.is_zero()
        False
        >>> h.restrict_domain(F.submodule()).is_zero()
        True
        >>> h.quotient_codomain(h.image()).is_zero()
        True
        )r   r:   r   s    r   r:   zModuleHomomorphism.is_zero  s    . zz|##%%r   c                 H    	 | |z
  j                         S # t        $ r Y yw xY w)NF)r:   r   rG   s     r   __eq__zModuleHomomorphism.__eq__  s,    	3J'')) 		s    	!!c                     | |k(   S rC    rG   s     r   __ne__zModuleHomomorphism.__ne__  s    CK  r   N)"__name__
__module____qualname____doc__r   r   r   r   r   r(   r+   r.   r1   r5   r8   r;   r=   rA   rE   rI   rL   rN   rP   rS   __rmul__rV   rX   r[   r]   r_   ra   r:   rd   rg   rf   r   r   r
   r
      s    #J,,""""""%)N+@)>$+L"M"""K" H"

'.-.<0&2!r   r
   c                   L    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)MatrixHomomorphisma  
    Helper class for all homomoprhisms which are expressed via a matrix.

    That is, for such homomorphisms ``domain`` is contained in a module
    generated by finitely many elements `e_1, \ldots, e_n`, so that the
    homomorphism is determined uniquely by its action on the `e_i`. It
    can thus be represented as a vector of elements of the codomain module,
    or potentially a supermodule of the codomain module
    (and hence conventionally as a matrix, if there is a similar interpretation
    for elements of the codomain module).

    Note that this class does *not* assume that the `e_i` freely generate a
    submodule, nor that ``domain`` is even all of this submodule. It exists
    only to unify the interface.

    Do not instantiate.

    Attributes:

    - matrix - the list of images determining the homomorphism.
    NOTE: the elements of matrix belong to either self.codomain or
          self.codomain.container

    Still non-implemented methods:

    - kernel
    - _apply
    c                    t         j                  | ||       t        |      |j                  k7  r$t	        d|j                  dt        |            | j
                  j                  t        | j
                  t        t        f      r | j
                  j                  j                  t        fd|D              | _        y )NzNeed to provide z elements, got c              3   .   K   | ]  } |        y wrC   rf   ).0x	converters     r   	<genexpr>z.MatrixHomomorphism.__init__.<locals>.<genexpr>  s     9QIaL9s   )r
   r   lenrankr   r   rD   r   r   r   	containertuplematrix)r   r   r   ry   rs   s       @r   r   zMatrixHomomorphism.__init__  s    ##D&(;v;&++% &S[: ; ; MM))	dmmi1B%CD//77I9&99r   c                 "   ddl m} d }t        | j                  t        t
        f      rd } || j                  D cg c]1  } ||      D cg c]  }| j                  j                  |       c}3 c}}      j                  S c c}w c c}}w )z=Helper function which returns a SymPy matrix ``self.matrix``.r   )Matrixc                     | S rC   rf   rr   s    r   <lambda>z2MatrixHomomorphism._sympy_matrix.<locals>.<lambda>  s    a r   c                     | j                   S rC   )datar}   s    r   r~   z2MatrixHomomorphism._sympy_matrix.<locals>.<lambda>  s
    !&& r   )
sympy.matricesr{   r   r   r   r   ry   r   to_sympyT)r   r{   rK   rr   ys        r   _sympy_matrixz MatrixHomomorphism._sympy_matrix  sg    )dmmn6G%HI AdkkRqt<!		**1-<RSUUU<Rs   B
"B/B
B
c                    t        | j                               j                  d      }d| j                  d| j                  }dt        |      z  }t        |      }t        |dz        D ]  }||xx   |z  cc<    ||dz  xx   |z  cc<   t        |dz  dz   |      D ]  }||xx   |z  cc<    dj                  |      S )N
z : z ->     rU   )reprr   splitr   r   ru   rangejoin)r   linestsnis         r   __repr__zMatrixHomomorphism.__repr__  s    T'')*006![[$--8AJJqAv 	A!HMH	a1fq!tax# 	A!HMH	yyr   c                 D    t        || j                  | j                        S r%   )SubModuleHomomorphismr   ry   r&   s     r   r(   z#MatrixHomomorphism._restrict_domain  s    $RDDr   c                 P    | j                  | j                  || j                        S r*   )	__class__r   ry   r&   s     r   r+   z%MatrixHomomorphism._restrict_codomain  s    ~~dkk2t{{;;r   c                 j    | j                  | j                  |z  | j                  | j                        S r-   r   r   r   ry   r&   s     r   r.   z#MatrixHomomorphism._quotient_domain  s%    ~~dkk"ndmmT[[IIr   c           
      2   | j                   |z  }|j                  }t        | j                   t              r|j                  j                  }| j                  | j                  | j                   |z  | j                  D cg c]
  } ||       c}      S c c}w r0   )r   rD   r   r   rw   r   r   ry   )r   r'   Qrs   rr   s        r   r1   z%MatrixHomomorphism._quotient_codomain  sq    MM"II	dmmY/++I~~dkk4==+;#';;/aYq\/1 	1/s   >Bc           
          | j                  | j                  | j                  t        | j                  |j                        D cg c]
  \  }}||z    c}}      S c c}}w rC   )r   r   r   zipry   )r   rH   rr   r   s       r   rN   zMatrixHomomorphism._add  sI    ~~dkk4==14T[[#**1MNAq1uNP 	PNs   Ac           	          | j                  | j                  | j                  | j                  D cg c]  }||z  	 c}      S c c}w rC   r   )r   rK   rr   s      r   rL   zMatrixHomomorphism._mul_scalar  s3    ~~dkk4==:T11Q3:TUU:Ts   Ac           
          | j                  | j                  |j                  | j                  D cg c]
  } ||       c}      S c c}w rC   r   )r   rH   rr   s      r   rI   zMatrixHomomorphism._compose  s3    ~~dkk3<<$++9VQ#a&9VWW9Vs   AN)rh   ri   rj   rk   r   r   r   r(   r+   r.   r1   rN   rL   rI   rf   r   r   rn   rn     s?    :	:V
 E<J1PVXr   rn   c                   "    e Zd ZdZd Zd Zd Zy)FreeModuleHomomorphisma  
    Concrete class for homomorphisms with domain a free module or a quotient
    thereof.

    Do not instantiate; the constructor does not check that your data is well
    defined. Use the ``homomorphism`` function instead:

    >>> from sympy import QQ
    >>> from sympy.abc import x
    >>> from sympy.polys.agca import homomorphism

    >>> F = QQ.old_poly_ring(x).free_module(2)
    >>> homomorphism(F, F, [[1, 0], [0, 1]])
    Matrix([
    [1, 0], : QQ[x]**2 -> QQ[x]**2
    [0, 1]])
    c                     t        | j                  t              r|j                  }t	        d t        || j                        D              S )Nc              3   ,   K   | ]  \  }}||z    y wrC   rf   rq   rr   es      r   rt   z0FreeModuleHomomorphism._apply.<locals>.<genexpr>/       <TQ1q5<   )r   r   r   r   sumr   ry   r?   s     r   rA   zFreeModuleHomomorphism._apply,  s5    dkk>299D<St{{%;<<<r   c                 H     | j                   j                  | j                   S rC   )r   	submodulery   r   s    r   r   zFreeModuleHomomorphism._image1  s    &t}}&&44r   c                     | j                         j                         } | j                  j                  |j                   S rC   )r   syzygy_moduler   r   gens)r   syzs     r   r   zFreeModuleHomomorphism._kernel4  s3     jjl((*$t{{$$chh//r   Nrh   ri   rj   rk   rA   r   r   rf   r   r   r   r     s    $=
50r   r   c                   "    e Zd ZdZd Zd Zd Zy)r   a  
    Concrete class for homomorphism with domain a submodule of a free module
    or a quotient thereof.

    Do not instantiate; the constructor does not check that your data is well
    defined. Use the ``homomorphism`` function instead:

    >>> from sympy import QQ
    >>> from sympy.abc import x
    >>> from sympy.polys.agca import homomorphism

    >>> M = QQ.old_poly_ring(x).free_module(2)*x
    >>> homomorphism(M, M, [[1, 0], [0, 1]])
    Matrix([
    [1, 0], : <[x, 0], [0, x]> -> <[x, 0], [0, x]>
    [0, 1]])
    c                     t        | j                  t              r|j                  }t	        d t        || j                        D              S )Nc              3   ,   K   | ]  \  }}||z    y wrC   rf   r   s      r   rt   z/SubModuleHomomorphism._apply.<locals>.<genexpr>T  r   r   )r   r   r   r   r   r   ry   r?   s     r   rA   zSubModuleHomomorphism._applyQ  s6    dkk#4599D<St{{%;<<<r   c                      | j                   j                  | j                  j                  D cg c]
  } | |       c} S c c}w rC   )r   r   r   r   )r   rr   s     r   r   zSubModuleHomomorphism._imageV  s5    &t}}&&$++:J:J(KQa(KLL(Ks   Ac                    | j                         j                         } | j                  j                  |j                  D cg c]2  }t        d t        || j                  j                        D              4 c} S c c}w )Nc              3   ,   K   | ]  \  }}||z    y wrC   rf   )rq   xigis      r   rt   z0SubModuleHomomorphism._kernel.<locals>.<genexpr>\  s     ?FB"R%?r   )r   r   r   r   r   r   r   )r   r   r   s      r   r   zSubModuleHomomorphism._kernelY  sj    jjl((*$t{{$$xx! ?c!T[[-=-=&>?? !" 	"!s   7A>Nr   rf   r   r   r   r   >  s    $=
M"r   r   c           
          d } ||       \  }}}} ||      \  }}	}
}t        |||D cg c]
  } ||       c}      j                  |      j                  |	      j                  |
      j	                  |      S c c}w )a>  
    Create a homomorphism object.

    This function tries to build a homomorphism from ``domain`` to ``codomain``
    via the matrix ``matrix``.

    Examples
    ========

    >>> from sympy import QQ
    >>> from sympy.abc import x
    >>> from sympy.polys.agca import homomorphism

    >>> R = QQ.old_poly_ring(x)
    >>> T = R.free_module(2)

    If ``domain`` is a free module generated by `e_1, \ldots, e_n`, then
    ``matrix`` should be an n-element iterable `(b_1, \ldots, b_n)` where
    the `b_i` are elements of ``codomain``. The constructed homomorphism is the
    unique homomorphism sending `e_i` to `b_i`.

    >>> F = R.free_module(2)
    >>> h = homomorphism(F, T, [[1, x], [x**2, 0]])
    >>> h
    Matrix([
    [1, x**2], : QQ[x]**2 -> QQ[x]**2
    [x,    0]])
    >>> h([1, 0])
    [1, x]
    >>> h([0, 1])
    [x**2, 0]
    >>> h([1, 1])
    [x**2 + 1, x]

    If ``domain`` is a submodule of a free module, them ``matrix`` determines
    a homomoprhism from the containing free module to ``codomain``, and the
    homomorphism returned is obtained by restriction to ``domain``.

    >>> S = F.submodule([1, 0], [0, x])
    >>> homomorphism(S, T, [[1, x], [x**2, 0]])
    Matrix([
    [1, x**2], : <[1, 0], [0, x]> -> QQ[x]**2
    [x,    0]])

    If ``domain`` is a (sub)quotient `N/K`, then ``matrix`` determines a
    homomorphism from `N` to ``codomain``. If the kernel contains `K`, this
    homomorphism descends to ``domain`` and is returned; otherwise an exception
    is raised.

    >>> homomorphism(S/[(1, 0)], T, [0, [x**2, 0]])
    Matrix([
    [0, x**2], : <[1, 0] + <[1, 0]>, [0, x] + <[1, 0]>, [1, 0] + <[1, 0]>> -> QQ[x]**2
    [0,    0]])
    >>> homomorphism(S/[(0, x)], T, [0, [x**2, 0]])
    Traceback (most recent call last):
    ...
    ValueError: kernel <[1, 0], [0, 0]> must contain sm, got <[0,x]>

    c                     t         t              r   j                          fdfS t         t              r' j                   j                   j
                   fdfS t         t              r1 j                  j                   j                   j
                   fdfS  j                    j                          fdfS )z
        Return a tuple ``(F, S, Q, c)`` where ``F`` is a free module, ``S`` is a
        submodule of ``F``, and ``Q`` a submodule of ``S``, such that
        ``module = S/Q``, and ``c`` is a conversion function.
        c                 &    j                  |       S rC   )rD   rr   modules    r   r~   z0homomorphism.<locals>.freepres.<locals>.<lambda>  s    PQAR r   c                 :    j                  |       j                  S rC   )rD   r   r   s    r   r~   z0homomorphism.<locals>.freepres.<locals>.<lambda>  s    fnnQ/44 r   c                 N    j                   j                  |       j                  S rC   )rw   rD   r   r   s    r   r~   z0homomorphism.<locals>.freepres.<locals>.<lambda>  s    f..66q9>> r   c                 :    j                   j                  |       S rC   )rw   rD   r   s    r   r~   z0homomorphism.<locals>.freepres.<locals>.<lambda>  s    &**2215 r   )r   r   r   r   basekilled_moduler   rw   )r   s   `r   freepreszhomomorphism.<locals>.freepres  s     fj)66#3#3#57RRRfn-KKf.B.B46 6f/0KK))6;;8L8L>@ @   &&*:*:*<57 	7r   )r   r5   r8   r=   r;   )r   r   ry   r   SFSSSQ_TFTSTQrK   rr   s                r   homomorphismr   `  s~    x7$ V$MBBX&MBB!"b*@A1Q4*@ ?200  R !45*@s   A;N)rk   sympy.polys.agca.modulesr   r   r   r   r   sympy.polys.polyerrorsr   r
   rn   r   r   r   rf   r   r   <module>r      sX   " " 1g! g!TZX+ ZXz"0/ "0J". "DS5r   