
    wg}                         d Z ddlmZ  G d d      Z G d d      Z G d d      Zdd
Zd Zd Zd Z	d Z
d Zd Zd Zd Zy	)aG   Generic Unification algorithm for expression trees with lists of children

This implementation is a direct translation of

Artificial Intelligence: A Modern Approach by Stuart Russel and Peter Norvig
Second edition, section 9.2, page 276

It is modified in the following ways:

1.  We allow associative and commutative Compound expressions. This results in
    combinatorial blowup.
2.  We explore the tree lazily.
3.  We provide generic interfaces to symbolic algebra libraries in Python.

A more traditional version can be found here
http://aima.cs.berkeley.edu/python/logic.html
    )kbinsc                   (    e Zd ZdZd Zd Zd Zd Zy)Compoundzr A little class to represent an interior node in the tree

    This is analogous to SymPy.Basic for non-Atoms
    c                      || _         || _        y N)opargs)selfr   r	   s      U/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/sympy/unify/core.py__init__zCompound.__init__   s    	    c                     t        |       t        |      u xr4 | j                  |j                  k(  xr | j                  |j                  k(  S r   )typer   r	   r
   others     r   __eq__zCompound.__eq__   s@    T
d5k) (dgg.A (		UZZ'	)r   c                 X    t        t        |       | j                  | j                  f      S r   )hashr   r   r	   r
   s    r   __hash__zCompound.__hash__"   s     T$Z$))455r   c                     t        | j                        ddj                  t        t         | j                              dS )N[z, ])strr   joinmapr	   r   s    r   __str__zCompound.__str__%   s)    tww<3sDII3F)GHHr   N__name__
__module____qualname____doc__r   r   r   r    r   r   r   r      s    )6Ir   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)Variablez A Wild token c                     || _         y r   )arg)r
   r'   s     r   r   zVariable.__init__*   s	    r   c                 d    t        |       t        |      u xr | j                  |j                  k(  S r   )r   r'   r   s     r   r   zVariable.__eq__-   s'    DzT%[(BTXX-BBr   c                 B    t        t        |       | j                  f      S r   )r   r   r'   r   s    r   r   zVariable.__hash__0   s    T$Z*++r   c                 2    dt        | j                        z  S )NzVariable(%s)r   r'   r   s    r   r   zVariable.__str__3   s    DHH--r   Nr   r#   r   r   r%   r%   (   s    C,.r   r%   c                   (    e Zd ZdZd Zd Zd Zd Zy)CondVariablez A wild token that matches conditionally.

    arg   - a wild token.
    valid - an additional constraining function on a match.
    c                      || _         || _        y r   )r'   valid)r
   r'   r/   s      r   r   zCondVariable.__init__<   s    
r   c                     t        |       t        |      u xr4 | j                  |j                  k(  xr | j                  |j                  k(  S r   )r   r'   r/   r   s     r   r   zCondVariable.__eq__@   sA    T
d5k) *EII%*

ekk)	+r   c                 X    t        t        |       | j                  | j                  f      S r   )r   r   r'   r/   r   s    r   r   zCondVariable.__hash__E   s     T$Z4::677r   c                 2    dt        | j                        z  S )NzCondVariable(%s)r+   r   s    r   r   zCondVariable.__str__H   s    !CM11r   Nr   r#   r   r   r-   r-   6   s    
+
82r   r-   Nc              +     K   |xs i }| |k(  r| yt        | t        t        f      rt        | ||fi |E d{    yt        |t        t        f      rt        || |fi |E d{    yt        | t              rt        |t              r|j                  dd       }|j                  dd       }t        | j                  |j                  |fi |D ]o  } ||       r ||      rt        | j                        t        |j                        k  r| |fn|| f\  }} ||       r* ||      r"t        |j                  |j                  d      }	n!t        |j                  |j                  d      }	|	D ]s  \  }
}|
D cg c]!  }t        t	        |j                  |            # }}|D cg c]!  }t        t	        |j                  |            # }}t        |||fi |E d{    u t        | j                        t        |j                        k(  sFt        | j                  |j                  |fi |E d{    r yt        |       rmt        |      rat        |       t        |      k(  rIt        |       dk(  r| yt        | d   |d   |fi |D ]  }t        | d	d |d	d |fi |E d{      yyyy7 7 `c c}w c c}w 7 7 7 w)
a
   Unify two expressions.

    Parameters
    ==========

        x, y - expression trees containing leaves, Compounds and Variables.
        s    - a mapping of variables to subtrees.

    Returns
    =======

        lazy sequence of mappings {Variable: subtree}

    Examples
    ========

    >>> from sympy.unify.core import unify, Compound, Variable
    >>> expr    = Compound("Add", ("x", "y"))
    >>> pattern = Compound("Add", ("x", Variable("a")))
    >>> next(unify(expr, pattern, {}))
    {Variable(a): 'y'}
    Nis_commutativec                      yNFr#   xs    r   <lambda>zunify.<locals>.<lambda>k       r   is_associativec                      yr6   r#   r7   s    r   r9   zunify.<locals>.<lambda>l   r:   r   commutativeassociativer      )
isinstancer%   r-   	unify_varr   getunifyr   lenr	   allcombinationsunpackis_args)r8   ysfnsr4   r;   sopabcombsaaargsbbargsr'   aabbsheads                   r   rC   rC   K   s~    . 	
RAAv	A,/	0Q1,,,,	A,/	0Q1,,,,	Ax	 Z8%<!1?C!1?CqttQ.#. 	=Ca ^A%6!$QVVs166{!:1vA1!!$):+AFFAFFMJE+AFFAFFMJE&+ 9NFFAGH#&!$$!45HBHAGH#&!$$!45HBH$RS8C8889 QVVAFF+ <<<<	= 

s1vQ'7q6Q;GqtQqT144 = 12!"u<<<<=	 (8
) 	-, IH8< =sw   8KK,K'K(DK&K
(K.&KK'K(3K%KKA6K9K:KK
KKKc              +     K   | |v rt        ||    ||fi |E d {    y t        | |      ry t        | t              r!| j	                  |      rt        || |       y t        | t              rt        || |       y y 7 dwr   )rC   occur_checkr@   r-   r/   assocr%   )varr8   rI   rJ   s       r   rA   rA      s{     
ax3A----	S!		C	&399Q<AsA	C	"AsA 
# 	.s   BB A%Bc                       |k(  ryt        |t              rt         |j                        S t	        |      rt         fd|D              ryy)z# var occurs in subtree owned by x? Tc              3   6   K   | ]  }t        |        y wr   )rU   ).0xirW   s     r   	<genexpr>zoccur_check.<locals>.<genexpr>   s     0{3#0s   F)r@   r   rU   r	   rG   any)rW   r8   s   ` r   rU   rU      sB    
ax	Ax	 3''	0a00r   c                 0    | j                         } || |<   | S )z- Return copy of d with key associated to val )copy)dkeyvals      r   rV   rV      s    	AAcFHr   c                 :    t        |       t        t        t        fv S )z Is x a traditional iterable? )r   tuplelistsetr7   s    r   rG   rG      s    7udC(((r   c                 t    t        | t              r't        | j                        dk(  r| j                  d   S | S )Nr?   r   )r@   r   rD   r	   r7   s    r   rF   rF      s.    !X3qvv;!#3vvayr   c           	   #   f  K   |dk(  rd}|dk(  rd}t        |       t        |      k  r| |fn|| f\  }}t        t        t        t        |                  t        |      |      D ]H  }||k(  r!t	        d | D              t        ||      f )t        | |      t	        d |D              f J yw)a  
    Restructure A and B to have the same number of elements.

    Parameters
    ==========

    ordered must be either 'commutative' or 'associative'.

    A and B can be rearranged so that the larger of the two lists is
    reorganized into smaller sublists.

    Examples
    ========

    >>> from sympy.unify.core import allcombinations
    >>> for x in allcombinations((1, 2, 3), (5, 6), 'associative'): print(x)
    (((1,), (2, 3)), ((5,), (6,)))
    (((1, 2), (3,)), ((5,), (6,)))

    >>> for x in allcombinations((1, 2, 3), (5, 6), 'commutative'): print(x)
        (((1,), (2, 3)), ((5,), (6,)))
        (((1, 2), (3,)), ((5,), (6,)))
        (((1,), (3, 2)), ((5,), (6,)))
        (((1, 3), (2,)), ((5,), (6,)))
        (((2,), (1, 3)), ((5,), (6,)))
        (((2, 1), (3,)), ((5,), (6,)))
        (((2,), (3, 1)), ((5,), (6,)))
        (((2, 3), (1,)), ((5,), (6,)))
        (((3,), (1, 2)), ((5,), (6,)))
        (((3, 1), (2,)), ((5,), (6,)))
        (((3,), (2, 1)), ((5,), (6,)))
        (((3, 2), (1,)), ((5,), (6,)))
    r=      r>   N)orderedc              3   "   K   | ]  }|f 	 y wr   r#   )rZ   rL   s     r   r\   z"allcombinations.<locals>.<genexpr>   s     ((   c              3   "   K   | ]  }|f 	 y wr   r#   )rZ   rM   s     r   r\   z"allcombinations.<locals>.<genexpr>   s     +<QQD+<rl   )rD   r   re   rangerd   	partition)ABrj   smbgparts         r   rE   rE      s     F --1vAaVQFFBd5R>*CGWE =7(a(()At*<<<At$e+<!+<&<<<	=s   B/B1c           	      ^     t        |       |D cg c]  }t        | |       c}      S c c}w )z Partition a tuple/list into pieces defined by indices.

    Examples
    ========

    >>> from sympy.unify.core import partition
    >>> partition((10, 20, 30, 40), [[0, 1, 2], [3]])
    ((10, 20, 30), (40,))
    )r   index)itrt   inds      r   ro   ro      s)     48t4U2s^4554s   *c                 P     t        |       |D cg c]  }| |   	 c}      S c c}w )z Fancy indexing into an indexable iterable (tuple, list).

    Examples
    ========

    >>> from sympy.unify.core import index
    >>> index([10, 20, 30], (1, 2, 0))
    [20, 30, 10]
    )r   )rw   rx   is      r   rv   rv      s'     48C(qRU())(s   #r   )r"   sympy.utilities.iterablesr   r   r%   r-   rC   rA   rU   rV   rG   rF   rE   ro   rv   r#   r   r   <module>r|      s^   $ ,I I&. .2 2*5=n),=\
6
*r   