U
    ZÊ¹j±U  ã                   @   sv   d Z ddlmZmZmZmZmZ ddlmZ G dd„ dƒZ	G dd„ de	ƒZ
G dd	„ d	e
ƒZG d
d„ de
ƒZdd„ ZdS )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                   @   sü   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ ZeZd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Z d:d;„ Z!d<S )=Ú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                 C   sl   t |tƒstd| ƒ‚t |tƒs,td| ƒ‚|j|jkrHtd||f ƒ‚|| _|| _|j| _d | _d | _d S )NzSource must be a module, got %szTarget must be a module, got %sz8Source and codomain must be over same ring, got %s != %s)	Ú
isinstancer   Ú	TypeErrorÚringÚ
ValueErrorÚdomainÚcodomainÚ_kerÚ_img)Úselfr   r   © r   ú]/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/polys/agca/homomorphisms.pyÚ__init__8   s    

ÿzModuleHomomorphism.__init__c                 C   s   | j dkr|  ¡ | _ | 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]>
        N)r   Ú_kernel©r   r   r   r   ÚkernelF   s    

zModuleHomomorphism.kernelc                 C   s   | j dkr|  ¡ | _ | 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
        N)r   Ú_imager   r   r   r   Úimage\   s    

zModuleHomomorphism.imagec                 C   s   t ‚dS )zCompute the kernel of ``self``.N©ÚNotImplementedErrorr   r   r   r   r   r   s    zModuleHomomorphism._kernelc                 C   s   t ‚dS )zCompute the image of ``self``.Nr   r   r   r   r   r   v   s    zModuleHomomorphism._imagec                 C   s   t ‚dS )ú%Implementation of domain restriction.Nr   ©r   Úsmr   r   r   Ú_restrict_domainz   s    z#ModuleHomomorphism._restrict_domainc                 C   s   t ‚dS )ú'Implementation of codomain restriction.Nr   r   r   r   r   Ú_restrict_codomain~   s    z%ModuleHomomorphism._restrict_codomainc                 C   s   t ‚dS )ú"Implementation of domain quotient.Nr   r   r   r   r   Ú_quotient_domain‚   s    z#ModuleHomomorphism._quotient_domainc                 C   s   t ‚dS )ú$Implementation of codomain quotient.Nr   r   r   r   r   Ú_quotient_codomain†   s    z%ModuleHomomorphism._quotient_codomainc                 C   s6   | j  |¡std| j |f ƒ‚|| j kr,| S |  |¡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 %s, got %s)r   Úis_submoduler   r   r   r   r   r   Úrestrict_domainŠ   s     ÿ
z"ModuleHomomorphism.restrict_domainc                 C   s:   |  |  ¡ ¡s"td|  ¡ |f ƒ‚|| jkr0| S |  |¡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 %s must contain sm, got %s)r&   r   r   r   r!   r   r   r   r   Úrestrict_codomain±   s    
ÿ
z$ModuleHomomorphism.restrict_codomainc                 C   s8   |   ¡  |¡s"td|   ¡ |f ƒ‚| ¡ r.| S |  |¡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 %s must contain sm, got %s)r   r&   r   Úis_zeror#   r   r   r   r   Úquotient_domainÑ   s    
ÿz"ModuleHomomorphism.quotient_domainc                 C   s4   | j  |¡std| j |f ƒ‚| ¡ r*| S |  |¡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 %s, got %s)r   r&   r   r)   r%   r   r   r   r   Úquotient_codomainð   s    ÿz$ModuleHomomorphism.quotient_codomainc                 C   s   t ‚dS )zApply ``self`` to ``elem``.Nr   ©r   Úelemr   r   r   Ú_apply  s    zModuleHomomorphism._applyc                 C   s   | j  |  | j |¡¡¡S ©N)r   Úconvertr.   r   r,   r   r   r   Ú__call__  s    zModuleHomomorphism.__call__c                 C   s   t ‚dS )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.)
        Nr   ©r   Úothr   r   r   Ú_compose  s    zModuleHomomorphism._composec                 C   s   t ‚dS )z8Scalar multiplication. ``c`` is guaranteed in self.ring.Nr   ©r   Úcr   r   r   Ú_mul_scalar'  s    zModuleHomomorphism._mul_scalarc                 C   s   t ‚dS )zv
        Homomorphism addition.
        ``oth`` is guaranteed to be a homomorphism with same domain/codomain.
        Nr   r2   r   r   r   Ú_add+  s    zModuleHomomorphism._addc                 C   s&   t |tƒsdS |j| jko$|j| jkS )zEHelper to check that oth is a homomorphism with same domain/codomain.F)r	   r   r   r   r2   r   r   r   Ú
_check_hom2  s    
zModuleHomomorphism._check_homc                 C   sR   t |tƒr | j|jkr | | ¡S z|  | j |¡¡W S  tk
rL   t	 Y S X d S r/   )
r	   r   r   r   r4   r7   r   r0   r   ÚNotImplementedr2   r   r   r   Ú__mul__8  s    
zModuleHomomorphism.__mul__c                 C   s6   z|   d| j |¡ ¡W S  tk
r0   t Y S X d S )Né   )r7   r   r0   r   r:   r2   r   r   r   Ú__truediv__C  s    zModuleHomomorphism.__truediv__c                 C   s   |   |¡r|  |¡S tS r/   )r9   r8   r:   r2   r   r   r   Ú__add__I  s    

zModuleHomomorphism.__add__c                 C   s&   |   |¡r"|  | | j d¡¡¡S tS )Néÿÿÿÿ)r9   r8   r7   r   r0   r:   r2   r   r   r   Ú__sub__N  s    
zModuleHomomorphism.__sub__c                 C   s   |   ¡  ¡ 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   r   r   r   Úis_injectiveS  s    zModuleHomomorphism.is_injectivec                 C   s   |   ¡ | 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   r   r   r   Úis_surjectivej  s    z ModuleHomomorphism.is_surjectivec                 C   s   |   ¡ o|  ¡ 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
        )rA   rB   r   r   r   r   Úis_isomorphism�  s    z!ModuleHomomorphism.is_isomorphismc                 C   s   |   ¡  ¡ 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   r   r   r   r)   ™  s    zModuleHomomorphism.is_zeroc                 C   s*   z| |   ¡ W S  tk
r$   Y dS X d S )NF)r)   r
   r2   r   r   r   Ú__eq__²  s    zModuleHomomorphism.__eq__c                 C   s
   | |k S r/   r   r2   r   r   r   Ú__ne__¸  s    zModuleHomomorphism.__ne__N)"Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r!   r#   r%   r'   r(   r*   r+   r.   r1   r4   r7   r8   r9   r;   Ú__rmul__r=   r>   r@   rA   rB   rC   r)   rD   rE   r   r   r   r   r      s>   %' &
	r   c                   @   s`   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )Ú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                    sp   t  | ||¡ t|ƒ|jkr2td|jt|ƒf ƒ‚| jj‰ t| jtt	fƒrT| jj
j‰ t‡ fdd„|D ƒƒ| _d S )Nz#Need to provide %s elements, got %sc                 3   s   | ]}ˆ |ƒV  qd S r/   r   ©Ú.0Úx©Ú	converterr   r   Ú	<genexpr>ã  s     z.MatrixHomomorphism.__init__.<locals>.<genexpr>)r   r   ÚlenZrankr   r   r0   r	   r   r   Ú	containerÚtupleÚmatrix)r   r   r   rU   r   rO   r   r   Ú  s    ÿ
zMatrixHomomorphism.__init__c                    sH   ddl m} dd„ ‰ tˆjttfƒr,dd„ ‰ |‡ ‡fdd„ˆjD ƒƒjS )z=Helper function which returns a SymPy matrix ``self.matrix``.r   )ÚMatrixc                 S   s   | S r/   r   ©rN   r   r   r   Ú<lambda>è  ó    z2MatrixHomomorphism._sympy_matrix.<locals>.<lambda>c                 S   s   | j S r/   )ÚdatarW   r   r   r   rX   ê  rY   c                    s"   g | ]}‡fd d„ˆ |ƒD ƒ‘qS )c                    s   g | ]}ˆ j  |¡‘qS r   )r   Zto_sympy)rM   Úyr   r   r   Ú
<listcomp>ë  s     z?MatrixHomomorphism._sympy_matrix.<locals>.<listcomp>.<listcomp>r   rL   ©r6   r   r   r   r\   ë  s     z4MatrixHomomorphism._sympy_matrix.<locals>.<listcomp>)Zsympy.matricesrV   r	   r   r   r   rU   ÚT)r   rV   r   r]   r   Ú_sympy_matrixå  s
    z MatrixHomomorphism._sympy_matrixc                 C   sž   t |  ¡ ƒ d¡}d| j| jf }dt|ƒ }t|ƒ}t|d ƒD ]}||  |7  < qB||d   |7  < t|d d |ƒD ]}||  |7  < q~d |¡S )NÚ
z : %s -> %sú é   r<   )Úreprr_   Úsplitr   r   rR   ÚrangeÚjoin)r   ÚlinesÚtÚsÚnÚir   r   r   Ú__repr__í  s    zMatrixHomomorphism.__repr__c                 C   s   t || j| jƒS )r   )ÚSubModuleHomomorphismr   rU   r   r   r   r   r   ù  s    z#MatrixHomomorphism._restrict_domainc                 C   s   |   | j|| j¡S )r    )Ú	__class__r   rU   r   r   r   r   r!   ý  s    z%MatrixHomomorphism._restrict_codomainc                 C   s   |   | j| | j| j¡S )r"   ©rn   r   r   rU   r   r   r   r   r#     s    z#MatrixHomomorphism._quotient_domainc                    sJ   | j | }|j‰ t| j tƒr$|jj‰ |  | j| j | ‡ fdd„| jD ƒ¡S )r$   c                    s   g | ]}ˆ |ƒ‘qS r   r   rL   rO   r   r   r\     s     z9MatrixHomomorphism._quotient_codomain.<locals>.<listcomp>)r   r0   r	   r   rS   rn   r   rU   )r   r   ÚQr   rO   r   r%     s    
ÿz%MatrixHomomorphism._quotient_codomainc                 C   s&   |   | j| jdd„ t| j|jƒD ƒ¡S )Nc                 S   s   g | ]\}}|| ‘qS r   r   )rM   rN   r[   r   r   r   r\     s     z+MatrixHomomorphism._add.<locals>.<listcomp>)rn   r   r   ÚziprU   r2   r   r   r   r8     s    ÿzMatrixHomomorphism._addc                    s"   |   | j| j‡ fdd„| jD ƒ¡S )Nc                    s   g | ]}ˆ | ‘qS r   r   rL   ©r6   r   r   r\     s     z2MatrixHomomorphism._mul_scalar.<locals>.<listcomp>ro   r5   r   rr   r   r7     s    zMatrixHomomorphism._mul_scalarc                    s"   |   | jˆ j‡ fdd„| jD ƒ¡S )Nc                    s   g | ]}ˆ |ƒ‘qS r   r   rL   ©r3   r   r   r\     s     z/MatrixHomomorphism._compose.<locals>.<listcomp>ro   r2   r   rs   r   r4     s    zMatrixHomomorphism._composeN)rF   rG   rH   rI   r   r_   rl   r   r!   r#   r%   r8   r7   r4   r   r   r   r   rK   ¼  s   	rK   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú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                 C   s,   t | jtƒr|j}tdd„ t|| jƒD ƒƒS )Nc                 s   s   | ]\}}|| V  qd S r/   r   ©rM   rN   Úer   r   r   rQ   /  s     z0FreeModuleHomomorphism._apply.<locals>.<genexpr>)r	   r   r   rZ   Úsumrq   rU   r,   r   r   r   r.   ,  s    zFreeModuleHomomorphism._applyc                 C   s   | j j| jŽ S r/   )r   Ú	submodulerU   r   r   r   r   r   1  s    zFreeModuleHomomorphism._imagec                 C   s   |   ¡  ¡ }| jj|jŽ S r/   ©r   Zsyzygy_moduler   rx   Úgens©r   Zsyzr   r   r   r   4  s    zFreeModuleHomomorphism._kernelN©rF   rG   rH   rI   r.   r   r   r   r   r   r   rt     s   rt   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	rm   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                 C   s,   t | jtƒr|j}tdd„ t|| jƒD ƒƒS )Nc                 s   s   | ]\}}|| V  qd S r/   r   ru   r   r   r   rQ   T  s     z/SubModuleHomomorphism._apply.<locals>.<genexpr>)r	   r   r   rZ   rw   rq   rU   r,   r   r   r   r.   Q  s    zSubModuleHomomorphism._applyc                    s   ˆ j j‡ fdd„ˆ jjD ƒŽ S )Nc                    s   g | ]}ˆ |ƒ‘qS r   r   rL   r   r   r   r\   W  s     z0SubModuleHomomorphism._image.<locals>.<listcomp>)r   rx   r   rz   r   r   r   r   r   V  s    zSubModuleHomomorphism._imagec                    s(   ˆ   ¡  ¡ }ˆ jj‡ fdd„|jD ƒŽ S )Nc                    s(   g | ] }t d d„ t|ˆ jjƒD ƒƒ‘qS )c                 s   s   | ]\}}|| V  qd S r/   r   )rM   ÚxiÚgir   r   r   rQ   \  s     z;SubModuleHomomorphism._kernel.<locals>.<listcomp>.<genexpr>)rw   rq   r   rz   )rM   ri   r   r   r   r\   \  s   ÿz1SubModuleHomomorphism._kernel.<locals>.<listcomp>ry   r{   r   r   r   r   Y  s    
ÿÿzSubModuleHomomorphism._kernelNr|   r   r   r   r   rm   >  s   rm   c                    sZ   dd„ }|| ƒ\}}}}||ƒ\}}	}
‰ t ||‡ fdd„|D ƒƒ |¡ |	¡ |
¡ |¡S )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                    s†   t ˆ tƒr"ˆ ˆ ˆ  ¡ ‡ fdd„fS t ˆ tƒrFˆ jˆ jˆ j‡ fdd„fS t ˆ tƒrlˆ jjˆ jˆ j‡ fdd„fS ˆ jˆ ˆ  ¡ ‡ fd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                    s
   ˆ   | ¡S r/   )r0   rW   ©Úmoduler   r   rX   £  rY   z0homomorphism.<locals>.freepres.<locals>.<lambda>c                    s   ˆ   | ¡jS r/   )r0   rZ   rW   r   r   r   rX   ¦  rY   c                    s   ˆ j  | ¡jS r/   )rS   r0   rZ   rW   r   r   r   rX   ©  rY   c                    s   ˆ j  | ¡S r/   )rS   r0   rW   r   r   r   rX   ¬  rY   )r	   r   rx   r   ÚbaseZkilled_moduler   rS   r   r   r   r   Úfreepresœ  s    


ÿ

ÿ
ÿzhomomorphism.<locals>.freepresc                    s   g | ]}ˆ |ƒ‘qS r   r   rL   rr   r   r   r\   ±  s     z homomorphism.<locals>.<listcomp>)rt   r'   r(   r+   r*   )r   r   rU   r‚   ZSFZSSZSQÚ_ZTFZTSZTQr   rr   r   Úhomomorphism`  s    <ÿÿþþr„   N)rI   Zsympy.polys.agca.modulesr   r   r   r   r   Zsympy.polys.polyerrorsr   r   rK   rt   rm   r„   r   r   r   r   Ú<module>   s   	   -]%"