
Xc           @` s  d  d l  m Z m Z m Z d  d l m Z d  d l Z d  d l Z d  d l Z d  d l	 Z	 d  d l
 Z
 d  d l Z d  d l Z d  d l Z d  d l m Z m Z d  d l m Z m Z 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 d  d	 l m Z 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* d  d l+ m, Z, m- Z- m. Z. m/ Z/ m0 Z0 m1 Z1 m2 Z2 m3 Z3 m4 Z4 m5 Z5 m6 Z6 d  d l m7 Z7 d  d l8 m9 Z9 d  d l: m9 Z; d  d l m< Z< d  d l= m> Z> m? Z? d  d l@ mA ZA mB ZB mC ZC d  d l mD ZD mE ZE mF ZF d  d l mG ZG d  d lH mI ZI mJ ZJ mK ZK mL ZL mM ZM mN ZN d  d l mO ZO e jP d  ZQ d   ZR d   ZS d   ZT eU eV d  ZW eX d  ZY d eD f d      YZZ eZ e; j)  Z[ e< j\ j] d! e[ d" d# d$ d% d&  d'   Z^ d(   Z_ d)   Z` d*   Za d+   Zb d,   Zc e_ e` e jd e; je g  d-      Zf d.   Zg d/   Zh e jd e* g  d0    Zi e_ e jd eN g  d1     Zj e_ e jd e* g  d2     Zk e_ ei  ea ei  e_ ea e jd e; jl g  d3      Zm e_ ea e jd e; jn g  d4      Zo d5 e; jp f d6     YZq eq   Zr d7 f  d8     YZs e; jt ju eq es    d9 ev f d:     YZw d; eD f d<     YZx d= eD f d>     YZy e j< jz j\ j] d? ex   d@ d% dA  e j< jz j\ j] dB ey   dC  dD   Z{ ea e jd e; j) g  e{ e; j) e; jI e; j*   dE  Z| e jd e; j) g  dF    Z} e_ e}  ea e` e jd e; j~ g  dG      Z e< j\ j] dH e! e  dI d%  e< j\ j] dJ e! e|  dK d%  e_ dA  e^ e jd e; j~ g  dL      Z ea e` e_ e^ e jd e; j g  dM        Z ea e` e_ e jd e; j g  dN       Z e jd e; j g  dO    Z e< j\ j] dP e! e  dQ dR  ea e_ e jd e; j> g  dS      Z ea e_ e jd eX  dT      Z ea e_ e jd e. g  dU      Z ea e_ e jd e. g  dV      Z ea e_ dW  e^ e jd e. e3 g  dX       Z e^ e_ dA  ea e jd e; j) g  dY       Z ea e jd e; j) g  dZ     Z e_ ea e jd e; j) g  d[      Z e_ ea e jd e; j) g  d\      Z d]   Z d^ e; jp f d_     YZ e   Z e Z ea e jd e g  d`     Z e jd e g  da    Z e< j\ db j] dc e dd de eV e< j\ df j] dc e dd de eV e< j\ dg j] dc e dd de eV e< j\ dh j] dc e dd de eV e_ e jd e; j) g  di     Z e^ e_ ea e jd e/ g  dj       Z e_ e jd e1 g  dk     Z e^ e_ ea e jd e. g  dl       Z e_ ea e jd e. e3 g  dm      Z e_ dA  e jd e. g  dn     Z do   Z e_ ea e jd e. g  dp      Z e^ e_ ea e jd e. g  dq       Z e_ e` ea e jd e. g  dr       Z e_ e jd e; j g  ds     Z e< j\ j] dt e! e  du d%  e jd e/ g d& eU dv    Z e< j\ j] dw e e dx e j dy d% d&  e jd e1 g d& eU dz    Z e< j\ j] d{ e e dx e j dy d% d&  e_ d|  e` d|  e jd e/ e2 e1 g  d}      Z e_ d~  e` d~  e jd e/ g  d      Z e_ e` e jd e3 g  d      Z ea e` e_ e^ e jd e/ e2 e1 g  d        Z e^ e_ ea e jd e; j g  d       Z e_ ea e jd e; j g  d      Z d   Z ea e_ e^ e jd e; j g  d       Z e^ ea e_ e jd e; j g  d       Z ea e_ e^ e jd e; j g  d       Z e_ ea e jd e; j j g  d      Z e` ea e_ e jd e; j) g  d       Z e^ d  e_ dA d  ea e jd e; j) g  d       Z ea e_ e jd e; j g  d      Z e_ e jd e; j e; j g  d     Z e_ e jd e; j) g  d     Z e^ e_ e` e jd e; j g  d       Z e^ e_ ea e jd e; j g  d       Z e_ e` e jd e; j g  d      Z d   Z e_ e e; jN  d d e^ e_ e` e jd e; jN g  d       Z e_ e jd e; jN g  d     Z e_ e` e jd e; jN g  d      Z e_ e j e; j  d d d e j f d     YZ eV eX d  Z e e; j e; j e; j e eV  Z e_ e d d e jd e; j g  d    Z e_ e  ea e jd e; j e; j j g  d     Z ea e jd e; j) g  d     Z e^ ea e` e_ e jd e; j) g  d        Z e_ ea e jd e; j e; j j g  d      Z e_ e jd e; j e; j j g  d     Z e_ e jd e; j e; j j g  d     Z e; j j e; j j e; j j e; j j e; j j e; j j g Z e_ eb e jd e  d      Z e_ dA d  e^ d  e jd e  d      Z e_ eb ea e jd e  d       Z ea e jd e; j e; j j g  d     Z ea e jd e; j g  d     Z ea e jd e; j g  d     Z e jd e; j g  d    Z e_ e  e jd e; j g  d    Z ea e  e jd e; j g  d    Z e_ e  e jd e; j g  d    Z e_ e  ea e jd e; j g  d     Z e_ e jd e; j g  d     Z e_ ea e jd e; j e; j g  d      Z e jd e; j g  d    Z ea e  ec e jd e; j g  d     Z e jd e; j g  d    Z ea e  e jd e; j g  d    Z ea e  e! e j e e} d eU d d Z d   Z e j e d  e_ e jd e; j g  d     Z ea e jd e; j e; j g  d     Z e` ea e jd e; j g  d      Z e` ea e jd e; j g  d      Z e jd e; j g  d    Z e< j\ j] d e! e d eU d d%  eV eX d  Z e e; j e; j e; j e  Z e! e j e e} d eU d d Z e_ e d d d  d  Z d   Z e_ e` e jd e; j e; j e; j g  d      Z e jd eX  d    Z e! e d eU d d Z e_ e dA d eU eb e dA d eU e` e dA d eU ea e dA d eU d   Z d   Ze je; j d e; jd f f e; je; j d f f d eU d d d e; jg d e Ze_ e e` e ea e e je; j d e; jd f f e; jd f d eU d d Ze_ e e` e ea e e je; j d e; j d e; jd f f f e; jd f d eU d d Ze_ e e` e ea e e je; j d e; j e; jd f f f e; jd f d eU d d d e; jg d eZe_ e e` e ea e e je; j d e; jd f f e; j e; jd f f d eU d d d e; jg d e Z	e_ e	 e` e	 ea e	 e je; j d e; jd f f e; jd f d eU d d d e; jg d e Z
e_ e
 e` e
 ea e
 e je; j d e; j e; jd f f f e; jd f d eU d d d e; jg d eZe_ e e` e ea e e je; j d e; j d e; jd f f f e; jd f d eU d d d e; jg d eZe_ e e` e ea e e je; j d e; j e; jd f f f e; jd f d eU d d d e; jg d eZe_ e e` e ea e e je; j d e; je; j d f f f e; jd f d eU d d d e; jg d e Ze_ e e` e ea e e je; j d e; je; j d d f f f e; jd f d eU d d d e; jg d e Ze_ e e` e ea e e` ea e jd e; j g  d      Ze` ea e jd e; j g  d      Zd   eX d  Zd   Zee; j) e Zd eD f d     YZd   Ze' jjreQ jd  e j  Zej] d ee d  d% d  ej] d ee d d% d  e< j\ j] d ed d% d d d  n2 eQ jd  e< j\ j] d ee d d d d  e_ e jd e) g  d     Ze_ e j e jj dA d% d d e_ e j e jj dA d% d d e_ e j e jj dA d% d d e_ e jd e jj g  d     Z!e^ e_ e` ea e jd e; jI g  d        Z"d S(   i    (   t   absolute_importt   print_functiont   division(   t   defaultdictN(   t   integer_typest	   iteritems(   t   reducet   xrange(   t   gof(   t   izip(   t   optt   InconsistencyErrort   TopoOptimizert   graph(   t   Variablet   Constant(   t   copy_stack_tracet   in2out(   t   MethodNotDefined(   t   DisconnectedType(   t   config(   t   Elemwiset
   DimShuffle(   t   get_idx_listt   get_canonical_form_slicet	   Subtensort   IncSubtensort   make_constantt   AdvancedIncSubtensor1t   AdvancedIncSubtensort   AdvancedSubtensor1t   advanced_subtensort   advanced_subtensor1t   advanced_inc_subtensor1(   t   scalar(   t   basic(   t   compile(   t   Shapet   Shape_i(   t   values_eq_approx_remove_inft   values_eq_approx_remove_nant   values_eq_approx_remove_inf_nan(   t	   Optimizert   pre_constant_merget   pre_greedy_local_optimizer(   t   toolbox(   t   Alloct   get_scalar_constant_valuet
   ShapeErrort   extract_constantt   NotScalarConstantErrort   Reshape(   t   StringIOs   theano.tensor.optc         C` s*   x  | D] } t  j | |   }  q W|  g S(   N(   t   Tt   fill(   t   new_outt   orig_inputst   i(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   _fill_chain=   s    c         C` sK   t  |   t  |  k  r t S|  t  |  }  t d   t |  |  D  S(   sB  

    Parameters
    ----------
    b1
        The broadcastable attribute of a tensor type.
    b2
        The broadcastable attribute of a tensor type.

    Returns
    -------
    bool
        True if the broadcastable patterns b1 and b2 are such that b2 is
        broadcasted to b1's shape and not the opposite.

    c         s` s"   |  ] \ } } | o | Vq d  S(   N(    (   t   .0t   v1t   v2(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>W   s    (   t   lent   Falset   anyt   zip(   t   b1t   b2(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   encompasses_broadcastableC   s    c         C` s#   g  t  |    D] } t |  ^ q S(   N(   RA   t   all(   t   broadcastablest   bcast(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   merge_broadcastablesZ   s    c         C` s   g  } g  } g  } xe |  D]] } y6 t  | d | d | } | j |  | j |  Wq t k
 ru | j |  q Xq W| | | f S(   sQ   Partition a list of variables into two kinds:
    scalar constants, and the rest.t   elemwiset   only_process_constants(   R/   t   appendR2   (   t   inputsRI   RJ   t   constst
   origconstst	   nonconstsR9   t   v(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   scalarconsts_rest^   s    	c         C` s  t  j |   }  |  j | j k r% |  S| | j k rC t d   n  | d k r[ | j } n  t  j |  |  }  |  j | j k r |  St | d  r | j	 j
 | } n	 | j } t  j |  |  } | j | j k rt  j | g  t | j  D]' } | j | r | j | r | ^ q  } n  | j j | k s6t  | j j | j k r{t d t | j j  d t | j    n  | S(   s   
    Return a Variable with the same shape and dtype as the template,
    filled by broadcasting value through it. `value` will be cast as
    necessary.

    sS   broadcast_like currently requires the template Variable to be in the fgraph alreadyt   shape_features   rval.type.broadcastable is s    but template.broadcastable isN(   R5   t   as_tensor_variablet   typet	   variablest   NotImplementedErrort   Nonet   dtypet   castt   hasattrRR   t   shape_oft   shapet   alloct   broadcastablet   unbroadcastR   t   ndimt   AssertionErrort   str(   t   valuet   templatet   fgraphRX   t	   new_shapet   rvalR9   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   broadcast_likeo   s0    	 t   InplaceElemwiseOptimizerc           B` sP   e  Z d  Z d   Z d   Z e d d   Z d   Z e j	 d d d  Z
 RS(   sL   
    We parametrise it to make it work for Elemwise and GpuElemwise op.
    c         C` s   | |  _  d  S(   N(   t   op(   t   selft   OP(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   __init__   s    c         C` s   | j  t j j j    d  S(   N(   t   attach_featuret   theanoR   t   destroyhandlert   DestroyHandler(   Rk   Re   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   add_requirements   s    i    c         C` s   d | } t  | d | d j d |  x4 d d d d g D]  } t  | | | | d |  q: W| d	 } | r t  | d	 d
 d |  x7 t | j    D]  } t  | | | | d |  q Wn  d  S(   Ns       s   InplaceElemwiseOptimizer R
   t   filet   node_beforet   nb_call_replacet   nb_call_validatet   nb_inconsistentR`   t   nb(   t   printRj   t   sortedt   keys(   t   streamt   proft   levelt   blanct   kR`   t   n(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   print_profile   s    

c   &   
   C` s%  i |  d 6t  | j  d 6d d 6d d 6d d 6t d    d 6} t j j } | d	 k r t  | j  d
 k rx d } q d } n  d } | j   } | j r g  | j D] } | j | ^ q } n g  } g  | j	 D]' } t
 | t j j j  r | j ^ q }	 t |	 g   }	 |	 j | j  xt t j | j | j   D]}
 |
 j } t |  |  j k sgq=n  | d k rt |
 j d j d d	  d k rq=n  | j r_| j } g  t t  |
 j   D] } | | k r| ^ q} g  t t  |
 j   D]_ } | | j   k rt
 |
 j | t  r| j |
 j |  r|
 j | |	 k r| ^ q} n g  } t t t  |
 j    } g  t t  |
 j   D]M } t
 |
 j | t  r| j |
 j |  r|
 j | |	 k r| ^ q} t } | } x| D]} |
 j | } | } | | k rSg  } x\ t  | j  D]K \ } } | | k r8| | j k r8| j | } | j! | j |  q8q8Wg  } g  } g  } x | D] } |
 j | } | | k r| j! |  qt" | d  r1| j# r1t$ g  | D]' } | j% j& j' | d  | j# k ^ q r1| j! |  q| j! |  qW| | | } n  xi| D]a} |
 j | j |
 j | j k rqZn  t) |  } | | | <yt" | j* d  r | j* j+ t, j- g  t  |
 j  D]! \ } } | j' | | j.  ^ q   }  nI | j* j/ t, j- g  t t  |
 j   D] } | j' | d  ^ q%   }  |  j |  |  |
 j t) d t0    }! |! d j# }" xF t1 |
 j |!  D]2 \ }# }$ | d c d 7<| j2 |# |$ d d qW| d 7} | d | j3 c d 7<| | k r"| d c d 7<| j4   | j   } d } n  Wn{ t5 t6 f k
 r}% | d c d 7<| d k r| rt7 d d t8 j9 t7 |% d t8 j9 t0 } n  | j: |  qZn X| j; |  |" }
 | } PqZWqWq=W| d k r!y | j4   Wq!t< k
 r| st7 d d t8 j9 n  | j: |  q!Xn  | S(   s0  
        Usage: InplaceElemwiseOptimizer(op).optimize(fgraph)

        Attempts to replace all Broadcast ops by versions of them
        that operate inplace. It operates greedily: for each Broadcast
        Op that is encountered, for each output, tries each input to
        see if it can operate inplace on that input. If so, makes the
        change and go to the next output or Broadcast Op.

        Examples
        --------

            `x + y + z -> x += y += z`

            `(x + y) * (x * y) -> (x += y) *= (x * y) or (x + y) *= (x *= y)`

        R
   Rt   i    Ru   Rv   Rw   c           S` s   d S(   Ni    (    (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   <lambda>   s    R`   ii  i
   i   t   destroy_handlert   make_new_inplacet   return_listt   reasont   inplace_elemwise_optimizersD   Some inplace optimization was not performed due to unexpected error:Rs   sC   Some inplace optimization was not performed due to unexpected errorN(=   R>   t   apply_nodesR   R   t   tensort$   insert_inplace_optimizer_validate_nbt
   checkpointt   update_mappingt   outputst	   _featurest
   isinstanceRo   R$   t   function_modulet
   Supervisort	   protectedt   sumt   extendt   listR   t   io_toposortRL   Rj   RT   t   getattrt   inplace_patternR   t   valuesR   t
   destroyerst   rangeR?   t	   enumerateRK   RZ   t   ownerR@   R   t   root_destroyert   getRW   t   dictt	   scalar_opR   R"   t   transfer_typeRX   t	   __class__t   TrueRA   t   replaceR`   t   validatet
   ValueErrorR   Ry   t   syst   stderrt   revertt   removet	   Exception(&   Rk   Re   R}   t   check_each_changet   nb_change_no_validatet   chkR9   t   update_outst   ft   protected_inputst   nodeRj   t   baselinet   candidate_outputst   candidate_inputst   verboset   raised_warningt   candidate_outputt   candidate_out_vart   sorted_candidate_inputst   updated_inputst   f_outt   updated_inp_idxt   updated_varst   vars_from_inplacet
   other_varst   inp_idxt   inpt   up_inpt   candidate_inputR   t   ot   new_scalt   new_outputst   new_nodet   rt   new_rt   e(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   apply   s    &
			&'%	"		"	4
	=	7

	
		ic         C` s.   t  d d | |  j j |  j f d | t S(   Ns	   %s%s (%s)t    Rs   (   Ry   R   t   __name__Rj   R   (   Rk   R|   R~   t   depth(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   print_summary  s    $(   R   t
   __module__t   __doc__Rm   Rr   t   staticmethodR   R   R   t   stdoutR   (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRi      s   			t   inplace_elemwise_optiK   t   inplace_optR   t   fast_runt   inplacec         ` sp   t    t k r+     f d   } | S  j d d   pC  j } t j j j |  d d      Sd  S(   Nc         ` s   t  |       S(   N(   t   register_useless(   t
   inner_lopt(   t   kwargst   loptt   tags(    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   register  s    t   namet   lastR   (	   RT   Rb   t   popRW   R   R$   t   modet   local_uselessR   (   R   R   R   R   R   (    (   R   R   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    
c         ` sn   t    t k r+     f d   } | S  j d d   pC  j } t j d j |  d      Sd  S(   Nc         ` s   t  |       S(   N(   t   register_canonicalize(   R   (   R   R   R   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    R   t   canonicalizeR   (   RT   Rb   R   RW   R   R$   t   optdbR   (   R   R   R   R   R   (    (   R   R   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    
c         ` sn   t    t k r+     f d   } | S  j d d   pC  j } t j d j |  d      Sd  S(   Nc         ` s   t  |       S(   N(   t   register_stabilize(   R   (   R   R   R   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    R   t	   stabilizeR   (   RT   Rb   R   RW   R   R$   R   R   (   R   R   R   R   R   (    (   R   R   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    
c         ` sn   t    t k r+     f d   } | S  j d d   pC  j } t j d j |  d      Sd  S(   Nc         ` s   t  |       S(   N(   t   register_specialize(   R   (   R   R   R   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    R   t
   specializeR   (   RT   Rb   R   RW   R   R$   R   R   (   R   R   R   R   R   (    (   R   R   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    
c         ` st   t    t k r+     f d   } | S  rC   j d d   pI  j } t j d j |  d      Sd  S(   Nc         ` s   t  |       S(   N(   t   register_uncanonicalize(   R   (   R   R   R   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    R   t   uncanonicalizeR   (   RT   Rb   R   RW   R   R$   R   R   (   R   R   R   R   R   (    (   R   R   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    !c         ` st   t    t k r+     f d   } | S  rC   j d d   pI  j } t j d j |  d      Sd  S(   Nc         ` s   t  |       S(   N(   t   register_specialize_device(   R   (   R   R   R   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    R   t   specialize_deviceR   (   RT   Rb   R   RW   R   R$   R   R   (   R   R   R   R   R   (    (   R   R   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    !c         C` sn  t  |  j t j  s t S|  j d } |  j d } t } y% t | d t d k r] t } n  Wn t k
 rq n Xy% t | d t d k r t } n  Wn t k
 r n X| rjt j	 d d |  j
 d j j } | j d k r>| j d k r>t | t j | j d | j d   } t j | | j d | j d  g S| j d k r| j d k rt | t j | j d | j d   } t j | | j d  g S| j d k r | j d k r t | t j | j d | j d   } t j | | j d  g S| j d k rN| j d k rNt | t j | j d | j d   } | g St j d | j | j  n  d  S(   Ni    i   RJ   RX   i   s   Optimization Warning: Optimization theano/opt.py:local_0_dot_x Found that it could apply, but was not implemented for dot product with these input types:
(%s, %s)(   R   Rj   R5   t   DotR?   RL   R/   R   R2   t   constantR   RT   RX   R`   t   assert_t   eqR\   R]   t   _loggert   warning(   R   t   xt   yR   t   constant_zero(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_0_dot_x  sF    "#$###	c         C` s1   |  j  s |  St j |  j   } | r- | d S|  S(   Ni    (   R   t   local_dimshuffle_liftt	   transform(   t   vart   new(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   apply_local_dimshuffle_lift  s    	c         C` s   t  } t |   | j j k r g  t | j j  D] \ } } | r1 | ^ q1 d g } x_ t | j j  D]B } |  | | k s | | k r |  | | k r t  } qi t } Pqi Wn t } | S(   NR   (   R   R>   RT   R`   R   R^   R   R?   (   t	   new_ordert   inputt
   is_uselessR9   t   is_broadcastablet   all_broadcastable_dims(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   is_dimshuffle_useless-  s    	c   
      C` s  |  j  } t | t  s t S|  j d } | j } | j } | r t | j  t  r t | j	  d k r g  } xE | j D]: } | j
 | j j | j  |  } | j t |   qx Wt |  j d |  | j  | t d t    } | S| rFt | j  t  rFg  | D]( }	 |	 d k r d p-| j  j |	 ^ q} | j d } n  t | |  r\| g S| rt | j  t  r| j
 | j j |  |  } t |  } t |  j d |  | g Sd S(   s  
    "Lifts" DimShuffle through Elemwise operations and merges
    consecutive DimShuffles. Basically, applies the following
    transformations on the whole graph:

    DimShuffle(Elemwise(x, y)) => Elemwise(DimShuffle(x), DimShuffle(y))
    DimShuffle(DimShuffle(x)) => DimShuffle(x)
    DimShuffle{0,1,...}(x) => x (when the dimshuffle do nothing)

    After this transform, clusters of Elemwise operations are
    void of DimShuffle operations.

    i    i   R   R   N(   Rj   R   R   R?   RL   R   R   R   R>   t   clientsR   RT   R^   RK   R   R   R   R   R   R  (
   R   Rj   R  t   inodeR   t
   new_inputsR   t   new_inpt   retR   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR   @  s4    			-2c   
      ` sK  |  j  } t | t  s t S|  j d j d k	 oK t |  j d j j  t  sR t S|  j d j j  j } |  j d j j d } |  j d j	 } g    x3 t
 | |  D]" \ } } | s   j |  q q Wt   f d   t t    d  D  } | rG|  j d } | j |  j d j  | |  }	 t |  j d |	  |	 g Sd S(   sO  
    Removes useless DimShuffle operation inside Reshape:

      reshape(vector.dimshuffle('x', 0), shp) => reshape(vector, shp)
      reshape(matrix.dimshuffle('x', 0, 'x', 1), shp) => reshape(matrix, shp)
      reshape(row.dimshuffle(1, 'x'), shp) => reshape(row, shp)
      reshape(col.dimshuffle(0), shp) => reshape(col, shp)

    i    c         3` s'   |  ] }   |   | d  k Vq d S(   i   N(    (   R;   R9   (   t   new_order_of_nonbroadcast(    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s   i   N(   Rj   R   R3   R?   RL   R   RW   R   R   R^   RA   RK   RE   R   R>   R   R   R`   R   (
   R   Rj   R   R  RF   R9   t   bdt   no_change_in_orderR\   R
  (    (   R  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt#   local_useless_dimshuffle_in_reshapen  s*    	"c         C` s   t  |  j t j  o$ |  j j d k s+ t S|  j d j oW t  |  j d j j t j  s^ t S|  j d j j \ } } | j	 | j	 k o d k n r t j
 | j | j  g } t |  j d |  | Sd S(   s  
    dot(x,y).T -> dot(y.T, x.T)

    These optimizations "lift" (propagate towards the inputs) DimShuffle
    through dot product.  It allows to put the graph in a more standard shape,
    and to later merge consecutive DimShuffles.

    The transformation should be apply whether or not the transpose is
    inplace.  The newly-introduced transpositions are not inplace, this will
    be taken care of in a later optimization phase.

    i   i    i   N(   i   i    (   R   Rj   R5   R   R   R?   RL   R   R   R`   t   dotR   (   R   R   R   R
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt    local_lift_transpose_through_dot  s    '"c         C` sa   t  |  j t j  r] |  j d } | j r] t  | j j t j  r] | j j d } | g Sn  d S(   s.   tensor_from_scalar(scalar_from_tensor(x)) -> xi    N(   R   Rj   R5   t   TensorFromScalarRL   R   t   ScalarFromTensor(   R   t   st   t(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_tensor_scalar_tensor  s
    !c         C` sa   t  |  j t j  r] |  j d } | j r] t  | j j t j  r] | j j d } | g Sn  d S(   s.   scalar_from_tensor(tensor_from_scalar(x)) -> xi    N(   R   Rj   R5   R  RL   R   R  (   R   R  R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_scalar_tensor_scalar  s
    !t
   MakeVectorc           B` s_   e  Z d  Z d Z d d  Z d   Z d   Z d   Z d   Z d   Z	 d	   Z
 d
   Z RS(   s   Concatenate a number of scalars together into a vector.

    This is a simple version of stack() that introduces far less cruft
    into the graph. Should work with 0 inputs. The constant_folding
    optimization will remove it.

    RX   t   int64c         C` s   | |  _  d  S(   N(   RX   (   Rk   RX   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRm     s    c         ` s  t  t t j     t  f d    D  s] t   d k r( d j  j k r(t j j	  j g   D] } | j ^ qs       j k s t
 d   t    f d    D  s t d  j t g   D] } | j ^ q  f   n  g   D] } t j | d   ^ q n  t  f d    D  sJt
  t d    D  sft
   r d j j   n	  j   t } t j d	 | f d    } t j   |   g  S(
   Nc         3` s%   |  ] } | j    d  j  k Vq d S(   i    N(   RT   (   R;   t   a(   RL   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s    i    sP   The upcast of the inputs to MakeVector should match the dtype given in __init__.c         3` s0   |  ]& }  j  t j | d    j  k Vq d S(   RX   N(   RX   R5   RY   (   R;   R9   (   RX   Rk   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s   s=   MakeVector.make_node expected inputs upcastable to %s. got %sRX   c         3` s!   |  ] }   j  | j  k Vq d  S(   N(   RX   (   R;   R  (   Rk   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s    c         s` s   |  ] } | j  d  k Vq d S(   i    N(   R`   (   R;   R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s    R^   (   R   t   mapR5   RS   RE   R>   RX   Ro   R"   t   upcastRa   t	   TypeErrorRb   RY   RT   R?   t
   TensorTypet   Apply(   Rk   RL   R9   t	   bcastablet   otype(    (   RX   RL   Rk   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt	   make_node  s&    (.	2+"	c         C` sj   | \ } | d d  k s2 | d j t |  k rX t j | d | j d j | d <n | | d d <d  S(   Ni    RX   .(   RW   t   sizeR>   Ro   t   _asarrayR   RX   (   Rk   R   RL   t   out_t   out(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   perform  s    	)&c         C` s   d S(   Ni   (   i   (    (   Rk   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   c_code_cache_version  s    c         C` s   | \ } t  |  } t j | j d j  j } | j d j j   d }	 t  |  d k r |  j | j d j k s| t  d | d } n  d t	   }
 x+ t
 |  D] \ } } |
 d t	   7}
 q W|
 S(   Ni    i   s   PyArray_TYPE(%s)s   
        npy_intp dims[1];
        dims[0] = %(out_shape)s;
        if(!%(out)s || PyArray_DIMS(%(out)s)[0] != %(out_shape)s){
            Py_XDECREF(%(out)s);
            %(out)s = (PyArrayObject*)PyArray_EMPTY(1, dims, %(out_num)s, 0);
        }
        s{   
            *((%(out_dtype)s *)PyArray_GETPTR1(%(out)s, %(idx)s)) = *((%(out_dtype)s *) PyArray_DATA(%(i)s));
            (   R>   t   numpyRX   R   t   numRT   t   dtype_specsRL   Ra   t   localsR   (   Rk   R   R   R   R$  t   subR%  t	   out_shapet   out_numt	   out_dtypeR
  t   idxR9   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   c_code  s    		c         C` s   t  |  f g S(   N(   R>   (   Rk   R   t   ishapes(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   infer_shape*  s    c         C` s}   |  j  t j j k rA g  | D]! } | j   j t j j  ^ q Sg  } x/ t |  D]! \ } } | j	 | d |  qT W| S(   Ni    (
   RX   Ro   R   t   discrete_dtypest
   zeros_liket   astypeR   t   floatXR   RK   (   Rk   RL   t   output_gradientst   iptt   gradsR9   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   grad-  s    )c         C` s#   d  | k r d  g S|  j |   j S(   N(   RW   R!  R   (   Rk   RL   t   eval_points(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   R_op8  s    (   s   dtype(   R   R   R   t	   __props__Rm   R!  R&  R'  R1  R3  R;  R=  (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s   							t   MakeVectorPrinterc           B` s   e  Z d    Z RS(   c         C` s   | j  d  k r t d   n t | j  j t  r t | d d   } z8 d | _ g  | j  j D] } | j	 j
 |  ^ q^ } Wd  | | _ Xd d j |  St d   d  S(   Ns   Can only print make_vector.t
   precedencei  s   [%s]s   , (   R   RW   R  R   Rj   R  R   R@  RL   t   pprintert   processt   join(   Rk   R   t   pstatet   old_precedenceR  R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRB  A  s    	,
(   R   R   RB  (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR?  @  s   t   ShapeFeaturec           B` s   e  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z e	 d  Z
 d   Z d	   Z d
   Z d   Z d   Z d   Z d   Z d   Z d d d  Z RS(   s!  Graph optimizer for removing all calls to shape().

    This optimizer replaces all Shapes and Subtensors of Shapes with
    Shape_i and MakeVector Ops.

    This optimizer has several goals:

    1. to 'lift' Shapes to as close to the inputs as possible.

    2. to infer the shape of every node in the graph in terms of the
       input shapes.

    3. remove all fills (T.second, T.fill) from the graph

    Lifting shapes as close to the inputs as possible is important for
    canonicalization because it is very bad form to have to compute
    something just to know how big it will be.  Firstly, it is a waste
    of time to compute such outputs.  But it is important to get rid
    of these outputs as early as possible in the compilation process
    because the extra computations make it appear as if many internal
    graph nodes have multiple clients.  Many optimizations refuse to
    work on nodes with multiple clients.

    Lifting is done by using an `<Op>.infer_shape` function if one is
    present, or else using a conservative default.  An Op that
    supports shape-lifting should define a infer_shape(self, node,
    input_shapes) function.  The argument input_shapes is a tuple of
    tuples... there is an interior tuple for each input to the node.
    The tuple has as many elements as dimensions.  The element in
    position i of tuple j represents the i'th shape component of the
    j'th input.  The function should return a tuple of tuples.  One
    output tuple for each node.output.  Again, the i'th element of the
    j'th output tuple represents the output[j].shape[i] of the
    function.  If an output is not a TensorType, then None should be
    returned instead of a tuple for that output.

    For example the infer_shape for a matrix-matrix product would accept
    input_shapes=((x0,x1), (y0,y1)) and return ((x0, y1),).

    Inferring the shape of internal nodes in the graph is important
    for doing size-driven optimizations.  If we know how big various
    intermediate results will be, we can estimate the cost of many Ops
    accurately, and generate c-code that is specific [e.g. unrolled]
    to particular sizes.

    In cases where you cannot figure out the shape, raise a ShapeError.

    Notes
    -----
    Right now there is only the ConvOp that could really take
    advantage of this shape inference, but it is worth it even
    just for the ConvOp.  All that's necessary to do shape
    inference is 1) to mark shared inputs as having a particular
    shape, either via a .tag or some similar hacking; and 2) to
    add an optional In() argument to promise that inputs will
    have a certain shape (or even to have certain shapes in
    certain dimensions). We can't automatically infer the shape of
    shared variables as they can change of shape during the
    execution by default.  (NOT IMPLEMENTED YET, BUT IS IN TRAC)


    **Using Shape information in Optimizations**

    To use this shape information in OPTIMIZATIONS, use the
    ``shape_of`` dictionary.

    For example:

    .. code-block:: python

        try:
            shape_of = node.fgraph.shape_feature.shape_of
        except AttributeError:
            # This can happen when the mode doesn't include the ShapeFeature.
            return

        shape_of_output_zero = shape_of[node.output[0]]

    The ``shape_of_output_zero`` symbol will contain a tuple, whose
    elements are either integers or symbolic integers.

    TODO: check to see if the symbols are necessarily
    non-constant... or are integer literals sometimes Theano
    constants?? That would be confusing.

    c         C` s}  y | j  j } Wn t k
 r, |  j } n Xy0 | | g  | j D] } |  j | ^ q@  } Wnt k
 r |  j | g  | j D] } |  j | ^ q  } n t k
 r } t d |   n t k
 rx} d | j  g  | j D] } |  j | ^ q t	 |  t
 |  t j   f } t j d k r9t |   n t j |  |  j | g  | j D] } |  j | ^ qY } n X| S(   Ns   Code called by infer_shape failed raising a NotImplementedError. Raising NotImplementedError to indicate that a shape cannot be computed is no longer supported, and one should now use tensor.ShapeError instead. The original exception message is: %ss   Failed to infer_shape from Op %s.
Input shapes: %s
Exception encountered during infer_shape: %s
Exception message: %s
Traceback: %st   raise(   Rj   R3  t   AttributeErrort   default_infer_shapeRL   R[   R0   RV   R   RT   Rb   t	   tracebackt
   format_excR   t   on_shape_errorR   R   (   Rk   R   t   shape_inferR   t   o_shapesR   t   msg(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   get_node_infer_shape  s0    *&&"-c         C` s  |  j  | | } | j rt | j j t  r| j j d | j j k r| j sZ t  | j } x< | j D]1 } t	 | d d  d k rm |  j | d  qm qm W|  j |  } t |  t | j  k s t  x t | | j  D] \ } } t | d  sq n  t |  j  |  }	 t }
 xr t | j  D]a } |	 | } | j r/t | j j t  r/| j j d | j j k r/t }
 | | |	 | <q/q/W|
 r |  j | |	 d t q q W|  j  | | } n  | S(   s   Optimization can call this to get the current shape_i

        It is better to call this then use directly shape_of[var][idx]
        as this method should update shape_of if needed.

        TODO: Up to now, we don't update it in all cases. Update in all cases.
        i    R`   t   overrideN(   R[   R   R   Rj   R&   RL   Re   RU   Ra   R   RW   t	   get_shapeRP  R>   R   RA   RZ   R   R?   R   R`   R   t	   set_shape(   Rk   R   R0  R   R   R9   RN  t   new_shpsR%  t   merged_shpst   changedt   n_r(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRR    s6    		!
	c         C` sg   t  | j d  r) | j j | r) |  j St |  |  } y t |  } Wn t k
 r^ n X| Sd S(   s8   Return symbolic r.shape[i] for tensor variable r, int i.R^   N(   RZ   RT   R^   t   lscalar_oneR&   R/   R2   (   Rk   R9   R   R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   shape_ir  s    "c         C` sE   t  | d  s d St g  t | j  D] } |  j | |  ^ q&  S(   s<   Return a tuple of symbolic shape vars for tensor variable r.R`   N(   RZ   RW   t   tupleR   R`   RY  (   Rk   R   R9   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   shape_tuple  s    c         C` sY   g  } xL | j  D]A } y | j |  j |   Wq t k
 rP | j d  q Xq W| S(   s  Return a list of shape tuple or None for the outputs of node.

        This function is used for Ops that don't implement infer_shape.
        Ops that do implement infer_shape should use the i_shapes parameter,
        but this default implementation ignores it.

        N(   R   RK   R[  RH  RW   (   Rk   R   t   i_shapesRg   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRI  	  s    c         C` s  | d
 k	 s t  | d k r% |  j St |  t k rX t |  | k rX t |  } n  t |  t k s t | t j	  s t | t j
  r | j d k r | d k  r d } | t j j |  7} t |   n  t j | d d St |  t t f k rt |   n  | j r)t | j j t  r)| j j d j r)t | j j d j j t j  r)| j d k svt  t | j j j  d k st  t | j j | j j j  } t |  d k st  | d } y t |  } Wn t k
 rq)X| j j d j j d } |  j | | } n  | j j  t! j" j# k rlt$ | j d d  rht% d |   n  | St% d | t |  t$ | d	 d
    d
 S(   s   Return a symbolic integer scalar for the shape element s_i.

        The s_i argument was produced by the infer_shape() of an Op subclass.

        var: the variable that correspond to s_i. This is just for
        error reporting.

        i   i    s'   There is a negative shape in the graph!RX   R  R`   s   Shape element must be scalars   Unsupported shape elementRT   N(&   RW   Ra   RX  RT   t   floatt   intR   R   R(  t   integert   ndarrayR`   R   t   utilst   get_variable_trace_stringR   R5   R   RZ  R   RV   R   Rj   R   RL   R%   R>   t   idx_listR   R/   R2   R[   RX   Ro   R   t   integer_dtypesR   R  (   Rk   t   s_iR   RO  R0  R9   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   unpack  sH    
$!	"!
c         C` s  | s$ | |  j  k s$ t d   n  | d k r@ | |  j  | <nt | t t f  sm t d | | f   n  | j t |  k r t	   } t
 j j | d | d t t d t |  | j | j   f   n  g  } xi t | j  D]X } t | j d  r#| j j | r#| j |  j  q | j |  j | | |   q Wt g  t | j  D]_ } t | j d  p| j j | p|  j j | |  p|  j j t j | |   ^ qW st  t |  |  j  | <x- | D]% } |  j j | t    j |  qWd S(   s`  Assign the shape `s` to previously un-shaped variable `r`.

        Parameters
        ----------
        r : a variable
        s : None or a tuple of symbolic integers
        override : If False, it mean r is a new object in the fgraph.
            If True, it mean r is already in the fgraph and we want to
            override its shape.

        s   r already in shape_ofs   shapes must be tuple/listRs   t
   print_typesd   Something inferred a shape with %d dimensions for a variable with %d dimensions for the variable:
%sR^   N(   R[   Ra   RW   R   RZ  R   R  R`   R>   R4   Ro   t   printingt
   debugprintR   t   getvalueR   RZ   RT   R^   RK   RX  Rf  RE   t   equalsR5   R1   t   shape_of_reverse_indext
   setdefaultt   sett   add(   Rk   R   R  RQ  t   siot
   shape_varsR9   t   sv(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRS  \  s.    	%!{c   	      C` s  | |  j  k s! t d | f   |  j  | } | d k r> d S| |  j  k r] |  j  | } n |  j | |  d S| j r | j r | j j | j j k r | j j | j j k r d Sg  } xyt |  D]k\ } } | d k r | r | j | |  q | j rht	 t
 | j d d  t  rh| j j j | k rh| j j d | | f k rh| j | |  q t	 | | t t f  r| j | |  q t	 | | t t f  r| j | |  q | | | | k r| j | |  q | | t j j j | | g  k r$| j | |  q | j | |  q Wt g  t | j  D]v } t | j d  p| j j | r| j j | p|  j j | |  p|  j j t j | | d t  ^ qL st  t |  |  j  | <x4 |  j  | D]% } |  j j  | t!    j" |  qWd S(   s   Replace shape of r by shape of other_r.

        If, on some dimensions, the shape of other_r is not informative,
        keep the shape of r on those dimensions.

        s   other_r not in shape_ofNRj   i    R^   RJ   (#   R[   Ra   RW   RS  R   RL   Rj   R   RK   R   R   R&   R9   R   R   Ro   R   R   t	   ancestorsRE   R   R`   RZ   RT   R^   RX  Rk  R5   R1   R   RZ  Rl  Rm  Rn  Ro  (	   Rk   R   t   other_rt   other_shapet   r_shapet   merged_shapeR9   t   psRr  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   update_shape  sF    !	&c   
      C` sI  | |  j  k s t  |  j  | } g  } xO t |  D]A \ } } | | k ri | j |  j | |   q5 | j |  q5 Wt g  t | j  D]_ } t | j	 d  p | j	 j
 | p |  j j | |  p |  j j t j | |   ^ q  s t  t |  |  j  | <x4 |  j  | D]% }	 |  j j |	 t    j |  qWd S(   s'   Replace element i of shape_of[r] by s_iR^   N(   R[   Ra   R   RK   Rf  RE   R   R`   RZ   RT   R^   RX  Rk  R5   R1   RZ  Rl  Rm  Rn  Ro  (
   Rk   R   R9   Re  t
   prev_shapeRf   t   jt   s_jR0  Rr  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   set_shape_i  s    {c         C` sW   | |  j  k rS y |  j | |  j |   WqS t k
 rO |  j | d  qS Xn  d S(   s.   Register r's shape in the shape_of dictionary.N(   R[   RS  R[  RH  RW   (   Rk   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   init_r  s
    c         C` s   t  |  j |   S(   N(   t   make_vectorR[   (   Rk   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   make_vector_shape  s    c         C` s   t  | d  s t  |  | _ t j d d d |  _ |  j j t j k sR t  i  |  _ i  |  _	 i  |  _
 x* | j   D] } |  j | | d d qz Wd  S(   NRR   i   RX   R  R   t	   on_attach(   RZ   Ra   RR   R5   R   RX  RT   t   lscalarR[   t	   scheduledRl  t   toposortt	   on_import(   Rk   Re   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s    				c         C` s%   i  |  _  i  |  _ i  |  _ | ` d  S(   N(   R[   R  Rl  RR   (   Rk   Re   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt	   on_detach  s    			c         C` s  | j  d |  j k rJ x- | j  | j D] } | |  j k s' t  q' Wd  Sx* t | j  D] \ } } |  j |  qZ W|  j |  } t |  t | j   k r t d d d t	 | j
  t |  t | j   f   n  xt |  D]u\ } } | d  k rq n  t | t t f  sBt d t	 |  t	 |  f   n  g  }	 x t |  D] \ } }
 t |
 d d  d k rU|
 j t j j k st | |
 j f   t	 |
 j  d k st |   |	 | t |	  | d	 !7}	 t |
 t j  rt j |
 j d d } n t j j |
 d  } | |	 | <qUqUW|	 r |	 | t |	  7}	 t |	  | | <q q Wx0 t | j  |  D] \ } } |  j | |  qvWd  S(
   Ni    s7   The infer_shape method for the Op "%s" returned a list s5   with the wrong number of element: len(o_shapes) = %d s    != len(node.outputs) = %ds@   infer_shape of %s didn't return a list of list. It returned '%s'RX   R  t   uint64i   (   R   R[   RL   Ra   R   R~  RP  R>   R   Rb   Rj   RW   R   R   RZ  R   R   RX   Ro   R   R4  R5   R   R   t   dataRY   R	   RS  (   Rk   Re   R   R   R   R9   RN  t   sh_idxt   shRf   t   dt   casted_dR  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    sD    	*!c         C` s$  | |  j  k r |  j |  n  |  j | |  x!| j | | f g D]	\ } } t t | d d   t  rF | j j	 } |  j  | | }	 |	 j
 | k r qF n  |	 j
 r |	 j
 j d | j d k r t |	 j
 j t  r |	 j
 j j	 | j j	 k r qF n  | j d t j j j |	 g  k r?t d | | | | f   n  | |  j | <qF qF Wg  |  j j   D] \ }
 } | | k rc|
 ^ qc} x | D] }
 |  j |
 =qWxk |  j j | g   D]T } xK t |  j  j | g    D]. \ } } | | k r|  j | | |  qqWqWt   |  j | <d  S(   NRj   i    sU   This substitution would insert a cycle in the graph:node: %s, i: %i, r: %s, new_r: %s(   R[   R~  Ry  R  R   R   RW   R&   Rj   R9   R   RL   R   Ro   R   R   Rs  R   R  t   itemsRl  R   R   R}  Rn  (   Rk   Re   R   R9   R   R   R   t   shpnodeR0  t   replR   RP   t   unscheduledt   iit   svi(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   on_change_inputT  s6    
#	%4(c         C` s  |  j  | } |  j  | } | d k s2 | d k r6 t S| d k	 rR | | g } n  | d k	 rn | | g } n  t |  t |  k s t  x t | |  D] \ } } | | k r q n  | j s | j r t St | j j t	  s t | j j t	  rt S| j j }	 | j j }
 |	 j
 |
 j
 k s0t S| j j d | j j d k rVq n  d d l m } | | g | g  s t Sq Wt S(   s   Return True if we are able to assert that x and y have the
        same shape.

        dim_x and dim_y are optional. If used, they should be an index
        to compare only 1 dimension of x and y.

        i    (   t   equal_computationsN(   R[   RW   R?   R>   Ra   RA   R   R   Rj   R&   R9   RL   t   theano.scan_module.scan_utilsR  R   (   Rk   R   R   t   dim_xt   dim_yt   sxt   syt   dxt   dyt   opxt   opyR  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt
   same_shape  s6     N(   R   R   R   RP  RR  RY  R[  RI  Rf  R?   RS  Ry  R}  R~  R  R  R  R  R  RW   R  (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRF  S  s"   V	"	)				C0	O						9	Ct   ShapeOptimizerc           B` s    e  Z d  Z d   Z d   Z RS(   s?   Optimizer that serves to add ShapeFeature as an fgraph feature.c         C` s   | j  t    d  S(   N(   Rn   RF  (   Rk   Re   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRr     s    c         C` s   d  S(   N(    (   Rk   Re   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    (   R   R   R   Rr   R   (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s   	t   UnShapeOptimizerc           B` s   e  Z d  Z d   Z RS(   s3   Optimizer remove ShapeFeature as an fgraph feature.c         C` s7   x0 | j  D]% } t | t  r
 | j |  q
 q
 Wd  S(   N(   R   R   RF  t   remove_feature(   Rk   Re   t   feature(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    (   R   R   R   R   (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s   t   ShapeOptg?t   fast_compilet
   UnShapeOpti
   c         ` s       f d   } | S(   Nc         ` sc  t  |  j   s t St |  j  d k rs t g  |  j d D]% } | j j |  j d j j k ^ q<  ss t  n  t	 g  |  j
 D]% } | j j |  j d j j k ^ q  s t S   f d   } t	 g  |  j
 D]0 } | j o t  | j j    p | |  ^ q  st Sd } xs t |  j
  D]b \ } } | j j |  j d j j k r$| j ovt  | j j    pv| |  s| } Pqq$q$W| d k  rCg  |  j
 D]6 } | j rt  | j j    s| |  r| ^ q} t |  d k r<g  t |  j
  D]+ \ } } | j |  j d j k r| ^ q} | d } qCt Sn  |  j
 | } | }	 g  }
 |  j j j } x|  j
 D]} | j rt  | j j    r| j j
 d j | j j d j k r| j j |	 j k st  t j j j r|  j j j } g  } x{ t | j j  D]g } | j j | r| | |	 | |  r| | |  } | |	 |  } | j t j | |   qqW| rt | |  } qn  |
 j | j j
 d  qu| j r| |  r| j j |	 j j k st  t j j j rtg  t | j j  D]M } | j j | r| | |	 | |  rt j | j | |	 j |  ^ q} | rtt | |  } qtn  | j j
 d j j
 d } | j | j j
 d j k r| j j
 d j | j } | j d g | t t | j    } n  | j j |  } t | |  |
 j |  qu|
 j |  quW| |
 | <|  j d t  |
  } t |  j |  | S(   se  
        elemwise(alloc(x, shp), ..., y.TensorType(BROADCAST CONDITION))
          -> elemwise(x, y.TensorType(BROADCAST CONDITION))

        elemwise(dimshuffle(alloc(x, shp)),... ,y.TensorType(BROADCAST CONDITION))
          -> elemwise(x.dimshuffle(...), y.TensorType(BROADCAST CONDITION))

        BROADCAST CONDITION: the condition is that the one input that are
        not to be optimized to have the same broadcast pattern as the
        output.

        We can change the alloc by a dimshuffle as the elemwise
        already have the shape info.  The dimshuffle will be faster
        to exec.

        i   i    c         ` sE   t  |  j j   oD |  j j d j oD t  |  j j d j j    S(   Ni    (   R   R   Rj   RL   (   R9   (   t   AllocOPt   DimShuffleOP(    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   dimshuffled_alloc  s    iR   R   (!   R   Rj   R?   R>   R   RE   RT   R^   Ra   R@   RL   R   R   Re   RR   R  R`   Ro   R   t   experimentalt   local_alloc_elemwise_assertRR  R   RK   R5   R   R   R\   t
   dimshuffleR   R   R   R   (   R   R   R9   R  t   assert_op_idxR0  t   l2t   lt	   assert_opt   cmp_opt   new_iR  RR  t   condt   i_shpt   cmp_shpt   assert_condt   alloc_inputt   nb_dim_to_addt   r_iR
  (   R  R  t
   ElemwiseOP(    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_elemwise_alloc  s    B5@%& <

(    (   R  R  R  R  (    (   R  R  R  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_elemwise_alloc_op  s    t   local_alloc_elemwisec         C` s  t  |  d  s8 t |  j t j  s8 |  j t j k r< t Sg  } g  } xm |  j D]b } | j r | j j t j k r | j	 | j j d  | j	 | j j d  qR | j	 |  qR W| s t S|  j |   } x5 | D]- } | j
 | j
 k r t j | |  } q q Wi | |  j d 6} x |  j d j D] \ } } t  | d  r.t | j t j  r.| j t j k r.| j }	 | |	 | <| j |	   }
 | j d j |
 j j d _ t j |
 j  } | sq.n  | j |  q.q.W| S(   sv   
    f(fill(a, b), fill(c, d), e) -> fill(c, fill(a, f(b, d, e)))
    f need to be an elemwise that isn't a fill.
    Rj   i    i   (   RZ   R   Rj   R5   R   R6   R?   RL   R   RK   RT   R   R  t   local_fill_sinkR   t   update(   R   t   modelsRL   R  t   ct   modelt   replacementst   clientt   cl_idxt   client_inputst
   new_clientR   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR  y  s>    

c         C` s?  |  j  t j k r;|  j \ } } | j |  j d j k rF | g } n | j j |  j d j j k r t j | |  j d j j  g } na | j j |  j d j j k r t	 | | |  j
 d | j } t |  j d |  | g } n d S| d j |  j d j k s7t d | d j d |  j d j d |  f   | Sd S(   s   fill(s,v) -> alloc(v, shape(s))

    This is an important optimization because with the shape_to_shape_i
    optimization, the dependency on 's' is often removed.

    i    RX   NRg   t   origR   (   Rj   R5   R6   RL   RT   R   R^   RY   RX   Rh   Re   R   Ra   (   R   R   RP   Rg   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_fill_to_alloc  s    %  R  g)\(?R  gRQ?c         C` sH   |  j  t j k rD |  j \ } } | j |  j d j k rD | g Sn  d S(   s   fill(s,v) -> v

    This optimization is only needed in FAST_COMPILE to make the code
    more readable. Normally, it is done by the local_fill_to_alloc
    opt.

    i    N(   Rj   R5   R6   RL   RT   R   (   R   R   RP   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_fill  s    c         C` sS   |  j  } t | t  s t S|  j d } |  j d } | j | j k rO | g Sd S(   s   
    If the input type is the same as the output type (dtype and broadcast)
    there is no change in the shape of the input. So this is just a simple copy
    of the input. This is not needed.

    i    N(   Rj   R   R.   R?   RL   R   RT   (   R   Rj   R  t   output(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_alloc  s    	c         C` s  |  j  } t | t  s t S|  j d } |  j d } | j | j k rO | g St | d g   } x6 | D]. \ } } | d k rh t | j  t  rh d Sqh W|  j d } d } xK t t	 |  | j
  D]0 } t | | d t d k r | d 7} q Pq W| | }	 | d k rt	 |	  | j
 k r| j | | j k rE| }
 n | | g |	   }
 d g | t t t	 |	    } t |
 j j |  |
  g Sd S(   s  If the input type is the same as the output type (dtype and broadcast)
    there is no change in the shape of the input. So this is just a simple copy
    of the input. This is not needed. (as local_useless_alloc)

    Also, it will canonicalize alloc by creating Dimshuffle after the
    alloc to introduce the dimensions of constant size 1.

    See https://github.com/Theano/Theano/issues/4072 to know why this
    is needed.

    i    R  R  Ni   RJ   R   (   Rj   R   R.   R?   RL   R   RT   R   R   R>   R`   R1   R   R^   R   R   R   (   R   Rj   R  R  R  R  R9   t   output_shapet"   num_dims_with_size_1_added_to_leftt   new_output_shapet   innert   dimshuffle_new_order(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_canonicalize_alloc	  s2    	 
!	
c         C` s<   t  |  j t j  r8 t j |  j d |  j d j g Sd S(   s  This convert AllocEmpty to Alloc of 0.

    This help investigate NaN with NanGuardMode.  Not registered by
    default. To activate it, use the Theano flag
    optimizer_including=alloc_empty_to_zeros. This also enable
    the GPU version of this optimizations.

    RX   i    N(   R   Rj   R5   t
   AllocEmptyt   zerosRL   R   RX   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_alloc_empty_to_zeros@  s    
R  gfffffH@t   alloc_empty_to_zerosc         C` si   |  j  t j k re t |  j d  s( d  S|  j j } | j |  j d  } t |  j	 d |  | g Sd  S(   NRR   i    (
   Rj   R5   R\   RZ   Re   RR   R  RL   R   R   (   R   RR   R
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_shape_to_shape_iS  s    c         C` su   y |  j  j } Wn t k
 r$ d  SX|  | j k rq t |  j t  sL t  | j |  } | j | |  j j	 g Sd  S(   N(
   Re   RR   RH  R  R   Rj   R&   Ra   R[   R9   (   R   RR   t   replacement(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_track_shape_id  s    c         C` sY  t  |  j t  rU|  j d } | j s? t  | j j t  rC d S| j j j sV d S| j j d |  j d k rNt | j j j  t |  j j  k rN|  j	 d } | j j d } | j
 | j
 k r | j | j
  } n  | j | j k r | g S| j | j k st  |  j | j j d | j j d  } t j | | j  g SqUd Sn  d S(   s7   
    Subtensor(SetSubtensor(x, y, idx), idx) -> y

    i    Ni   i   (   R   Rj   R   RL   R   R   t   set_instead_of_incRZ  Rc  R   RX   R6  RT   R^   Ra   R5   R]   R\   (   R   R   R%  R   t   x_subtensor(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_subtensor_inc_subtensoru  s$     '&c   
      C` s  t  |  j t  r! |  j j } n d Sg  } d } x t |  D]\ } } t  | t j  r |  j | } t |  t	 j j
 j k r | j } n  | d k r |  j d j | r | j |  | d 7} qPd Sq> t  | t  r | t d  k rPd Sq> t  | t t j f  rD| d k rP|  j d j | rP| j |  qPq> t d   q> Wt |  d k rjd St |  j d j  } g  | D] } | | k r| ^ q}	 |  j d j t |	   g Sd S(   s   
    Remove broadcastable dimension with index 0 or -1
    a[:,:,:,0] -> a.dimshuffle(0,1,2), when
        a.broadcastable = (False, False, False, True)
    a[0,:,-1,:] -> a.dimshuffle(1,3), when
        a.broadcastable = (True, False, True, False)

    Ni   i    is   case not expected(   i    i(   i    i(   R   Rj   R   Rc  R   R"   t   ScalarRL   RT   Ro   R#   t   ScalarConstantRc   R^   RK   t   sliceRW   R   R(  R_  R  R>   R   R`   R  RZ  (
   R   R0  t
   remove_dimt   node_inputs_idxt   dimt   elemt	   dim_indext   all_dimR   t
   remain_dim(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt*   local_subtensor_remove_broadcastable_index  s4      %t   fast_compile_gpuc         C` s  |  j  d } | j s) | j j t k r- d St |  j t  r y |  j j \ } Wn t k
 rh   n Xt | t j	 t
 j f  r | |  j  d } } | j | k s t  q n& t |  j t  r |  j  d } n d St | t t j f  r| j j  | g St | t  rW| j d k ryr t | d t } t | t j  rVt |  } n  y | j j  | g } Wn t k
 rt d   n X| SWqTt k
 rqTXq| j d k rHt | t
 j  rHt t t t | j    } t g  | D] } | j j  | ^ q  } t |  j d |  t
 j | |  j d j   } | g St! d   n t | t"  ryl |  j j# |  j  d t$ d } t | j j  |   } t |  j |  t
 j | |  j d j   } | g SWqt k
 rqXn t! d   d S(   s   
    Replace all subtensor(make_vector) like:
    [a,b,c][0] -> a
    [a,b,c][0:2] -> [a,b]

    Replace all AdvancedSubtensor1(make_vector) like:
    [a,b,c][[0,2]] -> [a,c]

    We can do this for constant indexes.

    i    Ni   RJ   s   Bad user graph!s   case not expectedt   allow_partial(%   RL   R   Rj   R  R   R   Rc  R   R"   R  R5   R  RT   Ra   R   R   R(  R_  R   R`   R/   R   R^  t
   IndexErrorR2   R   R   R  Rc   R   R   t   patternbroadcastR^   R  R  t   get_constant_idxR?   (   R   R   R0  t   old_idxRP   R
  R   t   const_slice(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_subtensor_make_vector  s^    !)c         C` s   t  |  j t j  r|  j d j } |  j j t j j	 k r t
 |  j  d k r |  j d |  j d k rt j |  j d d | d t } t |  j d |  | g Sq|  j j t j j k r3t
 |  j  d k r3|  j d |  j d k rt j |  j d d | d t } t |  j d |  | g Sq|  j j t j j k rnt
 |  j  d k rn|  j d g S|  j j t j j k rt
 |  j  d k r|  j d g S|  j j t j j k rt
 |  j  d k r|  j d g St  |  j j t j  rHt
 |  j  d k rHt  |  j d t j  rt j |  j d d t } t  | t  s| d k rt j |  j d d | d t g S|  j d j |  j d j  g Sqn  t  |  j d t j  rt j |  j d d t } t  | t  sE| d k rt j |  j d d | d t g S|  j d j |  j d j  g SqEqqt  |  j j t j  rt
 |  j  d k rt  |  j d t j  rt j |  j d d t } t  | t  s| d k r|  j d j |  j d j  g St j |  j d d | d t g Sqn  t  |  j d t j  rt j |  j d d t } t  | t  s| d k r|  j d j |  j d j  g St j |  j d d | d t g Sqqqt  |  j j t j  rt
 |  j  d k r|  j d |  j d k rt j |  j d d | d t g Sqn  d S(   s   
    eq(x,x) -> 1
    neq(x,x) -> 0
    mul(x) -> x
    add(x) -> x
    identity(x) -> x
    and(x,1) -> x
    and(x,0) -> zeros_like(x)
    or(x,0) -> x
    or(x,1) -> ones_like(x)
    xor(x,x) -> zeros_like(x)

    i    i   i   RX   R
   RJ   N(   R   Rj   R5   R   R   RX   R   Ro   R"   R   R>   RL   t	   ones_likeR   R   t   neqR5  t   mulRo  t   identityt   ANDt   TensorConstantR1   R   R6  t   ORt   XOR(   R   RX   R
  t	   const_val(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_elemwise  sn    -"
-"
--
'
*!!c         C` s   t  |  j t j  r t |  j  d k r |  j d } | j r t  | j j t j  r | j j d } | j j d } |  j |  } t |  j	 d |  t j
 t j | |  j	 d j  |  } t |  j	 d | g |  | g Sn  d S(   s,   unary(alloc(x, shp)) -> alloc(unary(x), shp)i   i    N(   R   Rj   R5   R   R>   RL   R   R.   R   R   R]   RY   RX   (   R   R  R   t   shpRP   R
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_alloc_unary  s    *!(c         C` s   t  |  j t j  s/ t  |  j j t j  r3 d S|  j d } | j s t  | j j t j  s t  | j j j t j  r d S|  j j j	 | j j j j	 k r | g Sd S(   s   cast(cast(x, dtype1), dtype2)

    when those contrain:
    dtype1 == dtype2
    TODO: the base dtype is the same (int, uint, float, complex)
          and the first cast cause an upcast.

    Ni    (
   R   Rj   R5   R   R   R"   t   CastRL   R   t   o_type(   R   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_cast_cast  s    
!c         C` s  t  j t  j f t  j t  j f t  j t  j f t  j t  j f t  j	 t  j	 f t  j
 t  j
 f t  j t  j f f } |  j d } t |  j t j  s d S| j s t | j j t j  r d S| j j j } |  j j } x* | D]" } t | | |  r | j j Sq Wd S(   sy   
    Check for two consecutive operations that are functional inverses
    and remove them from the function graph.

    i    N(   R#   t   Deg2Radt   Rad2Degt   Cosht   ArcCosht   Tanht   ArcTanht   Sinht   ArcSinht   Conjt   Negt   InvRL   R   Rj   R5   R   R   R   t   is_inverse_pair(   R   t	   inv_pairsR   t   prev_opt   node_opt   inv_pair(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_func_inv  s$    
#c         C` sb   t  |  | d  } t  |  | d  } t  | | d  } t  | | d  } | rX | pa | oa | S(   sj   
    Given two consecutive operations, check if they are the
    provided pair of inverse functions.

    i    i   (   R   (   R  R  R  t   node_is_op0t   node_is_op1t   prev_is_op0t   prev_is_op1(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR	    s
    t   Assertc           B` s   e  Z d  Z e Z d Z i d g d 6Z e Z d d  Z	 d   Z
 d   Z d   Z d   Z d	   Z d
   Z d   Z d   Z RS(   s  
    Implements assertion in a computational graph.

    Returns the first parameter if the condition is true, otherwise, triggers
    AssertionError.

    Notes
    -----
    This Op is a debugging feature. It can be removed from the graph
    because of optimizations, and can hide some possible optimizations to
    the optimizer. Specifically, removing happens if it can be determined
    that condition will always be true. Also, the output of the Op must be
    used in the function computing the graph, but it doesn't have to be
    returned.

    Examples
    --------
    >>> import theano
    >>> T = theano.tensor
    >>> x = T.vector('x')
    >>> assert_op = T.opt.Assert()
    >>> func = theano.function([x], assert_op(x, x.size<2))

    RO  i    s   Theano Assert failed!c         C` s   | |  _  d  S(   N(   RO  (   Rk   RO  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRm   	  s    c         C` s/   |  j  j |  t |  d  s+ d |  _ n  d  S(   NRO  s   Theano Assert failed!(   t   __dict__R  RZ   RO  (   Rk   t   attrs(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   __setstate__	  s    c         G` s   t  | t  s! t j |  } n  g  | D] } t j |  ^ q( } t j g  | D] } | j j d k ^ qP  sw t  t	 j
 |  | g | | j   g  S(   Ni    (   R   R   R5   RS   R(  RE   RT   R`   Ra   R   R  (   Rk   Rc   t   condsR  R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR!  
	  s
    "4c         C` sC   | \ } | d } | | d <t  j | d  s? t |  j   d  S(   Ni    i   (   R(  RE   Ra   RO  (   Rk   R   RL   R$  R%  RP   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR&  	  s    	

c         C` s   | t      g t |  d S(   Ni   (   R   R>   (   Rk   R  R8  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR;  	  s    c         C` s%   d g g d g g t  | j  d S(   Ni   i    (   R>   RL   (   Rk   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   connection_pattern	  s    c         C` s   | d } | d } g  } | d }	 |  j  j d d  j d d  }
 xT t t |  d  D]< } | | d } | j | d j } | j d t    q\ Wd j |  } d	 t   S(
   Ni    t   failt   "s   \"s   
s   \ni   sg   if(!((npy_%(dtype)s*)PyArray_DATA(%(i)s))[0]){PyErr_SetString(PyExc_AssertionError,"%(msg)s");%(fail)s}ss   
        %(check)s
        Py_XDECREF(%(out)s);
        %(out)s = %(value)s;
        Py_INCREF(%(value)s);
        (	   RO  R   R   R>   RL   RX   RK   R+  RC  (   Rk   R   R   t   inamest   onamesR,  Rc   R%  t   checkR  RO  R0  R9   RX   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR1  	  s    


!	c         C` s   d S(   Ni   i    (   i   i    (    (   Rk   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR'  1	  s    c         C` s   | d g S(   Ni    (    (   Rk   R   t   input_shapes(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR3  4	  s    (   s   msg(   R   R   R   R   t   _f16_okR>  t   view_mapR?   t   check_inputRm   R  R!  R&  R;  R  R1  R'  R3  (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s   							c         C` s  t  |  j t  r g  } xq |  j d D]b } y; t |  } d | j k sV | d k rf | j |  n  Wq& t k
 r | j |  q& Xq& Wt |  d k r |  j d g St |  t |  j  d k r t	 |  j d |  } t
 |  j d |  | g Sn  d  S(   Ni   i    (   R   Rj   R  RL   R/   R`   RK   R2   R>   R   R   R   (   R   R  R  t   constR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_remove_useless_assert>	  s    c         C` s$   t  |  j t  s d S|  j d g S(   s   An optimization disabled by default that removes all asserts from
    the graph.

    Notes
    -----
    See the :ref:`unsafe` section to know how to enable it.

    Ni    (   R   Rj   R  RL   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_remove_all_assertY	  s    
R   R$  t   unsafet   use_db_name_as_tagR   R   t   uselessc   	      C` s@  t  |  j  d k r d Sy |  j j j } Wn t k
 rE d } n Xt |  j t	 j
  r<|  j j } t | d d  t	 j j t	 j j f k r<|  j d j j } g  } x/|  j D]$} | j j | k r | j |  q y t | d t } t | j  r+| j t	 j t	 j | |  | j   n] | d k r;d S| j t	 j t	 j | |  g  t | j  D] } | |  |  ^ qf  Wq t k
 rt | t	 j  r| j t	 j | |   q| j |  q Xq W| |  j k r9|  j |   g } | d j |  j d j k rd St |  j d |  | Sq<n  d S(   s   This explicitly upcasts constant inputs to elemwise Ops, when
    those Ops do implicit upcasting anyway.

    Rationale: it helps merge things like (1-x) and (1.0 - x).

    i   Nt   output_types_preferencei    RJ   (    R>   R   Re   RR   t   shape_iRH  RW   R   Rj   R5   R   R   R   t   scalt   upgrade_to_floatt
   upcast_outRT   RX   RL   RK   R/   R   RE   R^   t   shape_padleftRY   R`   R]   R   R2   R  R   (	   R   R)  R   t   output_dtypeR  R9   t   cval_iR  Rg   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt%   local_upcast_elemwise_constant_inputs	  sL    	
		3c         C` s  t  |  j t  s d S|  j j t k rm y- t |  j d d t } | d k rT d SWqm t k
 ri d SXn  |  j d j	 |  j d j	 k s |  j d j
 |  j d j
 k r d St |  j d |  j j  } t d   | D  rt |  j d  s d S|  j j j |  j d |  j d  s#d St d   |  j j D  rM|  j d g St |  j j  |  j d   } t |  j |  | g Sd S(   sY   
    Remove IncSubtensor, when we overwrite the full inputs with the
    new value.

    Ni    RJ   i   c         s` si   |  ]_ } t  | t  o` | j d k o` | j d k o` | j d k p` t j | j d  t d k Vq d S(   RJ   iN(	   R   R  t   startRW   t   stopt   stepR5   R1   R   (   R;   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>	  s   RR   c         s` s   |  ] } | j  d  k Vq d  S(   N(   R3  RW   (   R;   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>	  s   (   R   Rj   R   R  R?   R/   RL   R   R2   R`   R^   R   Rc  RE   RZ   Re   RR   R  R   R   R   (   R   R  t   idx_cstR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_inc_subtensor	  s6    
	  		c         C` s  t  |  j t  r|  j j r|  j d j rt  |  j d j j t  rt  |  j d j j j t j	  r|  j d j } d } d } | j d j r t  | j d j j t  r | j d j } | j d } nP | j d j r t  | j d j j t  r | j d j } | j d } n d S| j d |  j d k sX| j d |  j d k r\d St |  j d | |  j d  } t |  j |  | g Sd S(   s   
    AdvancedIncSubtensor1(x, x[ilist]+other, ilist, set_instead_of_inc=True) ->
    AdvancedIncSubtensor1(x, other, ilist, set_instead_of_inc=False)

    i   i    Ni   (   R   Rj   R   R  RL   R   R   R   R"   t   AddRW   R   R!   R   R   (   R   t   addnt   subnt   otherR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_set_to_inc_subtensor	  s.    " c         C` s+  t  |  j t  r't |  j |  j j  } t |  } x | d d d  D]n } t  | t  r | j d k r | j
 d k r | j d k s t j | j d t d k r | d 8} qJ PqJ W| t |  k  r't | |   } t j | |  d    } | |  j d |  } t |  j |  | g Sn  d S(   s6   
    Remove Subtensor of the form X[0, :] -> X[0]
    NiRJ   i   c         S` s   t  |  t j  S(   N(   R   R5   R   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR   9
  s    i    (   R   Rj   R   R   RL   Rc  R>   R  R1  RW   R2  R3  R5   R1   R   t   collapseR   R   (   R   t   slicest
   last_sliceR  t   subtenst   sl_insR%  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_slice"
  s     -c         C` s  t  |  d  s d St  |  j d  s) d S|  j j j } t |  j t  rg|  j j |  j d t	 d t	 } xq t
 |  D]c \ } } t | t  s t S| j d k	 r | j d k r t S| j d k	 rx | j d k rx t Sqx Wxt
 |  D]t\ } } | |  j d | } t | j t t j f  rqt j } y t | d t	 } Wn t k
 rZn X| j | k  r`t Sq t | j t j  rJ| j } | j rt | j j t j  r| j j d } n8 | j rt | j j t j  r| j j d } n t St | j j   d k st!  t | j j   d k s7t!  | | k r`t Sq | j d k r\q t Sq WnNt |  j t"  ry% t | |  j d d d t	 } Wn t k
 rt SX|  j d } t | t j#  r| j$ } t% |  | k rt St j& | t j' |  k  rt Sq| j d k	 rt | j j t j(  ry% t) d   | j j  \ }	 }
 } Wn t k
 rvt SX|	 d k rt S|
 | k rt S| d k rt Sqt Sn t S|  j d g S(   s  
    Remove Subtensor/AdvancedSubtensor1 if it takes the full input. In the
    AdvancedSubtensor1 case, the full input is taken when the indices are
    equivalent to `arange(0, input.shape[0], 1)` using either an explicit
    list/vector or the ARange op.

    Re   NRR   R  RJ   i    i   R  t   int8t   int16t   int32c         S` s   t  |  d t S(   NRJ   (   R/   R   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR   
  s   	(   s   int8RB  RC  s   int64(*   RZ   Re   RR   R[   R   Rj   R   R  RL   R   R   R  R?   R1  RW   R3  R2  R   R(  R_  R   t   maxsizeR/   R2   R   R   R   R5   R  R  Rb   RT   RX   Ra   R   R   Rc   R>   R@   t   aranget   ARangeR  (   R   R[   t   cdatat   posR0  t
   length_post   length_pos_datat   length_pos_shape_it   lengthR1  R2  R3  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_subtensor@
  s    							'	c         C` sh  t  |  j t  rd|  j d } | j s> t | j  d k rB t St  | j j t j	  r t | j j  d k r |  j d } |  j | j j d |  } t
 |  j |  | j j |  } t
 |  j d |  j d g |  | g St  | j j t j	  rg  } t g  | j j D] } t | j j  d k ^ q r|  j d } g  | j j D] } |  j | |  ^ qT} t
 |  j d |  | j j |   } t
 |  j d |  j d g |  | g St g  | j j D]' } t | j j  | j d g k ^ q r|  j d } g  } x | j j D] } t | j j  d k rZ| j |  j | |   q |  j d j | j k r| j |  q | j | j d g |  j d j   q Wt
 |  j d |  | j j |   } t
 |  j d |  j d g |  | g Sn  t  | j j t j  rdt | j j  d k s5t  g  } d } xV t |  j j  D]B \ } }	 t  |	 t  rT| | | j | f g 7} | d 7} qTqTWxP t t |  j j  t | j   D]* } | | | j | f g 7} | d 7} qW|  j | j j d |  j d  }
 t
 |  j d |
  t j |   |
  } t
 |  j d |  j d g |  | g Sn  d S(   s  
    unary(x)[idx] -> unary(x[idx])#any broadcast pattern.

    Handles the following unary ops:
    elemwise(x,...)[idx] -> elemwise(x[idx],...)
      when x,... are broadcasted scalar or not broadcasted at all
    rebroadcast(x)[idx] => rebroadcast(x[idx])

    i    i   R   N(   R   Rj   R   RL   R   R>   R  R?   R5   R   R   R   RE   R   RT   R^   R`   RK   R  t   RebroadcastRa   R   Rc  R  R   (   R   t   uR0  t   x_idxR
  R  R9   t   new_axisR{  R   t   subt_xt   rbcast_subt_x(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_subtensor_lift
  sf    0!7+!:%!
+#!c         C` s,  t  t t t t g } t |   t k	 r9 t d |    n  t |  |  \ } } t | |  \ } } t |  t k	 ro| d k rL| j
 | | j }	 t j t j | d  | d |	  }	 t j t j | |  | d |	  }	 t j t j | d  | d |	  }	 | j r9t j t j | j d  | d |	  }	 n  t | |	  }	 |	 S| j
 | | j }
 | j d | | j } t j j rt j d  n  t j t j | d  | |
  }	 t j t j | d  | d |	  }	 t j t j | |  | d |	  }	 t j t j | d  | d |	  }	 | j rYt j t j | j d  | d |	  }	 n  t | |	  }	 |	 Sn| j | j
 } | j | j } | j | j d } t j | j
 | j
 | j | j  } t j | j
 | j | j | j  } | j
 | j
 d | j } t j t j t j | d  t j | d   | d t j | | j   } | j
 | j d | j } t j | | j  } t j | d  } | j | j | j d } t j t j t j | d  t j | d   | d t j | j
 d |   } t j | j
 | j | j
 | j d  } t j | j
 | j d | j d | j  } t j | j
 | j | j
 | j  } t j t j | | d  t j t j | d  | |  t j t j | d  | |   } t j t j | | d  t j t j | d  | |  t j t j | d  | |   } t j t j | | d  | |  } t j t j | d  d |  } t j t j | d  d |  } t | |  } t | |  } t | |  } t | |  } t | |  } t | |  } t | | | g  \ } } } t | | |  Sd S(   so  
     This function merges two slices into a single slice. The code works on
     the assumption that:

     a) slice1 is actually a slice and not an index, while slice2
        can be just an index.

     b) the two slices **have been applied consecutively** on the same
        tensor

    The output slice is **not** in canonical form, but actually just a slice
    that can be applied to a tensor to produce the same output as applying
    the two consecutive slices.
    ``len1`` is the length of the tensor **before** applying the first slice,
    while ``len2`` is the length **after** applying the first slice.
    sG   First provided slice should actually be of typeslice and not an index !i    i   s   Your current code is fine, but Theano versions prior to 0.5rc2 might have given an incorrect result. To disable this warning, set the Theano flag warn.subtensor_merge_bug to False.iN(   t   local_abs_merget   local_mul_switch_sinkR0  t   local_useless_switcht   constant_foldingRT   R  R   R   RW   R1  R3  R5   t   switcht   let   get   ltR   R,   R2  R   t   warnt   subtensor_merge_bugR   t   minimumt   and_t   gtt   maximumR+   (   t   slice1t   len1t   slice2t   len2t   list_optt   sl1t   reverse1t   sl2t   reverse2t   valt   p_valt   n_valt   flent   p_stept   n_stept   pp_startt   pp_stopt   pn_stopt   pn_startt   np_stopt   np_startt   nn_startt   nn_stopR1  R2  R3  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   merge_two_slices'  s    %%&	+
!%%&	+&&*"&$%!!c         C` s  t  |  j t  r|  j d } | j rt  | j j t  r| j j d } t | j j | j j j  } t |  j |  j j  } y* |  j j j	 | } |  j j j	 | } Wn# t
 k
 r | j } | j } n Xg  } d } d }	 x |	 t |  k  rw| t |  k  rw| |	 }
 t |
  t k r]| j t |
 | |	 | | | |   | d 7} n | j |
  |	 d 7}	 q W| t |  k  r| | | 7} n | | |	 7} t |  } t |  } t j | d    } | | |  } |  j d } t | |  j d g |  | j | j k r| j | j k s6t  | j | j k sNt  t j | | j  } t | |  j d g |  n  | g Sn  d S(   s   
    Refactored optimization to deal with all cases of tensor merging.
    Given a subgraph of the form Subtensor(Subtensor(u)), the optimization
    expresses all slices in a canonical form, and then merges them together.

    i    i   c         S` s   t  |  t j  S(   N(   R   R5   R   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    N(   R   Rj   R   RL   R   R   Rc  Re   RR   R[   RH  R\   R>   RT   R  RK   Rz  R   R;  R   R   RX   Ra   R`   R5   R  R^   (   R   RO  R   t   slices1t   slices2t   xshapet   ushapet   merged_slicest   pos_2t   pos_1Rc  R>  R?  R%  t   orig_out(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_subtensor_merge  sV    	'
c         C` su  t  |  j t  s t S|  j d } | j d k r6 t St  | j j t j  sR t St	 |  j |  j j
  } | j j d } | j j d } t |  t |  k s t  | j | j } g  } g  } x t t | |   D] \ } \ }	 }
 | | k rH| j j | | k r8| j j | | r8| j t d   qH| j |	  n  t |	 |
  \ } } t |  t k	 rrq | j | j } | j d k rt j | | j  } n  | | g 7} q W| t |  } | | t |  7} | j t |  k rt St j | |  } t |  t t f k r-| g } n  | d j |  j d j k rqt j | d |  j d j  | d <n  | S(   s   

    alloc(val)[x:y] -> alloc(val[...])
    alloc(val)[x:y] -> alloc(val)
    This can be seen as a lift, but it also reduce the number of computation/memory.

    i    i   N(   R   Rj   R   R?   RL   R   RW   R5   R.   R   Rc  R>   Ra   R`   R   RA   RT   R^   RK   R  R   R2  R1  R3  t   ceil_intdivRZ  R]   R   R   R  (   R   RO  R<  Rl  t   dimst   n_added_dimst   nw_dimst
   val_slicesR9   t   slR  t   cslt   _t   nw_dimt   nw_valRg   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_subtensor_of_alloc  sJ    ('c   
      C` s  t  |  j t  s d S|  j d j sG t  |  j d j j t j  rK d St |  j d j  d k rk d S|  j d j j d } |  j d j j d } t	 |  j |  j j
  } t | j d t |   } | |  } | | } | j d k r?t |  | j d k r?| | j d  t d d d  f | | j d } n  | j t |   } | ro| j t |   n | } t |  j d | | g  t j | |  }	 t |  j d |  j d g |	  |	 g S(   sb  
    This optimization translates T.dot(A, B)[idxs] into T.dot(A[idxs_a], B[idxs_b]),
    where idxs_a and idxs_b are defined appropriately.

    idxs_a is the first A.ndim-1 entries of idxs,
    and idxs_b is the remaining entries of idxs (if any),
    modified to skip the second-to-last dimension of B
    (because dot sums over this dimension).

    Ni    i   i   (   R   Rj   R   RL   R   R5   R   R>   R  R   Rc  t   minR`   R  RW   t   __getitem__RZ  R   R   R  (
   R   R  t   bRc  t   num_a_indicest	   a_indicest	   b_indicest   a_subt   b_subR   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_subtensor_of_dotF  s*     

(6!!c         ` s`    f d   } |  j  t j k r\|  j d j   g  |  j D] } | |  r; | ^ q; } | r\g  |  j D] } | |  si | ^ qi g  | D] } | j j d ^ q } t j |   } t |  j d |  | } x~ | D]v } | j   k s t  | j | j j d j k st  | j j  | | j j d  } t |  j | j j |  q W| g Sn  d S(   sK  
    When using Subtensor, gradient graphs can be ugly.

    If we ask for grad(f(a[0]), a), we are going to get something like

        IncSubtensor(Elemwise{second}(a, 0), g(f(a[0])), [0])

    This might be ugly, but at least it's as fast as you could want.
    If we ask for grad(f(a[0], a[1], a[2]), a), it's much worse...

        Elemwise{Add}
            IncSubtensor(Elemwise{second}(a, 0), g(f(a[0])), [0])
            IncSubtensor(Elemwise{second}(a, 0), g(f(a[1])), [1])
            IncSubtensor(Elemwise{second}(a, 0), g(f(a[2])), [2])

    This is much worse because this time we have to produce 3 matrices
    the size of 'a', just so we can add them together.

    This Op rearranges IncSubtensor's that all work on the same
    initial argument (here, Elemwise{second}(a,0)) into a chain.  The
    advantage of the chain structure is that each one can be optimized
    later in the pipeline to operate inplace.

    Ideally, the op will do something like this:

    #
    #  add(x, incsubtensor(b, c), incsubtensor(b, d))
    #  -> incsubtensor(incsubtensor(add(x,b,b), c), d)

    c         ` sY   |  j  oX t |  j  j t t t f  oX |  j   k oX t |  j  d k oX |  j  j j	 S(   Ni   (
   R   R   Rj   R   R   R   RT   R>   R  R  (   R9   (   R  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   movable  s    	i    i   N(	   Rj   R5   Ro  R   RT   RL   R   R   Ra   (   R   R  R9   t   movable_inputst   miR  t   new_addt   tip(    (   R  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_IncSubtensor_serialize  s     !
(%$"t    pre_local_IncSubtensor_serializegGz?c         C` s   t  |  j t  r |  j j r |  j j } |  j j |  j j d t d |  j j d | } | |  j	   } t
 |  j d j d t  } | | j _ t |  j |  | g St S(   s)   
    Also work for GpuIncSubtensor.

    R   R  t   destroyhandler_tolerate_aliasedi    t   nan_guard_mode_check(   R   Rj   R   R   R  R   Rc  R   R  RL   R   R   t   tagR  R   R?   (   R   t   dtat   new_opR   Rl  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_inplace_setsubtensor  s    		R  t   failure_callbacki<   c         C` sX   t  |  j t  rT |  j j rT |  j j   } | |  j   } t |  j |  | g St S(   s2   
    Also work for GpuAdvancedIncSubtensor1.

    (	   R   Rj   R   R   t   clone_inplaceRL   R   R   R?   (   R   R  R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_inplace_incsubtensor1  s    R  t   local_incsubtensor_of_allocsc         C` s   t  |  j t t t f  r} |  j j r} |  j d } |  j d } y# t | d t d k rd | g SWq} t	 k
 ry d SXn  d S(   s+   
    IncSubtensor(x, zeros, idx) -> x

    i    i   RI   N(
   R   Rj   R   R   R   R  RL   R/   R?   R2   (   R   R   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_incsubtensor_of_zeros  s    
t   local_setsubtensor_of_allocsc         C` s   t  |  j t  r |  j j r |  j d } |  j d } y t | d t } Wn t k
 rb d SXy t | d t } Wn t k
 r d SX| | k r | g St Sn  d S(   sN   
    SetSubtensor(x, x[idx], idx) -> x

    when x is constant or alloc.

    i    i   RI   N(   R   Rj   R   R  RL   R/   R?   R2   (   R   R   R   t	   replace_xt	   replace_y(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_setsubtensor_of_constants'  s    
c   	      C` s  t  |  j t  s d S|  j d } | j sC t  | j j t  rG d S|  j d } | j j d } | j j d } | j j d } | | k	 r d S| j j j r t j | d t	 d k r d St j
 t j t j | | j d  t j | | j d    g } |  j j j | | d d  sP| j t j | j d | j d   n  t d  | |  } t | |  | j |  j d j k r| g St j | |  j d j  } t | |  | g S(   sx  Optimize the possible AdvSub1(AdvIncSub1(...), ...).

    AdvancedSubtensor1(AdvancedIncSubtensor1(0s, y, idx), idx) -> y
    AdvancedSubtensor1(AdvancedSetSubtensor1(x, y, idx), idx) -> y

    Notes
    -----
    This opt add AssertOp. Otherwise, it would remove shape and
    index error. If you want to get rid of them, see the
    :ref:`unsafe_optimization` section.

    Ni    i   i   RI   sI   Bad indexing or shapes in a AdvancedIncSubtensor1 that was optimized away(   R   Rj   R   RL   R   R   R  R5   R1   R?   RE   R`  R\  R\   R[  Re   RR   R  RK   R   R  R   RX   R   RY   (	   R   R   R0  t   idx2R   R   R  R   t   r2(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_adv_sub1_adv_inc_sub1J  s4    
E*	c      	   C` s  t  |  j t t t f  r|  j d } |  j d } |  j d } | j d k	 rt  | j j t j	  r| j j d } y |  j
 j } Wn t k
 r t SX| j } | j } t  |  j t  r t |  j j  | |  } nT t  |  j t  rt | |  } n0 t  |  j t  r(t | |  } n t d   d }	 | | k rf| j |  j
 | j d |	  n  | j | j k rt j | | j | j  } | | k r| j |  j
 | j d |	  qn  t f | j | j | j }
 g  t | j  D] } |
 | r| | | d | d	 | r| | | d k rt j t j | j | d  t j | j | | j |   ^ q} t |  d k rd
 } t |  | |  } n  |  j | | |  } t  |  j! |  | g Sn  d S(   s   
    Replaces an [Advanced]IncSubtensor[1], whose increment is an `alloc` of
    a fully or partially broadcastable variable, by one that skips the
    intermediate `alloc` where possible.

    i    i   i   s   Should never happen!t    local_useless_incsubtensor_allocs   %s: add `xi`s   %s: add `y`R  R  s*   `x[i]` and `y` do not have the same shape.N("   R   Rj   R   R   R   RL   R   RW   R5   R.   Re   RR   RH  R?   R[   R  R   Rc  R   R    R   R  R`   R-  R   R^   R   t   or_R   R\   R>   R  R   R   (   R   R   R   R9   t   zRR   R[   R  t   xiR   t   z_broadR   R  RO  R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt!   local_useless_inc_subtensor_alloc  sT    '		
Yc         C` s   t  |  j t j  r |  j d } t j | j |  j d j k  rK | g Si  } xF t	 |  j j
 j    D], \ } } | j | | k rj | | | <qj qj W| |  j j
 k r d St j t	 | j      |  } t |  j |  | g Sn  d S(   sV   
    Remove Rebroadcast if id does not actually change the broadcasting pattern.

    i    N(   R   Rj   R5   RN  RL   R(  RE   R^   R   R   t   axisR  R   (   R   R   RQ  R  t   bcR   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_rebroadcast  s    	"%!c         C` s  |  j  } t | t j  s t S|  j d } | j } | r t | j  t  r t | j  d k r t	 | d  r t | j
  d k r t j t | j j      | j d  } t |  j |  | j  j |  j } t |  j |  j |  | Sn  | r}t | j  t j  r}| j  j j   } | j | j  | j d } t j t | j      |  g } t |  j |  j |  | Sd S(   s   
    Lifts Rebroadcast through unary Elemwise operations,
    and merges consecutive Rebroadcasts.

    Rebroadcast(Elemwise(x)) => Elemwise(Rebroadcast(x))
    Rebroadcast(Rebroadcast(x)) => Rebroadcast(x)

    i    i   R  N(   Rj   R   R5   RN  R?   RL   R   R   R>   RZ   R  R   R  R  R   R   R!  t   copyR  (   R   Rj   R  R  t   rebroadcastedRg   R  t   iinput(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_rebroadcast_lift  s(    		-$$c         C` s   t  } x | r |  j r t } t j j j j |  j  } | rj t |  d k sW t	  | d }  t  } n  |  j r	 t j j j
 j |  j  } | r t |  d k s t	  | d }  t  } q q	 q	 W|  S(   s   
    Apply as many times as required the optimization local_useless_rebroadcast
    and local_rebroadcast_lift.

    Parameters
    ----------
    rval: a Variable

    Returns
    -------
    A Variable (the same if no optimization can be applied)

    i   i    (   R   R   R?   Ro   R   R
   R  R   R>   Ra   R  (   Rg   RV  t   rval2(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   apply_rebroadcast_optK  s"    
		
c         C` sG   t  |  j t j  s d S|  j d } t |  d k rC | d g Sd S(   sI   Join(i, x) => x

    Remove Join() when only one element is joined.

    Ni   i    (   R   Rj   R5   t   JoinRL   R>   (   R   t   tensors(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_join_1p  s
    
c         C` s  t  |  j t j  s d Sg  } y t |  j d d t } Wn t k
 rP d SXxh t d t	 |  j   D]N } |  j | } t  | t
 j  r | j j | d k r qj n  | j |  qj Wt	 |  t	 |  j  d k  rt	 |  d k r d St j |  j d |  } |  j d } | j | j k r-d St |  j |  | j | j k r| j | j k sgt  | j | j k st  t j | |  j d j  } n  t |  j |  | g Sd S(   sp   Join(i, x, y, empty) => Join(i, x, y)

    Remove empty inputs to joins. The empty inputs can be anywhere.

    Ni    RJ   i   (   R   Rj   R5   R  R/   RL   R   R2   R   R>   Ro   R   R  R\   RK   RC  R   RX   R   RT   Ra   R`   R  R^   (   R   R  t   join_idxR0  R   R
  R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_join_empty  s6    
(c         C` sw  t  |  j t j  s, |  j d j d k r0 d S|  j d g } x t d t |  j   D] } |  j | } | j	 rt  | j	 j t
  r| d j	 rt  | d j	 j t
  r| j	 j | d j	 j k r| d j	 j | j	 j } | j	 j |   | d <t |  j | d  qY | j |  qY Wt |  t |  j  d k  rst j |  j d |  } t |  j |  | g Sd S(   s   Join(0, make_vector1, make_vector2, ...) => Join(0, make_vector12, ...)

    Merge MakeVector inputs to Join. This can make the join completly
    disapear with the local_join_1 opt.

    i    i   Ni   i(   R   Rj   R5   R  R   R`   RL   R   R>   R   R  R   RK   RC  (   R   R  R0  R   t   inpsR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_join_make_vector  s$    ,	c   	      C` s  t  |  j t j j  rt  |  j j t j j j	  r|  j j
 d k r|  j d } |  j d } | j rt  | j j t j  rt  | j j j t j j j  r| j j d } | j r
t  | j j t j  r
t  | j j j t j j j  r
t | j j  d k r
| j j \ } } t  | j j t j j  r| j j j d	 k rt  | j j t j j  r| j j j d
 k r| j j d } | j j d } t j t j |  t j |  j d d   } | j | j k rt j | d | j } n  | g Sq
qn  d S(   s   
    This optimization detects T.sqr( W.dimshuffle('x',0,1) * G.dimshuffle(0,'x',1) ).sum(axis=(1,2))
     and converts this to T.dot(T.sqr(G), T.sqr(W).sum(axis=0)).
    i   i   i    R   R  RX   N(   i   i   (   R   i    i   (   i    R   i   (   R   Rj   R5   RI   t   SumR   Ro   R"   R#   R6  R  RL   R   R   R   t   Sqrt   MulR>   R   R   R  t   sqrR   RX   RY   (	   R   t   in1R%  t   in_sqrt   in_mul1t   in_mul2t   Wt   GR7   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_sumsqr2dot  s"    0B!9000c         C` s  t  |  j t j  rt  |  j j t j j j  r|  j	 \ } } |  j
 d } | j rt  | j j t j  rt  | j j j t j j j  rt j | d t d k r| j j	 d } t j |  } | j | j k r t j | d | j } n  | j | j k rd S| g Sn  d S(   sK   
    This optimization detects exp(a)-1 and converts this to expm1(a).
    i    RJ   i   RX   N(   R   Rj   R5   R   R   Ro   R"   R#   t   SubRL   R   R   t   ExpR1   R?   t   expm1RX   RY   RT   (   R   R  t   in2R%  t   in11R7   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_expm1  s    Bt   local_remove_switch_const_condc         C` s  t  |  j t j  rt  |  j j t j j  rt j |  j	 d d t
 } t |  t j k rp | j d k s t  | t j  r| d k r |  j	 d } n |  j	 d } | j |  j d j k r t S| j |  j d j k r t j | |  j d j  } n | } | j j |  j d j j k rg  } x t t | j j |  j d j j   D] \ } \ } } | | k r| j | j |  qT|  j	 d j j | s| j |  j	 d j |  qT| j |  j	 d j |  qTWt j | |  } n | } t |  j | |  | g S|  j	 d |  j	 d k r| j |  j	 d j k rT|  j	 d g St j | |  j	 d  } t |  j |  j	 d |  | g S|  j	 d }	 |  j	 d }
 |  j	 d } | j rt  | j j t j  rt  | j j j t j  r| j j	 d j rt  | j j	 d j j t  rt j | j j	 d d t
 d k rt j |	 d t
 d k r|
 | j j	 d k r|
 j |  j d j k st  |
 g St St S(   sP  
    This optimization makes the following changes in the graph:
        T.switch(cond,left,right) -->
               if cond is constant and cond == 0: right
               if cond is constant and cond != 0: left
               if left is right -> left

        T.switch(le(shape_i{id}(X), 0), 0, shape_i{id}(X)) -> shape_i{id}(X)
    i    RJ   i   i   (    R   Rj   R5   R   R   R"   R#   t   SwitchR1   RL   R   RT   R(  R`  R`   t   numberR   R?   RX   RY   R^   R   RA   RK   R\   R]   R   R6   R   t   LER&   Ra   (   R   R  t   correct_outR%  t   shpsR0  RB   RC   R
  t   leftt   rightt   cond_var(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRW  $  s`    	$)	%c         C` s  |  j  t j k r t Sxt |  j  D]\ } } | j r& | j j  t j k r& | j } y t | j d d t	 d k r|  j |  |  j | d } t j | | j d g   } t
 |  j |  t j | j d d |  g } t | d j _ t
 |  j | j |  | SWn t k
 r"n Xy t | j d d t	 d k r|  j |  |  j | d } t j | | j d g   } t
 |  j |  t j | j d | d  g } t | d j _ t
 |  j | j |  | SWqt k
 rqXq& q& Wt S(   s  
    This optimization makes the folowing changes in the graph:
    T.mul(A,T.switch(cond,0,iff),B) -->  T.switch(cond,0,T.mul(A,B,iff))
    T.mul(A,T.switch(cond,ift,0),B) -->  T.switch(cond,T.mul(A,B,ift),0)
    A and B being several (or none) symbolic variables.
    This is useful because A and B may not be numerically stable and give
    NaN or inf values for cases where the switch returns 0.
    With this optimization T.grad(T.switch(...)) has the right behavior.

    Examples
    --------
      x -> f(x)
      x -> g(x)
      y = T.switch(cond,f(x),g(x))
      **without the optimization
      T.grad(y,x) -> grad(f(x),x) * grad(y,f(x)) +  grad(g(x),x) * grad(y,g(x))
      **with the optimization
      T.grad(y,x) -> switch(cond,grad(f(x),x), 0) + switch(cond,0,grad(g(x),x))
    This will be particularly useful for the lazyif because we skip
    an entire part of the graph.

    i   RJ   g        i   i    (   Rj   R5   R  R?   R   RL   R   RY  R/   R   R   R   R(   R  t   values_eq_approxR2   (   R   R0  R9   RY  t   listmult   fmult   fct(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRV  }  s@    	c         C` s  |  j  t j k r( |  j  t j k r( t S|  j  } |  j d j r|  j d j j  t j k r|  j d j } y t | j d d t	 d k r| | j d |  j d  } t
 |  j |  t j | j d d |  g } t | d j _ t
 |  j | j |  | SWn t k
 rn Xy t | j d d t	 d k r| | j d |  j d  } t
 |  j |  t j | j d | d  g } t | d j _ t
 |  j | j |  | SWqt k
 rqXn  t S(   s  
    This optimization makes the folowing changes in the graph:
    T.div(T.switch(cond,0,iff),A) -->  T.switch(cond,0,T.div(iff,A))
    T.div(T.switch(cond,ift,0),A) -->  T.switch(cond,T.div(ift,A),0)

    A being a symbolic variable.
    This is useful because A may not be numerically stable and give
    NaN or inf values for cases where the switch returns 0.
    See local_mul_switch_sink for more details.

    i    i   RJ   g        i   (   Rj   R5   t   true_divt   int_divR?   RL   R   RY  R/   R   R   R   R(   R  R  R2   (   R   Rj   RY  t   fdivR  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_div_switch_sink  s<    $	,c         ` s  t  j  t |  j t j  sG t |  j j  j  j  j	 f  rK d  St
  f d   |  j D  sn d  S|  j d j j d   t
   f d   |  j d D  s d  St j   |  j g  |  j D] } | j j d ^ q   |  j g  |  j D] } | j j d ^ q    g S(   Nc         3` sK   |  ]A } | j  oB t | j  j t j  oB t | j  j j   j  Vq d  S(   N(   R   R   Rj   R5   R   R   R  (   R;   R  (   R*  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>   s   i    c         3` s%   |  ] } | j  j d    k Vq d S(   i    N(   R   RL   (   R;   R  (   R  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>&  s    i   i   (   Ro   R"   R   Rj   R5   R   R   t   BinaryScalarOpR6  R  RE   RL   R   RY  (   R   R  (    (   R  R*  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_merge_switch_same_cond  s    	%#	,c         C` sB  t  |  j t j  r>yt j |  j d d t } | d k r%y t j |  j d  } | |  j d j k r} |  j d g S| |  j d j k  r d S|  j d g Sd S|  j d j } d g | | t	 |  } |  j d j
 |  } t |  j |  j d |  | g SWq%t k
 r!d SXn  Wq>t k
 r:d SXn  d S(   sn   Tile(x, (1,)*N) -> x

    This is useless tile. (1,)*N, just mean a vector with all element
    being 1.

    i   RJ   i    NR   (   R   Rj   R5   t   TileR/   RL   R   t   get_vector_lengthR`   R   R  R   R   R   R2   (   R   R  R  t   x_ndt   broadR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_tile1  s,    	c         C` s   t  |  j t j  r |  j j d k r |  j \ } } } t | t j | j d d   } t	 |  j
 |  t | t j | j | | d   } t	 | |  | g Sn  d S(   sH    Split{n_splits=1}(x, y) -> x

    Remove Split with only 1 split.

    i   i    N(   R   Rj   R5   t   Splitt
   len_splitsRL   R  R   R\   R   R   (   R   R   R  t   splitsR%  t   out2(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_split`  s    
"&c         C` s   t  |  j t j  r |  j d j r t  |  j d j j t j  r t |  j d j j  d k r |  j |  j d j j d  } t |  j	 |  |  j d j j |  } t |  j	 |  j d g |  | g Sd S(   s   
    Flatten(UnaryElemwise(x)) -> UnaryElemwise(Flatten(x))

    This optimization is needed by optimization
    nnet/sigm.py:log1msigm_to_softplus to get applied when there is a flatten.

    i    i   N(
   R   Rj   R5   t   FlattenRL   R   R   R>   R   R   (   R   R   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_flatten_liftz  s     c         ` s%   t  j   g    f d    } | S(   Nc         ` s{   t  j |       s t S|  j |  j d j j d |  j d  } t |  j |  | j |  j d j k rs | g St Sd S(   sE   
        Reshape(Reshape(shape1),shape2) -> Reshape(shape2)

        i    i   N(	   R
   t   check_chainR?   Rj   RL   R   R   R   R^   (   R   Rg   (   Rj   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    *
(   R   t   local_optimizer(   Rj   R   (    (   Rj   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_reshape_chain  s    !R   R  c         C` s  |  j  } t | t  s t S|  j d } |  j d } |  j d } | j | j k rY t S| j d k r | j d k r | j | j k r | g S| j r t | j j  t	  r | j j d } | | k r | g Sn  | j rt | j j  t
  r| j j } t |  d  sd } n t |  j d d  } t g | j } xt | j  D]}	 | |	 }
 |
 j rt |
 j j  t  r|
 j j  j |	 k r|
 j j d | k rt | |	 <qKn  |
 j rft |
 j j  t  rft |
 j j  d k rft |
 j j d  |	 k rf|
 j j d } | j rft | j j  t	  rf| j j d } | | k rct | |	 <qKqcqfn  | j |	 rt |
 d d d k rt | |	 <qKn  | rK| j | |	  } | |
 k st | d d t |
 d d k rt | |	 <qKqqKqKWt |  r| g Sn  d S(   s   
    Remove two kinds of useless reshape.

    Remove Reshape when both the input and output have a single dimension.
    Remove Reshape when reshaping to the shape of the input.

    i    i   Re   RR   i   RJ   N(   Rj   R   R3   R?   RL   R   R`   R^   R   R%   R  RZ   RW   R   Re   R   R&   R9   R   R   R>   R1   RR  RE   (   R   Rj   R  R  R  t   shape_inputt   output_shape_isRR   t   shape_matchR  t   outshp_it   subtensor_inpt   shape_input_it   inpshp_i(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_reshape  sf    	
	

	


c         C` s8  |  j  } t | t  s t S|  j d } |  j d } |  j d } g  } g  } d } xs t | j  D]b } t | | d t d t }	 |	 d k r | j	 d  qe | j	 |  | j	 |	  | d } qe W| | j k r4| j
 t |   | |  }
 t | |
  t |
 j j |  |
  g } t | |  | Sd S(   s  
    Broadcastable dimensions in Reshape are replaced with dimshuffle.

    The goal is to avoid using reshape to add or remove broadcastable
    dimensions, but use dimshuffle instead, so dimshuffles can cancel out
    or be removed later on.

    For example:
        - reshape(x, (1, n)) --> dimshuffle{x,0}(reshape(x, (n,))
        - reshape(x, (1, m, 1, n, 1, 1))
          --> dimshuffle{x,0,x,1,x,x}(reshape(x, (m, n)))
    i    i   RJ   RI   R   N(   Rj   R   R3   R?   RL   R   R   R`   R1   RK   R   R>   R   R   RT   R^   (   R   Rj   R  R  R  R  R  t   indexR9   R  R  R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_reshape_to_dimshuffle  s.    		c         C` s#  t  |  j t j  r|  j d j rt  |  j d j j t j  rt |  j d j j  d k r|  j |  j d j j d |  j d  } t |  j	 |  |  j d j j |  } t |  j	 |  j |  | j
 |  j	 d j
 k rt j | |  j	 d j  } t | |  n | } | g Sd S(   s   
    Reshape(UnaryElemwise(x)) -> UnaryElemwise(Reshape(x))

    This optimization is needed by optimization
    nnet/sigm.py:log1msigm_to_softplus to get applied when there is a reshape.

    i    i   N(   R   Rj   R5   R3   RL   R   R   R>   R   R   RT   R  R^   (   R   R   R   t   re(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_reshape_liftJ  s    *t   remove_tensor_copyt	   Canonizerc           B` s}   e  Z d  Z e d  Z d   Z d   Z d   Z d   Z e	 d    Z
 d   Z d   Z d d	  Z d
   Z d   Z RS(   s  
    Simplification tool. The variable is a local_optimizer. It is best used
    with a TopoOptimizer in in_to_out order.

    Usage: Canonizer(main, inverse, reciprocal, calculate)

    Parameters
    ----------
    main
        A suitable Op class that is commutative, associative and
        takes one to an arbitrary number of inputs, e.g. add or
        mul
    inverse
        An Op class such that inverse(main(x, y), y) == x
        e.g. sub or true_div
    reciprocal
        A function such that main(x, reciprocal(y)) == inverse(x, y)
        e.g. neg or inv
    calculate
        Function that takes a list of numpy.ndarray instances
        for the numerator, another list for the denumerator,
        and calculates inverse(main(\*num), main(\*denum)). It
        takes a keyword argument, aslist. If True, the value
        should be returned as a list of one element, unless
        the value is such that value = main(). In that case,
        the return value should be an empty list.

    Examples
    --------
    >>> import theano.tensor as T
    >>> from theano.tensor.opt import Canonizer
    >>> add_canonizer = Canonizer(T.add, T.sub, T.neg, \
    ...                           lambda n, d: sum(n) - sum(d))
    >>> mul_canonizer = Canonizer(T.mul, T.true_div, T.inv, \
    ...                           lambda n, d: prod(n) / prod(d))

    Examples of optimizations mul_canonizer can perform:

    | x / x -> 1
    | (x * y) / x -> y
    | x / y / x -> 1 / y
    | x / y / z -> x / (y * z)
    | x / (y / z) -> (x * z) / y
    | (a / b) * (b / c) * (c / d) -> a / d
    | (2.0 * x) / (4.0 * y) -> (0.5 * x) / y
    | 2 * x / 2 -> x
    | x * y * z -> Elemwise(T.mul){x,y,z} #only one pass over the memory.
    |           !-> Elemwise(T.mul){x,Elemwise(T.mul){y,z}}

    c         C` s:   | |  _  | |  _ | |  _ | |  _ | |  _ g  |  _ d  S(   N(   t   maint   inverset
   reciprocalt	   calculatet   use_reciprocalt   external_simplifiers(   Rk   R  R	  R
  R  R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRm     s    					c         C` s   |  j  j | | f  d  S(   N(   R  RK   (   Rk   t
   simplifierR   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   add_simplifier  s    c         C` s   |  j  |  j |  j g S(   N(   R  R	  R
  (   Rk   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   tracks  s    c         C` s  | j  d k s3 | j  j |  j |  j |  j g k r | j  r t | j  j t j  r | j  } | j } | j	 d } d | j
 j | j
 j t t | j
 j   } | j | k r |  j | j  j	 d  S| g g  f Sq | g g  f Sn  g  } g  } | j  } g  | j	 D] }	 |  j |	  ^ q}
 | j |  j k rt t j t t j d  |
   } t t j t t j d  |
   } nz | j |  j k r|
 d d |
 d d } |
 d d |
 d d } n1 | j |  j k r|
 d d } |
 d d } n  | | f S(   s  
        This extract two lists, num and denum, such that the input is:
        self.inverse(self.main(\*num), self.main(\*denum)). It returns
        the two lists in a (num, denum) pair.

        For example, for main, inverse and reciprocal = \*, / and inv(),

        | input -> returned value (num, denum)

        | x*y -> ([x, y], [])
        | inv(x) -> ([], [x])
        | inv(x) * inv(y) -> ([], [x, y])
        | x*y/z -> ([x, y], [z])
        | log(x) / y * (z + x) / y -> ([log(x), z + x], [y, y])
        | (((a / b) * c) / d) -> ([a, c], [b, d])
        | a / (b / c) -> ([a, c], [b])
        | log(x) -> ([log(x)], [])
        | x**y -> ([x**y], [])
        | x * y * z -> ([x, y, z], [])

        i    R   i   N(   R   (   R   RW   Rj   R  R	  R
  R   R5   R   RL   RT   R`   RZ  R   R   t   get_num_denumR   R   t   __iadd__R  t   operatort
   itemgetter(   Rk   R  t   dsnt   dsopt   dsi0t   compatible_orderR)  t   denumt   parentt   input2t   pairs(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s6    .!
			%$'c         C` s   t  |  t  |  } } | r@ | r@ t j |  j g  g    S| s |  j rh |  j |  j | g    S|  j g  g  d t g } n  | s | d k r t | d t	 j
  s t  | d S|  j |   Sn  |  j |  j | g   |  j | g    S(   s  
        Utility function which takes two lists, num and denum, and
        returns something which is equivalent to inverse(main(\*num),
        main(\*denum)), but depends on the length of num and the length
        of denum (in order to minimize the number of operations).

        Let n = len(num) and d = len(denum):

        | n=0, d=0: neutral element (given by self.calculate([], []))
        |           (for example, this would be 0 if main is addition
        |           and 1 if main is multiplication)
        | n=1, d=0: num[0]
        | n=0, d=1: reciprocal(denum[0])
        | n=1, d=1: inverse(num[0], denum[0])
        | n=0, d>1: reciprocal(main(\*denum))
        | n>1, d=0: main(\*num)
        | n=1, d>1: inverse(num[0], main(\*denum))
        | n>1, d=1: inverse(main(\*num), denum[0])
        | n>1, d>1: inverse(main(\*num), main(\*denum))

        Given the values of n and d to which they are associated, all
        of the above are equivalent to:
        inverse(main(\*num), main(\*denum))

        t   aslisti   i    (   R>   R5   RS   R  R  R
  t   merge_num_denumR?   R   R   R   Ra   R  R	  (   Rk   R)  R  t   lnt   ld(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR  ^  s    	c         C` sw   t  |  t  r\ t |  j d d  d k	 r9 |  j j } n	 |  j } | j d k rU | Sd Sn t  |  t  ro d S|  Sd S(   s   

        Returns
        -------
        object
            A numeric constant if v is a Constant or, well, a
            numeric constant. If v is a plain Variable, returns None.

        t   unique_valuei    N(	   R   R   R   R  RW   R!  R  R`   R   (   RP   R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   get_constant  s    	c         C` sK   |  j  d | |  j | |   } x# |  j D] \ } } | |   } q+ W| S(   s   
        Shorthand for:

        .. code-block:: python

            self.simplify_constants(*self.simplify_factors(num, denum))

        t   out_type(   t   simplify_constantst   simplify_factorsR  (   Rk   R)  R  R#  Rg   R   R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   simplify  s
    		c   	      C` s   t  |  } t  |  } | d k r | d k r x t r t |  } t  |  t  |  k } | j |  } x( | D]  } | j |  | j |  qs W| s | r3 Pq3 q3 Wn@ x= t |  D]/ } | | k r | j |  | j |  q q W| | f S(   s   
        For any Variable r which is both in num and denum, removes it
        from both lists. Modifies the lists inplace. Returns the
        modified lists. For example:

        | [x], [x] -> [], []
        | [x, y], [x] -> [y], []
        | [a, b], [c, d] -> [a, b], [c, d]

        i   (   R>   R   Rn  t   intersectionR   R   (	   Rk   R)  R  R  R   R  t   redot   interRP   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR%    s"    	c         C` s  g  g  } } g  g  } } xF | D]> } |  j  |  }	 |	 d k	 rR | j |	  q! | j |  q! WxF | D]> } |  j  |  }	 |	 d k	 r | j |	  qj | j |  qj W|  j s | r |  j | | d t d | }	 n! |  j | | d t d | g }	 g  |	 D] }
 t j |
 d | j	 ^ q}	 | rt
 |  d k rt
 |  d k r|	 rt
 |	  d k spt  |  j  | d  } | d k	 r|	 d j j |	 d j |  r| | f Sn  |	 | | f S(   sB  
        Find all constants and put them together into a single constant.

        Finds all constants in orig_num and orig_denum (using
        get_constant) and puts them together into a single
        constant. The constant is inserted as the first element of the
        numerator. If the constant is the neutral element, it is
        removed from the numerator.

        Examples
        --------
        Let main be multiplication:

        | [2, 3, x], [] -> [6, x], []
        | [x, y, 2], [4, z] -> [0.5, x, y], [z]
        | [x, 2, y], [z, 2] -> [x, y], [z]

        R  R#  RX   i   i    N(   R"  RW   RK   R  R  R   R?   R5   R   RX   R>   Ra   RT   t	   values_eqR  (   Rk   t   orig_numt
   orig_denumR#  R)  R  t   numctt   denumctRP   t   ctR  t   first_num_ct(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR$    s2    +0#	c      
   C` s  | j  } | |  j |  j |  j g k r+ t St | j  d k sF t  | j d } t | d  sf d  Sx | j	 D] \ } } | d k r qp n  xS t
 t | d d   t  r t | j d j	  d k r | j d j	 d d } q Wt | d d  |  j |  j |  j g k rp t Sqp W|  j | j d  \ } } |  j t |  t |  | j  \ } }	 d   }
 |
 | |  r|
 | |	  rt S|  j | |	  } | j j | j j k rt j t j t j t t | j j     } | |  } n  | j | j k | j | j k k st  | j | j k sFt | | j  d } n  | j | j k rkt | j _ | g St j d j  d	 | d
 | d | j d
 | j f   t Sd  S(   Ni   i    R  R  Rj   t    c         S` s5   t  |   t  |  k o4 t d   t |  |  D  S(   Nc         s` s*   |  ]  \ } } t  j | | k  Vq d  S(   N(   R(  RE   (   R;   t   xet   ye(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>M  s    (   R>   RE   RA   (   R   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   sameL  s    !R   s   CANONIZE FAILED: new, out = t   ,t   types(!   Rj   R  R	  R
  R?   R>   R   Ra   RZ   R  R   R   RW   R   R  R&  R   RT   R  RX   R5   R   R"   t   Identityt   specific_outR:   RL   R)   R  R  R   R   RC  (   Rk   R   Rj   R%  R  t   c_idxR+  R,  R)  R  R4  R   t   elem_op(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR   +  sH    	*	+c         C` s&   t  |  d d |  j |  j |  j f  S(   NR   s   Canonizer(%s, %s, %s)(   R   R  R	  R
  (   Rk   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   __str__n  s    N(   R   R   R   R   Rm   R  R  R  R  R   R"  R&  R%  RW   R$  R   R;  (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR    s   2				v	-		 U	Cc         C` s   |  r( | r( | r g  St  j d  Sn  | d  k r` t j g  |  | D] } | j ^ qE   } n	 | j } t j d d | } t t  j	 |  |  t t  j	 | |  } | r t  j
 | d k  r g  S| g Sn  | S(   Ni   RX   (   R(  RA  RW   R"   R  RX   Ro   R#  R   t   multiplyRE   (   R)  R  R  R#  RP   R/  t   one(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   mul_calculates  s    ,	(
t   local_mul_canonizerc         C` sI   |  j  t j k rE t j t j d d |  j d j |  j d  g Sd  S(   NiRX   i    (   Rj   R5   t   negR  R(  t   arrayRL   RX   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_neg_to_mul  s    "c         C` s  t  |  j t j t j j f  r|  j \ } | j r:| j j t j k r:| j j } g  | D]' } t	 j
 | j j  r^ | j   ^ q^ } t |  d k r d Sg  | D] } t	 j
 | j  s | ^ q } t |  d k r d } d } nl t |  d k r"| d j } |  j | d  } n7 t j |   } t |  j |  | j } |  j |  } t |  d k s~t |  j |  n  t  |  j t j j  r| d k rg  | D] }	 |	 | ^ q} n  | }
 | d k r|
 j |  n  t |
  d k r
t |  j |
  |
 St j |
   } t |  j | g |
  | g Sn  t  |  j t j  r| j r| j j t j k r|  j | j j d  }	 t j |	  } t |  j |	 | g  | g Sn  d S(   s   
    sum(scalar * smth) -> scalar * sum(smth)
    sum(-smth) -> -sum(smth)

    or

    prod(scalar * smth) -> scalar ** size(smth) * prod(smth)
    prod(-smth) -> -1 ** size(smth) * prod(smth)

    i    Ni   (   R   Rj   R5   R  RI   t   ProdRL   R   R  R(  RE   RT   R^   R  R>   R"  R   R   RK   R@  (   R   t	   node_inpst   termsR  t   scalarst   non_scalarst   new_op_input_nb_elementst   new_op_outputt   new_op_inputR  t
   mul_inputsR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_sum_prod_mul_by_scalar  sL    !'+		 
3c         C` s   t  |  j t j  r |  j j j d k r |  j j t j k r |  j d |  j d k r t j	 |  j d  } t
 |  j |  | g Sd S(   s-   
    Elemwise{sub}(X,X) -> zeros_like(X)
    i   i    i   N(   R   Rj   R5   R   R   t   ninR"   R,  RL   R5  R   R   (   R   t   res(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_elemwise_sub_zeros  s    c         ` s  t  |  j t j  s d S|  j j j d k r2 d S|  j d j } t  |  j j t j	 t j
 f  r |  j d |  j d k r t j |  j d d | d t } t |  j |  | g St  |  j j t j t j f  r*|  j d |  j d k r*t j |  j d d | d t } t |  j |  | g St  |  j j t j t j f  r|  j d |  j d k r|  j d } t |  j |  | g St  |  j j t j	  r(|  j d j r(t  |  j d j j t  r(t j |  j d d t d k r(t j |  j d d | d t } t |  j |  | g St  |  j j t j  r|  j d j rt  |  j d j j t  rt j |  j d d t d k rt j |  j d d | d t } t |  j |  | g St  |  j j t j  r;|  j d j r;t  |  j d j j t  r;t j |  j d d t d k r;|  j d g St  |  j j t j  rt j |  j d d t d k r|  j d j rt  |  j d j j t  r|  j d g St  |  j j t j  rN|  j d j rNt  |  j d j j t  rNt j |  j d d t d k rNt j |  j d d | d t } t |  j |  | g St  |  j j t j  rt j |  j d d t d k r|  j d j rt  |  j d j j t  rt j |  j d d | d t } t |  j |  | g St  |  j j t j	  r|  j d j rt  |  j d j j t  rt  |  j d j j j t j  rt g  |  j d j j D]$ } t  | j o| j j t  ^ qj rt j |  j d d t d k rt j |  j d d | d t } t |  j |  | g St  |  j j t j  r|  j d j rt  |  j d j j t  rt  |  j d j j j t j  rt g  |  j d j j D]$ } t  | j o| j j t  ^ qo rt j |  j d d t d k rt j |  j d d | d t } t |  j |  | g S  f d     t  |  j j t j  r|  j d j r  |  j d j  ryb t |  j d d t } t j |  j d d | d t } | d k  rt |  j |  | g SWqt k
 rqXn  d S(	   s  ...

    :note: These cases appear in the graph generated by scan.
           These optimizations will make the graph easier to read.
    # Comparing to itself is constant
    Elemwise[{LT,GT}](X, X) -> Elemwise[zeros](X)
    Elemwise[{LE,GE}](X, X) -> Elemwise[ones](X)
    Elemwise[{minimum,maximum}](X, X) -> X

    # Comparing shape to 0 can be constant
    Elemwise[LT](X.shape[i], 0) -> Elemwise[zeros](X)
    Elemwise[GE](X.shape[i], 0) -> Elemwise[ones](X)
    Elemwise[maximum](X.shape[i], 0) -> X.shape[i]
    Elemwise[maximum](0, X.shape[i]) -> X.shape[i]
    Elemwise[minimum](X.shape[i], 0) -> 0
    Elemwise[minimum](0, X.shape[i]) -> 0

    # The shape can be replaced with sum of shapes
    Elemwise[LT](add([anything that is shapes]), 0) -> Elemwise[zeros](X)
    Elemwise[GE](add([anything that is shapes]), 0) -> Elemwise[ones](X)

    # Shapes are never negative
    # Needed by Reshape.infer_shape
    Elemwise[EQ](Subtensor(Shape(x)), -N) -> Elemwise[zeros](X)

    Ni   i    i   RX   R
   RJ   c         ` s   t  |  j t j t f  r t St  |  j t  rU |  j d j rU   |  j d j  St  |  j t j	  r t
   f d   |  j d D  St  |  j t  r t
   f d   |  j D  Sd S(   s.    Return True if values will be shapes, so >= 0i    c         3` s'   |  ] } | j  o   | j   Vq d  S(   N(   R   (   R;   RP   (   t   investigate(    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s   i   c         3` s'   |  ] } | j  o   | j   Vq d  S(   N(   R   (   R;   RP   (   RP  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s   N(   R   Rj   R5   R%   R&   R   R   RL   R   R  RE   R  (   R   (   RP  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRP    s    "(   R   Rj   R5   R   R   RM  R   RX   R"   t   LTt   GTRL   R5  R   R   R  t   GER  t   Minimumt   MaximumR   R&   R1   R6  RE   t   EQR/   R2   (   R   RX   RN  R   t   cst(    (   RP  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt!   local_useless_elemwise_comparison   s     !"!"!""""""""""">""">"" 	"c         ` s%  t  |  j t j t j j f  r!|  j j     d k rX t t	 |  j
 d j     n  |  j
 d } | j r!| j j t j k r!| j j
 \ } } t j j rBt  |  j t j  rB| j rBt  | j j t j  rB| j j j } t } x:   D]2 } t |  | k s| | d k r t } Pq q W| rBt j d  qBn  | j rt  | j j t j  r| j j
 d } | j j j } g  } g  }	 xM   D]E } | t |  k  r| | d k r| j |  q|	 j |  qWg  }
 xD |	 D]< } |
 j | t g  | D] } | | k  rd ^ q  qWt |  d k rt   f d   t |  D  } x- t |  d k r| d d k r| d =qbWt d   t |  D  r| } nO t j | j j |  |  } t j j rt  |  j t j  rt j d  n  t  |  j t j  rlt j | d | } t j | |  } t |
  d k rt j | d |
 } qn t  |  j t j j  rt j | d | } | j } t j | | t j g  | D] } | j | j  |  ^ q  } t |
  d k rt j | d |
 } qn  | g Sqq!n  d S(	   s   
    sum(a / dimshuffle{...}(b), axis=l) -> sum(a, axis={...}) / b,
    if dimension l of the DimShuffle is 'x'

    or

    prod(a / dimshuffle{...}(b), axis=l) ->
    prod(a, axis={...}) / b ** a.shape[l],
    if dimension l of the DimShuffle is 'x'
    i    R   s   WARNING: Your current code is fine, but Theano versions between rev. 3bd9b789f5e8 (2010-06-16) and cfc6322e5ad4 (2010-08-03) would have given an incorrect result. To disable this warning, set the Theano flag warn.sum_div_dimshuffle_bug to False.i   c         3` s3   |  ]) \ } } |   k s' | d  k r | Vq d S(   R   N(    (   R;   R9   t   ax(   R  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s    	c         s` s!   |  ] \ } } | | k Vq d  S(   N(    (   R;   R9   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pys	   <genexpr>  s    R  N(!   R   Rj   R5   R  RI   RC  R  RW   R   R   RL   R`   R   R  R   R]  t   sum_div_dimshuffle_bugR   R   R   R>   R?   R   RK   R   R   RE   RT   R^   t   prodRX   R\   R6  (   R   t
   node_inputt	   numeratort   denominatorR   t   compatible_dimsRY  t   dimshuffle_inputt   dimshuffle_ordert   incompatible_dimst   reordered_incompatible_dimst   ic_axt   c_axt   optimized_dimshuffle_ordert   optimized_dimshufflet   op_on_compatible_dimsRg   RX   (    (   R  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_sum_prod_div_dimshuffle  s    !	"	.			
			-c         C` s   t  |  j t j  s- t  |  j t j j  r t  |  j t j  rK t j n	 t j j } |  j j d k rm d St |  j j  t t	 |  j
 d j j   k r | d d d |  j j  |  j
 d  g Sn  d S(   sA   
    Sum{0,1,...N} -> Sum{} or
    Prod{0,1,...N} -> Prod{}

    Ni    R  RX   (   R   Rj   R5   R  RI   RC  R  RW   Rn  R   RL   RT   R`   RX   (   R   t   opt_type(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_sum_prod_all_to_none7  s    -*1c         C` s  t  |  j t j j  s- t  |  j t j  rt  |  j t j  rK t j n	 t j j } |  j \ } |  j j } t | j	  d k r| j
 rt  | j
 j |  j j  r| j
 j j d k s |  j j d k r | d d | | j
 j d  g St t | j
 j j   } xl |  j j D]^ } | } x0 | j
 j j D] } | | k r6| d 7} q6q6W| | k skt  | j |  qWt |  t t | j
 j j  t |  j j   k st  t t | j
 j d j j   } g  t |  D]' \ } }	 | | j
 j j k r|	 ^ q} g  t |  D]$ \ } }	 | |  j j k r"|	 ^ q"} g  t | j
 j d j j  D] } | | k ri| ^ qi}
 t j j j r| |
 k rt |  t |
  k rt j d  n  | | d | } | | j
 j d  g Sqn  d S(   sN   
    Prod(Prod()) -> single Prod()
    or
    Sum(Sum()) -> single Sum()

    i   RX   i    s  WARNING (YOUR CURRENT CODE IS FINE): Theano versions between version 9923a40c7b7a and August 2nd, 2010 generated bugged code in this case. This happens when there are two consecutive sums in the graph and the intermediate sum is not used elsewhere in the code. Some safeguard removed some bad code, but not in all cases. You are in one such case. To disable this warning (that you can safely ignore since this bug has been fixed) set the theano flag `warn.sum_sum_bug` to False.N(   R   Rj   R5   RI   RC  R  RL   RX   R>   R  R   R   R  RW   R   RZ  Ra   RK   R   RT   R`   R   R   Ro   R   R]  t   sum_sum_bugR   (   R   Rj  RD  R/  t   newaxisR9   R  R  t   alldimsR  t   newaxis_oldt   combined(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_op_of_opI  sF    	-*	'" 
c         C` s{  t  |  j t j  rw|  j d j rwt  |  j d j j t j  rw|  j d j } t j | j d d t d k rz d St  |  j j	 t
 j t
 j f  r t | j  d k r d Sn> t  |  j j	 t
 j t
 j f  s d St | j  d k r d Sg  } x | j d D]p } | j } | s"d St  | j t  sa| j j d	 t t | j d j   k red S| j | j d  q	Wt |  j j	  |   } | j |  j d j k rd S|  j j } | d k rt t |  j d j   } n  t |  d k sd | k r*t j j j r&t  j d  n  d Sy1 t! | j d d t } | | d k rZd SWn t" k
 rod SX| g Sd S(
   sL  
    Reduce{scalar.op}(Join(axis=0, a, b), axis=0) -> Elemwise{scalar.op}(a, b)

    Notes
    -----
    Supported scalar.op are Maximum, Mimimum in some cases and Add and Mul in
    all cases.

    Currently we must reduce on axis 0. It is probably extensible to the case
    where we join and reduce on the same set of axis.

    i    RJ   Ni   i   i   R   s  Your current code is fine, but Theano versions prior to 0.7 (or this development version Sept 2014) might have given an incorrect result for this code. To disable this warning, set the Theano flag warn.reduce_join to False. The problem was an optimization, that modified the pattern "Reduce{scalar.op}(Join(axis=0, a, b), axis=0)", did not check the reduction axis. So if the reduction axis was not 0, you got a wrong answer.(   R   (#   R   Rj   R5   t   CAReduceRL   R   R  R1   R   R   R"   RU  RT  R>   R6  R  R   R   RZ  R   R`   RK   R   RX   R   R  RW   R   Ro   R   R]  t   reduce_joint   warningsR/   R2   (   R   RC  R	  R   R
  t   reduce_axist	   join_axis(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_reduce_join  sT    "!!	 
		t   local_cut_useless_reducec         C` sH   t  |  j t j  rD |  j \ } | j |  j d j k rD | g Sn  d S(   s   Sum(a, axis=[]) -> a  i    N(   R   Rj   R5   Rr  RL   RT   R   (   R   t   summed(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_reduce  s    c         C` s  t  |  j t j  r|  j \ } |  j d j } |  j j d k rk t	 | j
  r| j   j |  g Sqt |  j j  } g  | D] } | j
 | r | ^ q } | rg  } g  } d } xY t | j  D]H }	 |	 | k r |	 | k r | j |  n  | j |	  | d 7} q q W| j |   }
 | rt |  j  t j j j k rk|  j j |  j j d | } n |  j j d |  } | |
  g S|
 j |  g Sqn  d S(   s/   Remove reduction over broadcastable dimensions.i    i   R  N(   R   Rj   R5   Rr  RL   R   RX   R  RW   RE   R^   R  R6  R   R   R`   RK   RT   Ro   R   RI   R   R   (   R   t   reducedt   odtypeR  R  t   cuttableRQ  t   patternR  t   pt   new_reducedR  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_reduce_broadcastable  s4    &c         C` s  t  |  j t j  s- t  |  j t j j  r|  j \ } | j rt  | j j t j  r| j j d } | j j d } |  j j	 d k s |  j j	 t t | j   k r]y t | d t } | j d k s t  t j |   j t | j   } t  |  j t j  r'| j d  d | } n | j d  d | } | g SWqt k
 rYqXqyt | d t } | j d k st  | j d  d } g  t t |   D]" } | |  j j	 k r| | ^ q} | r+t j |   j t | j   } t  |  j t j  r| | 9} q+| | } n  t j | g  t t |   D]" } | |  j j	 k rG| | ^ qG g SWqt k
 rqXqn  d S(   s   
    sum(alloc(constant,shapes...)) => constant*prod(shapes)
    or
    prod(alloc(constant,shapes...)) => constant**prod(shapes)

    i    i   RJ   N(   R   Rj   R5   R  RI   RC  RL   R   R.   R  RW   RZ  R   R`   R/   R   R"  Ra   R  R6  Rb   RX   t   reshapeR2   R   R>   R]   (   R   RD  R  t   shapesRl  t   castedR9   t   to_prod(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_opt_alloc  sF    	-!!		!		"!	*c         C` s]   |  j  t j k rY |  j d j rY |  j d j j  t j k rY |  j d j j d g Sn  d  S(   Ni    (   Rj   R5   R@  RL   R   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_neg_negL  s    ,c         C` s  |  j  t j k r|  j d j r|  j d j j  t j k r|  j d } | j j \ } } | j r | j j  t j k r t | j  d k r| j j d } t j | |  g Sqt j	 | j
  rt | t  rt | j  d k r| j } t j | |  g Sqqn  d S(   sf   
    - (-a / b) -> a / b

    Also performs - (c / b) -> ((-c) / b) when c is a scalar constant.

    i    i   N(   Rj   R5   R@  RL   R   R  R>   R  R(  RE   R^   R   R   R  (   R   t   fracR)  t   denomt   new_num(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_neg_div_negV  s    	,!
c         C` s   |  j  t j k r |  j d j } xi |  j D][ } y t |  } Wn t k
 rX q, n X| d k r, t t	 j
 d d | j |  j  Sq, Wn  d S(   sX   
    As part of canonicalization, we replace multiplication by zero
    with zero.

    i    RX   N(   Rj   R5   R  R   RT   RL   R/   R2   R:   Ro   R#  RX   (   R   R   R9   Rc   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_mul_zeron  s    c         C` s   |  j  t j k r t j t j |  j d  d k  r |  j d } t j	 t j
 |  j d g    } | j | j k r t j | d | j } n  | j | j k r t | | |  j  } n  | g St Sd  S(   Ni    g      ?i   RX   (   Rj   R5   R  R(  RE   R?  R"  RL   R   t   invR  RX   RY   RT   Rh   Re   R?   (   R   R%  R7   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_div_to_inv  s    c         C` s4   |  j  t j k r, t j |  j d d  g St Sd  S(   Ni    g      (   Rj   R5   R  t   powRL   R?   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_inv_canon  s    c         C` s   |  j  t j k r t j |  j d  } | d k rQ t d |  j d |  j  g S| d k r t |  j d |  j d |  j  g Sn t	 Sd  S(   Ni   i    (
   Rj   R5   R  R?  R"  RL   Rh   R   Re   R?   (   R   RW  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_pow_canonicalize  s    'c         C` sb   |  j  t j k r^ t |  j  d k r^ |  j d |  j d k r[ t j |  j d  g Sq^ n  d S(   sw   
    x*x -> sqr(x)

    This is faster on the GPU when memory fetching is a big part of
    the computation time.

    i   i    i   N(   Rj   R5   R  R>   RL   R  (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_mul_to_sqr  s    
c         C` su   |  j  t j g k rq t |  j d t j  rq t j |  j d j d k  rq |  j d j	 |  j
 d j  g Sn  d S(   s   x // 1 -> x
    i   i    N(   Rj   R5   R  R   RL   R  R(  RE   Rc   R6  R   RX   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_intdiv_by_one  s    c         C` s   t  |  j t j  r t  |  j j t j j t j j f  r t	 j
 |  j d  d k r t d |  j d |  j  } t | j _ | g Sn  d S(   s   0 / x -> 0
    i    N(   R   Rj   R5   R   R   Ro   R"   t   IntDivt   TrueDivR?  R"  RL   Rh   R   Re   R(   R  R  (   R   R
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_zero_div  s    $c         C` s  |  j  t j k r|  j d j } |  j d } |  j d } t j |  } | d  k	 rt	 | j
 j | j
 j  rd  } t j | d k  r t j |  g } n  t j | d k  r | g } n  t j | d k  r t j | t j d d |  g } n  t j | d k  r)t j |  g } n  t j | d k  r\t j t j |   g } n  t j | d k  rt j |  g } n  t j | d k  rt j t j |   g } n  | rt j | d |  | d <| d j
 |  j d j
 k st | |  j f   | Sqn t Sd  S(	   Ni    i   i   RX   g      ?g      ii(   Rj   R5   R  R   RX   RL   R?  R"  RW   RD   RT   R^   R(  RE   R  R6   t   asarrayt   sqrtR  RY   Ra   R?   (   R   R|  t   xsymt   ysymR   Rg   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_pow_specialize  s:    ' 
c         C` s  |  j  t j k r|  j d j } |  j d } |  j d } t j |  } t | t	 j
  r | j d k sr t  y | d } Wq t k
 r q Xn  | d k	 rt | j j | j j  rd } t |  t t |   k rlt |  d k rl| g } t j j | j    g } t |  } xZ t t t	 j |    D]= }	 | j t j | |	   | j t j j | |	   q@Wd }
 d } xl | d k rt t	 j |   } |
 r|
 | | 9}
 | | | 9} n | | }
 | | } | d | 8} qWt |  d k r?t t j j | d g | g   j |  }
 n  | d k  r`t j |
  g } ql|
 g } n  | rt j | d |  | d <| d j |  j d j k st | |  j f   | Sqn  d S(   sU   
    This optimization is not the same on all device. We do it only on cpu here.
    i    i   i   i   N(    Rj   R5   R  R   RX   RL   R?  R"  R   R(  R`  R"  Ra   R  RW   RD   RT   R^   t   absR^  Ro   R"   t   get_scalar_typeR   t   log2RK   R  R   t	   CompositeR!  R  RY   (   R   R|  R  R  R   Rg   t   pow2t	   pow2_scalt   y_to_doR9   t   rval1t
   rval1_scalt	   log_to_do(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_pow_specialize_device  sX    
0	"!

	% c   	      C` s>  |  j  t j k r:t } g  } d } d } x |  j D] } xF | j r | j j  t j k r | t N} | j j d } | d 7} q= Wt j	 |  } | d k r | d 7} q4 | d k r | d 7} | t N} q4 | d k r t
 d |  j d |  j  g S| j |  q4 W| |  j k r:| rt |  d k rq| rd| d j t j d g k rVd S| d } q| d } nf | r| d k r| d k rd S| rt j d d	 |  j d j } | g | } n  t j |   } t
 | |  j d |  j  g S| rt
 d |  j d |  j  g St
 d |  j d |  j  g Sq:n  d S(
   s&  
    Remove special-case constants from mul arguments and useless neg in inputs.

    mul(-1, x) -> neg(x)
    mul(1, x, y) -> mul(x, y)
    mul(0, ...) -> alloc(0, shapes...)

    This is not done if we would add more nodes in the graph, like with:

    mul(-1, x, y) -/-> neg(mul(x, y))

    i    i   g      ?g      g        t   boolNiRX   (   Rj   R5   R  R?   RL   R   R@  R   R?  R"  Rh   R   Re   RK   R>   RX   t   uint_dtypesR(  R  (	   R   R@  R  t   nb_neg_nodet   nb_cstR  R   Rg   t   m1(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_mul_specializeB  sN    !

c   	      ` s    f d   }   j  t j k rg  } xc   j D]X } y t |  } Wn t k
 r` | } n Xt j | d k  r| q1 n  | j |  q1 Wt	 |  t	   j  k  r  j
 d j j } t	 |  d k r+  j
 d j j } t j t j d | d |  } | j j t f | k s!t  | |  St	 |  d k rP| | d  } n | t j |    } | d j | k rt j | d |  g } n  | Sn t Sd  S(   Nc         ` s   t  |    j  } | S(   N(   R:   RL   (   RP   R%  (   R   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt
   fill_chain  s    g        i    i   RX   (   i   (   Rj   R5   Ro  RL   R/   R2   R(  RE   RK   R>   R   RT   RX   R`   R   R  R^   R   Ra   RY   R?   (	   R   R  R  R  R   RX   R`   RW  R
  (    (   R   s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_add_specialize  s2    
"
t   apply_all_optst   mul_canonizer_groupsc         C` s   x t  |  D] } | j r | j j t j k r | j j d |  k r | j j d j j j d  ri q | j	 |  |  j	 | j j d  |  j
 t j | j j d   q q W|  | f S(   s   Convert x/abs(x) into sign(x). i    t   complex(   R   R   Rj   R5   t   abs_RL   RT   RX   t
   startswithR   RK   t   sgn(   t
   numeratorst   denominatorst   den(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   check_for_x_over_absX  s    't   X_over_absXc         C` s   |  j  t j k r |  j d j r |  j d k s7 t  |  j d j j  t j k r t j g  |  j d j j D] } t j |  ^ qm   g S|  j d j j  t j k r |  j d j j } t j t j | d  t j | d   g Sn  d S(   sn   
    Move the abs toward the input.

    This is needed for check_for_x_over_absX to apply in more case.

    i    i   N(	   Rj   R5   R  RL   R   RM  Ra   R  R  (   R   R9   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_abs_lift  s    	"9c         C` s  |  j  t j k r!t g  |  j D]$ } | j r | j j  t j k ^ q  d k r!g  } x |  j D] } | j r | j j  t j k r | j | j j d  qb t | t	  r y t
 | d t } Wn t k
 r t SX| d k j   s t S| j |  qb t Sqb Wt j t j |    g S|  j  t j k rt g  |  j D]$ } | j r@| j j  t j k ^ q@ d k rt j t j |  j d j j d |  j d j j d   g Sd S(   s]   
    Merge abs generated by local_abs_lift when the canonizer don't
    need it anymore

    i   i    RJ   i   N(   Rj   R5   R  R   RL   R   R  RK   R   R   R/   R   R2   R?   RE   R  (   R   R9   RL   R"  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRU    s*    %-	: c         C` s  |  j  t j k r|  j \ } | j r | j j  t j k r t | j j d t \ } } } | rt j	 t j
 |  d  r| r t |  d k r t j |   } n
 | d } | j | j j k r | j |  j d j  } n  t t j |  |  Sqq| j r| j j  t j k rt j | j j d d t } | d k rLd  S| j j d } | j | j k r| j | j  } n  t j t j |   g Sn  d  S(   NRJ   i   i    (   Rj   R5   t   logRL   R   Ro  RQ   R   R(  t   allcloseR   R>   RX   RT   R6  R   R:   t   log1pR,  R1   R@  (   R   t   log_argRF  t   scalar_inputsRO   t   ninpR=  R9  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_log1p	  s,    !
	c         C` s   |  j  t j k r|  j d } | j r| j j  t j k r| j j } t |  d k r_ d  Sg  | D]4 } | j rf | j j  t j k rf | j j d ^ qf } t |  t |  k rt j |   } | t j	 t j t j g  | D] } | | ^ q     } t
 | j _ | g Sqn  d  S(   Ni    i   (   Rj   R5   R  RL   R   Ro  R>   t   expRb  R  R'   R  R  (   R   R  t   ziR   t   pre_expt   max_preR  R
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_log_add+  s    4$c   	      C` sY  |  j  t j k r d  S|  j d j } | r] t | j  t j  r] | j  } | j d j } n d  } | s t | j  t j  r d  S| j d j | j  j	 } } | s t | j  t
  o t | j  j t j  r d  S| j d } t j | d | } t j | | |  } | t j t j t j | |  d |  } | rR| |  } n  | g S(   Ni    R  (   Rj   R5   R  RL   R   R   R   RW   R  R  R   R   R"   R  t   maxt   makeKeepDimsR   R  (	   R   t   sum_nodet   dimshuffle_opt   exp_nodeR  R  t   max_pre_expt   max_pre_exp_keepdimsR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_log_sum_expL  s,    	,R  t   ignore_newtreesg?c         C` s   | d  k r d } n t j d d | j } t t j |  |  t t j | |  } | r~ t j | d k  rt g  S| g Sn  | S(   Ng        i    RX   (   RW   Ro   R#  RX   R   R(  Ro  RE   (   R)  R  R  R#  t   zeroRP   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   add_calculatew  s    	(
t   add_canonizer_groupt   local_add_canonizerc         C` s:  d } t  |  | t  |  } t t j t j g  |  D]# \ } }	 | | |	 | | f ^ q6   }
 t t j t j g  | D]# \ } }	 | | |	 | | f ^ q{   } xg t |  | |
 |  D]N \ \ } }	 \ } } | t  |  | t  |	  t  |  | t  |  7} q W| | k r-t |  | f St |
 | f S(   Ng      ?(	   R>   R   t	   itertoolst   starmapR?  R&  RA   R?   R   (   t	   pos_pairst	   neg_pairsR)  R  R#  t   minscoret   div_costt   scoreR   R  t   new_pos_pairst   new_neg_pairst   nnt   dd(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   distribute_greedy  s    33 :c         C` s  t  j |   \ } } t |  d k r> | r> t |  | | f St t t j |   } t t t j |   } t } xT t |  D]F }	 t | | |	 g g  |  \ }
 } } |
 r t } | j	 |	  q q WxT t |  D]F } t | | g  | g |  \ }
 } } |
 r t } | j	 |  q q W| s8| |  | | f S| t  j
 t t j t j
 |   t t j t j
 |    | | f Sd  S(   Ni   (   R  R  R>   R?   R   R  R?  R  R   R   R  R  R  (   t   factorR)  R  R#  RH  R@  R  R  t   changeR   t   successR  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   attempt_distribution  s2    		c         C` s  |  j  d } t j |  \ } } t |  d k r? | r? t Sg  g  } } t } | j } xk t |  D]] } | | k r qh n  | j |  t | | | |  \ }	 } } } | |	 O} | j	 |  qh Wxk t |  D]] } | | k r q n  | j |  t | | | |  \ }	 } } } | |	 O} | j	 |  q W| sAt S| | 7} | | 7} t j
 | |  }
 |
 j | j k s}t S|
 g S(   s'  
    Optimize by reducing the number of multiplications and/or divisions.

    This optimization tries to apply distributivity of multiplication
    to addition in order to reduce the number of multiplications
    and/or divisions that must be done. The algorithm weighs division
    more than multiplication to account for the former's slightly
    greater computational cost.

    The following expressions are simplified:
    1. ((a/x + b/y) * x * y) --> a*y + b*x
    2. ((a/x + b) * x) --> a + b*x
    3. There are other forms too where node is a true_div.

    The following expressions are not simplified:
    4. ((a + b) * x) -/-> a*x + b*x

    This optimization aims to reduce computational cost. It may also
    increase numerical stability, e.g. when x and/or y tend to 0 in
    example 1.

    i    i   (   R   R?  R  R>   R?   RT   R   R   R  RK   R  (   R   R%  R)  R  R  t	   new_denumR  R#  t	   candidatet   _changeRg   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_greedy_distributor  s>    	



c         C` s  x$ |  j  D] } t | t  s
 t Sq
 W|  j j |   s= t St g  |  j  D] } | | j g f ^ qJ  } t g  |  j  D] } | t g f ^ qx  } x+ |  j	 D]  } d  g | | <t g | | <q Wd  } t |  j d  r |  j j |   r d } n  |  j j |  | | d g  d | } |   } | s1t  g  }	 x |  j	 D] }
 | |
 d sot |
 | |
 d f   y |
 j j } Wn t k
 rt } n X| |
 j | |
 d  } t |
 |  |	 j |  qAW|	 S(   Nt   python_constant_foldingt   pyt   no_recyclingt   impli    (   RL   R   R   R?   Rj   t   do_constant_foldingR   R  R   R   RW   RZ   R  t
   make_thunkRa   RT   RH  R   RK   (   R   R  R9   t   storage_mapt   compute_mapR   R  t   thunkt   requiredRg   R  R   RP   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRX    s:    .+		(
t   topo_constant_foldingt	   final_optc         C` s3   g  |  j  d j D] \ } } | d k r | ^ q S(   s:   
    Used by erf/erfc opt to track less frequent op.

    i    R  (   R   R  (   R   R  R9   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   get_clientsN  s    c         C` s   g  } xv |  j  d j D]d \ } } | d k r xI | j  D]; } | j g  | j D] \ } } | d k rO | ^ qO  q9 Wq q W| S(   s:   
    Used by erf/erfc opt to track less frequent op.

    i    R  (   R   R  R   (   R   R  R  R9   R   t   ccR  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   get_clients2W  s    @i   R   t   allow_multiple_clientst   local_one_plus_erfR  t	   get_nodest   local_one_minus_erfit   local_one_minus_erf2t   local_one_plus_neg_erft   local_erf_minus_onet   local_one_minus_erfct   local_one_minus_erfc2t   local_one_minus_erfc3t   local_one_add_neg_erfct   local_erf_neg_minus_onet   local_erf_neg_minus_one2c         C` sr  |  j  t j k r t S|  j d j sC |  j d j j  t j k rG t St |  j d  r] t St	 |  j _
 |  j d j j d } | d t j |  d t j t j  t j d d d | d d d | d d d	 | d
  } |  j d j d k s|  j d j d k rd } n |  j d j d k r=d } n  t j | | k  |  j d |  } t | j _ | g S(   Ni    t   local_log_erfc_appliedi   g      ?i   i   i   i   i   i   t   float32t   float16gQ8o$@t   float64gWaI:@(   Rj   R5   R  R?   RL   R   t   erfcRZ   R  R   R  R(  t   piR   RX   RY  R'   R  (   R   R   t
   stab_valuet	   thresholdR
  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_log_erfc  s&    -))		"c         ` s  |  j  t j k r t S|  j d j sC |  j d j j  t j k rG t S|  j d } | j j d } |  j d j sx t S|  j d j j  t j k r d  } g  } |  j d j s |  j d j j  t j	 k r t S|  j d } n |  j d } d  } xH t
 | j j  D]4 \ } } | j r| j j  t j	 k r| } PqqWt | j j  d k rq| j j d | g } n | j j } | | =~ | j j d j st S| j j d j j  t j k r(| j j d } | j j d j s| j j d j j  t j k rt S| j j d }	 |	 j j d }
 n| j j d j j  t j k r| j j d }   f d       | j j  } x_ t t |   D]K } t | t  r| d k rPq| d } | | | d <| | | <PqqWt j |   } y  t | j j d d t } Wn t k
 rt SXt | j j  d k r| j j d j si| j j d j j  t j k rmt S| j j d }	 |	 j j d }
 nS t | j j  d k r| j j d | j j d k	 rt S| j j d }
 n t S| d k r| j s&| j j  t j k s&t | j j  d k r*t S| j j d | j j d k	 rNt S| }
 y  t | j j d d t } Wn t k
 rt SX| | d k rt Sq| |
 k	 rt Sn t St |  j d  rt St j | |  } t | j j _ |
 t j d d d |
 d d d	 |
 d	 d
 d |
 d d  t j t j t j  d |
 j } |
 j d k su|
 j d k r~d } n |
 j d k rd } n  t j |
 | k  | |  } | rt j | |  } n  t | j _ | g S(   Ni   i    i   c         ` sb   g  } xU |  D]M } | j  rM | j  j t j k rM | j   | j  j   q | j |  q W| S(   N(   R   Rj   R5   R  R   RL   RK   (   RL   R  R9   (   R!  (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR!  W  s    RJ   i   it   local_grad_log_erfc_negi   i   i   i   RX   R  R  g"@R  gWaI:@(    Rj   R5   R  R?   RL   R   R  R  RW   R  R   R>   R@  R  R   R   R   R/   R   R2   RZ   R  R  R  RY   R  R(  R	  RX   RY  R)   R  (   R   R  t   erfc_xR  R   R  R0  R   R@  R  R   t   mul_negRK  R9   t   tmpt   cst2RW  t   true_div_no_mulR
  R  R
  (    (   R!  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR  "  s    --

  C%		c         C` s   d S(   Ni    (    (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR   ]  s    c         ` s:    d k r   f d    n       f d     S(   s  
    We parametrize it to make it work for Elemwise and GpuElemwise op.

    Parameters
    ----------
    OP
        GpuElemwise or Elemwise class (the one that we want to fuse)
    max_input_fct
        A function that returns the maximum number of inputs
        that this elemwise can take (useful for GpuElemwise).
        GPU kernel currently has a limit of 256 bytes for
        the size of all parameters passed to it. As currently
        we pass many information only by parameter, we must
        limit how many ops we fuse together to avoid busting
        that 256 limit.

        On the CPU we limit to 32 input variables
        since that is the maximum numpy support.

    c         ` s
     |  S(   N(    (   R   R   (   Rl   (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   makert  s    c         ` s  t  |  j    k	 r t St |  j  d k r2 d Sg  } g  } g  }  |   } t |  j  } t } x|  j D]} t } t }	 g  }
 g  } | j rt | j j    rt t g  | j	 D] \ } } | ^ q   d k r| j j d j
 |  j d j
 k rt } yg  } x| j j D] } | | k rM| j | | j |   q| |
 k rv| j | |
 j |   qt j | j  j   } yJ t j j |  } | j d k r| j   d | j _ n | | j _ Wn t k
 rn X| j |  |
 j |  | j | d  qW| j j j d t |  } | j j j j | d j d g  | j j D] } d ^ q_g  | j j D] } d ^ q{i   Wn- t k
 rt }	 n t k
 rt }	 n X|	 rt j d	 t | j j j   t } qn  | t |
  d } x* |
 D]" } | |  j k r| d 8} qqW| r}| | k r}t } | } | j  |
  | j  |  | j  |  qo | j! |  |  j j! |  k r| | j |  } n t j | j  j   } yS t" j# j$ d
 k rt j j |  } | j d k r| j   d | j _ qn  Wn t k
 r2n X| j |  | j |  | j |  qo W| sht S| t |  k st |  t |  k rt% d   n  |  j j d t |  } yT | d j j j | d j d g  | D] } d ^ qg  | D] } d ^ qi   Wne t k
 rBt j d	 t | d j j   t St k
 rtt j d	 t | d j j   t SXt j& | |  }  |  |  |   j } t | j  d k st'  |  j d j | j d j k st'  t | j  | k rt j d  t Sxx t r |  } | t k	 r|| d k	 r|t |  t | j  k sTt'  t |  d k slt'  | d j } q	Pq	W| j S(   s%  
        As part of specialization, we fuse two consecutive elemwise Ops of the
        same shape.

        For mixed dtype, we let the Composite op do the cast. It lets the C
        compiler do the cast.
        The number of dimensions is validated at call time by theano itself.

        i   Ni    iR   t   test_presence_of_c_codeR   R  ss   %s does not implement the c_code function. As well as being potentially slow, this disables loop fusion of this op.t   offs   Something has gone wrong with the elemwise
fusion optimization. We skip this optimization. You can ignore this message,
your code will run correctly, but may be slower.sA   loop fusion failed because Op would exceed kernel argument limit.()   RT   Rj   R?   R>   R   RL   R   R   Rn  R  R^   R   RK   R  R"   R  RX   t   make_variableR   t   get_test_valueR"  t   flattenR  t
   test_valueRH  R   R1  R   RV   R   t   infoRb   R   t   countRo   R   t   compute_test_valueR   R  Ra   RW   (   R   RL   t   s_inputst   s_gt   max_nb_inputt   new_nb_inputt   fusedR9   t	   do_fusiont   catcht	   tmp_inputt
   tmp_scalarR   R0  t   tmp_s_inputR  R  t   tvt   s_opR   R  t   new_nb_input_R  RP   t	   s_new_outt   CR
  (   Rl   t
   local_fuseR  t   max_input_fct(    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR,  w  s    "	4	
	! *!		&	!N(   RW   (   Rl   R-  R  (    (   Rl   R,  R  R-  s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_elemwise_fusion_op]  s    c         C` s   t  j j s d Sd S(   Ni   i   (   Ro   R   t   cxx(   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   elemwise_max_input_fctQ  s    t   FusionOptimizerc           B` s;   e  Z d  Z d   Z d   Z d   Z e d d   Z RS(   s2   Graph optimizer for Fusion of elemwise operations.c         C` s   t  j |   | |  _ d  S(   N(   R*   Rm   t	   optimizer(   Rk   R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRm   _  s    c         C` s   | j  t j    d  S(   N(   Rn   R-   t   ReplaceValidate(   Rk   Re   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRr   c  s    c         C` s  t  } d } d } d } d } | j rN | j j } | j j   } | j }	 n  x| r_t j   }
 t | j    } | t j   |
 7} | j	   t
 } x | D] } | | j k r |  j |  } | rNt |  t | j  k s t  y? | j t t | j |   d |  j j t  } | d 7} WqKt k
 rG| d 7} qKXqNq q W| d 7} qQ W| j r| j j | } | j |	 } i  } x] t | j  D]7 \ } } | | k r| | | | | <q| | | <qWn d  } d  } i  } |  | | | | | | | f S(   Ni    R   i   (   R   t   profilet   validate_timet   execute_callbacks_timesR  t   execute_callbacks_timet   timeR   R  t   reverseR?   R   R2  R>   R   Ra   t   replace_all_validateRA   R   R   R   R   RW   (   Rk   Re   t   did_somethingt   nb_itert   nb_replacementt   nb_inconsistency_replacet   time_toposortt   validate_beforet   callbacks_beforet   callback_beforet   t0t   nodelistR   R   R5  t   callback_timet   callbacks_timeR   RP   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR   f  sZ    		
!
			i    c         C` s=  d | } t  | d d |  t  | d | d d |  t  | d | d d |  t  | d | d	 d |  t  | d
 | d d |  t  | d | d d |  | d d k rt  | d d |  xZ t t | d  d d   d  d  d  D]) } | d d k r t  | d |  q q Wn  t  | d | d d |  d  S(   Ns       R1  Rs   s    nb_iteri   s    nb_replacementi   s    nb_inconsistency_replacei   s    validate_timei   s    callback_timei   s    callbacks_timei   t   keyc         S` s   |  d S(   Ni   (    (   R  (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    ii    s        s    time_toposorti   (   Ry   Rz   R   (   R|   R}   R~   R   R9   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR     s    
3(   R   R   R   Rm   Rr   R   R   R   (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyR1  ]  s   			3c   	      C` s  t  |  j t  s5 t  |  j j t j t j f  r9 t S|  j j j } g  } t } t	 |  j
  } t d  } t |  j d  r |  j j |   } n  x |  j
 D] } | j r-t  | j j t  r-t  | j j j |  r-t	 | j  d k r-| t	 | j j
  d | k r-| j | j j
  t } q | j |  q W| r|  j |   } t |  j d |  | j rt | j  } | r| Sn  | g Sd S(   s<  Fuse consecutive add or mul in one such node with more inputs.

    It is better to fuse add/mul that way then in a Composite node as
    this make the inner graph of the Composite smaller. This allow to
    put more computation in a Composite before hitting the max
    recusion limit when pickling Composite.

    t   inft
   max_inputsi   i    N(   R   Rj   R   R   R"   R6  R  R?   R   R>   RL   R]  RZ   RI  R   R  R   R   RK   R   R   t   local_add_mul_fusion(	   R   R(  R	  R!  t	   nb_inputsRI  R   R  t   output2(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyRJ    s6    	"	 		s1   enabling optimization fusion elemwise in fast_runRJ  t   fusiont   composite_elemwise_fusiont   elemwise_fusioni1   t   local_elemwise_fusions5   not enabling optimization fusion elemwise in fast_runc         C` s  t  |  j t  s, t  |  j j t j  r0 d S|  j j } g  t |  j  D] \ } } | j rL | ^ qL } t	 |  t	 |  j  k  rg  | D] } | j | ^ q } t j d | j
 d |  } t d |  d t |  j
  } t t g  | D] } |  j | ^ q |   Sd S(   sb   For elemwise Composite that have multiple outputs, remove the
    outputs that are not used.

    NRL   R   R   R   (   R   Rj   R   R   R"   R  R   R   R  R>   RL   R   R   RA   (   R   t   compR9   t   o_externR0  R   R  R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_useless_composite  s     	t   remove_consider_constantt   remove_zero_gradt   remove_disconnected_gradc         C` s#   t  |  j t j j  r |  j Sd  S(   N(   R   Rj   Ro   t   gradientt   GradClipRL   (   R   (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_grad_clip  s    c   
      C` sD  t  |  j t j  s t S|  j d j sJ t  |  j d j j t j  rN t S|  j } |  j d j j } | d } | d } | d  d  d  } | d  d  d  } d } x t | |  D]o \ } }	 | |	 k rt  | t  r | j	 d k r qt
 d  |	 t j |	 |   | d | <n  | d 7} q Wt j | d |  g S(   Ni    i   is   You have a shape error in your graph. To see a better error message and a stack trace of where in your code the error is created, use the Theano flags optimizer=None or optimizer=fast_compile.(   R   Rj   R5   R.   R?   RL   R   RA   R   R  R  R   R]   (
   R   t   inputs_outert   inputs_innert
   dims_outert
   dims_innert   dims_outer_revt   dims_inner_revR9   t	   dim_innert	   dim_outer(    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   local_merge_alloc  s*    
	

#(#  t
   __future__R    R   R   t   collectionsR   t   loggingR  R  R   R8  RJ  Rt  R(  t   sixR   R   t	   six.movesR   R   Ro   R   t   theano.compatR	   t
   theano.gofR
   R   R   R   R   R   t   theano.gof.optR   R   t   theano.gof.utilsR   t   theano.gradientR   t   theano.configparserR   t   theano.tensor.elemwiseR   R   t   theano.tensor.subtensorR   R   R   R   R   R   R   R   R   R    R!   R"   t   theano.scalarR#   t   theano.tensorR5   R$   t   theano.compile.opsR%   R&   t   theano.tensor.typeR'   R(   R)   R*   R+   R,   R-   t   theano.tensor.basicR.   R/   R0   R1   R2   R3   R4   t	   getLoggerR   R:   RD   RH   R   R?   RQ   RW   Rh   Ri   R   R   R   R   R   R   R   R   R   R  R   R   R   R  R   R  R  R  R  R  R  t   OpR  R  R?  t   pprintt   assignt   objectRF  R  R  R   R  R  R  R6   R  R  R]   R  R  R  R  R  R  R  R  R  R  R  R  R  R	  R  R   R  R#  R$  R0  R5  R:  R@  RM  RT  Rz  R  R  R  Ro  R  R  t   warn_inplaceR  R  R  R  R  RN  R  R  R  R  R  R  R  RI   R  R  R  RW  R  RV  R  R  R  R  R  R  R  R  R  R  R  R  R  R  t   OpRemovet   tensor_copyt   LocalOptimizerR  R>  R  R?  R@  RB  RC  RL  RO  RX  Ri  Rk  Rq  Rr  t   Allt   Anyt   ProdWithoutZerost
   ALL_REDUCERw  Rz  R  R  R  R  R  R  R  R  R  R  R  R  R  R  R  R  t   LocalOptGroupt   mul_canonizerR  R  R  R  RU  R  R  R  R  R  R,  R  t   add_canonizerR  R  R  RX  R  R  R  t
   PatternSubt   erfR  R  R  R  R  R  R  R  R   R  R  R  R  R  R.  R0  RP  R1  RJ  R   t   debugt
   SequenceDBt   fuse_seqoptRS  RW  t   consider_constant_t
   zero_grad_t   disconnected_grad_RX  RY  Rb  (    (    (    s1   /tmp/pip-build-X4mzal/theano/theano/tensor/opt.pyt   <module>   sd  "L.			' 
						$3		.#

$$e	  v				,
$)	
	
	$*'4	$!!!.	'T	'`!$$#	T	!G$3$$$~	f	!M$E$:!J	
!	!						!!!3	!m'$7	%''4')''	'V$Q'F!','$!	!'W!-$Q !
*X!*-{**DO	
!&*2!	!




!!
*$
!CL
(
		!'$ $&
		 	!0D(					


	


	


	


	


	


	


	


	


	


	


$'$ :			M	.					
		$