ó
~9­\c           @   sd  d  d l  Z  d  d l m Z d  d l m Z d  d l m Z m Z m Z m	 Z	 m
 Z
 m Z m Z d  d l m Z d  d l m Z d  d l m Z m Z d  d l m Z d  d	 l m Z d  d
 l m Z d  d l m Z m Z m Z m Z m Z d  d l  m! Z! m" Z" d  d l# m$ Z$ d e f d „  ƒ  YZ% d e% f d „  ƒ  YZ& d „  Z' d e% f d „  ƒ  YZ( d e% f d „  ƒ  YZ) d e% f d „  ƒ  YZ* d „  Z+ d e% f d „  ƒ  YZ, d „  Z- d „  Z. d „  Z/ d „  Z0 d  „  Z1 d! „  Z2 d" „  Z3 d# „  Z4 d$ „  Z5 g  d% „ Z6 d& „  Z7 d' e8 f d( „  ƒ  YZ9 d) e: f d* „  ƒ  YZ; d+ „  Z< d, „  Z= d- „  Z> d. „  Z? d S(/   iÿÿÿÿN(   t   reduce(   t   defaultdict(   t   Indexedt   IndexedBaset   Tuplet   Sumt   Addt   St   Integer(   t   Permutation(   t   Basic(   t
   accumulatet   default_sort_key(   t   Mul(   t   _sympify(   t   KroneckerDelta(   t   MatAddt   MatMult   Tracet	   Transposet   MatrixSymbol(   t
   MatrixExprt   MatrixElement(   t	   NDimArrayt   _CodegenArrayAbstractc           B   s/   e  Z e d  „  ƒ Z d „  Z e d „  ƒ Z RS(   c         C   s   |  j  S(   s	  
        Returns the ranks of the objects in the uppermost tensor product inside
        the current object.  In case no tensor products are contained, return
        the atomic ranks.

        Examples
        ========

        >>> from sympy.codegen.array_utils import CodegenArrayTensorProduct, CodegenArrayContraction
        >>> from sympy import MatrixSymbol
        >>> M = MatrixSymbol("M", 3, 3)
        >>> N = MatrixSymbol("N", 3, 3)
        >>> P = MatrixSymbol("P", 3, 3)

        Important: do not confuse the rank of the matrix with the rank of an array.

        >>> tp = CodegenArrayTensorProduct(M, N, P)
        >>> tp.subranks
        [2, 2, 2]

        >>> co = CodegenArrayContraction(tp, (1, 2), (3, 4))
        >>> co.subranks
        [2, 2, 2]
        (   t	   _subranks(   t   self(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   subranks   s    c         C   s   t  |  j ƒ S(   s*   
        The sum of ``subranks``.
        (   t   sumR   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   subrank0   s    c         C   s   |  j  S(   N(   t   _shape(   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   shape6   s    (   t   __name__t
   __module__t   propertyR   R   R   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR      s   	t   CodegenArrayContractionc           B   sÑ   e  Z d  Z d „  Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z d „  Z	 e d „  ƒ Z
 e d „  ƒ Z e d	 „  ƒ Z e d
 „  ƒ Z e d „  ƒ Z d „  Z d „  Z d „  Z e d „  ƒ Z RS(   sx   
    This class is meant to represent contractions of arrays in a form easily
    processable by the code printers.
    c            s:  t  ˆ  ƒ ‰  t | ƒ } t ˆ  ƒ d k r. | St | t ƒ rM |  j | ˆ  Œ St j |  | ˆ  Œ } t | ƒ | _	 t
 | j	 ƒ | _ ‡  f d †  t t | j	 ƒ ƒ Dƒ } | | _ | j ‰ ˆ r-xE ˆ  D]= } t t ‡ f d †  | Dƒ ƒ ƒ d k rÇ t d ƒ ‚ qÇ qÇ Wt ‡  f d †  t ˆ ƒ Dƒ ƒ ‰ n  ˆ | _ | S(   Ni    c            s>   i  |  ]4 } t  g  ˆ  D] } | | k ^ q ƒ r | | “ q S(    (   t   all(   t   .0t   it   cind(   t   contraction_indices(    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys
   <dictcomp>N   s   	 c         3   s   |  ] } ˆ  | Vq d  S(   N(    (   R%   t   j(   R   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>U   s    i   s+   contracting indices of different dimensionsc         3   s7   |  ]- \ ‰  } t  ‡  f d  †  ˆ Dƒ ƒ s | Vq d S(   c         3   s   |  ] } ˆ  | k Vq d  S(   N(    (   R%   R)   (   R&   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>W   s    N(   t   any(   R%   t   shp(   R(   (   R&   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>W   s    (   t   _sort_contraction_indicesR   t   lent
   isinstanceR#   t   _flattenR
   t   __new__t   _get_subranksR   t   _get_mapping_from_subrankst   _mappingt   rangeR   t   _free_indices_to_positionR   t   sett
   ValueErrort   tuplet	   enumerateR   (   t   clst   exprR(   t   kwargst   objt   free_indices_to_positionR&   (    (   R(   R   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR0   @   s&    %		(%	c         C   sx   i  } g  | D] } | D] } | ^ q q } d } x? |  D]7 } x | | k r[ | d 7} qB W| | | <| d 7} q9 W| S(   Ni    i   (    (   t   free_indicesR(   R>   R&   R)   t   flattened_contraction_indicest   countert   ind(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt!   _get_free_indices_to_position_map[   s    &
c         C   sò   |  j  } g  | D] } | D] } | ^ q q } | j ƒ  t |  ƒ } t | ƒ } | | } g  t | ƒ D] } d ^ qh } d }	 d }
 xe t | ƒ D]W } x4 |
 | k  rÏ |	 | |
 k rÏ |	 d 7}	 |
 d 7}
 qœ W| | c |
 7<|	 d 7}	 q“ W| S(   s»  
        Get the mapping of indices at the positions before the contraction
        occures.

        Examples
        ========

        >>> from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayTensorProduct
        >>> from sympy import MatrixSymbol
        >>> M = MatrixSymbol("M", 3, 3)
        >>> N = MatrixSymbol("N", 3, 3)
        >>> cg = CodegenArrayContraction(CodegenArrayTensorProduct(M, N), [1, 2])
        >>> cg._get_index_shifts(cg)
        [0, 2]

        Indeed, ``cg`` after the contraction has two dimensions, 0 and 1. They
        need to be shifted by 0 and 2 to get the corresponding positions before
        the contraction (that is, 0 and 3).
        i    i   (   R(   t   sortt   get_rankR-   R4   (   R;   t   inner_contraction_indicesR&   R)   t	   all_innert
   total_rankt
   inner_rankt
   outer_rankt   shiftsRA   t   pointer(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   _get_index_shiftsg   s     	&


c            s/   t  j |  ƒ ‰  t ‡  f d †  | Dƒ ƒ } | S(   Nc         3   s+   |  ]! } t  ‡  f d  †  | Dƒ ƒ Vq d S(   c         3   s   |  ] } ˆ  | | Vq d  S(   N(    (   R%   R)   (   RK   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>‘   s    N(   R8   (   R%   R&   (   RK   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>‘   s    (   R#   RM   R8   (   R;   t   outer_contraction_indices(    (   RK   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt'   _convert_outer_indices_to_inner_indicesŽ   s    c         G   s5   |  j  } t j |  | Œ } | | } t |  j | Œ S(   N(   R(   R#   RO   R;   (   R;   RN   RF   R(   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR/   ”   s    	
c         C   s:   |  j  } g  |  j D]# } g  | D] } | | ^ q  ^ q S(   s  
        Return tuples containing the argument index and position within the
        argument of the index position.

        Examples
        ========

        >>> from sympy import MatrixSymbol, MatrixExpr, Sum, Symbol
        >>> from sympy.abc import i, j, k, l, N
        >>> from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayTensorProduct
        >>> A = MatrixSymbol("A", N, N)
        >>> B = MatrixSymbol("B", N, N)

        >>> cg = CodegenArrayContraction(CodegenArrayTensorProduct(A, B), (1, 2))
        >>> cg._get_contraction_tuples()
        [[(0, 1), (1, 0)]]

        Here the contraction pair `(1, 2)` meaning that the 2nd and 3rd indices
        of the tensor product `A\otimes B` are contracted, has been transformed
        into `(0, 1)` and `(1, 0)`, identifying the same indices in a different
        notation. `(0, 1)` is the second index (1) of the first argument (i.e.
                0 or `A`). `(1, 0)` is the first index (i.e. 0) of the second
        argument (i.e. 1 or `B`).
        (   R3   R(   (   R   t   mappingR&   R)   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   _get_contraction_tuples›   s    	c            sO   |  j  } d g t t | ƒ ƒ ‰  g  | D]" } t ‡  f d †  | Dƒ ƒ ^ q) S(   Ni    c         3   s#   |  ] \ } } ˆ  | | Vq d  S(   N(    (   R%   R)   t   k(   t   cumulative_ranks(    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>¼   s    (   R   t   listR   R8   (   R;   t   contraction_tuplest   ranksR&   (    (   RS   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt*   _contraction_tuples_to_contraction_indices·   s    	c         C   s   |  j  S(   N(   t   _free_indices(   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR?   ¾   s    c         C   s   t  |  j ƒ S(   N(   t   dictR5   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR>   Â   s    c         C   s   |  j  d S(   Ni    (   t   args(   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR;   Æ   s    c         C   s   |  j  d S(   Ni   (   RZ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR(   Ê   s    c         C   sŽ   |  j  } t | t ƒ s' t d ƒ ‚ n  | j } i  } d } xK t | ƒ D]= \ } } x. t | ƒ D]  } | | f | | <| d 7} qb WqI W| S(   Ns(   only for contractions of tensor productsi    i   (   R;   R.   t   CodegenArrayTensorProductt   NotImplementedErrorR   R9   R4   (   R   R;   RV   RP   RA   R&   t   rankR)   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt"   _contraction_indices_to_componentsÎ   s    		c            sá   |  j  } t | t ƒ s |  S| j } t t | ƒ d d „  ƒ} t | Œ  \ ‰  } ‡  f d †  t | ƒ Dƒ } |  j ƒ  } g  | D]/ } g  | D] \ } }	 | | |	 f ^ qŽ ^ q } t | Œ  }
 |  j |
 | ƒ } t	 |
 | Œ S(   s  
        Sort arguments in the tensor product so that their order is lexicographical.

        Examples
        ========

        >>> from sympy import MatrixSymbol, MatrixExpr, Sum, Symbol
        >>> from sympy.abc import i, j, k, l, N
        >>> from sympy.codegen.array_utils import CodegenArrayContraction
        >>> A = MatrixSymbol("A", N, N)
        >>> B = MatrixSymbol("B", N, N)
        >>> C = MatrixSymbol("C", N, N)
        >>> D = MatrixSymbol("D", N, N)

        >>> cg = CodegenArrayContraction.from_MatMul(C*D*A*B)
        >>> cg
        CodegenArrayContraction(CodegenArrayTensorProduct(C, D, A, B), (1, 2), (3, 4), (5, 6))
        >>> cg.sort_args_by_name()
        CodegenArrayContraction(CodegenArrayTensorProduct(A, B, C, D), (0, 7), (1, 2), (5, 6))
        t   keyc         S   s   t  |  d ƒ S(   Ni   (   R   (   t   x(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   <lambda>ô   t    c            s(   i  |  ] \ } } ˆ  j  | ƒ | “ q S(    (   t   index(   R%   R&   t   arg(   t
   pos_sorted(    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys
   <dictcomp>ö   s   	 (
   R;   R.   R[   RZ   t   sortedR9   t   zipRQ   RW   R#   (   R   R;   RZ   t   sorted_datat   args_sortedt   reordering_mapRU   R&   R)   RR   t   c_tpt   new_contr_indices(    (   Re   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   sort_args_by_nameÛ   s    		<	c         C   s   t  |  j |  j Œ S(   s“  
        Returns a dictionary of links between arguments in the tensor product
        being contracted.

        See the example for an explanation of the values.

        Examples
        ========

        >>> from sympy import MatrixSymbol, MatrixExpr, Sum, Symbol
        >>> from sympy.abc import i, j, k, l, N
        >>> from sympy.codegen.array_utils import CodegenArrayContraction
        >>> A = MatrixSymbol("A", N, N)
        >>> B = MatrixSymbol("B", N, N)
        >>> C = MatrixSymbol("C", N, N)
        >>> D = MatrixSymbol("D", N, N)

        Matrix multiplications are pairwise contractions between neighboring
        matrices:

        `A_{ij} B_{jk} C_{kl} D_{lm}`

        >>> cg = CodegenArrayContraction.from_MatMul(A*B*C*D)
        >>> cg
        CodegenArrayContraction(CodegenArrayTensorProduct(A, B, C, D), (1, 2), (3, 4), (5, 6))
        >>> cg._get_contraction_links()
        {0: {1: (1, 0)}, 1: {0: (0, 1), 1: (2, 0)}, 2: {0: (1, 1), 1: (3, 0)}, 3: {0: (2, 1)}}

        This dictionary is interpreted as follows: argument in position 0 (i.e.
        matrix `A`) has its second index (i.e. 1) contracted to `(1, 0)`, that
        is argument in position 1 (matrix `B`) on the first index slot of `B`,
        this is the contraction provided by the index `j` from `A`.

        The argument in position 1 (that is, matrix `B`) has two contractions,
        the ones provided by the indices `j` and `k`, respectively the first
        and second indices (0 and 1 in the sub-dict).  The link `(0, 1)` and
        `(2, 0)` respectively. `(0, 1)` is the index slot 1 (the 2nd) of
        argument in position 0 (that is, `A_{\ldot j}`), and so on.
        (   t   _get_contraction_linksR   R(   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRn      s    (c         C   s±   g  } g  } g  } x= |  j  D]2 } t | t ƒ rA | j | ƒ q | j | ƒ q Wg  t t | ƒ d ƒ D]" } d | d d | d f ^ qi } t j | ƒ t t	 | Œ  | Œ S(   Ni   i   (
   RZ   R.   R   t   appendR4   R-   R   t   fromiterR#   R[   (   R;   t   args_nonmatRZ   t   contractionsRd   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   from_MatMul*  s    ?	(   R    R!   t   __doc__R0   t   staticmethodRC   RM   RO   R/   RQ   RW   R"   R?   R>   R;   R(   R^   Rm   Rn   Rs   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR#   ;   s    	'			%	*c         C   s   t  |  d ƒ r |  j Sd S(   NR   (    (   t   hasattrR   (   R;   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt	   get_shape;  s    R[   c           B   s&   e  Z d  Z d „  Z e d „  ƒ Z RS(   sF   
    Class to represent the tensor product of array-like objects.
    c   
         s«  g  | D] } t  | ƒ ^ q } |  j | ƒ } g  | D] } t | ƒ ^ q5 } t | ƒ d k rg | d Sd „  t | ƒ Dƒ } | r2t t d g | ƒ ƒ d  ‰  |  g  | D]$ } t | t ƒ rÈ | j	 n | ^ qª Œ  } g  | j
 ƒ  D]; \ ‰ } | j D]% } t ‡  ‡ f d †  | Dƒ ƒ ^ q÷ qä } t | | Œ St j |  | Œ } | | _ g  | D] ‰ t ˆ ƒ ^ qT}	 t d „  |	 Dƒ ƒ rŽd  | _ n t d „  |	 Dƒ ƒ | _ | S(   Ni   i    c         S   s.   i  |  ]$ \ } } t  | t ƒ r | | “ q S(    (   R.   R#   (   R%   R&   Rd   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys
   <dictcomp>O  s   	 iÿÿÿÿc         3   s   |  ] } ˆ  ˆ | Vq d  S(   N(    (   R%   RR   (   RS   R&   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>S  s    c         s   s   |  ] } | d  k Vq d  S(   N(   t   None(   R%   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>^  s    c         s   s"   |  ] } | D] } | Vq q d  S(   N(    (   R%   R&   R)   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>a  s    (   R   R/   RE   R-   R9   RT   R   R.   R#   R;   t   itemsR(   R8   R
   R0   R   Rw   R*   Rx   R   (
   R:   RZ   Rd   RV   Rr   t   tpR)   R(   R=   t   shapes(    (   RS   R&   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR0   E  s$    7N	c         C   sE   g  | D]4 } t  | |  ƒ r% | j n | g D] } | ^ q, q } | S(   N(   R.   RZ   (   R:   RZ   Rd   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR/   d  s    A(   R    R!   Rt   R0   t   classmethodR/   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR[   A  s   	t   CodegenArrayElementwiseAddc           B   s   e  Z d  Z d „  Z RS(   s0   
    Class for elementwise array additions.
    c         G   s!  g  | D] } t  | ƒ ^ q } t j |  | Œ } g  | D] } t | ƒ ^ q8 } t t | ƒ ƒ } t | ƒ d k rƒ t d ƒ ‚ n  | | _ g  | D] } | j	 ^ q“ } t t g  | D] } | d  k	 rµ | ^ qµ ƒ ƒ d k rî t d ƒ ‚ n  t d „  | Dƒ ƒ rd  | _ n | d | _ | S(   Ni   s!   summing arrays of different rankss   mismatching shapes in additionc         s   s   |  ] } | d  k Vq d  S(   N(   Rx   (   R%   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>y  s    i    (   R   R
   R0   RE   RT   R6   R-   R7   R   R   Rx   R*   R   (   R:   RZ   Rd   R=   RV   R{   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR0   n  s    	7(   R    R!   Rt   R0   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR}   j  s   t   CodegenArrayPermuteDimsc           B   s>   e  Z d  Z d „  Z e d „  ƒ Z e d „  ƒ Z d „  Z RS(   sì  
    Class to represent permutation of axes of arrays.

    Examples
    ========

    >>> from sympy.codegen.array_utils import CodegenArrayPermuteDims
    >>> from sympy import MatrixSymbol
    >>> M = MatrixSymbol("M", 3, 3)
    >>> cg = CodegenArrayPermuteDims(M, [1, 0])

    The object ``cg`` represents the transposition of ``M``, as the permutation
    ``[1, 0]`` will act on its indices by switching them:

    `M_{ij} \Rightarrow M_{ji}`

    This is evident when transforming back to matrix form:

    >>> from sympy.codegen.array_utils import recognize_matrix_expression
    >>> recognize_matrix_expression(cg)
    M.T

    >>> N = MatrixSymbol("N", 3, 2)
    >>> cg = CodegenArrayPermuteDims(N, [1, 0])
    >>> cg.shape
    (2, 3)
    c            sÅ   d d l  m } t | ƒ } | ˆ  ƒ ‰  ˆ  j d } | t | ƒ k rK | St j |  | ˆ  ƒ } t | ƒ g | _ | j	 ‰ ˆ d  k r“ d  | _ n. t ‡  ‡ f d †  t t ˆ ƒ ƒ Dƒ ƒ | _ | S(   Niÿÿÿÿ(   R	   i    c         3   s   |  ] } ˆ ˆ  | ƒ Vq d  S(   N(    (   R%   R&   (   t   permutationR   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>©  s    (   t   sympy.combinatoricsR	   R   RZ   Rf   R
   R0   RE   R   R   Rx   R   R8   R4   R-   (   R:   R;   R   R	   t   plistR=   (    (   R   R   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR0   œ  s    	.c         C   s   |  j  d S(   Ni    (   RZ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR;   ¬  s    c         C   s   |  j  d S(   Ni   (   RZ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR   °  s    c            s)  |  j  } t | t ƒ rf| j } | j ƒ  } t t | ƒ ƒ } g  | D] } |  j | ƒ ^ qF } i  } d } xÉ t | | j	 ƒ D]µ \ } }	 | | | | !}
 | | 7} t
 |
 ƒ } t g  t t | ƒ d ƒ D]" } | | d | | d k ^ qÍ ƒ sü |  Sg  | D] } |
 j | ƒ ^ q} t |	 | ƒ | | d <q€ Wg  t
 | ƒ D] } | | ^ qF} t | Œ  St | t ƒ rê|  j j } t j | | Œ } t | ƒ ‰  g  | j D]" } t ‡  f d †  | Dƒ ƒ ^ q©} t t | j  ˆ  ƒ | Œ St | t ƒ r%t g  | j	 D] }	 t |	 |  j ƒ ^ qŒ  S|  S(   s  
        Nest the permutation down the expression tree.

        Examples
        ========

        >>> from sympy.codegen.array_utils import (CodegenArrayPermuteDims, CodegenArrayTensorProduct, nest_permutation)
        >>> from sympy import MatrixSymbol
        >>> from sympy.combinatorics import Permutation
        >>> Permutation.print_cyclic = True

        >>> M = MatrixSymbol("M", 3, 3)
        >>> N = MatrixSymbol("N", 3, 3)
        >>> cg = CodegenArrayPermuteDims(CodegenArrayTensorProduct(M, N), [1, 0, 3, 2])
        >>> cg
        CodegenArrayPermuteDims(CodegenArrayTensorProduct(M, N), (0 1)(2 3))
        >>> nest_permutation(cg)
        CodegenArrayTensorProduct(CodegenArrayPermuteDims(M, (0 1)), CodegenArrayPermuteDims(N, (0 1)))

        In ``cg`` both ``M`` and ``N`` are transposed. The cyclic
        representation of the permutation after the tensor product is
        `(0 1)(2 3)`. After nesting it down the expression tree, the usual
        transposition permutation `(0 1)` appears.
        i    i   c         3   s   |  ] } ˆ  | ƒ Vq d  S(   N(    (   R%   R)   (   t   newpermutation(    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>ç  s    (   R;   R.   R[   R   R   RT   R4   R   Rg   RZ   Rf   R$   R-   Rc   R~   R#   t   cyclic_formRO   R	   R(   R8   R}   (   R   R;   R   R   t   lR&   t   pt   dargsRA   Rd   t   p0t   s0R)   t   subpermutationRZ   t   cyclest	   newcyclesRl   (    (   R‚   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   nest_permutation´  s6    		"
E"#
2,(   R    R!   Rt   R0   R"   R;   R   RŒ   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR~   €  s
   	c         C   s!   t  |  t ƒ r |  j ƒ  S|  Sd  S(   N(   R.   R~   RŒ   (   R;   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRŒ   ï  s    
t   CodegenArrayDiagonalc           B   sD   e  Z d  Z d „  Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z RS(   sö  
    Class to represent the diagonal operator.

    In a 2-dimensional array it returns the diagonal, this looks like the
    operation:

    `A_{ij} \rightarrow A_{ii}`

    The diagonal over axes 1 and 2 (the second and third) of the tensor product
    of two 2-dimensional arrays `A \otimes B` is

    `\Big[ A_{ab} B_{cd} \Big]_{abcd} \rightarrow \Big[ A_{ai} B_{id} \Big]_{adi}`

    In this last example the array expression has been reduced from
    4-dimensional to 3-dimensional. Notice that no contraction has occurred,
    rather there is a new index `i` for the diagonal, contraction would have
    reduced the array to 2 dimensions.

    Notice that the diagonalized out dimensions are added as new dimensions at
    the end of the indices.
    c            s,  t  | ƒ } g  ˆ  D] } t t | ƒ Œ  ^ q ‰  t | t ƒ rP |  j | ˆ  Œ St j |  | ˆ  Œ } t | ƒ | _	 | j
 ‰ ˆ d  k r• d  | _ n“ xE ˆ  D]= } t t ‡ f d †  | Dƒ ƒ ƒ d k rœ t d ƒ ‚ qœ qœ Wt ‡  f d †  t ˆ ƒ Dƒ ƒ } t ‡ f d †  ˆ  Dƒ ƒ } | | | _ | S(   Nc         3   s   |  ] } ˆ  | Vq d  S(   N(    (   R%   R)   (   R   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>  s    i   s+   contracting indices of different dimensionsc         3   s7   |  ]- \ ‰  } t  ‡  f d  †  ˆ Dƒ ƒ s | Vq d S(   c         3   s   |  ] } ˆ  | k Vq d  S(   N(    (   R%   R)   (   R&   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>  s    N(   R*   (   R%   R+   (   t   diagonal_indices(   R&   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>  s    c         3   s   |  ] } ˆ  | d  Vq d S(   i    N(    (   R%   R&   (   R   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>  s    (   R   R   Rf   R.   R   R/   R
   R0   R1   R   R   Rx   R   R-   R6   R7   R8   R9   (   R:   R;   RŽ   R&   R=   t   shp1t   shp2(    (   RŽ   R   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR0     s     %	("c         C   s   |  j  d S(   Ni    (   RZ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR;   "  s    c         C   s   |  j  d S(   Ni   (   RZ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRŽ   &  s    c            s$  |  j  } g  | D] } | D] } | ^ q q } | j ƒ  t |  ƒ } t | ƒ } | | } g  t | ƒ D] } d ^ qh ‰  d }	 d }
 xe t | ƒ D]W } x4 |
 | k  rÏ |	 | |
 k rÏ |	 d 7}	 |
 d 7}
 qœ Wˆ  | c |
 7<|	 d 7}	 q“ Wt ‡  f d †  | Dƒ ƒ } | | } t |  j | Œ S(   Ni    i   c         3   s+   |  ]! } t  ‡  f d  †  | Dƒ ƒ Vq d S(   c         3   s   |  ] } ˆ  | | Vq d  S(   N(    (   R%   R)   (   RK   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr><  s    N(   R8   (   R%   R&   (   RK   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr><  s    (   RŽ   RD   RE   R-   R4   R8   R   R;   (   R;   t   outer_diagonal_indicest   inner_diagonal_indicesR&   R)   RG   RH   RI   RJ   RA   RL   RŽ   (    (   RK   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR/   *  s$    	&



(	   R    R!   Rt   R0   R"   R;   RŽ   Ru   R/   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR   ö  s
   	c         C   sÌ   t  |  t t f ƒ r d St  |  t ƒ r2 |  j ƒ  St  |  t ƒ rK |  j ƒ  St  |  t ƒ ra |  j St  |  t ƒ r– |  j	 } | d  k r‰ d St | ƒ Sn  t  |  t ƒ r¯ |  j ƒ  St  |  t ƒ rÈ |  j ƒ  Sd S(   Ni   iÿÿÿÿi    (   R.   R   R   R   R   R   R]   R   R   R   Rx   R-   t   _RecognizeMatOpt   _RecognizeMatMulLines(   R;   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRE   A  s$    

	

c         C   s'   t  |  t ƒ r |  j St |  ƒ g Sd  S(   N(   R.   R   R   RE   (   R;   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR1   W  s    c         C   s^   i  } d } xK t  |  ƒ D]= \ } } x. t | ƒ D]  } | | f | | <| d 7} q2 Wq W| S(   Ni    i   (   R9   R4   (   R   RP   RA   R&   R]   R)   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR2   ^  s    c         G   sÄ   t  |  ƒ } g  | D]# } g  | D] } | | ^ q  ^ q } t t ƒ } xo | D]g } t | ƒ d k rv t d ƒ ‚ n  | \ \ } }	 \ }
 } |
 | f | | |	 <| |	 f | |
 | <qO Wt | ƒ S(   Ni   s.   three or more axes contracted at the same time(   R2   R   RY   R-   R\   (   R   R(   RP   R&   R)   RU   t   dlinkst   linkst   arg1t   pos1t   arg2t   pos2(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRn   g  s    0c         C   s<   g  |  D] } t  t | ƒ Œ  ^ q }  |  j d d „  ƒ |  S(   NR_   c         S   s
   t  |  ƒ S(   N(   t   min(   R`   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   v  Rb   (   R   Rf   RD   (   t   pairing_indicesR&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR,   t  s    %c            sø   t  t ƒ } xF t ˆ  ƒ D]8 \ } } t | t t f ƒ r@ q n  | | j | ƒ q Wd „  | j ƒ  Dƒ } g  ˆ  D] } | | k rr | ^ qr } t | ƒ } | j d ‡  f d †  ƒ g  | D] } t	 | | ƒ ^ q¼ } | | 7} t	 | ƒ } | | f S(   Nc         S   s1   i  |  ]' \ } } t  | ƒ d  k r | | “ q S(   i   (   R-   (   R%   RR   t   v(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys
   <dictcomp>  s   	 R_   c            s   ˆ  j  |  ƒ S(   N(   Rc   (   R`   (   t   flattened_indices(    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   …  Rb   (
   R   RT   R9   R.   t   intR   Ro   Ry   RD   R8   (   Rž   t   axes_contractionR&   RB   t   ret_indicest   diag_indicesRŽ   (    (   Rž   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   _get_diagonal_indicesz  s    %#
c         C   sl   xO t  |  ƒ D]A \ } } | | k r) | St | t t f ƒ r | | k r | Sq Wt d | |  f ƒ ‚ d  S(   Ns   %s not found in %s(   R9   R.   R6   t	   frozensett
   IndexError(   t
   subindicesRB   R&   t   sind(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   _get_argindexŒ  s    !c   "         s{  t  |  t ƒ r§|  j } |  j } t | ƒ \ } } | j } | r¤ x\ |  j D]Q \ } } } t | | ƒ }	 | d k p‡ | d | |	 k r t d | ƒ ‚ n  qL Wn  g  }
 t	 | ƒ } t  | t
 ƒ r¸t	 | j ƒ } | t | ƒ } | t | ƒ  } xG | D]? } | | k r<| j | ƒ } |
 j | | ƒ t | | <n  qý Wg  | D] }	 |	 t k	 r_|	 ^ qG} x) t | ƒ D] \ }	 } | | k rn  qrW| r¬t
 | j | Œ } n	 | j } n  t t	 ƒ } xD t | ƒ D]6 \ }	 } | | k r| | j |	 ƒ t | |	 <n  qÑWx- | j ƒ  D] \ } } |
 j t | ƒ ƒ qWg  | D] }	 |	 t k	 rZ|	 ^ qB‰  t	 ˆ  ƒ } | j d ‡  f d †  ƒ t | d ˆ  |
 Œt | ƒ f Sn  t  |  t ƒ rjt g  |  j D] } t | ƒ ^ qÃŒ  \ } } i  } x© | D]¡ } t  | t ƒ rqñn  | j \ }	 } t | j ƒ } |	 | k rK| j | |	 ƒ n  | | k rk| j | | ƒ n  t | ƒ } x | D] } | | | <q~WqñWg  } g  } xL t | | ƒ D]; \ } } t  | t ƒ rÓq²n  | j | ƒ | j | ƒ q²Wg  | D]% }	 |	 D] } | j | | ƒ ^ qqø} t  | ƒ \ } } t! | Œ  } | r]t
 | | Œ | f Sn
 | | f Sn  t  |  t" ƒ rÏ|  j d } t  | ƒ \ } } | r»t
 |  j d | Œ | f Sn |  j d | f Sn  t  |  t# ƒ r,|  j } t  | ƒ \ } } | rt
 |  j$ | Œ | f Sn |  j d | f Sn  t  |  t% ƒ rDt& ‚ n  t  |  t ƒ rc|  |  j f Sn  t  |  t' ƒ rat g  |  j D] } t | ƒ ^ qŒ  \ } } t	 | ƒ } t | d ƒ } | d }  x… t( d t | ƒ ƒ D]n }	 t | |	 ƒ | k rt& d ƒ ‚ n  t) g  | |	 D] } |  j | ƒ ^ qƒ }! t* | |	 |! ƒ | |	 <qÜWt+ | Œ  |  f Sn  |  f  f St& d |  ƒ ‚ (	   Ni    i   s0   summation index and array dimension mismatch: %sR_   c            s   ˆ  j  |  ƒ S(   N(   Rc   (   R`   (   R?   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   ¾  Rb   R?   s   indices must be the sames!   could not recognize expression %s(,   R.   R   t   functiont	   variablest   _codegen_array_parseR   t   limitsR¨   R7   RT   R   RŽ   R-   Rc   Ro   Rx   R9   R;   R   Ry   R8   RD   R#   R   Rg   RZ   R   t   indicesR6   t   updateR¤   t   getR£   R[   R   R   t   baseR   R\   R   R4   R	   R~   R}   ("   R;   R©   t   summation_indicest   subexprR¦   R   RB   t   istartt   iendR&   R(   RŽ   t   dindicesRc   t   positionR    RR   R   t   indices_retRd   RZ   R­   t   kronecker_delta_replR)   t   kindicest   newargst
   newindicest   loc_indicesRž   R¡   Rz   t	   index0sett   index0R   (    (   R?   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR«   •  sÆ    			 %%	.2		.
,
c         C   sE  t  |  t ƒ rÙ g  } g  } g  } x= |  j D]2 } t  | t ƒ rP | j | ƒ q+ | j | ƒ q+ Wg  t t | ƒ d ƒ D]" } d | d d | d f ^ qx } t j | ƒ t	 t
 g  | D] } t | ƒ ^ q¹ Œ  | Œ St  |  t ƒ rt g  |  j D] } t | ƒ ^ qõ Œ  St  |  t ƒ r=t t |  j d ƒ d d g ƒ S|  Sd  S(   Ni   i   i    (   R.   R   RZ   R   Ro   R4   R-   R   Rp   R#   R[   t   _parse_matrix_expressionR   R}   R   R~   (   R;   Rq   RZ   Rr   Rd   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR¿     s&    ?"#c         C   s¤   t  |  ƒ \ } } | s | Sx* | D]" } | | k r# | j | ƒ q# q# W| j g  | D] } | | k rV | ^ qV ƒ g  | D] } | j | ƒ ^ q| } t | | ƒ S(   s”  
    Parse indexed expression into a form useful for code generation.

    Examples
    ========

    >>> from sympy.codegen.array_utils import parse_indexed_expression
    >>> from sympy import MatrixSymbol, Sum, symbols
    >>> from sympy.combinatorics import Permutation
    >>> Permutation.print_cyclic = True

    >>> i, j, k, d = symbols("i j k d")
    >>> M = MatrixSymbol("M", d, d)
    >>> N = MatrixSymbol("N", d, d)

    Recognize the trace in summation form:

    >>> expr = Sum(M[i, i], (i, 0, d-1))
    >>> parse_indexed_expression(expr)
    CodegenArrayContraction(M, (0, 1))

    Recognize the extraction of the diagonal by using the same index `i` on
    both axes of the matrix:

    >>> expr = M[i, i]
    >>> parse_indexed_expression(expr)
    CodegenArrayDiagonal(M, (0, 1))

    This function can help perform the transformation expressed in two
    different mathematical notations as:

    `\sum_{j=0}^{N-1} A_{i,j} B_{j,k} \Longrightarrow \mathbf{A}\cdot \mathbf{B}`

    Recognize the matrix multiplication in summation form:

    >>> expr = Sum(M[i, j]*N[j, k], (j, 0, d-1))
    >>> parse_indexed_expression(expr)
    CodegenArrayContraction(CodegenArrayTensorProduct(M, N), (1, 2))

    Specify that ``k`` has to be the starting index:

    >>> parse_indexed_expression(expr, first_indices=[k])
    CodegenArrayPermuteDims(CodegenArrayContraction(CodegenArrayTensorProduct(M, N), (1, 2)), (0 1))
    (   R«   t   removet   extendRc   R~   (   R;   t   first_indicest   resultR­   R&   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   parse_indexed_expression#  s    .,"c         C   s-   t  |  t ƒ r t St  |  t ƒ r) |  j St S(   N(   R.   R”   t   TrueR“   t   multiple_linest   False(   R;   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   _has_multiple_lines]  s
    R“   c           B   s;   e  Z d  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   s<   
    Class to help parsing matrix multiplication lines.
    c         C   sD   | |  _  | |  _ t d „  | Dƒ ƒ r1 t } n t } | |  _ d  S(   Nc         s   s   |  ] } t  | ƒ Vq d  S(   N(   RÈ   (   R%   Rd   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>l  s    (   t   operatorRZ   R*   RÅ   RÇ   RÆ   (   R   RÉ   RZ   RÆ   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   __init__i  s    			c         C   s   |  j  t k r d Sd S(   Ni    i   (   RÉ   R   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR]   r  s    c         C   sq   |  j  } | t k r d } n5 | t k r3 d } n  | j } d | t |  j ƒ f Sd | j d „  |  j Dƒ ƒ S(   Nt   *t   +s   _RecognizeMatOp(%s, %s)s   _RecognizeMatOp(%s)c         s   s   |  ] } t  | ƒ Vq d  S(   N(   t   repr(   R%   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>  s    (   RÉ   R   R   R    RÍ   RZ   t   join(   R   t   opt   s(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   __repr__x  s    				c         C   sI   t  | t |  ƒ ƒ s t S|  j | j k r/ t S|  j | j k rE t St S(   N(   R.   t   typeRÇ   RÉ   RZ   RÅ   (   R   t   other(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   __eq__ƒ  s    c         C   s   t  |  j ƒ S(   N(   t   iterRZ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   __iter__Œ  s    (   R    R!   Rt   RÊ   R]   RÑ   RÔ   RÖ   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR“   e  s   						R”   c           B   s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   sB   
    This class handles multiple parsed multiplication lines.
    c         C   s*   t  | ƒ d k r | d St j |  | ƒ S(   Ni   i    (   R-   RT   R0   (   R:   RZ   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR0   ”  s    c         C   s/   t  d „  g  |  D] } t | ƒ ^ q t j ƒ S(   Nc         S   s   |  | S(   N(    (   R`   t   y(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   š  Rb   (   R    RE   R   t   One(   R   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR]   ™  s    c         C   s   d t  t |  ƒ j ƒ  S(   Ns   _RecognizeMatMulLines(%s)(   t   superR”   RÑ   (   R   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRÑ   œ  s    (   R    R!   Rt   R0   R]   RÑ   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyR”     s   		c            s,  t  | t ƒ s | g } n  g  | D] } t | ƒ ^ q" } t d „  g  t | | ƒ D] \ } } | d k rS | ^ qS t j ƒ } t | ƒ } t | |  Œ } g  |  D] } | D] }	 |	 ^ q¬ q¢ ‰  t	 | ƒ }
 ‡  f d †  t
 |
 ƒ Dƒ } g  } x
| rû| r?t | j ƒ  d d „  ƒ\ } } | j | ƒ | | \ } } n d  } t | ƒ } d } | | } } g  } d  } xOt rÁ| | } | d k r¤t t | g ƒ } n  | j | ƒ | | k rÁPn  d | } | j | ƒ } | | k r8| r.g  | j ƒ  D]( \ } }	 | |	 | | f k rù| ^ qùd } n d  } Pn  t | ƒ d k rYt d ƒ ‚ n  | | \ } } | | k rst | ƒ d k r¨t t t t | ƒ g ƒ g } n t t | ƒ g } PqsqsW| j | d  ƒ | j | d  ƒ | j t t | ƒ ƒ qò W| d k r"| d j j d | ƒ n  t | ƒ S(	   Nc         S   s   |  | S(   N(    (   R`   R×   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   ¤  Rb   i    c            s%   i  |  ] } | ˆ  k r | | “ q S(    (    (   R%   R&   (   t   flatten_contractions(    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys
   <dictcomp>ª  s   	 R_   c         S   s   |  d S(   Ni   (    (   R`   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   ®  Rb   i   i   s    not a matrix multiplication line(   R.   RT   RE   R    Rg   R   RØ   R2   Rn   R   R4   R›   Ry   t   popRx   RÅ   R“   R   Ro   R-   R\   R   R   RZ   t   insertR”   (   R(   RZ   R&   R   Rd   t   srankt   coeffRP   R•   R)   RH   R?   t   return_listt   first_indext   starting_argindt   starting_post   current_argindt   current_post   matmul_argst
   last_indext   elemt	   other_post	   link_dict(    (   RÚ   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   _support_function_tp1_recognize   sb    F&	!	

B!c         C   s   t  |  ƒ } t | ƒ S(   sD	  
    Recognize matrix expressions in codegen objects.

    If more than one matrix multiplication line have been detected, return a
    list with the matrix expressions.

    Examples
    ========

    >>> from sympy import MatrixSymbol, MatrixExpr, Sum, Symbol
    >>> from sympy.abc import i, j, k, l, N
    >>> from sympy.codegen.array_utils import CodegenArrayContraction, CodegenArrayTensorProduct
    >>> from sympy.codegen.array_utils import recognize_matrix_expression, parse_indexed_expression
    >>> A = MatrixSymbol("A", N, N)
    >>> B = MatrixSymbol("B", N, N)
    >>> C = MatrixSymbol("C", N, N)
    >>> D = MatrixSymbol("D", N, N)

    >>> expr = Sum(A[i, j]*B[j, k], (j, 0, N-1))
    >>> cg = parse_indexed_expression(expr)
    >>> recognize_matrix_expression(cg)
    A*B
    >>> cg = parse_indexed_expression(expr, first_indices=[k])
    >>> recognize_matrix_expression(cg)
    (A*B).T

    Transposition is detected:

    >>> expr = Sum(A[j, i]*B[j, k], (j, 0, N-1))
    >>> cg = parse_indexed_expression(expr)
    >>> recognize_matrix_expression(cg)
    A.T*B
    >>> cg = parse_indexed_expression(expr, first_indices=[k])
    >>> recognize_matrix_expression(cg)
    (A.T*B).T

    Detect the trace:

    >>> expr = Sum(A[i, i], (i, 0, N-1))
    >>> cg = parse_indexed_expression(expr)
    >>> recognize_matrix_expression(cg)
    Trace(A)

    Recognize some more complex traces:
    >>> expr = Sum(A[i, j]*B[j, i], (i, 0, N-1), (j, 0, N-1))
    >>> cg = parse_indexed_expression(expr)
    >>> recognize_matrix_expression(cg)
    Trace(A*B)

    More complicated expressions:

    >>> expr = Sum(A[i, j]*B[k, j]*A[l, k], (j, 0, N-1), (k, 0, N-1))
    >>> cg = parse_indexed_expression(expr)
    >>> recognize_matrix_expression(cg)
    A*B.T*A.T

    Expressions constructed from matrix expressions do not contain literal
    indices, the positions of free indices are returned instead:

    >>> expr = A*B
    >>> cg = CodegenArrayContraction.from_MatMul(expr)
    >>> recognize_matrix_expression(cg)
    A*B

    If more than one line of matrix multiplications is detected, return
    separate matrix multiplication factors:

    >>> cg = CodegenArrayContraction(CodegenArrayTensorProduct(A, B, C, D), (1, 2), (5, 6))
    >>> recognize_matrix_expression(cg)
    [A*B, C*D]

    The two lines have free indices at axes 0, 3 and 4, 7, respectively.
    (   t   _recognize_matrix_expressiont   _unfold_recognized_expr(   R;   t   rec(    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   recognize_matrix_expressionÝ  s    Kc      
      s-  t  |  t ƒ r® t |  j ƒ } |  j } t  | t ƒ r‚ | j t k r‚ g  } x' | j D] } | j	 t
 | | ƒ ƒ qU Wt t | ƒ St  | t ƒ rž t
 | | ƒ St
 | | g ƒ St  |  t ƒ r÷ g  } x$ |  j D] } | j	 t | ƒ ƒ qÍ Wt t | ƒ St  |  t t f ƒ r|  St  |  t ƒ rÄ|  j j d d d g k rTt t t |  j ƒ g ƒ St  |  j t ƒ r»|  j j } g  t t | ƒ ƒ D] } |  j | ƒ ^ q…} g  }	 d }
 x0 | D]( } |	 j	 | |
 |
 | !ƒ |
 | 7}
 q³Wg  } x™ t |	 |  j j ƒ D]‚ \ } } | t | ƒ k r9| j	 t | ƒ | d f ƒ qût | ƒ d k rw| j	 t t t | ƒ g ƒ | d f ƒ qût ‚ qûW| j d d „  ƒ g  | D] } | d ^ q›} t | ƒ St ‚ net  |  t ƒ rg  |  j D] } t | ƒ ^ qÝ} g  | D] } t | ƒ ^ qü‰  t ˆ  ƒ rùt ‡  f d †  t | ƒ Dƒ ƒ rKt ‚ n  g  t | ƒ D]( \ } } ˆ  | rw| j n | g ^ qX} t j | Œ  } t t g  | D]J } t g  | D]1 } t  | t ƒ rÍ| n | g D] } | ^ qÔq²ƒ ^ q¢ƒ } | St | ƒ St  |  t ƒ r|  St  |  t  ƒ r)|  S|  S(   Ni    i   i   R_   c         S   s   |  d S(   Ni   (    (   R`   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRa   R  Rb   c         3   s.   |  ]$ \ } } ˆ  | r | j  t k Vq d  S(   N(   RÉ   R   (   R%   R&   t   a(   RÆ   (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pys	   <genexpr>[  s    (!   R.   R#   Rë   R;   R(   R“   RÉ   R   RZ   Ro   Rê   R”   R}   R   R   R~   R   R   R[   R   R4   R   Rg   Rf   R-   R\   RD   RÈ   R*   R9   t	   itertoolst   productR   (   R;   RZ   R(   t   addendsRd   t   add_argsRV   R&   t   newranget   newposRA   R]   Rº   t   post   expand_argst   itR)   RR   t   ret(    (   RÆ   s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRë   ,  sp    	." ,

	""	;`
c         C   sl   t  |  t ƒ r8 |  j g  |  j D] } t | ƒ ^ q Œ  St  |  t ƒ rd g  |  D] } t | ƒ ^ qN S|  Sd  S(   N(   R.   R“   RÉ   RZ   Rì   R”   (   R;   R&   (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyRì   i  s
    )(@   Rð   t	   functoolsR    t   collectionsR   t   sympyR   R   R   R   R   R   R   R€   R	   t   sympy.core.basicR
   t   sympy.core.compatibilityR   R   t   sympy.core.mulR   t   sympy.core.sympifyR   t(   sympy.functions.special.tensor_functionsR   t   sympy.matrices.expressionsR   R   R   R   R   t"   sympy.matrices.expressions.matexprR   R   t   sympy.tensor.arrayR   R   R#   Rw   R[   R}   R~   RŒ   R   RE   R1   R2   Rn   R,   R£   R¨   R«   R¿   RÄ   RÈ   t   objectR“   RT   R”   Rê   Rî   Rë   Rì   (    (    (    s8   lib/python2.7/site-packages/sympy/codegen/array_utils.pyt   <module>   sL   4()ÿ 	)o	K										s	:	+	=	O	=