U
    L?h}                     @   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                   @   s0   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   s   || _ || _d S N)opargs)selfr   r    r   B/var/www/html/venv/lib/python3.8/site-packages/sympy/unify/core.py__init__   s    zCompound.__init__c                 C   s(   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   s   t t| | j| jfS r   )hashr   r   r   r   r   r   r	   __hash__"   s    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                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )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   s   dt | j S )NzVariable(%s)r   r   r   r   r   r	   r   3   s    zVariable.__str__Nr   r   r   r   r	   r   (   s
   r   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )CondVariablez A wild token that matches conditionally.

    arg   - a wild token.
    valid - an additional constraining function on a match.
    c                 C   s   || _ || _d S r   )r   valid)r   r   r   r   r   r	   r
   <   s    zCondVariable.__init__c                 C   s(   t | t |ko&| j|jko&| j|jkS r   )r   r   r   r   r   r   r	   r   @   s
    

zCondVariable.__eq__c                 C   s   t t| | j| jfS r   )r   r   r   r   r   r   r   r	   r   E   s    zCondVariable.__hash__c                 C   s   dt | j S )NzCondVariable(%s)r   r   r   r   r	   r   H   s    zCondVariable.__str__Nr   r   r   r   r	   r   6   s
   r   Nc                 +   s0  |pi }| |kr|V  nt | ttfrBt| ||f|E dH  nt |ttfrjt|| |f|E dH  nt | trt |tr|ddd }|ddd }t| j|j|f|D ]}|| rx||rxt| j	t|j	k r| |fn|| f\ || r||rt
 j	j	d}nt
 j	j	d}|D ]D\}}	 fd	d
|D }
fdd
|	D }t|
||f|E dH  q0qt| j	t|j	krt| j	|j	|f|E dH  qnt| r,t|r,t| t|kr,t| dkr|V  nFt| d |d |f|D ],}t| dd |dd |f|E dH  qd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   s   dS NFr   xr   r   r	   <lambda>k       zunify.<locals>.<lambda>is_associativec                 S   s   dS r!   r   r"   r   r   r	   r$   l   r%   commutativeassociativec                    s   g | ]}t t j|qS r   unpackr   r   .0r   )ar   r	   
<listcomp>u   s     zunify.<locals>.<listcomp>c                    s   g | ]}t t j|qS r   r)   r+   )br   r	   r.   v   s     r      )
isinstancer   r   	unify_varr   getunifyr   lenr   allcombinationsis_args)r#   ysfnsr    r&   ZsopZcombsZaaargsZbbargsZaaZbbZsheadr   )r-   r/   r	   r4   K   s6    
(&r4   c                 k   sp   | |kr$t ||  ||f|E d H  nHt| |r0n<t| trT| |rTt|| |V  nt| trlt|| |V  d S r   )r4   occur_checkr1   r   r   assocr   )varr#   r9   r:   r   r   r	   r2      s    

r2   c                    sH    |krdS t |tr"t |jS t|rDt fdd|D rDdS dS )z# var occurs in subtree owned by x? Tc                 3   s   | ]}t  |V  qd S r   )r;   )r,   xir=   r   r	   	<genexpr>   s     zoccur_check.<locals>.<genexpr>F)r1   r   r;   r   r7   any)r=   r#   r   r?   r	   r;      s    
 r;   c                 C   s   |   } || |< | S )z- Return copy of d with key associated to val )copy)dkeyvalr   r   r	   r<      s    r<   c                 C   s   t | tttfkS )z Is x a traditional iterable? )r   tuplelistsetr"   r   r   r	   r7      s    r7   c                 C   s*   t | tr"t| jdkr"| jd S | S d S )Nr0   r   )r1   r   r5   r   r"   r   r   r	   r*      s    
r*   c                 c   s   |dkrd}|dkrd}t | t |k r0| |fn|| f\}}tttt |t ||dD ]J}||krtdd | D t||fV  qZt| |tdd |D fV  qZd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,)))
    r'      r(   N)orderedc                 s   s   | ]}|fV  qd S r   r   )r,   r-   r   r   r	   r@      s     z"allcombinations.<locals>.<genexpr>c                 s   s   | ]}|fV  qd S r   r   )r,   r/   r   r   r	   r@      s     )r5   r   rG   rangerF   	partition)ABrJ   smbgpartr   r   r	   r6      s    #$" r6   c                    s   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)r,   inditr   r	   r.      s     zpartition.<locals>.<listcomp>r   )rU   rQ   r   rT   r	   rL      s    
rL   c                    s   t   fdd|D S )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   )r,   irT   r   r	   r.      s     zindex.<locals>.<listcomp>rV   )rU   rS   r   rT   r	   rR      s    
rR   )N)r   Zsympy.utilities.iterablesr   r   r   r   r4   r2   r;   r<   r7   r*   r6   rL   rR   r   r   r   r	   <module>   s   
7

.