o
    8Va}                     @   s   d Z ddlmZ G dd dZG dd dZG dd dZd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 )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                   @   0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )Compoundzr A little class to represent an interior node in the tree

    This is analogous to SymPy.Basic for non-Atoms
    c                 C      || _ || _d S N)opargs)selfr   r    r
   2/usr/lib/python3/dist-packages/sympy/unify/core.py__init__      
zCompound.__init__c                 C   (   t | t |ko| j|jko| j|jkS r   )typer   r   r	   otherr
   r
   r   __eq__   s   
zCompound.__eq__c                 C      t t| | j| jfS r   )hashr   r   r   r	   r
   r
   r   __hash__"      zCompound.__hash__c                 C   s    dt | jdtt | jf S )Nz%s[%s]z, )strr   joinmapr   r   r
   r
   r   __str__%   s    zCompound.__str__N__name__
__module____qualname____doc__r   r   r   r   r
   r
   r
   r   r      s    r   c                   @   r   )Variablez A Wild token c                 C   s
   || _ d S r   )arg)r	   r"   r
   r
   r   r   *   s   
zVariable.__init__c                 C   s   t | t |ko| j|jkS r   )r   r"   r   r
   r
   r   r   -   s   zVariable.__eq__c                 C   s   t t| | jfS r   )r   r   r"   r   r
   r
   r   r   0   s   zVariable.__hash__c                 C      dt | j S )NzVariable(%s)r   r"   r   r
   r
   r   r   3      zVariable.__str__Nr   r
   r
   r
   r   r!   (   s    r!   c                   @   r   )CondVariablez A wild token that matches conditionally.

    arg   - a wild token.
    valid - an additional constraining function on a match.
    c                 C   r   r   )r"   valid)r	   r"   r'   r
   r
   r   r   <   r   zCondVariable.__init__c                 C   r   r   )r   r"   r'   r   r
   r
   r   r   @   s
   

zCondVariable.__eq__c                 C   r   r   )r   r   r"   r'   r   r
   r
   r   r   E   r   zCondVariable.__hash__c                 C   r#   )NzCondVariable(%s)r$   r   r
   r
   r   r   H   r%   zCondVariable.__str__Nr   r
   r
   r
   r   r&   6   s    r&   Nc                 +   sN   |pi }| |kr|V  dS t | ttfr$t| ||fi |E dH  dS t |ttfr:t|| |fi |E dH  dS t | trt |tr|ddd }|ddd }t| j|j|fi |D ]w}|| r||rt| j	t|j	k rx| |fn|| f\ || r||rt
 j	j	d}nt
 j	j	d}|D ]#\}}	 fd	d
|D }
fdd
|	D }t|
||fi |E dH  qq`t| j	t|j	krt| j	|j	|fi |E dH  q`dS t| rt|r!t| t|kr#t| dkr|V  dS t| d |d |fi |D ]}t| dd |dd |fi |E dH  qdS dS dS dS )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                 S      dS NFr
   xr
   r
   r   <lambda>k       zunify.<locals>.<lambda>is_associativec                 S   r)   r*   r
   r+   r
   r
   r   r-   l   r.   commutativeassociativec                       g | ]
}t t j|qS r
   unpackr   r   .0r"   )ar
   r   
<listcomp>u       zunify.<locals>.<listcomp>c                    r2   r
   r3   r5   )br
   r   r8   v   r9   r      )
isinstancer!   r&   	unify_varr   getunifyr   lenr   allcombinationsis_args)r,   ysfnsr(   r/   ZsopZcombsZaaargsZbbargsZaaZbbZsheadr
   )r7   r:   r   r?   K   sB   
(&
 .r?   c                 k   s    | |v rt ||  ||fi |E d H  d S t| |rd S t| tr0| |r0t|| |V  d S t| tr>t|| |V  d S d S r   )r?   occur_checkr<   r&   r'   assocr!   )varr,   rD   rE   r
   r
   r   r=      s   "

r=   c                    sH    |krdS t |trt |jS t|r"t fdd|D r"dS dS )z# var occurs in subtree owned by x? Tc                 3   s    | ]}t  |V  qd S r   )rF   )r6   ZxirH   r
   r   	<genexpr>   s    zoccur_check.<locals>.<genexpr>F)r<   r   rF   r   rB   any)rH   r,   r
   rI   r   rF      s   
rF   c                 C   s   |   } || |< | S )z- Return copy of d with key associated to val )copy)dkeyvalr
   r
   r   rG      s   rG   c                 C   s   t | tttfv S )z Is x a traditional iterable? )r   tuplelistsetr+   r
   r
   r   rB      s   rB   c                 C   s&   t | trt| jdkr| jd S | S )Nr;   r   )r<   r   r@   r   r+   r
   r
   r   r4      s   
r4   c                 c   s    |dkrd}|dkrd}t | t |k r| |fn|| f\}}tttt |t ||dD ]%}||krDtdd | D t||fV  q.t| |tdd |D fV  q.dS )	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,)))
    r0      r1   N)orderedc                 s       | ]}|fV  qd S r   r
   )r6   r7   r
   r
   r   rJ          z"allcombinations.<locals>.<genexpr>c                 s   rU   r   r
   )r6   r:   r
   r
   r   rJ      rV   )r@   r   rQ   rangerP   	partition)ABrT   Zsmbgpartr
   r
   r   rA      s   #$"  rA   c                       t   fdd|D S )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,))
    c                    s   g | ]}t  |qS r
   )index)r6   inditr
   r   r8      s    zpartition.<locals>.<listcomp>r   )ra   r\   r
   r`   r   rX         
rX   c                    r]   )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]
    c                    s   g | ]} | qS r
   r
   )r6   ir`   r
   r   r8      s    zindex.<locals>.<listcomp>rb   )ra   r_   r
   r`   r   r^      rc   r^   r   )r    Zsympy.utilities.iterablesr   r   r!   r&   r?   r=   rF   rG   rB   r4   rA   rX   r^   r
   r
   r
   r   <module>   s    
7

.