
Xc           @` s  d  Z  d d l m Z m Z m Z d d l m Z m Z 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 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 d d	 l m Z m  Z  m! Z! m" Z" m# Z# d d
 l$ m% Z% d d l& m' Z' d d l( m) Z* e j+ d  Z, d g Z- d   Z. d e/ f d     YZ0 d e0 f d     YZ1 d   Z2 d   Z3 d e0 e4 f d     YZ5 d f  d     YZ6 d e/ f d     YZ7 d e0 f d     YZ8 e9 d  Z: d   Z; d  e/ f d!     YZ< d" e< f d#     YZ= d$ e< f d%     YZ> e? f  d&  Z@ d' e< f d(     YZA d) eA f d*     YZB d+ e< f d,     YZC d- e< f d.     YZD d/ e< f d0     YZE d1 f  d2     YZF d3 e0 f d4     YZG d5 eG f d6     YZH d7   ZI d8   ZJ d9 eG f d:     YZK d; f  d<     YZL d=   ZM d> eG f d?     YZN d@   ZO dA   ZP dB   ZQ dC   ZR dD dE dF  ZS d S(G   sm   
Defines the base class for optimizations as well as a certain
amount of useful generic optimization tools.

i    (   t   absolute_importt   print_functiont   division(   t   dequet   defaultdictt   OrderedDictN(   t   config(   t   izip(   t   string_typest	   iteritemst
   itervaluest   integer_types(   t   reduce(   t   grapht   opt   utilst   unifyt   toolbox(   t   InconsistencyError(   t
   OrderedSeti   (   t   destroyhandlers   theano.gof.optc         C` s   t  t j |  j |  j   S(   N(   t   listR   t   io_toposortt   inputst   outputs(   t   fgraph(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   _list_of_nodes#   s    t	   Optimizerc           B` st   e  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z	 e
 j d d	 d
  Z e d d   Z RS(   s   

    An L{Optimizer} can be applied to an L{FunctionGraph} to transform it.
    It can represent an optimization or in general any kind
    of transformation you could apply to an L{FunctionGraph}.

    c         C` s6   t  |  d  s/ t d |  _ t d c d 7<n  |  j S(   Nt   _optimizer_idxi    i   (   t   hasattrR   (   t   self(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __hash__0   s    c         C` s   t  |   t  |  k S(   N(   t   id(   R   t   other(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __eq__6   s    c         C` s   t  |   t  |  k S(   N(   R    (   R   R!   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __neq__;   s    c         C` s   d S(   s!  

        Applies the optimization to the provided L{FunctionGraph}. It may
        use all the methods defined by the L{FunctionGraph}. If the
        L{Optimizer} needs to use a certain tool, such as an
        L{InstanceFinder}, it can do so in its L{add_requirements} method.

        N(    (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   apply@   s    	c         O` sd   |  j  |  z= t j j j j } t t j j j _ |  j | | |  } Wd | t j j j _ X| S(   sv   

        This is meant as a shortcut to:
          opt.add_requirements(fgraph)
          opt.apply(fgraph)

        N(   t   add_requirementst   theanot   tensort   basict   constantt   enablet   FalseR$   (   R   R   t   argst   kwargst   origt   ret(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   optimizeK   s    c         C` s   |  j  |  S(   s2   

        Same as self.optimize(fgraph).

        (   R0   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __call__\   s    c         C` s   d S(   s   

        Add features to the fgraph that are required to apply the optimization.
        For example:
          fgraph.attach_feature(History())
          fgraph.attach_feature(MyFeature())
          etc.

        N(    (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%   d   s    
i    ic         C` sF   t  |  d d   } t d d | |  j j | t |   f d | d  S(   Nt   names   %s%s %s id=%it    t   file(   t   getattrt   Nonet   printt	   __class__t   __name__R    (   R   t   streamt   levelt   depthR2   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   print_summaryp   s    c         C` s   | d  k	 r t d   n  d  S(   Ns[   The function print_profile must be overrided if the optimizer return profiling information.(   R6   t   NotImplementedError(   R:   t   profR;   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   print_profileu   s    (   R9   t
   __module__t   __doc__R   R"   R#   R$   R0   R1   R%   t   syst   stdoutR=   t   staticmethodR@   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   '   s   							t   FromFunctionOptimizerc           B` sJ   e  Z d  Z d d  Z d   Z e j d d d  Z d   Z d   Z	 RS(	   s   
    WRITEME

    c         C` s   | |  _  | |  _ d  S(   N(   R$   t   requirements(   R   t   fnRG   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __init__   s    	c         C` s"   x |  j  D] } | |  q
 Wd  S(   N(   RG   (   R   R   t   req(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%      s    i    ic         C` s4   t  d d | t |  j  t |   f d | d  S(   Ns
   %s%s id=%iR3   R4   (   R7   t   strR$   R    (   R   R:   R;   R<   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=      s    c         O` s   |  j  | |   S(   N(   RH   (   R   R,   R-   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1      s    c         C` s   |  j  S(   N(   R9   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __str__   s    (    (
   R9   RA   RB   RI   R%   RC   RD   R=   R1   RL   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRF   }   s   		c         C` s   t  |   } |  j | _ | S(   s/   
    Decorator for FromFunctionOptimizer.

    (   RF   R9   (   t   ft   rval(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt	   optimizer   s    c         ` s:   t  j     f d   f } t |  |  } |  j | _ | S(   s/   
    Decorator for FromFunctionOptimizer.

    c         ` s   |  j       S(   N(   t   attach_feature(   R   (   t
   dh_handler(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   <lambda>   s    (   t   dht   DestroyHandlerRF   R9   (   RM   RG   RN   (    (   RQ   s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   inplace_optimizer   s
    	t   SeqOptimizerc           B` sw   e  Z d  Z e d    Z d   Z d   Z d   Z d   Z e	 j
 d d d  Z e d d	   Z e d
    Z RS(   sU   

    Takes a list of L{Optimizer} instances and applies them
    sequentially.

    c         C` s|   t  j d t |   t  j d  t  j t j    t j d k rO |   n) t j d k rx t j t	 j
   d  n  d S(   s=   
        Default failure_callback for SeqOptimizer.

        s   SeqOptimizer apply %ss
   Traceback:t   raiset   pdbi   N(   t   _loggert   errorRK   t	   tracebackt
   format_excR   t   on_opt_errorRX   t   post_mortemRC   t   exc_info(   t   excR   RO   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   warn   s    	c         O` sp   t  |  d k r8 t | d t t f  r8 | d } n  | |  (| j d d  |  _ t  |  d k sl t  d S(   s  
        Parameters
        ----------
        *opts :
            The List of optimizers to be applied to a node
        failure_callback : callable or None
            Keyword only argument. A callback used when a failure
            happen during optimization.

        i   i    t   failure_callbackN(   t   lent
   isinstanceR   t   tuplet   popR6   Rb   t   AssertionError(   R   t   optst   kw(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI      s
    +c      
   C` s  g  } | j  r6 | j  j } | g } | j j   } n g  } g  } | j } t | j  } g  } g  }	 x |  D] }
 y t | j  } t j   } |
 j |  } | j	 t
 t j   |   | j	 |  |	 j	 | t | j  f  | j  r| j	 | j  j  n  Wqm t k
 r  qm t k
 rS} |  j rM|  j | |  |
  qm qT  qm Xqm W| j  r| j  j | } i  } xl t | j  D]L \ } } | | k r| | | } | d k r| | | <qq| | | <qWn d } i  } | j | } |  | | | | t | j  | | |	 | f
 S(   s>   

        Applies each L{Optimizer} in self in turn.

        i    N(   t   profilet   validate_timet   execute_callbacks_timest   copyt   execute_callbacks_timeRc   t   apply_nodest   timeR0   t   appendt   floatRg   t	   ExceptionRb   R	   R6   (   R   R   t   lt   validate_beforet   sub_validate_timet   callbacks_beforet   callback_beforet   nb_node_beforet	   sub_profst   nb_nodesRO   t   nb_nodes_beforet   t0t   sub_proft   eRk   t   callbacks_timet   kt   vt   tt   callback_time(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR$      sX    							c         C` s   d t  j |   S(   Ns
   SeqOpt(%s)(   R   RL   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    c         C` s   t  j |   S(   N(   R   t   __repr__(   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    i    ic         C` s   t  |  d d   } t d d | |  j j | t |   f d | | d k r | d 8} x. |  D]# } | j | d | d d	 | q_ Wn  d  S(
   NR2   s   %s%s %s id=%iR3   R4   i    i   R;   i   R<   (   R5   R6   R7   R8   R9   R    R=   (   R   R:   R;   R<   R2   t   opt(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=     s    *
c      
   C` s  | \
 } } } } } } } }	 }
 } d | } t  | d d d d |  t | d  ru t  | | j d d d |  n. t | d  r t  | | j d d d |  n  t  d t |  | | f d |  t  | d	 | d |  t  | d
 | d |  | d k rst  | d d |  x] t t |  d d   D]= } | d d k r/t  | d | d d | d d |  q/q/Wn  | d k rt  | d d |  n  g  } xp t | |
  D]_ \ } } t | d  r| j } n	 | j } | j |  } | j	 | | j
 j | f |  qWt t | |  d d   } x | d  d  d  D] \ } } | d } |	 r|	 | d |	 | } t  | d | | | f d |  n t  | d | | f d |  | | r@| | j |  | | d | d q@q@Wt  d |   d  S(   Ns       RV   t   endR3   R4   R2   R9   s5    time %.3fs for %d/%d nodes before/after optimizations     %.3fs for callbacks!         %.3fs for fgraph.validate()i   s     callbacks_timet   keyc         S` s	   |  d S(   Ni   (    (   t   a(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR   3  s    i    s         t   ,sM     time      - (name, class, index, nodes before, nodes after) - validate timec         S` s   |  d S(   Ni    (    (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR   F  s    ii   s     %.6fs - %s - %.3fss     %.6fs - %sR;   (   R7   R   R2   R9   t   sumt   sortedR	   t   zipt   indexRq   R8   R@   (   R:   R?   R;   Rh   Rk   R   Ry   t   nb_node_afterRz   Rv   R{   R   t   blanct   it   llR   t   nb_nR2   t   idxt   lllR   t   val_time(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR@     sR    $
".
	 
	
c      
   C` s  g  } g  } g  } x t  |  d  j t  | d   D] } |  d j |  } | d j |  } | j |  d | | d |  | j |  t | d  r t |  d |  t | d |  k s t  | j | j |  d | | d |   q6 | j d  q6 Wd d l	 m
 } xt  |  d  j t  | d   D]} g  | D] }	 |	 j ^ qK}
 | j |
 k r|
 j | j  } |   } |   } | j |  | | j |  | j   | j   k r>| |  d k r|  } n | } | | c | d | d j |  7<t | d  rt | d | d j |   t | |  k sSt  | j | | | d | d j |   | | <qd | | <q>q>n  | |  d k r|  } n | } | j | d | d j |   | d j |  } | j |  | j | d |  q>Wt |   } g  } xP t |  d | d  D]7 \ } } | j | d | d | d | d f  q<W| j |  d t |   | j | d t |   t |  d | d  } t  g  |  d D] } | j ^ q j t  g  | D] } | j ^ q  st  t  g  | d D] } | j ^ q# j t  g  | D] } | j ^ qE  sft  t |  t |  k ot |  k n st  | | |  d | d |  d	 | d	 d
 d
 | g  | | f
 S(   sF   
        Merge 2 profiles returned by this cass apply() fct.

        i    i   t   merge_profilei   (   t   StringIOi   i	   i   i   iN(   t   sett   intersectionR   Rq   R   Rc   Rg   R   R6   t   sixR   t   symmetric_differenceR2   R=   t   readRV   R   t   extendt
   merge_dictt   issubset(   t   prof1t   prof2t   new_tt   new_lt   new_sub_profileRt   t   idx1t   idx2R   t   ot   new_l_namesR   t   io1t   io2t   pt   new_optt   new_nb_nodest   p1t   p2t   new_callbacks_times(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   V  sv    *.*			%,	"$/&+&+4(   R9   RA   RB   RE   Ra   RI   R$   RL   R   RC   RD   R=   R@   R   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRV      s   		:		
6t	   _metadictc           B` sV   e  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z	 d   Z
 RS(	   s   
    WRITEME

    c         C` s   i  |  _  g  |  _ d  S(   N(   t   dRt   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    	c         C` s   |  j  | d   S(   N(   t   getR6   (   R   t   item(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __getitem__  s    c         C` s   y | |  j  | <Wnp t k
 r xF t |  j  D]5 \ } \ } } | | k r1 | | f |  j | <d  Sq1 W|  j j | | f  n Xd  S(   N(   R   Rs   t	   enumerateRt   Rq   (   R   R   t   valueR   R   t   val(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __setitem__  s    "c         C` s   y! | |  j  k r  |  j  | =d  SWn+ t k
 rN } d t |  k sO t  n XxI t |  j  D]8 \ } \ } } | | k r |  j | =d  St |   q_ Wd  S(   Ns   unhashable type(   R   t	   TypeErrorRK   Rg   R   Rt   t   KeyError(   R   R   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   __delitem__  s    
"
c         C` s   y! | |  j  k r  |  j  | =d  SWn+ t k
 rN } d t |  k sO t  n Xx= t |  j  D], \ } \ } } | | k r_ |  j | =d  Sq_ Wd  S(   Ns   unhashable type(   R   R   RK   Rg   R   Rt   (   R   R   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   discard  s    
"
c         C` s   y |  j  | SWnz t k
 r xj |  j D]W \ } } y' | | k rH | S| j |  r[ | SWq) t k
 r | | k r | Sq) Xq) W| Sn Xd  S(   N(   R   Rs   Rt   t   equals(   R   R   t   defaultt   item2R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    c         C` s   i  |  _  g  |  _ d  S(   N(   R   Rt   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   clear  s    	c         C` s   d |  j  |  j f S(   Ns   (%s, %s)(   R   Rt   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    (   R9   RA   RB   RI   R   R   R   R   R   R   RL   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s   			
				t   MergeFeaturec           B` sM   e  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z	 RS(   s   
    Keeps track of variables in fgraph that cannot be merged together.

    That way, the MergeOptimizer can remember the result of the last merge
    pass on the fgraph.

    c         C` s   t  | d  s t  |  | _ t   |  _ t   |  _ t   |  _ t   |  _ t	   |  _
 g  |  _ g  |  _ x' | j   D] } |  j | | d  qz Wd  S(   Nt   merge_featuret	   on_attach(   R   Rg   R   R   t   seen_constantsR   t	   const_sigt   const_sig_invt
   nodes_seenR   t   noinput_nodest	   scheduledt	   blacklistt   toposortt	   on_import(   R   R   t   node(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    			c         C` s|   | |  j  k r2 |  j  j |  |  j | |  n  t | t  sS | j sS t  n  t | t j  rx |  j	 | |  n  d  S(   N(
   R   R   t   process_nodeRd   R   R   Rg   R   t   Constantt   process_constant(   R   R   R   R   t   rt   new_rt   reason(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   on_change_input  s    c         C` sM   x6 | j  D]+ } t | t j  r
 |  j | |  q
 q
 W|  j | |  d  S(   N(   R   Rd   R   R   R   R   (   R   R   R   R   t   c(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   ,  s    c         C` s   |  j  j |  | j s, |  j j |  n  x~ | j D]s } t | t j  r6 t | j  d k r6 |  j	 | } |  j	 j |  |  j
 j |  |  j j t |   q6 q6 Wd  S(   Ni   (   R   R   R   R   Rd   R   R   Rc   t   clientsR   R   R   R    (   R   R   R   R   R   t   sig(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   on_prune3  s    	'c         C` s   t  |  |  j k r d S| j   } |  j j | d  } | d k	 r | j r^ | j | _ n  |  j j | | d f g g  n0 | |  j	 | <| |  j | <|  j j
 t  |   d S(   sQ   
        Check if a constant can be merged, and queue that replacement.

        Nt   merge(   R    R   t   merge_signatureR   R   R6   R2   R   Rq   R   t   add(   R   R   R   R   t   other_c(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   ?  s    	"c      	   C` s  | |  j  k r d St } | j rt | j d j  t | j d j  k  ra | j d j } n | j d j } t |  d k s t  g  | D]! \ } } | |  j  k r | ^ q } xg  D]} | j r t | j j t	 j
 j j  r t } g  | j j d j D]! \ } } | |  j  k r| ^ q}	 x t t |	   D]s }
 |	 |
 } t | j j t	 j
 j j  r?xB | j d j D]- } | d |  j  k r~|	 j | d  q~q~Wq?q?W| j |	  q q Wn	 |  j } g  } x| D]} | | k rqn  t | j  t | j  k rqn  t } g  } xb g  D]Z } | j rt | j j t	 j
 j j  rt } | j | j j d  q2| j |  q2W| j } | r
g  } xk | j D]T } | j rt | j j t	 j
 j j  r| j | j j d  q| j |  qWn	 | j } t d   t | |  D  } | r| j | j k r| | f |  j k reqn  | pn| st t | j | j d g t | j    } n | r| rt t | j | j d g t | j    } n |  j | |  } | j |   } t t | j | j j d g t | j    t t | j | j j d g t | j    } x6 | D]. } | d  \ } } | j rh| j | _ qhqhW| j |  qqW| r|  j j |  n, |  j  j |  | j s|  j j |  n  d S(   sM   
        Check if a node can be merged, and queue that replacement.

        Ni    ic         s` s!   |  ] \ } } | | k Vq d  S(   N(    (   t   .0t   node_int   cand_in(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pys	   <genexpr>  s   R   t   new_nodei   (   R   R+   R   Rc   R   Rg   t   ownerRd   R   R&   R'   R   t   Assertt   Truet   rangeR   Rq   R   R   t   allR   R   R   t   get_merged_assert_inputR2   R   R   (   R   R   R   t   node_has_assertR   R   R   t   merge_candidatest   _t   assert_clientsR   t   clientt   replacement_candidatest	   candidatet   cand_has_assertt   cand_inputs_assert_removedt   node_inputs_assert_removedt   inputs_matcht   pairst
   new_inputsR   t   pairt   node_outputt   cand_output(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   T  s    	,. 
								c   	      C` s   g  } x t  | j | j  D] \ } } | j r t | j j t j j j  r | j r t | j j t j j j  r | j j d } | j j d } t	 t
 | |   } | j t j j j | j j d |   q | j |  q | j |  q W| S(   Ni   i    (   R   R   R   Rd   R   R&   R'   R   R   R   R   Rq   t	   assert_op(	   R   R   R   R   t   node_it   cand_it	   node_condt	   cand_condt   new_cond(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s$    "		(
   R9   RA   RB   R   R   R   R   R   R   R   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s   	$					t   MergeOptimizerc           B` sJ   e  Z d  Z d   Z d   Z d   Z e d d   Z e d    Z RS(   s  
    Merges parts of the graph that are identical and redundant.

    The basic principle is that if two Applies have ops that compare equal, and
    identical inputs, then they do not both need to be computed. The clients of
    one are transferred to the other and one of them is removed from the graph.
    This procedure is carried out in input->output order through the graph.

    The first step of merging is constant-merging, so that all clients of an
    int(1) for example, are transferred to a particular instance of int(1).

    c         C` s&   t  | d  s" | j t    n  d  S(   NR   (   R   RP   R   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%     s    c          C` s  | j  j } d } t j   } | j rN | j j } | j } | j j   } n  d } d }	 x| r| j   }
 t	 } x|
 D]} | d \ } } } | d k r t
 | d  r n& t
 | d  s| t
 | d  r q| n  g  | D] } | d  ^ q } | j r| j r| j } | j } g  } x_ | j D]T } | j rqt | j j t j j j  rq| j | j j d  q*| j |  q*Wg  } x_ | j D]T } | j rt | j j t j j j  r| j | j j d  q| j |  qW| d k rt	 } n t d   t | |  D  } | s*q| n  t
 | d d j d  r| d d j | d d j } t g  | D]K \ } } | d k rnt
 | j d	  rn| t j | j j j    k ^ qn d k rq| qqn  t |  d k rU| d d j | d d j k rU| d d j j | d d  } | sU| d d | d d f g } qUn  y | j  | d
  WnP t! k
 rt" } | d 7} | j  j# j | d d j | d d j f  n X| r| | t |  7} t | d d t$ j%  r|	 d 7}	 n  Pq| q| Wq] W| j r| j j | } | j | } i  } xr t& | j  D]L \ } } | | k r| | | } | d k r| | | <qqA| | | <qAWn d  } d  } i  } g  | j  _# | t j   | | | | | |	 f S(   Ni    R   R   i   c         s` s!   |  ] \ } } | | k Vq d  S(   N(    (   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pys	   <genexpr>S  s   t   destroy_handleri   t   outputt   destroy_mapR   ((   R   R   Rp   Rj   Rk   Rn   Rl   Rm   Rf   R   R   R   R   Rd   R   R&   R'   R   R   Rq   R   R   R   R   R   R   t   flattenR  t   valuesRc   t   typet   convert_variablet   replace_all_validateR   R+   R   R   R   R	   R6   (    R   R   t   schedt   nb_failR}   Ru   Rx   Rw   t	   nb_mergedt   nb_constantt
   pairs_listt   successt   pairs_t   varR   t
   merge_modeR   R   R   R   R   R   R   R   R   t   resRk   R   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR$     s    								 B4"%
'	c         C` s
   |  j  j S(   N(   R8   R9   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    i    c      	   C` s   | \ } } } } } } }	 d | }
 t  |
 d d |  t  |
 d | | |	 f d |  t  |
 d | | | f d |  | d k r t  |
 d d |  x] t t |  d d	   D]= } | d d
 k r t  |
 d | d
 d | d d |  q q Wn  d  S(   Ns       R   R4   s%     nb fail=%5d merged=%5d constant=%5ds2     time replace=%2.2f validate=%2.2f callback=%2.2fi   s     callbacks_timeR   c         S` s   |  d S(   Ni   (    (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR     s    i    s         R   (   R7   R   R	   (   R:   R?   R;   R	  t   replace_timeRk   R   R   R
  R  R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR@     s    
		"c   
      C` s   d   } |  d | d } |  d | d } | |  d | d  } | |  d | d  } t  |  d | d  } |  d | d } |  d | d }	 | | | | | | |	 f S(	   Nc         S` s(   |  d  k r | S| d  k r  |  S|  | S(   N(   R6   (   t   v1t   v2(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   merge_none_number  s
    i    i   i   i   i   i   i   (   R   (
   R   R   R  R	  R  Rk   R   R   R
  R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    		(	   R9   RA   RB   R%   R$   RL   RE   R@   R   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR      s   		~	c         C` s3  | d k r i  } n  t j |  | | g  } | d d !} | d } t j j j |  } t j j j | | d t	 } x* t
 |  D] \ } } | j | |  q Wt   j |  g  | D] }	 | j |	 |	  ^ q }
 g  |
 D] }	 |	 j ^ q \ } } | d k r%| d k r%|
 d |
 d k S| | k Sd S(   s   
    Merge-based implementation of `theano.gof.graph.is_same_graph`.

    See help on `theano.gof.graph.is_same_graph` for additional documentation.

    i    i   t   clonei   N(   R6   Rm   t   deepcopyR&   t   gofR   R   t   fgt   FunctionGraphR+   R	   t   replaceR   R0   R   R   (   t   var1t   var2t   givenst   copiedt   varsR   R   t
   to_replacet
   replace_byR   t   vars_replacedt   o1t   o2(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   is_same_graph_with_merge  s    	
%"c         ` sU   t     i    t |  t j  r- |  g }  n      f d    t t  |    S(   s  
    Merge constants in the subgraph used to compute nodes in `vars`.

    `vars` is a list of nodes, and we want to merge together nodes
    that are constant inputs used to compute nodes in that list.

    Notes
    -----
    This function will ignore nodes that are in an fgraph.
    It is used to pre-merge nodes generated inside an optimization,
    before it is inserted in the fgraph.
    It is useful if there are many such replacements to make,
    so that DebugMode will not check each of them.

    c         ` s  |   k r |  St  |  d  s# |  S|  j rB t  |  j d  rB |  S j |   t |  t j  r |  j   } y" |   k r   | S|    | <Wn" t k
 r t j	 d |   n X|  S|  j r x9 t
 |  j j  D]" \ } }  |  |  j j | <q Wn  |  S(   NR   R   s   We work around a problem, the following variable signature isn't hashable. Please, report this to theano-dev so that the better fix is done. %s(   R   R   R   Rd   R   R   t	   signatureR   t   warningsRa   R   R   (   R  R   R   t   inp(   R   t   recursive_merget   seen_var(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR*    s.    	(   R   Rd   R   t   VariableR   t   map(   R   (    (   R   R*  R+  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   pre_constant_merge  s    	t   LocalOptimizerc           B` sG   e  Z d  Z d   Z d   Z d   Z d   Z e j d d d  Z	 RS(   s   
    A class for node-based optimizations.

    Instances should implement the transform function,
    and be passed to configure a fgraph-based Optimizer instance.

    c         C` s6   t  |  d  s/ t d |  _ t d c d 7<n  |  j S(   NR   i    i   (   R   R   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   %  s    c         C` s   d S(   sv   
        Return the list of op classes that this opt applies to.

        Return None to apply to all nodes.

        N(   R6   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   tracks+  s    c         C` s%   t  j d t |   |  j j   d S(   s1  
        Transform a subgraph whose output is `node`.

        Subclasses should implement this function so that it returns one of two
        kinds of things:

        - False to indicate that no optimization can be applied to this `node`;
          or
        - <list of variables> to use in place of `node`'s outputs in the
          greater graph.
        - dict(old variables -> new variables). A dictionary that map
          from old variables to new variables to replace.

        Parameters
        ----------
        node : an Apply instance

        t	   transformN(   R   t   MethodNotDefinedR  R8   R9   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1  4  s    	c         C` s   d S(   s   
        If this local optimization wants to add some requirements to the
        fgraph, this is the place to do it.

        N(    (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%   K  s    i    ic         C` s1   t  d d | |  j j t |   f d | d  S(   Ns
   %s%s id=%iR3   R4   (   R7   R8   R9   R    (   R   R:   R;   R<   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=   U  s    (
   R9   RA   RB   R   R0  R1  R%   RC   RD   R=   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR/    s   					
t   LocalMetaOptimizerc           B` sJ   e  Z d  Z d d d  Z d   Z d   Z d   Z d   Z d   Z	 RS(	   s   
    Base class for meta-optimizers that try a set of LocalOptimizers
    to replace a node and choose the one that executes the fastest.

    c         C` s+   | |  _  t |  |  _ t j j |  _ d  S(   N(   t   _tracksR   t
   optimizersR   t   metaoptt   verbose(   R   R0  R5  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI   a  s    	c         C` s   |  j  j |  d  S(   N(   R5  Rq   (   R   RO   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   registerf  s    c         C` s   |  j  S(   N(   R4  (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR0  i  s    c   
      ` s   j  d  k	 r1 t | j t  j    s1 d  Sn  i  } t   } x | j D]z } t | t j j	  rh qJ t
 | j d  r t j | j j | j j  | j d | j d t | | <qJ | j |  qJ W| r | j  j | |   | j | j    n  | r< j r8t d  j j | t |  | j f  n  d  S j rnt d  j j | t  j  f  n  g  } x  j D] } | j |  } | rOyG t j  g  | d | d d   t!    f d	   t" d
  D  } Wn3 t# k
 r}	  j r~t d | |	  q~q~qiX j r6t d | | f  n  | j$ | | | f  q~ j r~t d |  q~q~W| r| j%    j rt d | d d  n  | d d Sd  S(   Nt
   test_valuet   broadcastablet   borrows9   %s cannot meta-optimize %s, %d of %d input shapes unknowns#   %s meta-optimizing %s (%d choices):R  t   on_unused_inputt   ignorec         3` s   |  ] }  j     Vq d  S(   N(   t	   time_call(   R   R   (   RH   R   (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pys	   <genexpr>  s    i   s   * %s: exceptions   * %s: %.5g secs   * %s: not applicables   = %si    i   i   (&   R4  R6   Rd   R   Re   R   R   R&   t   compilet   SharedVariableR   t   tagt   sharedR  t   filterR9  R2   R:  R   R   t   updatet   provide_inputst   difference_updatet   keysR7  R7   R8   R9   Rc   t   ninR5  R1  t   functiont   minR   Rs   Rq   t   sort(
   R   R   R  t   missingt   inputt   timingsR   R   t   timingR   (    (   RH   R   s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1  l  sb    				&	#	)			
	c         C` s   t     d S(   s   
        If implemented, returns a dictionary mapping all symbolic variables
        in ``inputs`` to SharedVariable instances of suitable dummy values.
        The ``node`` can be inspected to infer required input shapes.

        N(   R>   (   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRE    s    c         C` s!   t  j    } |   t  j    | S(   N(   Rp   (   R   RH   t   start(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR>    s    N(    (
   R9   RA   RB   R6   RI   R8  R0  R1  RE  R>  (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR3  Z  s   			>		t   FromFunctionLocalOptimizerc           B` sM   e  Z d  Z d d	 d  Z d   Z d   Z d   Z e j	 d d d  Z
 RS(
   s   
    WRITEME

    c         C` s   | |  _  | |  _ | |  _ d  S(   N(   R1  R4  RG   (   R   RH   R0  RG   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    		c         C` s"   x |  j  D] } | |  q
 Wd  S(   N(   RG   (   R   R   RJ   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%     s    c         C` s   |  j  S(   N(   R4  (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR0    s    c         C` s   t  |  d d  S(   NR9   s%   <FromFunctionLocalOptimizer instance>(   R5   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    	i    ic         C` s4   t  d d | t |  j  t |   f d | d  S(   Ns
   %s%s id=%iR3   R4   (   R7   RK   R1  R    (   R   R:   R;   R<   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=     s    N(    (   R9   RA   RB   R6   RI   R%   R0  RL   RC   RD   R=   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRQ    s   			c         ` s       f d   } | S(   Nc         ` s    d k	 r t   d k r9 t d |  j |  j   n  xP  D]E } t | t j  pg t | t j	  s@ t d |  j |  j   q@ q@ Wn   }  r t
 j   t     f d   f } n  t |   |  } |  j | _ | S(   s   
        WRITEME

        i    s8   Use None instead of an empty list to apply to all nodes.s"   Tracks are op classes or instancesc         ` s   |  j       S(   N(   RP   (   R   (   RQ   (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR     s    N(   R6   Rc   t
   ValueErrorRA   R9   Rd   R   t   Opt
   issubclasst   PureOpRS   RT   Re   RQ  (   RM   R   RJ   RN   (   t   inplaceRG   R0  (   RQ   s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt	   decorator  s    $"		(    (   R0  RV  RG   RW  (    (   RV  RG   R0  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   local_optimizer  s    t   LocalOptGroupc           B` sk   e  Z d  Z d   Z d   Z d   Z d   Z e d d   Z d   Z	 e
 j d d d	  Z d
   Z RS(   s  Takes a list of LocalOptimizer and applies them to the node.

    Parameters
    ----------
    optimizers :
        The List of optimizers to be applied to a node
    reentrant : bool (Default True)
        Keyword only argument. Reentrant information. Some global
        optimizer like NavigatorOptimizer can use this value to
        determine if it ignore new nodes during a pass on the
        nodes. Sometimes, ignore_newtrees is not reentrant.
    apply_all_opts : bool (Default False)
        If False, it will return after the new node after the first optimizer
        applied. Otherwise, it will start again with the new node until no new
        optimization apply.

    c         O` s  t  |  d k r8 t | d t  r8 t | d  } n  | |  _ t |  j t  sY t  t d   | D  |  _ t d   | D  |  _	 | j
 d t  |  _ | j
 d t  |  _ t d    |  _ t  |  d k s t  |  j ri  |  _ i  |  _ i  |  _ i  |  _ n  x |  j D] } |  j rw|  j j | d  |  j j | d  |  j j | d  |  j j | d  n  x( | j   D] } |  j | j |  qWqWd  S(   Ni   i    c         s` s!   |  ] } t  | d  t  Vq d S(   t	   reentrantN(   R5   R   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pys	   <genexpr>  s   c         s` s!   |  ] } t  | d  t  Vq d S(   t   retains_inputsN(   R5   R+   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pys	   <genexpr>	  s   t   apply_all_optsRj   c           S` s   g  S(   N(    (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR     s    (   Rc   Rd   R   Re   Rh   Rg   t   anyRZ  R   R[  Rf   R+   R\  Rj   R   t	   track_mapt	   time_optst   process_countt   applied_truet   node_createdt
   setdefaultR0  Rq   (   R   R5  R-   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI      s2    %								c      	   C` s9   t  |  d d d j g  |  j D] } t |  ^ q   S(   NR9   s   LocalOptGroup(%s)R   (   R5   t   joinRh   RK   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL      s    	c         C` s@   g  } x3 |  j  D]( } | j   } | r | j |  q q W| S(   N(   Rh   R0  R   (   R   R   Rt   t   tt(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR0  %  s    c         C` s  t  |  j  d k r d  S| j } d  } xt r|  j t | j  |  j | j |  j d  } d  } x | D] } t j   } | j	 |  } t j   } |  j
 r |  j | c | | 7<|  j | c d 7<n  | s qm qm |  j
 r#|  j | c t  t j | j |   7<|  j | c d 7<n  Pqm W| s2| S|  j sJ| d j rN| St  |  d k rt g  | D] }	 |	 j ^ qj }
 t  |
  d k st  n  | } | d j } q+ Wd  S(   Ni    i   (   Rc   Rh   R   R6   R   R^  R  R   Rp   R1  Rj   R_  R`  Rb  R   t   opst	   variablesRa  R\  R   R   Rg   (   R   R   R   t   replRh   t   new_replR   t	   opt_startt
   opt_finishR   t   s(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1  -  s:    		/		("i    c      	   C` s  | \ } } } } } | s d  Sd t  |  } t | d d |  t | d d |  g  }	 g  }
 d } xv t |  D]h \ } } | d k r |	 j | | | | | | | | f  qt |
 j | | | f  | | | 7} qt W|	 rt | d d |  |	 j   xP |	 d  d  d  D]; \ } } } } } t | d | | | | | f d |  qWt | d	 | t |
  f d |  |
 j d
 d    xg |
 d  d  d  D]< \ } } | d k rt | d d | | f d |  qqWn t | d d |  t d |   d  S(   Ns       RY  R4   s   ---------------------i    sA     time taken - times applied - times tried - name - node_created:is     %.3fs - %d - %d - %s - %ds[     %.3fs - in %d optimization that were not used (display those with runtime greater than 0)R   c         S` s   |  d t  |  d  f S(   Ni    i   (   RK   (   t   nu(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR   k  s    s     s     %.3fs - %ss!    The Optimizer wasn't successful (   t   intR7   R	   Rq   RK  Rc   (   R:   R?   R;   R_  R`  Ra  Rb  Rj   R   t	   count_optt   not_usedt   not_used_timeR   t   countR   t   a_tt   n_c(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR@   N  s<    +
)	!	 +c         C` s
   t   d  S(   N(   R>   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   u  s    ic         C` s{   t  d d | |  j j t |   f d | | d k rw | d 8} x1 |  j D]# } | j | d | d d | qM Wn  d  S(	   Ns
   %s%s id=%iR3   R4   i    i   R;   i   R<   (   R7   R8   R9   R    Rh   R=   (   R   R:   R;   R<   t   lopt(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=   x  s    '
c         C` s%   x |  j  D] } | j |  q
 Wd  S(   N(   Rh   R%   (   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%     s    (   R9   RA   RB   RI   RL   R0  R1  RE   R@   R   RC   RD   R=   R%   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRY    s   	 			!&	t   GraphToGPULocalOptGroupc           B` s    e  Z d  Z d   Z d   Z RS(   s  This is the equivalent of LocalOptGroup for GraphToGPU.

    The main different is the function signature of the local
    optimizer that use the GraphToGPU signature and not the normal
    LocalOptimizer signature.

    apply_all_opts=True is not supported

    c         O` s2   t  t |   j | |   |  j t k s. t  d  S(   N(   t   superRv  RI   R\  R+   Rg   (   R   R5  R-   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    c         C` s  t  |  j  d k r d  S| d j } |  j t |  |  j | |  j d  } x | D] } t j   } | j | | | |  }	 t j   }
 |  j r |  j	 | c | |
 7<|  j
 | c d 7<n  |	 s qV n  |  j r|  j | c t  t j | j |	   7<|  j | c d 7<n  |	 SWd  S(   Ni    i   (   Rc   Rh   R   R^  R  R6   Rp   R1  Rj   R_  R`  Rb  R   Rf  Rg  Ra  (   R   R   t   context_nameR   R   R   Rh   R   Rj  Ri  Rk  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1    s"    )		((   R9   RA   RB   RI   R1  (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRv    s   		t   OpSubc           B` sJ   e  Z d  Z e Z e Z e d  Z d   Z d   Z	 d   Z
 d   Z RS(   s  

    Replaces the application of a certain op by the application of
    another op that takes the same inputs as what they are replacing.

    Parameters
    ----------
    op1, op2
        op1.make_node and op2.make_node must take the same number of
        inputs and have the same number of outputs.

    Examples
    --------
    OpSub(add, sub) ==>
        add(div(x, y), add(y, x)) -> sub(div(x, y), sub(y, x))

    c         C` s   | |  _  | |  _ | |  _ d  S(   N(   t   op1t   op2t   transfer_tags(   R   Rz  R{  R|  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    		c         C` s   |  j  S(   N(   Rz  (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   op_key  s    c         C` s
   |  j  g S(   N(   Rz  (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR0    s    c         C` s   | j  |  j k r t S|  j j | j   } |  j r t j | j  | _ x; t	 | j
 | j
  D]! \ } } t j | j  | _ q_ Wn  | j
 S(   N(   R   Rz  R+   R{  t	   make_nodeR   R|  Rm   RA  R   R   (   R   R   Rh  R  t
   new_output(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1    s    	"c         C` s   d |  j  |  j f S(   Ns   %s -> %s(   Rz  R{  (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    (   R9   RA   RB   R+   RZ  R   R[  RI   R}  R0  R1  RL   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRy    s   			
t   OpRemovec           B` sV   e  Z d  Z e Z d   Z d   Z d   Z d   Z d   Z	 e
 j d d d  Z RS(	   sq   

    Removes all applications of an op by transferring each of its
    outputs to the corresponding input.

    c         C` s   | |  _  d  S(   N(   R   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    c         C` s   |  j  S(   N(   R   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR}    s    c         C` s
   |  j  g S(   N(   R   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR0    s    c         C` s   | j  |  j  k r t S| j S(   N(   R   R+   R   (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1    s    c         C` s   d |  j  S(   Ns
   %s(x) -> x(   R   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    i    ic         C` s=   t  d d | |  j j t |  j  t |   f d | d  S(   Ns   %s%s(%s) id=%iR3   R4   (   R7   R8   R9   RK   R   R    (   R   R:   R;   R<   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=     s
    	(   R9   RA   RB   R+   RZ  RI   R}  R0  R1  RL   RC   RD   R=   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s   					t
   PatternSubc           B` sq   e  Z d  Z e d
 d
 e d d
 d
 d  Z d   Z d   Z e d  Z	 d   Z
 d   Z e j d d d	  Z RS(   s  

    @todo update

    Replaces all occurrences of the input pattern by the output pattern:

    input_pattern ::= (op, <sub_pattern1>, <sub_pattern2>, ...)
    input_pattern ::= dict(pattern = <input_pattern>,
                            constraint = <constraint>)
    sub_pattern ::= input_pattern
    sub_pattern ::= string
    sub_pattern ::= a Constant instance
    sub_pattern ::= int
    sub_pattern ::= float
    constraint ::= lambda fgraph, expr: additional matching condition

    output_pattern ::= (op, <output_pattern1>, <output_pattern2>, ...)
    output_pattern ::= string
    output_pattern ::= int
    output_pattern ::= float

    Each string in the input pattern is a variable that will be set to
    whatever expression is found in its place. If the same string is
    used more than once, the same expression must be found in those
    places. If a string used in the input pattern is used in the
    output pattern, the matching expression will be inserted in its
    place. The input pattern cannot just be a string but the output
    pattern can.

    If you put a constant variable in the input pattern, there will be a
    match iff a constant variable with the same value and the same type
    is found in its place.

    You can add a constraint to the match by using the dict(...)  form
    described above with a 'constraint' key. The constraint must be a
    function that takes the fgraph and the current Variable that we are
    trying to match and returns True or False according to an
    arbitrary criterion.

    The constructor creates a PatternSub that replaces occurrences of
    in_pattern by occurrences of out_pattern.

    Parameters
    ----------
    in_pattern
        The input pattern that we want to replace.
    out_pattern
        The replacement pattern.
    allow_multiple_clients : bool
        If False, the pattern matching will fail if one of the subpatterns has
        more than one client.
    skip_identities_fn : TODO
    name
        Allows to override this optimizer name.
    pdb : bool
        If True, we invoke pdb when the first node in the pattern matches.
    tracks : optional
        The values that self.tracks() will return. Useful to speed up
        optimization sometimes.
    get_nodes : optional
        If you provide `tracks`, you must provide this parameter. It must be a
        function that takes the tracked node and returns a list of nodes on
        which we will try this optimizer.

    Notes
    -----
    `tracks` and `get_nodes` can be used to make this optimizer track a less
    frequent Op, so this will make this optimizer tried less frequently.

    Examples
    --------
    PatternSub((add, 'x', 'y'), (add, 'y', 'x'))
    PatternSub((multiply, 'x', 'x'), (square, 'x'))
    PatternSub((subtract, (add, 'x', 'y'), 'y'), 'x')
    PatternSub((power, 'x', Constant(double, 2.0)), (square, 'x'))
    PatternSub((boggle, {'pattern': 'x',
                         'constraint': lambda expr: expr.type == scrabble}),
               (scrabble, 'x'))
    c
   
      C` s   | |  _  | |  _ |	 |  _ t | t t f  rC |  j  d |  _ n2 t | t  ri |  j  d d |  _ n t d   |  j	 j
 d t |   d |  _
 | |  _ | |  _ | r | |  _ n  | |  _ | |  _ | |  _ | d k r | s t  n  d  S(   Ni    t   patternsA   The pattern to search for must start with a specific Op instance.s   

This instance does: s   
(    (   t
   in_patternt   out_patternt   values_eq_approxRd   R   Re   R   t   dictR   R8   RB   RK   t   allow_multiple_clientst   skip_identities_fnR9   RX   R4  t	   get_nodesRg   (
   R   R  R  R  R  R2   RX   R0  R  R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI   M  s$    			!					c         C` s   |  j  S(   N(   R   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR}  i  s    c         C` s    |  j  d k r |  j  S|  j g S(   N(    (   R4  R   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR0  l  s    c         ` so  | r  j  d k	 r x  j  |  D] } | d k r= q% n   j | d t } | t k	 r% | d k	 r% t | j  t |  k s t   j r  j | j _ n  t	 t
 | j |   Sq% Wn  | j  j k r t St t   f d     j | j t j   t  j  } | rg  f d      j }   | |  }  j r` j | j _ n  | g St Sd S(   s   
        Checks if the graph from node corresponds to in_pattern. If it does,
        constructs out_pattern and performs the replacement.

        R  R  c   
      ` s         f d   } t   t t f  r  j d  k rF t S j j  d k sy   r t  j  d k r |   St   d t  j j	  k r |   Sxt
  d  j j	  D]. \ } }  | |   j    s t Sq Wnt   t  ry  d } Wn! t k
 r8t d    n X j d d    }	 |	   ry |    j d     S|   Sn t   t  rt j   }  | | k	 r |  k	 r|   S j  |   n t   t t f  r9t   t j  r9t j t j j   j  j k  r/ S|   Sn> t   t j  rpt   t j  rp j   rp S|   S| rd d  l } | j   n   S(	   Nc          ` sB    j  s t S j    }  |  d  k r, t S  |   d   S(   NR  (   R  R+   R6   (   t
   expr_equiv(   R  t   exprt   matchR  R   t   u(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   retry_with_equiv  s    	i    i   R  s.   Malformed pattern: %s (expected key 'pattern')t
   constraintc         S` s   t  S(   N(   R   (   R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR     s    R  (    Rd   R   Re   R   R6   R+   R   Rc   R   R   R   R  R  R   R   R   R   t   VarR   R   Rr   R   R   t   npR   R&   R'   R)   R   R   RX   t	   set_trace(
   R  R  R  R  RX   R  R   R   t   real_patternR  (   R  R   (   R  R  R  R  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    sZ    "&	

 '
c         ` s   t  |  t t f  rI g  |  d D] }   | |  ^ q  } |  d |   St  |  t  ri | t j |   St  |  t t f  r |  S|  j   Sd  S(   Ni   i    (	   Rd   R   Re   R   R   R  R   Rr   R  (   R  R  R   R,   (   t   build(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s    &N(   R  R6   R1  R+   Rc   R   Rg   R  RA  R  R   R   R  t   outR   t   UnificationR   RX   R  (   R   R   R  t	   real_nodeR/   R  R   (    (   R  R  R   s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR1  q  s.    !	>
		c         ` sH   t  |  d d   r |  j S  f d     d   |  j    |  j  f S(   NR9   c         ` s   t  |  t t f  rS d t |  d  d j g  |  d D] }   |  ^ q6  f St  |  t  r d   |  d  t |  j d d   f St |   Sd  S(	   Ns   %s(%s)i    s   , i   s   %s subject to %sR  R  s   no conditions(   Rd   R   Re   RK   Rd  R  R   (   R  R   (   t   pattern_to_str(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s    .s   %s -> %s(   R5   R6   R9   R  R  (   R   (    (   R  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    c         C` s
   t  |   S(   N(   RK   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    i    ic      	   C` sj   t  |  d t  |  d d    } t d d | |  j j | t |  j  t |  j  t |   f d | d  S(   NR9   R2   s   %s%s %s(%s, %s) id=%iR3   R4   (	   R5   R6   R7   R8   R9   RK   R  R  R    (   R   R:   R;   R<   R2   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=     s    	N(    (   R9   RA   RB   R+   R6   RI   R}  R0  R   R1  RL   R   RC   RD   R=   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s   O			h		t   Updaterc           B` sA   e  Z d d   Z d   Z d   Z d   Z d   Z d   Z RS(   c         C` s(   | |  _  | |  _ | |  _ | |  _ d  S(   N(   t   importert   prunert   chinR2   (   R   R  R  R  R2   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    			c         C` s   d t  |  j  S(   Ns   Updater{%s}(   RK   R2   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL     s    c         C` s   |  j  r |  j  |  n  d  S(   N(   R  (   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   
  s    	c         C` s   |  j  r |  j  |  n  d  S(   N(   R  (   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    	c         C` s)   |  j  r% |  j  | | | | |  n  d  S(   N(   R  (   R   R   R   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    	c         C` s   d  |  _ d  |  _ d  |  _ d  S(   N(   R6   R  R  R  (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt	   on_detach  s    		N(	   R9   RA   R6   RI   RL   R   R   R   R  (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s   				t   NavigatorOptimizerc           B` s   e  Z d  Z e d    Z e d    Z e d    Z d d d  Z d d d  Z	 d   Z
 d d  Z d	   Z e j d
 d d  Z RS(   s  
    Abstract class.

    Parameters
    ----------
    local_opt
        A LocalOptimizer to apply over a FunctionGraph (or None is Ok too).
    ignore_newtrees
        - True: new subgraphs returned by an optimization is not a
          candidate for optimization.
        - False: new subgraphs returned by an optimization is a candidate
          for optimization.
        - 'auto': let the local_opt set this parameter via its 'reentrant'
          attribute.
    failure_callback
            A function that takes (exception, navigator, [(old, new),
            (old,new),...]) and we call it if there's an exception.

            If the trouble is from local_opt.transform(), the new variables
            will be 'None'.

            If the trouble is from validation (the new types don't match for
            example) then the new variables will be the ones created by
            transform().

            If this parameter is None, then exceptions are not caught here
            (raised normally).

    c         C` s   t  j d k r` t j d t |   t j d t |   t j d  t j t j    n  t  j d k r t j t	 j
   d  n' t |  t  s t  j d k r |   n  d S(	   sL   
        Failure_callback for NavigatorOptimizer: print traceback.

        R=  s   Optimization failure due to: %ss   node: %ss
   TRACEBACK:RX   i   RW   N(   R   R]   RY   RZ   RK   R[   R\   RX   R^   RC   R_   Rd   Rg   (   R`   t   navt
   repl_pairst	   local_optR   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRa   ;  s    c         C` s,   t  |  t  r d St j |  | | | |  S(   s   
        Failure_callback for NavigatorOptimizer.

        Ignore InconsistencyErrors, print traceback.

        If error during replacement repl_pairs is set. Otherwise None.

        N(   Rd   R   R  Ra   (   R`   R  R  R  R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   warn_inplaceM  s    
c         C` s   d S(   sN   
        Failure_callback for NavigatorOptimizer: ignore all errors.

        N(    (   R`   R  R  R  R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   warn_ignore[  s    t   autoc         C` sD   | |  _  | d k r. t | d t  |  _ n	 | |  _ | |  _ d  S(   NR  RZ  (   R  R5   R   t   ignore_newtreesRb   (   R   R  R  Rb   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI   c  s
    		c         C` sW   |  j  r d } n  | d k r. | d k r. d St | | | d | } | j |  | S(   s  
        Install some FunctionGraph listeners to help the navigator deal with
        the ignore_trees-related functionality.

        Parameters
        ----------
        importer
            Function that will be called whenever optimizations add stuff
            to the graph.
        pruner
            Function to be called when optimizations remove stuff
            from the graph.
        chin
            "on change input" called whenever a node's inputs change.
        name
            name of the Updater to attach.

        Returns
        -------
        object
            The FunctionGraph plugin that handles the three tasks.
            Keep this around so that you can detach later!

        R2   N(   R  R6   R  RP   (   R   R   R  R  R  R2   R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   attach_updaterl  s    		c         C` s    | d k	 r | j |  n  d S(   s   
        Undo the work of attach_updater.

        Parameters
        ----------
        u
            A return-value of attach_updater.

        Returns
        -------
        None

        N(   R6   t   remove_feature(   R   R   R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   detach_updater  s    c         C` sq  | p |  j  } y | j |  } Wn^ t k
 r } |  j d k	 r| |  j | |  g  | j D] } | d f ^ qY | |  t S  n X| t k s | d k r t S| j } g  } t | t  rd | k r | j	 d  } n  t
 | j    } t
 | j    } n. t | t t
 f  s0t d | | f   n  t |  t |  k r[t d |   n  xM t | |  D]< \ }	 }
 |
 d k rkt |	 j  d k rkt d   qkqkWg  t | |  D]0 \ }	 }
 |
 |	 k	 r|
 d k	 r|	 |
 f ^ q} t |  d k rt Sy! | j | d | d | t SWnB t k
 rl} |  j d k	 rf|  j | |  | | |  t S  n Xd S(   sH  
        This function will use `lopt` to `transform` the `node`. The
        `transform` method will return either False or a list of Variables
        that are intended to replace `node.outputs`.

        If the fgraph accepts the replacement, then the optimization is
        successful, and this function returns True.

        If there are no replacement candidates or the fgraph rejects the
        replacements, this function returns False.

        Parameters
        ----------
        fgraph
            A FunctionGraph.
        node
            An Apply instance in `fgraph`
        lopt
            A LocalOptimizer instance that may have a better idea for
            how to compute node's outputs.

        Returns
        -------
        bool
            True iff the `node`'s outputs were replaced in the `fgraph`.

        t   removesK   Optimizer %s gave wrong type of replacement. Expected list or tuple. Got %ss.   Optimizer %s gave wrong number of replacementsi    s9   A local optimizer tried to remove a Variable that is usedR   N(   R  R1  Rs   Rb   R6   R   R+   Rd   R  Rf   R   RG  R  Re   R   Rc   RR  R   R   t   replace_all_validate_removeR   (   R   R   R   Ru  t   replacementsR   t   xt   old_varsR  R   t   rnewR  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     sT    
	!*c         C` s6   t  t |   j |  |  j r2 |  j j |  n  d  S(   N(   Rw  R  R%   R  (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%     s    	i    ic         C` sd   t  d d | |  j j t |   f d | | d k r` |  j j | d | d d | d n  d  S(	   Ns	   %s%s (%i)R3   R4   i    R;   i   R<   i   (   R7   R8   R9   R    R  R=   (   R   R:   R;   R<   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=     s
    'N(   R9   RA   RB   RE   Ra   R  R  R6   RI   R  R  R   R%   RC   RD   R=   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s   #	S	t   TopoOptimizerc           B` sG   e  Z d  Z d e d d  Z d d  Z e d d   Z d   Z	 RS(   s   
    TopoOptimizer has one local optimizer. It tries to apply to each node, in topological order (or reverse).
    Each time the local optimizer applies, the node gets replaced, and the topooptimizer moves on to the next one.

    t	   in_to_outc         C` s>   | d k r t  d   n  | |  _ t j |  | | |  d  S(   Nt	   out_to_inR  s(   order must be 'out_to_in' or 'in_to_out'(   R  R  (   RR  t   orderR  RI   (   R   R  R  R  Rb   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI   	  s
    	c      	   ` sz  | d  k r | j } n  | j } t | j  } t j   } t t j | j	 |    t j   | }    f d   }    f d   } |  j
 | | | d t |  d d   }	 d }
 zs t j   } xP  r|  j d k r  j   } n  j   } |   |
 |  j | |  7}
 q Wt j   | } Wd  |  j | |	  X| j | } t | j  } |  |
 | | | | | |  j f S(   Nc         ` s    |    k	 r  j  |   n  d  S(   N(   Rq   (   R   (   t   current_nodet   q(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s    c         ` s8   |    k	 r4 y  j  |   Wq4 t k
 r0 q4 Xn  d  S(   N(   R  RR  (   R   (   R  R  (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s
    R2   i    R  (   R6   R   Rn   Rc   Ro   Rp   R   R   R   R   R  R5   R  Rf   t   popleftR   R  R  (   R   R   t
   start_fromRx   t   nb_nodes_startR}   t   io_tR  R  R  t   nbR   t   loop_tR   t   nb_nodes_end(    (   R  R  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR$     s4    		i    c      
   C` s4  d | } | d  k r- t | d d |  d  S| \ } } } } } }	 }
 } t | d t | d t | d d   d |  t | d | | | f d |  t | d	 | d |  t | d
 |	 d |  t | d |
 d |  t | t  r0| j r0| j |  | j | j | j	 | j
 | j f d | d q0n  d  S(   Ns       s+   TopoOptimizer merge_profile not implementedR4   s   TopoOptimizer R2   R9   t    s     nb_node (start, end, changed)s     init io_toposorts     loop times     callback_timeR;   i   (   R6   R7   R5   Rd   RY  Rj   R@   R_  R`  Ra  Rb  (   R:   R?   R;   R   R   R  R  R  R  R  R   Ru  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR@   9  s*    
	%		c         C` s   t  |  d d  S(   NR9   s   <TopoOptimizer instance>(   R5   (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRL   U  s    	N(
   R9   RA   RB   R+   R6   RI   R$   RE   R@   RL   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s   (c          O` s   | o | j  d d  } t |   d k r9 t |    }  n |  \ }  | sT |  j } n  t |  d d d t j | } | r | | _ n  | S(   sS   
    Uses the TopoOptimizer from the output nodes to input nodes of the graph.
    R2   i   R  R  Rb   N(   Rf   R6   Rc   RY  R9   R  R  (   t
   local_optsR-   R2   R/   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   out2inZ  s    			c          O` s   | o | j  d d  } t |   d k r9 t |    }  n |  \ }  | sT |  j } n  t |  d d d t j | } | r | | _ n  | S(   sS   
    Uses the TopoOptimizer from the input nodes to output nodes of the graph.
    R2   i   R  R  Rb   N(   Rf   R6   Rc   RY  R9   R  R  (   R  R-   R2   R/   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   in2outo  s    			t   OpKeyOptimizerc           B` s/   e  Z d  Z e d d  Z d   Z d   Z RS(   s   
    WRITEME

    c         C` s8   t  | d  s t d   n  t j |  | | |  d  S(   NR}  s?   LocalOptimizer for OpKeyOptimizer must have an 'op_key' method.(   R   R   R  RI   (   R   R  R  Rb   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    c      	   ` s   |  j  j    t  t t f  rE t t j t | j     n t | j         f d   }     f d   } |  j	 | | | d t
 |  d d   } z3 x,  r  j   } |   |  j | |  q WWd  |  j | |  Xd  S(   Nc         ` s2   |    k	 r. |  j   k r.  j |   q. n  d  S(   N(   R   Rq   (   R   (   R  R   R  (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s    c         ` sG   |    k	 rC |  j   k rC y  j |   WqC t k
 r? qC Xn  d  S(   N(   R   R  RR  (   R   (   R  R   R  (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s
    R2   (   R  R}  Rd   R   Re   R   t   __iadd__R-  R  R  R5   R6   Rf   R   R  (   R   R   R  R  R  R   (    (   R  R   R  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR$     s    !	c         C` s-   t  t |   j |  | j t j    d S(   sx   
        Requires the following features:
          - NodeFinder
          - ReplaceValidate(Added by default)

        N(   Rw  R  R%   RP   R   t
   NodeFinder(   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%     s    N(   R9   RA   RB   R+   R6   RI   R$   R%   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s
   	t   ChangeTrackerc           B` s>   e  Z d    Z d   Z d   Z d   Z d   Z d   Z RS(   c         C` s   t  |  _ d |  _ d  S(   Ni    (   R+   t   changedt   nb_imported(   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s    	c         C` s   |  j  d 7_  t |  _ d  S(   Ni   (   R  R   R  (   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    c         C` s   t  |  _ d  S(   N(   R   R  (   R   R   R   R   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    c         C` s   t  |  _ d  S(   N(   R+   R  (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   reset  s    c         C` s   |  | _  d  S(   N(   t   change_tracker(   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    c         C` s
   | `  d  S(   N(   R  (   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s    (   R9   RA   RI   R   R   R  R   R  (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s   					c         C` sV   |  j    } xC t |  D]5 \ } } | | k rD | | c | 7<q | | | <q W| S(   s-   
    merge 2 dicts by adding the values.
    (   Rm   R	   (   t   d1t   d2R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR     s    t   EquilibriumOptimizerc           B` s}   e  Z d  Z d
 e e d
 d
 d
 d  Z d   Z d   Z d
 d  Z	 e
 j d d d  Z e d d   Z e d	    Z RS(   s  
    Apply optimizations until equilibrium point.

    Parameters
    ----------
    optimizers : list or set
        Local or global optimizations to apply until equilibrium.
        The global optimizer will be run at the start of each iteration before
        the local optimizer.
    max_use_ratio : int or float
        Each optimizer can be applied at most (size of graph * this number)
        times.
    ignore_newtrees
        See EquilibriumDB ignore_newtrees parameter definition.
    final_optimizers
        Global optimizers that will be run after each iteration.
    cleanup_optimizers
        Global optimizers that apply a list of pre determined optimization.
        They must not traverse the graph as they are called very frequently.
        The MergeOptimizer is one example of optimization that respect this.
        They are applied after all global optimizer, then when one local optimizer is applied, then after all final optimizer.

    c   
      C` s2  t  t |   j d  d | d | t   |  _ g  |  _ g  |  _ g  |  _ g  |  _	 | |  _
 x | D] } t | t  r | j   d  k r |  j j |  q xC | j   D]" }	 |  j j |	 g   j |  q Wqb |  j j |  qb W| r | |  _ n  | r
| |  _	 n  | |  _ |  j d  k	 s.t d   d  S(   NR  Rb   s    max_use_ratio has to be a number(   Rw  R  RI   R6   R   t   local_optimizers_mapt   local_optimizers_allt   global_optimizerst   final_optimizerst   cleanup_optimizerst   tracks_on_change_inputsRd   R/  R0  Rq   Rc  t   max_use_ratioRg   (
   R   R5  Rb   R  R  R  R  R  R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRI     s0    					#	c         c` sr   x |  j  D] } | Vq
 Wt   } xI t |  j  D]8 } x/ | D]' } | | k r? | V| j |  q? q? Wq2 Wd  S(   N(   R  R   R
   R  R   (   R   R   Rl  Ru  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   get_local_optimizers	  s    		c         C` s   t  t |   j |  x! |  j   D] } | j |  q# Wx |  j D] } | j |  qD Wx |  j D] } | j |  qe Wx |  j D] } | j |  q Wd  S(   N(   Rw  R  R%   R  R  R  R  (   R   R   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR%   $	  s    c   '      ` s  t       j    | d  k r.  j } n& x# | D] } |  j k s5 t  q5 Wt } t } d  } i   t  j  } t  j  } |  j	 }	 g  }
 g  } g  } i   g  } g  } i   g  } g  } g  } x_  j
 t  j     j  j D]6 }  j | d   j | d   j | d  q W        f d   } x| r)| r)i   t j   } t } i  } x  j D] } g  | | <qWg  } x  j
 D] }   j     j } t j   } | j   }  | c t j   | 7<| j |    j r j | d   | c d 7< | c d 7<t }  | c   j | 7< | |	 k rt } t | d d   pt | d d  } qqqW| j |  | j t t j   |   | | |  O} t j   } t t j  j |    | j t j   |  | j t    t | t    } |  j	 }	   f d   } d  }  j r  f d   } n   j  | d  d	 | d t  d d   } z{xt r0 j   } |  j k rqn  |  x@ j   j! j" t# | j$  g    j! j" | j$ g   D]}    j } t j   }  j%  | |   }!  |  c t j   | 7<|! s|q&n   j |  d   |  c d 7< |  c d 7<t }  |  c   j | 7<| | |  O}  |  |	 k rt } t |  d d   pt |  d d  } n  |  j k r&Pq&q&WqWWd   j&  |  Xg  } t j   }" x  j D] }   j     j } t j   } | j   }  | c t j   | 7<| j |    j rb j | d   | c d 7< | c d 7<t }  | c   j | 7< | |	 k rSt } t | d d   pJt | d d  } qSqbqbW| j |  | d
 c t j   |" 7<| | |  O} g  }# xX t' |  D]J \ } } | d } x$ | d D] }$ | j( | |$  } qW|# j |  qW| j |#  | j   |
 j t t j   |   qYWt  j  }% | rd | d d t) j* j	 }& t+ j) j, d k r|t |&   qt- j. |&  n   j/    t |  t |
  k st  t |  t |  k st  t |  t |  k st  t |  t |  k st  t |  t |  k s/t  t |  t |  k sMt  t |  t |  k skt   |
 | | |% | f | |  |  | | | f S(   Ni    c         ` s   t  } x  j D] }   j     j } t j   } | j   }  | c t j   | 7<|  | j |    j r  j | d   | c d 7< | c d 7<t	 }  | c   j | 7<q q W| S(   Ni    i   (
   R+   R  R  R  Rp   R$   Rq   R  Rc  R   (   t
   profs_dictR  t   coptR  t   t_optR~   (   R  R   t   global_process_countRb  R`  R   R_  (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   apply_cleanupR	  s    
		i   R2   R9   R  c         ` s    |    k	 r  j  |   n  d  S(   N(   Rq   (   R   (   R  R  (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR  	  s    c         ` s0   |    k	 r, t  |  t  r,  j |   n  d  S(   N(   Rd   RK   Rq   (   R   R   R   R   R   (   R  R  (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR  	  s    R  is'   EquilibriumOptimizer max'ed out by '%s's0   . You can safely raise the current threshold of s.   %f with the theano flag 'optdb.max_use_ratio'.RW   (0   R  RP   R6   R   Rg   R   R+   Rc   Ro   R  R  R   R  R  R  Rc  Rp   R  R  R$   Rq   R  R5   Rr   R   R   R   R   t   maxR  R  Rf   R  R  R   R  R   R   R  R	   R   R   t   optdbR&   R]   RY   RZ   R  ('   R   R   R  R   R  t   max_use_abortt   opt_namet   start_nb_nodest   max_nb_nodest   max_uset   loop_timingt   loop_process_countt   global_opt_timingt   io_toposort_timingR{   t   global_sub_profst   final_sub_profst   cleanup_sub_profsR   R  R}   t   iter_cleanup_sub_profsR  Rz   t   goptR  R  R~   t   topo_t0R  R  R  Ru  t   lopt_changet   t_before_final_optt   c_sub_profst   s_pt   end_nb_nodest   msg(    (	   R  R  R   R  Rb  R`  R  R   R_  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR$   /	  s.   	!
				"	
		
!		i    ic         C` s   t  |  d d   } t d d | |  j j | t |   f d | | d k r x8 |  j   D]' } | j | d | d d | d	 q[ Wn  d  S(
   NR2   s   %s%s %s id=%iR3   R4   i    R;   i   R<   i   (   R5   R6   R7   R8   R9   R    R  R=   (   R   R:   R;   R<   R2   Ru  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR=   	  s    *c   !      C` s  | \ } } } \ } } } }	 }
 } } } } } } d | } t  | d d d d |  t  | t | d t | d d   d |  t  | d	 t |  t |  f d |  t  | d
 | | | f d |  t  | d t |  d |  t g  | j   D] } | | ^ q  } t  | d | d |  t g  | j D] } | | ^ q4 } t  | d | d |  t g  | j D] } | | ^ qq } t  | d | d |  t g  | j D] } | | ^ q } t  | d | d |  xt t |   D] } d } | | rt	 t
 t t | |  d d     } d j g  | d  D]$ \ } } t t |  | f  ^ qC } t |  d k r| d 7} qn  t  | d | | | t | | j    |	 | | | |
 | | f d |  qWg  } g  } d } i  } xK | j t	 | j    t	 | j  t	 | j  D] } | j | d  q.Wx; | D]3 } x* t |  D] \ } } | | c | 7<qbWqOWxo t |  D]a \ } } | d k r| j | | | | | | f  q| j | | | f  | | | 7} qW| rt  | d d |  | j   xJ | d  d  d  D]5 \ } } } } t  | d | | | | f d |  q/Wt  | d | t |  f d |  | j d d    xQ | d  d  d  D]< \ } } | d k rt  | d d | | f d |  qqWt  d |   n  g  | j t	 | j  t	 | j  D]$ } | j j t j j k	 r&| ^ q&}  |  sZd  St  | d d |  xct t |   D]O} t  | d | d |  xc t | j | |  D]K \ } } y | j |  | | d  Wqt k
 rt  | d  |  qXqWxc t | j | |  D]K \ } } y | j |  | | d  Wqt k
 rdt  | d  |  qXqWxc t | j | |  D]K \ } } y | j |  | | d  Wqt k
 rt  | d  |  qXqWqWd  S(!   Ns       R  R   R3   R4   R2   R9   R  s     time %.3fs for %d passess&     nb nodes (start, end,  max) %d %d %ds     time io_toposort %.3fss      time in local optimizers %.3fss!     time in global optimizers %.3fss      time in final optimizers %.3fss"     time in cleanup optimizers %.3fsR   c         S` s   |  d S(   Ni   (    (   R   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR    
  s    i   s    ...sJ     %2d - %.3fs %d (%.3fs in global opts, %.3fs io_toposort) - %d nodes - %si    s1     times - times applied - nb node created - name:is     %.3fs - %d - %d - %ssW     %.3fs - in %d optimization that were not used (display only those with a runtime > 0)c         S` s   |  d t  |  d  f S(   Ni    i   (   RK   (   Rm  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyRR   K
  s    s     s     %.3fs - %ss%   Global, final and clean up optimizerss   Iter %di   s   merge not implemented for (   R7   R5   R   Rc   R  R  R  R  R   R   t   reversedR   R	   Rd  RK   R  Rc  Rq   RK  R@   t   __code__R   R   R>   (!   R:   R?   R;   R   R  R  R  R  R  R  R{   R_  R  Rb  R  R  R  R   R   Rl  R   Ru  R   R   R   Ro  Rp  Rq  R`  Rr  R   t	   n_createdt   gf_opts(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR@   
  s    3
	 	)&&&
	5	
#
&		 (	###c         ` s  t   d j    j  d j    } t   d j  j  d j  } t t   d j  j  d j   } t t   d j  j  d j   } t | j |  d d d | d | } d   } |  d  d  } t  d  }	 g  }
 g  } g  } x t t	 t
 |	  t
  d    D]   |	   } xK t  d    D]5 \ } } | | k r}| | c | 7<qR| | | <qRW    f d   } |
 j | | d	 d
   | j | | d d   | j | | d d   q-W|	 j  d t
 |	   |
 j  d
 t
 |
   | j  d t
 |   | j  d t
 |   |
 j  d
 t
 |	   | j  d t
 |	   | j  d t
 |	   t  d  d  } |  d  d  } |  d  d  } t  d  d  } |  d  d  } t
 |  t
 |  k ojt
 |
  k ojt
 |  k ojt
 |  k n sut  t
 |  t t
  d  t
  d   k st  t  d  d  } | | |	 | | | | | | |
 | | f S(   Ni    R  i   R  R  c         S` sb   t  j  |   } xL t |  D]> \ } } | t |  k  rM | | c | 7<q | j |  q W| S(   N(   Rm   R   Rc   Rq   (   t   l1t   l2Rt   R   R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   add_append_list}
  s    i   c   
      ` s  g  } x|  D] } t   d |  } t   d |  } | | k r | | k r  |   | j |  }  |   | j |  } d  }	 t | d  r | j | |  }	 q nE | | k r  |   | j |  }	 n  |   | j |  }	 | j |	  q W| S(   Ni    R   (   R5   R   R6   R   R   Rq   (
   Rh   t   attrR   t   tmpR   R$  R%  R   R   t   m(   R   R   R   (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   
  s    R  i	   i
   i   i   i   i   i   i   i   (   R   R  t   unionR  R   R  R  R  R   RJ  Rc   R	   Rq   R   R  R   Rg   (   R   R   t   local_optimizersR  R  R  R   R  R  R  R  R  R  R`  t   processRr  R   R  R  R{   R_  R  Rb  (    (   R   R   R   s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR   k
  st    			,
!+5N(   R9   RA   RB   R6   R   R+   RI   R  R%   R$   RC   RD   R=   RE   R@   R   (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s   			hc         C` s   t  t |   } x | r | j   } | d k rI |  j d k	 r t Sn |  j d k r\ t St | t j  r |  j j | k s t SnE y0 t	 | t j  r t |  j j |  r t SWn t
 k
 r t SX| r |  j j | j   }  q q W|  d k	 S(   s   
    WRITEME

    N(   R   R  Rf   R6   R   R+   Rd   R   RS  RT  R   R   (   R   t   chaint   elem(    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   _check_chain
  s(    	c         G` sE   t  |  t j  r" |  j d }  n  t |  t t j d   | D   S(   s   
    WRITEME

    i    c         s` s   |  ] } | d  g Vq d S(   i    N(    (   R   R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pys	   <genexpr>
  s    (   Rd   R   t   ApplyR   R  R   R   R  (   R   R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   check_chain
  s    c         ` sY     f d     | j  r0 | j  j j |  } n d }   |  | i  d  \ } } | | S(   s  
    This function traverses the computation graph described by all
    ``node`` in the graph before the variable out but that are not in the
    fgraph. It applies each of the local_optimizations on the traversed graph.

    Its main use is to apply locally constant folding when generating
    the graph of the indices of a subtensor.

    We should not apply optimizations on node that are in fgraph.
    So we don't optimize node that have an attribute fgraph.

    Notes
    -----
    This doesn't do an equilibrium... So if there is optimization
    like local_upcast_elemwise_constant_inputs in the list, that
    adds additional node to the inputs of the node, it can
    be needed to call this function multiple times.

    c         ` s  t  | d d   s | g | f S| j } t | d  rD | j | f Sx t | j  D] \ } } | | k ry | | } n | j r   |  | | | d  \ } } x- t | j j |  D] \ }	 }
 |
 | |	 <q W| | j j j |  } n | } | | | <| | j | <qT W| j } x |  D] } | j	 |  } | t
 k	 r| d  k	 rt |  t | j  k srt |   x* t | j |  D] \ }	 }
 |
 | |	 <qW| } | d j r| j } qPqqW| | f S(   NR   R   i   i    (   R5   R6   R   R   R   R   R   R   R   R1  R+   Rc   Rg   (   t   list_optR  t   optimized_varsR<   R   R   R)  t   nw_int   outsR   R   t   resultsR   R/   (   t   local_recursive_function(    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyR    s@    		"
	'i    (   R   R   R   (   t   list_optimizationsR  t	   out_indext
   final_outst   optimized_nodes(    (   R  s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   pre_greedy_local_optimizer   s    '	c         C` s   g  } t  |   t k rE x? |  D] } | t | j d g   7} q Wn t |  j d g   } | r t | d t  r | g } n  t  |  t k r xO | D]% } t | j d g   | | j _ q Wn t | j d g   | | j _ d S(   s?  
    Copies the stack trace from one or more tensor variables to
    one or more tensor variables.

    Parameters
    ----------
    from_var
        Tensor variable or list of tensor variables to copy stack traces from.
    to_var
        Tensor variable or list of tensor variables to copy stack traces to.

    Notes
    -----
    The stacktrace is assumed to be of the form of a list of lists
    of tuples. Each tuple contains the filename, line number, function name
    and so on. Each list of tuples contains the truples belonging to a
    particular variable.

    t   tracei    N(   R  R   R5   RA  Rd   Re   R  (   t   from_vart   to_vart   trR   (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   copy_stack_traceD  s     &t   lastRW   c         C` s  t  |  t j j j  r' |  j j } n- t  |  t j j j	  rH |  } n t
 d   t  | t j j  s t j |  r t | t j j  r | f } n  t  | t  r| d k r g  t t | j   D] } | j | j ^ q } qG| d k r| j } qGt
 d   n7t  | t t f  rg  } g  } x@ | D]8 } t  | t j j  rc| j |  q8| j |  q8Wt |  } g  | j D] }	 |	 j | k r|	 ^ qg  | j D]E }	 t  |	 j |  st |	 j d  rt  |	 j j |  r|	 ^ q} nF t | d  r;g  | j D] }	 | |	  r|	 ^ q} n t
 d   | sd }
 | d	 k rot j |
  q| d
 k rt |
   q| d k rqt
 d   n  xF | D]> }	 x5 |	 j D]* } t | j d  s| j j rt  SqWqWt! S(   s  
    This function checks if the outputs of specific ops of a compiled graph
    have a stack.

    Parameters
    ----------
    f_or_fgraph: theano.compile.function_module.Function or
          theano.gof.fg.FunctionGraph
        The compiled function or the function graph to be analysed.
    ops_to_check: it can be of four different types:
          - classes or instances inheriting from theano.gof.Op
          - tuple/list of classes or instances inheriting from theano.gof.Op
          - string
          - function returning a boolean and taking as input an instance of
            theano.gof.Op.
        - if ops_to_check is a string, it should be either 'last' or 'all'.
          'last' will check only the last op of the graph while 'all' will
          check all the ops of the graph.
        - if ops_to_check is an op or a tuple/list of ops, the function will
          check that all the outputs of their occurrences in the graph have a
          stack trace.
        - if ops_to_check is a function, it should take as input a
          theano.gof.Op and return a boolean indicating if the input op should
          be checked or not.
    bug_print: string belonging to {'raise', 'warn', 'ignore'}
        You can specify the behaviour of the function when the specified
        ops_to_check are not in the graph of f_or_fgraph: it can either raise
        an exception, write a warning or simply ignore it.

    Returns
    -------
    boolean
        True if the outputs of the specified ops have a stack, False otherwise.

    s(   The type of f_or_fgraph is not supportedR  R   s)   The string ops_to_check is not recognisedt	   scalar_opR1   s)   ops_to_check does not have the right typesH   Provided op instances/classes are not in the graph or the graph is emptyRa   RW   R=  s&   The string bug_print is not recognisedR  ("   Rd   R&   R?  t   function_modulet   Functiont   makerR   R  R  R  RR  RS  t   inspectt   isclassRT  R   R   Rc   R   R   Ro   Re   R   Rq   R   R   R  R(  Ra   Rs   RA  R  R+   R   (   t   f_or_fgrapht   ops_to_checkt	   bug_printR   R   t   apply_nodes_to_checkt   op_instancest
   op_classest   objR   R  R  (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   check_stack_traceu  s^    $	/(% (T   RB   t
   __future__R    R   R   t   collectionsR   R   R   Rm   R  t   loggingRX   RC   Rp   R(  R[   t   numpyR  R&   R   t   theano.compatR   R   R   R	   R
   R   t	   six.movesR   t
   theano.gofR   R   R   R   R   t   theano.gof.fgR   t   theano.misc.ordered_setR   R  R   RS   t	   getLoggerRY   R   R   t   objectR   RF   RO   RU   R   RV   R   R   R   R6   R&  R.  R/  R3  RQ  R+   RX  RY  Rv  Ry  R  R  R  R  R  R  R  R  R  R   R  R  R   R  R  R  (    (    (    s.   /tmp/pip-build-X4mzal/theano/theano/gof/opt.pyt   <module>   sv   "(		V	
	K '	9>_#1# X		5	 	"	
	D	1