
    QiB                         d Z ddlmZ ddlmZ ddlmZmZ ddlm	Z	 ddl
mZmZ d Zd	 Zd
 Zd Zd Zd Zd Zd Zd ZddddZdS )z,Functions returning normal forms of matrices    )defaultdict   )DomainMatrix)DMDomainErrorDMShapeError)symmetric_residue)QQZZc                 d    t          |           }t          j        || j        | j                  }|S )aI  
    Return the Smith Normal Form of a matrix `m` over the ring `domain`.
    This will only work if the ring is a principal ideal domain.

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy.polys.matrices import DomainMatrix
    >>> from sympy.polys.matrices.normalforms import smith_normal_form
    >>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
    ...                   [ZZ(3), ZZ(9), ZZ(6)],
    ...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
    >>> print(smith_normal_form(m).to_Matrix())
    Matrix([[1, 0, 0], [0, 10, 0], [0, 0, 30]])

    )invariant_factorsr   diagdomainshape)minvssmfs      x/var/www/development/aibuddy-work/election-extract/venv/lib/python3.11/site-packages/sympy/polys/matrices/normalforms.pysmith_normal_formr      s.    $ QD

D!(AG
4
4CJ    c                 2   | j         }| j        }|j        }|                                 } t	          |d                   D ]7}t	          |d                   D ]}||k    r	| |         |         |k    s  dS  8t          |d         |d                   }t	          d|          D ]s}| |dz
           |dz
           |k    r| |         |         |k    r dS 0|                    | |         |         | |dz
           |dz
                     d         }||k    r dS tdS )z8
    Checks that the matrix is in Smith Normal Form
    r   r   FT)r   r   zeroto_listrangemindiv)r   r   r   r   ijupperrs           r   is_smith_normal_formr    (   s>    XFGE;D			A58__  uQx 	 	AAvvQ47d??uuu #	 a%(##E1e__  QqS6!A#;$tAw$uu  

1Q47AacF1Q3K003ADyyuu  4r   c                     t          t          |                     D ]P}| |         |         }||z  || |         |         z  z   | |         |<   ||z  || |         |         z  z   | |         |<   Qd S Nr   len	r   r   r   abcdkes	            r   add_columnsr,   E   sz     3q66]] " "aDGA#!A$q'	/!QA#!A$q'	/!Q" "r   c                 l    | j         }| j        }|                                 } t          | ||d          S )a3  
    Return the tuple of abelian invariants for a matrix `m`
    (as in the Smith-Normal form)

    References
    ==========

    [1] https://en.wikipedia.org/wiki/Smith_normal_form#Algorithm
    [2] https://web.archive.org/web/20200331143852/https://sierra.nmsu.edu/morandi/notes/SmithNormalForm.pdf

    Fr   full)r   r   r   _smith_normal_decomp)r   r   r   s      r   r   r   N   s6     XFGE			A6UCCCCr   c                 (   | j         }| j        x\  }}}|                                 } t          | ||d          \  }}}t	          j        |||                                          }t	          ||||f          }t	          ||||f          }|||fS )a  
    Return the Smith-Normal form decomposition of matrix `m`.

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy.polys.matrices import DomainMatrix
    >>> from sympy.polys.matrices.normalforms import smith_normal_decomp
    >>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
    ...                   [ZZ(3), ZZ(9), ZZ(6)],
    ...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
    >>> a, s, t = smith_normal_decomp(m)
    >>> assert a == s * m * t
    Tr.   )r   r   )r   r   r   r0   r   r   to_dense)	r   r   rowscolsr   r   str   s	            r   smith_normal_decompr7   `   s      XF JD$			A%au4HHHJD!Q

D&%
0
0
9
9
;
;CQvdD\:::AQvdD\:::A19r   c           
      
    !" j         sd }t          |          |\  j        "j        "fd}d|v rrd |           |          fS dS r |            |          !d   "fd} !"fd} "fdt	                    D             }|rU|d         "k    rI |d                   d         c d<    |d         <   r# |d                   d         c d<    |d         <   n| "fd	t	                    D             }|r^|d         "k    rR D ]%}	|	|d                  |	d         c|	d<   |	|d         <   &r(!D ]%}	|	|d                  |	d         c|	d<   |	|d         <   &t           "fd
t	          d          D                       s*t           "fdt	          d          D                       rh |              |             t           "fd
t	          d          D                       >t           "fdt	          d          D                       hfd}
 d         d         dk    rs                     d         d                   j        rd d         d         z  j        k    r/ d         dxx         z  cc<   rfd d         D              d<   d|v rd}nd  dd         D             }t          |dz
  dz
  f          }r|\  }}}dgdgdz
  z  z   gd |D             z   }dgdgdz
  z  z   gd |D             z   }t          t          |
 |!|g                    \   }!}| z   !|z  !                                  !                                !n|} d         d         rk d         d         g}|                    |           t	          t          |          dz
            D ]%}||         ||dz            }}|r                    ||          d         "k    rr                    ||          \  }}}n                    ||          }                    ||          d         }r                    ||          d         }  ||dz   dd|d           t#          !||dz   d|dd             ||dz   d| dd           t#          !||dz   dd| d             ||dz   dddd           ||z  ||dz   <   |||<   & n@r,dk    r dd          d         gz    dk    rd !D             !| d         d         fz   }rt%          |           !fS t%          |          S )z
    Return the tuple of abelian invariants for a matrix `m`
    (as in the Smith-Normal form). If `full=True` then invertible matrices
    ``s, t`` such that the product ``s, m, t`` is the Smith Normal Form
    are also returned.
    zBThe matrix entries must be over a principal ideal domain, but got c                 @      fdt                     D             S )Nc                 L    g | ]fd t                    D              S )c                 $    g | ]}|k    rnS  r<   ).0r   r   oner   s     r   
<listcomp>z@_smith_normal_decomp.<locals>.eye.<locals>.<listcomp>.<listcomp>   s%    ;;;QQD;;;r   r   )r=   r   nr>   r   s    @r   r?   z5_smith_normal_decomp.<locals>.eye.<locals>.<listcomp>   s;    NNN;;;;;;%((;;;NNNr   r@   )rA   r>   r   s   `r   eyez!_smith_normal_decomp.<locals>.eye   s*    NNNNNNU1XXNNNNr   r   r<   c                     t          t          | d                             D ]P}| |         |         }||z  || |         |         z  z   | |         |<   ||z  || |         |         z  z   | |         |<   Qd S )Nr   r#   r%   s	            r   add_rowsz&_smith_normal_decomp.<locals>.add_rows   s     s1Q4yy!! 	& 	&A!QAcAad1gIoAaDGcAad1gIoAaDGG	& 	&r   c            
          d         d         } t          d          D ]}|         d         k    r
                    |         d         |           \  }}|k    r' 	d|dd| d           r 	d|dd| d           g
                    | |         d                   \  }}}
                    |         d         |          }
                    | |          } 	d|||||            r 	d|||||            |} d S Nr   r   )r   r   gcdexexquo)pivotr   r)   r   r&   r'   gd_0d_jrD   r   r/   r   r3   r5   r   s            r   clear_columnz*_smith_normal_decomp.<locals>.clear_column   sL   !Qq$ 	 	AtAw$::ad1gu--DAqDyyAq!QA... 3HQ1aQB222 ,,uad1g661all1Q47A..ll5!,,Aq!QcT222 7HQ1aC#666	 	r   c            
      @   d         d         } t          d	          D ]}d         |         k    r
                    d         |         |           \  }}|k    r/t          d|dd| d           rt          d|dd| d           o
                    | d         |                   \  }}}
                    d         |         |          }
                    | |          }t          d|||||            rt          d|||||            |} d S rF   )r   r   r,   rG   rH   )rI   r   r)   r   r&   r'   rJ   rK   rL   r4   r   r/   r   r6   r   s            r   	clear_rowz'_smith_normal_decomp.<locals>.clear_row   sD   !Qq$ 	 	AtAw$::ad1gu--DAqDyyAq!QA2q111 61aAr1555 ,,uad1g661all1Q47A..ll5!,,Aq!Q3555 :1aAsSD999	 	r   c                 8    g | ]}|         d          k    |S r   r<   r=   r   r   r   s     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>   s&    
5
5
5QqT!W__1___r   c                 8    g | ]}d          |         k    |S rQ   r<   )r=   r   r   r   s     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>   s&    999Q1aDqr   c              3   <   K   | ]}d          |         k    V  dS r   Nr<   rR   s     r   	<genexpr>z'_smith_normal_decomp.<locals>.<genexpr>   /      661qtAw$666666r   r   c              3   <   K   | ]}|         d          k    V  dS rU   r<   rR   s     r   rV   z'_smith_normal_decomp.<locals>.<genexpr>   rW   r   c                 l    t          | t          |           t          | d                   f          S )Nr   )r   r   )r   r$   )r   r   s    r   to_domain_matrixz._smith_normal_decomp.<locals>.to_domain_matrix   s-    Ac!ffc!A$ii%8HHHHr   c                     g | ]}|z  S r<   r<   )r=   elemr(   s     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>   s    222Tq222r   c                 "    g | ]}|d d         S )r   Nr<   )r=   r   s     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>   s     ,,,qu,,,r   Nr.   c                     g | ]}d g|z   	S rQ   r<   r=   rows     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>       (F(F(Fs!s(F(F(Fr   c                     g | ]}d g|z   	S rQ   r<   r_   s     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>   ra   r   c                 6    g | ]}|d d         |d         gz   S )r   Nr   r<   r_   s     r   r?   z(_smith_normal_decomp.<locals>.<listcomp>  s+    555CSWAx'555r   )is_PID
ValueErrorr   r>   r   anycanonical_unitis_Fieldr0   listmapr   extendr$   r   rG   gcdr,   tuple)#r   r   r   r/   msgrB   rM   rO   indr`   rZ   r   lower_rightrets_smallt_smalls2t2resultr   r&   r'   xyr)   alphabetarD   r(   r4   r>   r3   r5   r6   r   s#   `` `                       @@@@@@@@r   r0   r0   |   sQ    = [SY[[ooJD$;D
*CO O O O O O 	Ezz 	ss4yy##d))++2 CIICII& & &          (         * 6
5
5
5
5eDkk
5
5
5C
 >s1v~~CF)QqT!aAi 	.Ai1OAaD!CF)99999%++999 	>3q6T>> : :&)#a&k3q6#ACF > > >C*-c!f+s1v'CFCAKK 66666a66666 66666a66666	 66666a66666 66666a66666
I I I I I 	tAw!||!!!A$q'**? 	AaDGA
??aDGGGqLGGG 32222QqT222!Ezz,,ae,,,";ax*7 7 7 
	%("D'7#T!V$%(F(Fg(F(F(FFB#T!V$%(F(Fg(F(F(FFB$4q"an E EFFLAr1bQABA		A		AADtAw #A$q'ds6{{1}%% 	 	A!9fQqSkqA VZZ1%%a(D00 )$ll1a00GAq!!

1a((A

1a((+ 7!::a++A.DHQ1q5!Q15551a!eQ1a888HQ1q5!eVQ:::1a!eQD5!<<<HQ1q5!QA666%iqsq		 	6axxabbEQqTFNaxx5515551a
" V}}a""V}}r   c                 t    t          j        | |          \  }}}| dk    r|| z  dk    rd}| dk     rdnd}|||fS )a  
    This supports the functions that compute Hermite Normal Form.

    Explanation
    ===========

    Let x, y be the coefficients returned by the extended Euclidean
    Algorithm, so that x*a + y*b = g. In the algorithms for computing HNF,
    it is critical that x, y not only satisfy the condition of being small
    in magnitude -- namely that |x| <= |b|/g, |y| <- |a|/g -- but also that
    y == 0 when a | b.

    r   rc   r   )r
   rG   )r&   r'   rx   ry   rJ   s        r   _gcdexr}   "  sO     hq!nnGAq!Avv!a%1**a%%BBQa7Nr   c                 R   | j         j        st          d          | j        \  }}|                                                                 } |}t          |dz
  dd          D ]}|dk    r n	|dz  }t          |dz
  dd          D ]x}| |         |         dk    rdt          | |         |         | |         |                   \  }}}| |         |         |z  | |         |         |z  }
}	t          | |||||
 |	           y| |         |         }|dk     rt          | ||dddd           | }|dk    r|dz  }t          |dz   |          D ])}| |         |         |z  }t          | ||d| dd           *t          j
        |                                           dd|df         S )a  
    Compute the Hermite Normal Form of DomainMatrix *A* over :ref:`ZZ`.

    Parameters
    ==========

    A : :py:class:`~.DomainMatrix` over domain :ref:`ZZ`.

    Returns
    =======

    :py:class:`~.DomainMatrix`
        The HNF of matrix *A*.

    Raises
    ======

    DMDomainError
        If the domain of the matrix is not :ref:`ZZ`.

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
       (See Algorithm 2.4.5.)

    Matrix must be over domain ZZ.r   rc   r   N)r   is_ZZr   r   to_ddmcopyr   r}   r,   r   from_repto_dfm_or_ddm)Ar   rA   r*   r   r   uvr)   r   r5   r'   qs                r   _hermite_normal_formr   7  s   8 8> ><=== 7DAq	

A 	
A1q5"b!! !2 !266 E	Q q1ub"%% 	2 	2AtAw!|| !1a!A$q'221atAw!|QqT!W\1Aq!QA2q111aDGq551aQA...A 66FAA
 1q5!__ 2 2aDGqLAq!QAq11112
  !2!233AAAqrrE::r   c                 h   | j         j        st          d          t          j        |          r|dk     rt          d          d }t          t                    }| j        \  }}||k     rt          d          | 	                                } |}|}t          |dz
  dd          D ]a}|dz  }t          |dz
  dd          D ]u}	| |         |	         dk    rat          | |         |         | |         |	                   \  }
}}| |         |         |z  | |         |	         |z  }} || |||	|
|| |           v| |         |         }|dk    r|x| |         |<   }t          ||          \  }
}}t          |          D ]}|
| |         |         z  |z  ||         |<    ||         |         dk    r|||         |<   t          |dz   |          D ]5}	||         |	         ||         |         z  }t          ||	|d| dd           6||z  }ct          |||ft                                                    S )a[  
    Perform the mod *D* Hermite Normal Form reduction algorithm on
    :py:class:`~.DomainMatrix` *A*.

    Explanation
    ===========

    If *A* is an $m \times n$ matrix of rank $m$, having Hermite Normal Form
    $W$, and if *D* is any positive integer known in advance to be a multiple
    of $\det(W)$, then the HNF of *A* can be computed by an algorithm that
    works mod *D* in order to prevent coefficient explosion.

    Parameters
    ==========

    A : :py:class:`~.DomainMatrix` over :ref:`ZZ`
        $m \times n$ matrix, having rank $m$.
    D : :ref:`ZZ`
        Positive integer, known to be a multiple of the determinant of the
        HNF of *A*.

    Returns
    =======

    :py:class:`~.DomainMatrix`
        The HNF of matrix *A*.

    Raises
    ======

    DMDomainError
        If the domain of the matrix is not :ref:`ZZ`, or
        if *D* is given but is not in :ref:`ZZ`.

    DMShapeError
        If the matrix has more rows than columns.

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
       (See Algorithm 2.4.8.)

    r   r   z0Modulus D must be positive element of domain ZZ.c                 $   t          t          |                     D ]r}| |         |         }	t          ||	z  || |         |         z  z   |z  |          | |         |<   t          ||	z  || |         |         z  z   |z  |          | |         |<   sd S r"   )r   r$   r   )
r   Rr   r   r&   r'   r(   r)   r*   r+   s
             r   add_columns_mod_Rz8_hermite_normal_form_modulo_D.<locals>.add_columns_mod_R  s     s1vv 	F 	FA!QA'QQqT!W)<(A1EEAaDG'QQqT!W)<(A1EEAaDGG	F 	Fr   z2Matrix must have at least as many columns as rows.rc   r   )r   r   r   r
   of_typer   dictr   r   r   r   r}   r,   r   r2   )r   Dr   Wr   rA   r*   r   r   r   r   r   r)   r   r5   r'   iir   s                     r   _hermite_normal_form_modulo_Dr     sp   Z 8> ><===:a== PAEENOOOF F F 	DA7DAq1uuOPPP			A	A	A1q5"b!!  	Qq1ub"%% 	; 	;AtAw!|| 1a!A$q'221atAw!|QqT!W\1!!!Q1aQB:::aDG66OAaDGaA,,1a(( 	& 	&B2qzA~AbE!HHQ47a<<AaDGq1ua 	. 	.A!Q1Q47"A1aQB1----	aAq62&&//111r   NF)r   
check_rankc                    | j         j        st          d          |M|r;|                     t                                                    | j        d         k    rt          | |          S t          |           S )a)  
    Compute the Hermite Normal Form of :py:class:`~.DomainMatrix` *A* over
    :ref:`ZZ`.

    Examples
    ========

    >>> from sympy import ZZ
    >>> from sympy.polys.matrices import DomainMatrix
    >>> from sympy.polys.matrices.normalforms import hermite_normal_form
    >>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
    ...                   [ZZ(3), ZZ(9), ZZ(6)],
    ...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
    >>> print(hermite_normal_form(m).to_Matrix())
    Matrix([[10, 0, 2], [0, 15, 3], [0, 0, 2]])

    Parameters
    ==========

    A : $m \times n$ ``DomainMatrix`` over :ref:`ZZ`.

    D : :ref:`ZZ`, optional
        Let $W$ be the HNF of *A*. If known in advance, a positive integer *D*
        being any multiple of $\det(W)$ may be provided. In this case, if *A*
        also has rank $m$, then we may use an alternative algorithm that works
        mod *D* in order to prevent coefficient explosion.

    check_rank : boolean, optional (default=False)
        The basic assumption is that, if you pass a value for *D*, then
        you already believe that *A* has rank $m$, so we do not waste time
        checking it for you. If you do want this to be checked (and the
        ordinary, non-modulo *D* algorithm to be used if the check fails), then
        set *check_rank* to ``True``.

    Returns
    =======

    :py:class:`~.DomainMatrix`
        The HNF of matrix *A*.

    Raises
    ======

    DMDomainError
        If the domain of the matrix is not :ref:`ZZ`, or
        if *D* is given but is not in :ref:`ZZ`.

    DMShapeError
        If the mod *D* algorithm is used but the matrix has more rows than
        columns.

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*
       (See Algorithms 2.4.5 and 2.4.8.)

    r   Nr   )	r   r   r   
convert_tor	   rankr   r   r   )r   r   r   s      r   hermite_normal_formr     so    v 8> ><===}j}ALL,<,<,A,A,C,Cqwqz,Q,Q,Q222#A&&&r   )__doc__collectionsr   domainmatrixr   
exceptionsr   r   sympy.ntheory.modularr   sympy.polys.domainsr	   r
   r   r    r,   r   r7   r0   r}   r   r   r   r<   r   r   <module>r      s8   2 2 # # # # # # & & & & & & 3 3 3 3 3 3 3 3 3 3 3 3 3 3 & & & & & & & &  .  :" " "D D D$  8c c cL  *J; J; J;ZU2 U2 U2p !% @' @' @' @' @' @' @'r   