
    \h}                         S r SSKJr   " S S5      r " S S5      r " S S5      rSS
 jrS rS rS r	S r
S rS rS rS rg	)aF  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                   0    \ rS rSrSrS rS rS rS rSr	g)	Compound   ziA little class to represent an interior node in the tree

This is analogous to SymPy.Basic for non-Atoms
c                     Xl         X l        g N)opargs)selfr	   r
   s      H/var/www/auris/envauris/lib/python3.13/site-packages/sympy/unify/core.py__init__Compound.__init__   s    	    c                     [        U 5      [        U5      L =(       a9    U R                  UR                  :H  =(       a    U R                  UR                  :H  $ r   )typer	   r
   r   others     r   __eq__Compound.__eq__   s@    T
d5k) (dgg.A (		UZZ'	)r   c                 X    [        [        U 5      U R                  U R                  45      $ r   )hashr   r	   r
   r   s    r   __hash__Compound.__hash__"   s     T$Z$))455r   c                     [        U R                  5      < SSR                  [        [         U R                  5      5      < S3$ )N[z, ])strr	   joinmapr
   r   s    r   __str__Compound.__str__%   s)    tww<3sDII3F)GHHr   )r
   r	   N
__name__
__module____qualname____firstlineno____doc__r   r   r   r!   __static_attributes__ r   r   r   r      s    )6Ir   r   c                   0    \ rS rSrSrS rS rS rS rSr	g)	Variable(   zA Wild token c                     Xl         g r   arg)r   r0   s     r   r   Variable.__init__*   s    r   c                 n    [        U 5      [        U5      L =(       a    U R                  UR                  :H  $ r   )r   r0   r   s     r   r   Variable.__eq__-   s'    DzT%[(BTXX-BBr   c                 B    [        [        U 5      U R                  45      $ r   )r   r   r0   r   s    r   r   Variable.__hash__0   s    T$Z*++r   c                 2    S[        U R                  5      -  $ )NzVariable(%s)r   r0   r   s    r   r!   Variable.__str__3   s    DHH--r   r/   Nr#   r*   r   r   r,   r,   (   s    C,.r   r,   c                   0    \ rS rSrSrS rS rS rS rSr	g)	CondVariable6   zxA wild token that matches conditionally.

arg   - a wild token.
valid - an additional constraining function on a match.
c                     Xl         X l        g r   r0   valid)r   r0   r>   s      r   r   CondVariable.__init__<   s    
r   c                     [        U 5      [        U5      L =(       a9    U R                  UR                  :H  =(       a    U R                  UR                  :H  $ r   )r   r0   r>   r   s     r   r   CondVariable.__eq__@   sA    T
d5k) *EII%*

ekk)	+r   c                 X    [        [        U 5      U R                  U R                  45      $ r   )r   r   r0   r>   r   s    r   r   CondVariable.__hash__E   s     T$Z4::677r   c                 2    S[        U R                  5      -  $ )NzCondVariable(%s)r7   r   s    r   r!   CondVariable.__str__H   s    !CM11r   r=   Nr#   r*   r   r   r:   r:   6   s    
+
82r   r:   Nc              +   >  #    U=(       d    0 nX:X  a  Uv   g[        U [        [        45      (       a  [        XU40 UD6 Sh  vN   g[        U[        [        45      (       a  [        XU40 UD6 Sh  vN   g[        U [        5      (       Ga  [        U[        5      (       Ga  UR                  SS 5      nUR                  SS 5      n[        U R                  UR                  U40 UD6 GH  nU" U 5      (       Ga   U" U5      (       Ga  [        U R                  5      [        UR                  5      :  a  X4OX4u  pxU" U 5      (       a/  U" U5      (       a"  [        UR                  UR                  S5      n	O![        UR                  UR                  S5      n	U	 Hx  u  pU
 Vs/ s H"  n[        [	        UR                  U5      5      PM$     nnU Vs/ s H"  n[        [	        UR                  U5      5      PM$     nn[        XU40 UD6 Sh  vN   Mz     GM2  [        U R                  5      [        UR                  5      :X  d  GMa  [        U R                  UR                  U40 UD6 Sh  vN   GM     g[        U 5      (       av  [        U5      (       ae  [        U 5      [        U5      :X  aL  [        U 5      S:X  a  Uv   g[        U S   US   U40 UD6 H  n[        U S	S US	S U40 UD6 Sh  vN   M!     gggg GN GNs  snf s  snf  GN N N!7f)
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                     gNFr*   xs    r   <lambda>unify.<locals>.<lambda>k       Ur   is_associativec                     grI   r*   rJ   s    r   rL   rM   l   rN   r   commutativeassociativer      )
isinstancer,   r:   	unify_varr   getunifyr	   lenr
   allcombinationsunpackis_args)rK   ysfnsrG   rO   sopabcombsaaargsbbargsr0   aabbsheads                   r   rW   rW   K   sy    . 	
RAv	A,/	0	0Q1,,,,	A,/	0	0Q1,,,,	Ax	 	 Z8%<%<!1?C!1?CqttQ.#.Ca  ^A%6%6!$QVVs166{!:v!!$$):):+AFFAFFMJE+AFFAFFMJE&+NFAGH#&!$$!45BHAGH#&!$$!45BH$RS8C888 ', QVVAFF+ <<<< / 


s1vQ'7q6Q;GqtQqT144 12!"u<<<< 5	 (8
) 	-, IH8< =sz   ALL0L4L	5D5L*)LL)LLL5L%L4L5BL9L:L	LLLLc              +   (  #    X;   a  [        X    X40 UD6 S h  vN   g [        X5      (       a  g [        U [        5      (       a%  U R	                  U5      (       a  [        X U5      v   g [        U [        5      (       a  [        X U5      v   g g  Nu7fr   )rW   occur_checkrT   r:   r>   assocr,   )varrK   r]   r^   s       r   rU   rU      sy     
x----	S			C	&	&399Q<<AA	C	"	"AA 
# 	.s   BBA6Bc                    ^  T U:X  a  g[        U[        5      (       a  [        T UR                  5      $ [	        U5      (       a  [        U 4S jU 5       5      (       a  gg)z"var occurs in subtree owned by x? Tc              3   <   >#    U  H  n[        TU5      v   M     g 7fr   )ri   ).0xirk   s     r   	<genexpr>occur_check.<locals>.<genexpr>   s     0a{3##as   F)rT   r   ri   r
   r[   any)rk   rK   s   ` r   ri   ri      sJ    
ax	Ax	 	 3''	0a000r   c                 .    U R                  5       n X U'   U $ )z,Return copy of d with key associated to val )copy)dkeyvals      r   rj   rj      s    	AcFHr   c                 <    [        U 5      [        [        [        4;   $ )zIs x a traditional iterable? )r   tuplelistsetrJ   s    r   r[   r[      s    7udC(((r   c                     [        U [        5      (       a(  [        U R                  5      S:X  a  U R                  S   $ U $ )NrS   r   )rT   r   rX   r
   rJ   s    r   rZ   rZ      s1    !X3qvv;!#3vvayr   c           	   #   b  #    US:X  a  SnUS:X  a  Sn[        U 5      [        U5      :  a  X4OX4u  p4[        [        [        [        U5      5      5      [        U5      US9 HH  nXA:X  a!  [	        S U  5       5      [        X5      4v   M)  [        X5      [	        S U 5       5      4v   MJ     g7f)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,)))
rQ      rR   N)orderedc              3   &   #    U  H  o4v   M	     g 7fr   r*   )rn   r`   s     r   rp   "allcombinations.<locals>.<genexpr>   s     (aa   c              3   &   #    U  H  o4v   M	     g 7fr   r*   )rn   ra   s     r   rp   r      s     +<!QD!r   )rX   r   rz   rangery   	partition)ABr   smbgparts         r   rY   rY      s     F --1vAaVQFFBd5R>*CGWE7(a(()A*<<<A$e+<!+<&<<<	 Fs   B-B/c           	      b    [        U 5      " U Vs/ s H  n[        X5      PM     sn5      $ s  snf )zPartition 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)itr   inds      r   r   r      s)     8t4tU2^t4554s   ,c                 T    [        U 5      " U Vs/ s H  o U   PM	     sn5      $ s  snf )zFancy 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   )r   r   is      r   r   r      s'     8C(CqUC())(s   %r   )r(   sympy.utilities.iterablesr   r   r,   r:   rW   rU   ri   rj   r[   rZ   rY   r   r   r*   r   r   <module>r      s^   $ ,I I&. .2 2*5=n),=\
6
*r   