ó
¡¼™\c           @  sÖ   d  Z  d d l m Z m Z d d l m Z d d l m Z d e f d „  ƒ  YZ	 d e f d „  ƒ  YZ
 d	 e f d
 „  ƒ  YZ d d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d S(   sG   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
iÿÿÿÿ(   t   print_functiont   division(   t   range(   t   kbinst   Compoundc           B  s2   e  Z d  Z d „  Z d „  Z d „  Z d „  Z RS(   sr    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(   t   opt   args(   t   selfR   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyt   __init__   s    	c         C  s:   t  |  ƒ t  | ƒ k o9 |  j | j k o9 |  j | j k S(   N(   t   typeR   R   (   R   t   other(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyt   __eq__!   s    *c         C  s   t  t |  ƒ |  j |  j f ƒ S(   N(   t   hashR	   R   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyt   __hash__%   s    c         C  s,   d t  |  j ƒ d j t t  |  j ƒ ƒ f S(   Ns   %s[%s]s   , (   t   strR   t   joint   mapR   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyt   __str__(   s    (   t   __name__t
   __module__t   __doc__R   R   R   R   (    (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR      s
   			t   Variablec           B  s2   e  Z d  Z d „  Z d „  Z d „  Z d „  Z RS(   s    A Wild token c         C  s   | |  _  d  S(   N(   t   arg(   R   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   -   s    c         C  s(   t  |  ƒ t  | ƒ k o' |  j | j k S(   N(   R	   R   (   R   R
   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   0   s    c         C  s   t  t |  ƒ |  j f ƒ S(   N(   R   R	   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   3   s    c         C  s   d t  |  j ƒ S(   Ns   Variable(%s)(   R   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   6   s    (   R   R   R   R   R   R   R   (    (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   +   s
   			t   CondVariablec           B  s2   e  Z d  Z d „  Z d „  Z d „  Z d „  Z RS(   s‚    A wild token that matches conditionally

    arg   - a wild token
    valid - an additional constraining function on a match
    c         C  s   | |  _  | |  _ d  S(   N(   R   t   valid(   R   R   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   ?   s    	c         C  s:   t  |  ƒ t  | ƒ k o9 |  j | j k o9 |  j | j k S(   N(   R	   R   R   (   R   R
   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   C   s    c         C  s   t  t |  ƒ |  j |  j f ƒ S(   N(   R   R	   R   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   H   s    c         C  s   d t  |  j ƒ S(   Ns   CondVariable(%s)(   R   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   K   s    (   R   R   R   R   R   R   R   (    (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   9   s
   			c         k  s1  | p	 i  } |  | k r  | Vnt  |  t t f ƒ r] xõt |  | | |  D] } | VqK WnÐt  | t t f ƒ rš x¸t | |  | |  D] } | Vqˆ Wn“t  |  t ƒ r‹t  | t ƒ r‹| j d d „  ƒ } | j d d „  ƒ } xHt |  j | j | |  D]†} | |  ƒ r8| | ƒ r8t |  j	 ƒ t | j	 ƒ k  rF|  | f n	 | |  f \ } }	 | |  ƒ r‹| | ƒ r‹t
 | j	 |	 j	 d ƒ }
 n t
 | j	 |	 j	 d ƒ }
 xÞ |
 D]‡ \ } } g  | D] } t t | j | ƒ ƒ ^ q½} g  | D] } t t |	 j | ƒ ƒ ^ qè} x" t | | | |  D] } | Vq"WqªWqþ t |  j	 ƒ t | j	 ƒ k rþ x+ t |  j	 | j	 | |  D] } | VqrWqþ qþ Wn¢ t |  ƒ r-t | ƒ r-t |  ƒ t | ƒ k r-t |  ƒ d k rÕ| Vq-xU t |  d | d | |  D]3 } x* t |  d | d | |  D] } | VqWqóWn  d	 S(
   s   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'}
    t   is_commutativec         S  s   t  S(   N(   t   False(   t   x(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyt   <lambda>p   t    t   is_associativec         S  s   t  S(   N(   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR   q   R   t   commutativet   associativei    i   N(   t
   isinstanceR   R   t	   unify_varR   t   gett   unifyR   t   lenR   t   allcombinationst   unpackt   is_args(   R   t   yt   st   fnst   matchR   R   t   sopt   at   bt   combst   aaargst   bbargsR   t   aat   bbt   shead(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR$   N   s@    "<++"0$$c         k  s£   |  | k r8 x t  | |  | | |  D] } | Vq& Wng t |  | ƒ rJ nU t |  t ƒ r| |  j | ƒ r| t | |  | ƒ Vn# t |  t ƒ rŸ t | |  | ƒ Vn  d  S(   N(   R$   t   occur_checkR!   R   R   t   assocR   (   t   varR   R*   R+   R,   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR"   Š   s     c           sb   ˆ  | k r t  St | t ƒ r/ t ˆ  | j ƒ St | ƒ r^ t ‡  f d †  | Dƒ ƒ r^ t  Sn  t S(   s#    var occurs in subtree owned by x? c         3  s   |  ] } t  ˆ  | ƒ Vq d  S(   N(   R6   (   t   .0t   xi(   R8   (    s/   lib/python2.7/site-packages/sympy/unify/core.pys	   <genexpr>œ   s    (   t   TrueR!   R   R6   R   R(   t   anyR   (   R8   R   (    (   R8   s/   lib/python2.7/site-packages/sympy/unify/core.pyR6   •   s     c         C  s   |  j  ƒ  }  | |  | <|  S(   s-    Return copy of d with key associated to val (   t   copy(   t   dt   keyt   val(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR7   Ÿ   s    
c         C  s   t  |  ƒ t t t f k S(   s    Is x a traditional iterable? (   R	   t   tuplet   listt   set(   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR(   ¥   s    c         C  s7   t  |  t ƒ r/ t |  j ƒ d k r/ |  j d S|  Sd  S(   Ni   i    (   R!   R   R%   R   (   R   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR'   ©   s    $c         c  só   | d k r d } n  | d k r* d } n  t |  ƒ t | ƒ k  rN |  | f n	 | |  f \ } } xŒ t t t t | ƒ ƒ ƒ t | ƒ d | ƒD]] } | | k rÇ t d „  |  Dƒ ƒ t | | ƒ f VqŽ t |  | ƒ t d „  | Dƒ ƒ f VqŽ Wd S(   sï  
    Restructure A and B to have the same number of elements

    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   i   R    t   orderedc         s  s   |  ] } | f Vq d  S(   N(    (   R9   R.   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pys	   <genexpr>Ö   s    c         s  s   |  ] } | f Vq d  S(   N(    (   R9   R/   (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pys	   <genexpr>Ø   s    N(   t   NoneR%   R   RB   R   RA   t	   partition(   t   At   BRD   t   smt   bgt   part(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyR&   ¯   s     		64'c         C  s,   t  |  ƒ g  | D] } t |  | ƒ ^ q ƒ S(   sÖ    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	   t   index(   t   itRK   t   ind(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyRF   Ú   s    
c         C  s'   t  |  ƒ g  | D] } |  | ^ q ƒ S(   s¼    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	   (   RM   RN   t   i(    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyRL   æ   s    
N(   R   t
   __future__R    R   t   sympy.core.compatibilityR   t   sympy.utilities.iterablesR   t   objectR   R   R   RE   R$   R"   R6   R7   R(   R'   R&   RF   RL   (    (    (    s/   lib/python2.7/site-packages/sympy/unify/core.pyt   <module>   s   <		
				+	