
Xc           @` s  d  Z  d d l m Z m Z m Z d Z d Z d Z d Z d d l	 Z	 d d l
 Z
 d d l Z d d l m Z d d l Z d d l Z d d	 l m Z d d
 l m Z m Z d d l m Z d d l m Z d d l m Z m Z d d l m Z m Z d d l m Z e
 j d  Z  d d d  Z" d e# f d     YZ$ d d  Z% d   Z& e#   Z' d e( e( e' d  Z) g  d  Z* d   Z+ d   Z, d   Z- d   Z. d d d  Z/ d   Z0 d e# f d      YZ1 d!   Z2 d"   Z3 d#   Z4 d d$  Z5 d% e# f d&     YZ6 d'   Z7 d S((   s\   
This module provides utility functions for the Scan Op.

See scan.py for details on scan.

i    (   t   absolute_importt   print_functiont   divisions   restructedtext ensM   Razvan Pascanu Frederic Bastien James Bergstra Pascal Lamblin Arnaud Bergerons    (c) 2010, Universite de Montreals    Razvan Pascanu <r.pascanu@gmail>N(   t   OrderedDict(   t   izip(   t   string_typest	   iteritems(   t   xrange(   t   rebuild_collect_shared(   t   goft   compat(   t   tensort   scalar(   t   get_scalar_constant_values   theano.scan_utilst    c         C` s   t  |  d  r. |  j d k	 r. |  j | } n d } t |  t j  r | r |  j | k r |  j |  } |  j | j	 |  j
 |  j  } t |  j  | _ | S|  j   Sn t |  t j  rK| r t j d |    } n |  j	   } | | _ t j j d k rGy t j j |   } Wn t k
 r+qGX| j	 j |  | j _ n  | Sy t j |   }  Wn t k
 rqn X| r|  j | k r|  j |  }  n  |  j	   } | | _ t j j d k ry% t j t j j |    | j _ Wqt k
 rqXn  | S(   s]  
    Internal function that constructs a new variable from x with the same
    type, but with a different name (old name + tag). This function is used
    by gradient, or the R-op to construct new variables for the inputs of
    the inner graph such that there is no interference between the original
    graph and the newly constructed graph.

    t   namet   dtypet   offN(   t   hasattrR   t   Nonet
   isinstancet   theanot   ConstantR   t   astypet	   __class__t   typet   datat   copyt   tagt   cloneR   t   ScalarVariablet   get_scalar_typet   configt   compute_test_valueR	   t   opt   get_test_valuet   AttributeErrort   filtert
   test_valueR   t   as_tensor_variablet	   TypeErrort   deepcopy(   t   xR   R   t   nw_namet   casted_xt   nwxt   nw_xt   x_test_value(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   safe_new)   sH    			%t   untilc           B` s   e  Z d  Z d   Z RS(   s  
    Class used to encode the different things the inner function of scan can
    (or needs) to return.

    This class has to be used when scan needs to halt when a condition is
    met, otherwise the list of outputs and dictionary can directly be return
    as a tuple. The reason is that otherwise scan has no way to distinguish
    between the condition and the list of outputs ( unless we enforce and
    order, but since this was not impose up to know it can make quite a bit
    of code to fail).

    c         C` s.   t  j |  |  _ |  j j d k s* t  d  S(   Ni    (   R   R'   t	   conditiont   ndimt   AssertionError(   t   selfR2   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   __init__~   s    (   t   __name__t
   __module__t   __doc__R6   (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR1   p   s   c         C` s  | d k r t   } n  |  | k r( | S| j |   d d l m } d d l m } m } d d l m	 } d d l
 m }	 |  | k r t | j | j  r | j |  | |  <n4 t | j |	  s t  | | j j  |  | |  <| S|  j d k r | S| j rG|  j j | j k rG|  j j | g k rGt j |  | |  <| S| r|  j j | k r|  j j | g k rt j |  | |  <| Sx, |  j j D] }
 t |
 | | | |  } qW| Sd S(   s  
    Function used by scan to parse the tree and figure out which nodes
    it needs to replace.

    There are two options :
        1) x and x_copy or on host, then you would replace x with x_copy
        2) x is on gpu, x_copy on host, then you need to replace
        host_from_gpu(x) with x_copy
    This happens because initially shared variables are on GPU... which is
    fine for the main computational graph but confuses things a bit for the
    inner graph of scan.

    i    (   t   cuda(   t   gpu_from_hostt   host_from_gpu(   t   pygpu_activated(   t   GpuArrayTypeN(   R   t   sett   addt   theano.sandboxR:   t   theano.gpuarray.basic_opsR;   R<   t   theano.gpuarrayR=   t   theano.gpuarray.typeR>   R   R   t   CudaNdarrayTypeR4   t   context_namet   ownert   cuda_availableR"   t   inputsR   R'   t   traverse(   t   outR*   t   x_copyt   dt   visitedR:   R;   R<   R=   R>   t   inp(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRJ      s<    	c         C` s   d } t  |  t  rU x t |   D], \ } } | t |  N} | t |  N} q" WnI t  |  t t f  r x1 |  D] } | t |  N} qq Wn | t |   N} | S(   Ni    (   R   t   dictR   t   hash_listsDictsTuplest   listt   tuplet   hash(   R*   t
   hash_valuet   kt   v(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRQ      s    c         C` s^  | t  k	 r. t j d  | s% t  | } n  t | t  rR t | j    } n[ t | t t f  rp | } n= | d k r g  } n( t
 d t |  t t |   f   g  | D] \ } } | | j   f ^ q } g  t | |  D]$ \ \ }	 } \ }	 } | | f ^ q }
 t |  g  | g  | |  \ }	 } }	 t | g  |
 g  | |  \ }	 } }	 | S(   s  
    Function that allows replacing subgraphs of a computational graph.

    It returns a copy of the initial subgraph with the corresponding
    substitutions.

    Parameters
    ----------
    output : Theano Variables (or Theano expressions)
        Theano expression that represents the computational graph.
    replace : dict
        Dictionary describing which subgraphs should be replaced by what.
    share_inputs : bool
        If True, use the same inputs (and shared variables) as the original
        graph. If False, clone them. Note that cloned shared variables still
        use the same underlying storage, so they will always have the same
        value.
    copy_inputs
        Deprecated, use share_inputs.

    se   In `clone()` function, the argument `copy_inputs` has been deprecated and renamed into `share_inputs`sZ   replace is neither a dictionary, list, tuple or None ! The value provided is %s,of type %sN(   t   DEPRECATED_ARGt   warningst   warnR4   R   RP   RR   t   itemsRS   R   t
   ValueErrort   strR   t   zipR   (   t   outputt   replacet   strictt   share_inputst   copy_inputsR[   R*   t   yt   tmp_replacet   _t   new_replacet   _outst   outs(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR      s8    			"+	1c         ` s  t         f d    t |  } t t  t j j |  t |    } t t  |   } g  t | |  D]$ \ } } | | k	 rt | | f ^ qt } t | d t d | } t t  t j j |  t |    } g  | D] } t	 | d t
  r | ^ q }	 t |	 d t
 }
 t t |	 |
   } t t  |  t  |	   t |
  } t | d t d | } t j j | | d t
 } t     t j j d    f d    } t j j | d  } | j |  | j } | j   | S(	   sd  Construct new graphs based on 'graphs' with some variables replaced
    according to 'replacer'.

    :param replacer: function that takes a variable and returns its
         replacement.
    :param graphs: an iterable of graphs in which to replace variables
    :param additional_inputs: an iterable of graph inputs not used in any
         of 'graphs' but possibly used in the graphs returned by `replacer`
    :return: the new graphs, in the same order as 'graphs'

    Example:

    .. code-block:: python

        tag = "replaceme"

        a = tensor.scalar("a")
        b = tensor.scalar("b")
        c = tensor.scalar("c")

        ab = a + b
        ab.tag.replacement = a * b

        u = ab + c
        v, = map_variables(lambda graph:
            return getattr(graph.tag, "replacement", graph),
            [u])

        # v is now equal to a * b + c
    c         ` s1   |    k r |  S |   }   j  |  | Sd  S(   N(   R@   (   t   grapht	   new_graph(   t   graphs_seent   replacer(    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   wrapped_replacer)  s
    Rb   R`   t   cachedR   c      
   ` s1  |    k r t  Sd d l m } d d l m } t |  j | | f  r
t  d |  j j d |  j d |  j j	 d |  j \ } } } t |  j |  r | | | |  j j
 d d  } n- t |  j |  r | | | |  j j  } n  | j |   }   j |  | j	 S  j |   t t  |  j	   Sd  S(	   Ni    (   t   Scan(   t   OpFromGrapht   inner_inputst   outer_inputst   inner_outputst   containing_opt   typeConstructor(   t   Falset   theano.scan_module.scan_opRp   t   theano.compileRq   R   R"   t   _map_variables_innerRI   t   outputst   infoR   t   kwargst	   make_nodeR@   RR   t   map(   t   nodeRp   Rq   t   new_inner_inputst   new_outer_inputst   new_inner_outputst   new_opt   new_node(   t
   nodes_seenRn   (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   local_transformN  s2    	t	   out_to_inN(   R?   RR   R	   Rj   RI   R   R^   R   t   Truet   getattrRw   t   fgt   FunctionGrapht   optt   local_optimizerR   t   TopoOptimizert   optimizeR{   t   disown(   Rm   t   graphst   additional_inputst   inputs_t
   new_inputst   input_t	   new_inputt   replacementsR*   t   cached_constantst   copied_constantsR   R   t   topo_transformt
   new_graphs(    (   Rl   R   Rm   Rn   s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   map_variables  s.    !	((+&	$&	
c   
      ` s   t  t | |    g   g   d d l m  d d l m } d d l m          f d   } t | |  } t	 | |    } t	 | |    }	 | |	 | f S(   Ni    (   t
   scan_utils(   t   chain(   R	   c   
      ` s   |   } g  } g  } xa  j  j | g  D]J } t |  j  r. t |  j  rh | j |  qx | j |  q. q. Wt t |  t  j     } | r | r | Sg  } x= | D]5 } | j	   } d | j
 | _
 | j | | f  q Wx | D] } t | d t  r.t d |   f   n  |  j   k r  j | d d }	 |	  | < j |	   j |  |  j j j |	  q q W| j  j    t j	 | g d t d | \ } | S(   Ns	   %s_copiedt   updates   Replacement introduces shared variable %s which has an update associated with it into the inner graph of %s. This is not currently supported.R   t   _copyRb   R`   (   Rj   RI   R   t   VariableR   t   appendRR   R?   t   valuesR   R   R   Rw   t   NotImplementedErrort   keysR0   RG   t   fgrapht	   add_inputt   extendR[   R   R   (
   Rj   Rk   t   other_inputst	   constantsR   t   foreign_inputsR   R   t   outer_inputt   inner_input(   Ru   t   extra_inner_inputst   extra_outer_inputsR	   t   outer_to_innerRm   R   (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   inner_replacer  s@    "	
(
   RP   R^   t   theano.scan_moduleR   t	   itertoolsR   R   R	   R   RR   (
   Rm   Rr   Rs   Rt   Ru   R   R   R   R   R   (    (   Ru   R   R   R	   R   Rm   R   s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRz   |  s    !@c         ` s  d   } d   } d   } d   }   f d       |   sN t  d   n  | |   rp d | |   t   f S| |   r d g  t |   f Sd |  f } t |  t t f  s t  |   n  t |   }  d } t |   d	 k r| |  d
  re| |  d  r%d | |  d
  t |  d  f S| |  d  rV|  d j | |  d
  t   f St  |   q| |  d
  r| |  d  rt  |   q| |  d  r|  d j g  t |  d
  f St  |   qt  |   n t |   d k rw| |  d
  rh| |  d  rY| |  d	  rJ|  d	 j | |  d
  t |  d  f St  |   qtt  |   qt  |   n t  |   d S(   s~  
    This function tries to recognize the updates OrderedDict, the
    list of outputs and the stopping condition returned by the
    lambda expression and arrange them in a predefined order.

    WRITEME: what is the type of ls? how is it formatted?
            if it's not in the predefined order already, how does
            this function know how to put it in that order?

    c         S` s^   t  |  t t f  rD t g  |  D] } t  | t j  ^ q  rD t St  |  t j  rZ t St S(   N(   R   RR   RS   t   allR   R   R   Rw   (   t   elemR*   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt
   is_outputs  s    +c         S` s   t  |  t  r\ t  |  t j  rX t |   d k rX t j d t t |    d  n  t	 St  |  t
 t f  r t g  |  D]- } t  | t
 t f  o t |  d k ^ q{  r t	 St S(   Ni   s,   Expected OrderedDict or OrderedUpdates, got s.   . This can make your script non-deterministic.i   (   R   RP   R
   R   t   lenRY   RZ   R]   R   R   RR   RS   R   Rw   (   R   R*   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt
   is_updates  s    :c         S` s   t  |  t j j  S(   N(   R   R   t   scan_moduleR1   (   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   is_condition  s    c         S` s*   t  |  t t f  r t |   S|  g Sd  S(   N(   R   RR   RS   (   R*   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   _list  s    
c         ` s   d } t |  t  s$ t |  t  r- |  } n t |  t  rK t |   } n  | d k	 rq t   f d   | D  St |  t j  p t |  t j	 j
  Sd S(   s   
        Ensure `x` is made only of allowed data types.

        Return True iff `x` is made only of lists, tuples, dictionaries, Theano
        variables or `theano.scan_module.until` objects.

        c         3` s   |  ] }   |  Vq d  S(   N(    (   t   .0Rd   (   t   _filter(    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pys	   <genexpr>  s    N(   R   R   RR   RS   RP   R   R   R   R   R   R1   (   R*   t   iter_on(   R   (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR     s    		s*  The return value of your scan lambda expression may only be made of lists, tuples, or dictionaries containing Theano variables (or `theano.scan_module.until` objects for conditions). In particular if you need to use constant values, you can use `tensor.constant` to turn them into Theano variables.sJ   Scan cannot parse the return value of your lambda expression, which is: %ss   The return value of the lambda function has been restricted. you have to always return first the outputs (if any), afterwards the updates (if any) and at the end the conclusioni   i    i   i   N(   R\   R   R   R   RR   RS   R   R2   (   t   lsR   R   R   R   t	   error_msgt   deprecation_msg(    (   R   s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   get_updates_and_outputs  sR    				
!!(c         C` s  |  d  k } y1 t j |   } t j |   } t |  t  } Wn# t k
 rb t } t } t } n X| r | r y. t |   } t j |  } t j |  } Wq t k
 r t } t } q Xn  t |  t	 j
  r t |  j t  r t } n t } | p
| p
| p
| S(   N(   R   t   numpyt   isnant   isinfR   R   t	   ExceptionRw   R   R	   R   R   R   (   R*   t   isNonet   isNaNt   isInft   isStrt   val(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   isNaN_or_Inf_or_NoneM  s*    
$	c         C` s   | d k r |  Sg  t  |  j  D] } |  j | ^ q  } | | d g | d } t j |  j  |   } t j | | d  |   } t | j _	 | S(   s   
    Transforms the shape of a tensor from (d1, d2 ... ) to ( d1+size, d2, ..)
    by adding uninitialized memory at the end of the tensor.

    i    i   (
   R   R3   t   shapeR   t
   AllocEmptyR   t   set_subtensorRw   R   t   nan_guard_mode_check(   t
   tensor_vart   sizeR*   t   shapest	   new_shapet   emptyt   ret(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   expand_emptyf  s    )c         ` sW  t  |   t  |  k s t  | d k r3 g  } n  | d k rH g  } n  x t |  |  D] \ } } | j r{ | j r{ t S| j r | j r t S| j r | j j j |  | j j j |  k r t Sn  | | k rX | j | j k rX t SqX Wt  |  t  |  k rt Sx3 t | |  D]" \ } } | j | j k rt SqWt	 t
 | |   } t	   }	 x t |  |  D]t \ }
 } |
 j srt |
 t j  rt | t j  r|
 j |  st Sq|
 | f | k r|
 | k rt SqrqrW  f d     xW t t  |    D]C } |  | j r  |  | j | | j | |	  } | sOt SqqWt S(   s  Checks if Theano graphs represent the same computations.

    The two lists `xs`, `ys` should have the same number of entries. The
    function checks if for any corresponding pair `(x,y)` from `zip(xs,ys)`
    `x` and `y` represent the same computations on the same variables
    (unless equivalences are provided using `in_xs`, `in_ys`).

    If `in_xs` and `in_ys` are provided, then when comparing a node `x` with
    a node `y` they are automatically considered as equal if there is some
    index `i` such that `x == in_xs[i]` and `y == in_ys[i]`(and they both
    have the same type). Note that `x` and `y` can be in the list `xs` and
    `ys`, but also represent subgraphs of a computational graph in `xs`
    or `ys`.

    c         ` s&  |  j  | j  k r t St |  j  t | j  k r8 t St |  j  t | j  k rZ t St } xT t |  j | j  D]= \ } } | | f | k r t S| | f | k rv t } qv qv W| r t Sx!t |  j | j  D]
\ } } | | f | k r | j rl| j rl| j j j |  | j j j |  k rl  | j | j | |  } | s| j	 | | f  t Sq| j d k r| j d k r| | k rt | t j  rt | t j  r| j |  st Sqt Sqqt Sq q Wx6 t |  j | j  D] \ } } | j	 | | f  qWt Sd S(   sh  
        Compare two nodes to determine if they perform equal computation.
        This is done by comparing the ops, the number of inputs, outputs and
        by ensuring that the inputs themselves are the result of equal
        computation.

        NOTE : This function relies on the variable common to cache
        results to be more efficient.

        N(   R"   Rw   R   RI   R{   R   R   RG   t   indexR@   R   R   R   R   t   equals(   t   nd_xt   nd_yt   commont	   differentt   all_in_commont   dxt   dyt   nodes_equal(   t   compare_nodes(    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR     sD    ""
"N(   R   R4   R   R   RG   Rw   R{   R   R   R?   R^   R   R   R   R   t   rangeR   (   t   xst   yst   in_xst   in_ysR*   Rd   t   _xt   _yR   R   R   R   t   it   is_equal(    (   R   s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   equal_computationsx  sL    			*		D#c         ` s  x\ t  | |  D]K \ } } | d k	 r t |  | j k r t |  | j k s[ t  q q Wt j j     j t	 j
 j g  g    x- t  | |  D] \ } }  j | |  q W   f d     g  } x, |  D]$ }   |  | j  j |  q W| S(   s   
    Compute the shape of the outputs given the shape of the inputs of a theano
    graph.

    We do it this way to avoid compiling the inner function just to get
    the shape. Changes to ShapeFeature could require changes in this function.

    c         ` s   |   j  k r d S|  j d k r2  j |   nR x0 |  j j D]" } |  j  k r?   |  q? q? Wd }  j | |  j d d d S(   sX   
        Go back in the graph, from out, adding computable shapes to shape_of.

        Nt   reasont   dummy(   t   shape_ofRG   R   t   init_rRI   t	   on_import(   RK   RO   t   dummy_fgraph(   t   local_traverset   shape_feature(    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR     s    N(   R   R   R   R3   R4   R   R   t   ShapeFeaturet	   on_attachR   R	   R   t	   set_shapeR   R   (   Ri   RI   t   input_shapesRO   t   inp_shpR   t   o(    (   R   R   s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   infer_shape  s    !"
t	   Validatorc           B` s)   e  Z d  Z d d d d  Z d   Z RS(   s   
    Check if variables can be expressed without using variables in invalid.

    Parameters
    ----------
    valid_equivalent
        Provides a dictionary mapping some invalid variables to valid ones that
        can be used instead.

    c         C` s   | d  k r g  } n  | d  k r* g  } n  | d  k rB t   } n  t |  |  _ t |  |  _ | j   |  _ |  j j t | j	     |  j j t | j
     d  S(   N(   R   R   R?   t   validt   invalidR   t   valid_equivalentR   RR   R   R   (   R5   R   R   R   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR6   >  s    		c   
      C` s  | |  j  k r | t f S| |  j k r9 |  j | t f S| |  j k rL d S| j d k r t | t j	  r | j
   } |  j  j |  |  j j |  | |  j | <| t f S| t f Sn  g  | j j D] } |  j |  ^ q } d | k r|  j j |  d Sg  | D] \ } } | ^ q} g  | D] \ } } | s+| ^ q+} | r| j j |  }	 |	 j | j } |  j j |  |  j  j |  | |  j | <| t f S| t f S(   s  
        Go backwards in the graph, from out, and check if out is valid.

        If out is a valid node, (out, True) is returned.
        If out is not valid, but has an equivalent e, (e, False) is returned.
        If out is not valid and has no equivalent, None is returned.

        N(   R   R   R   Rw   R   R   RG   R   R   t   TensorConstantR   R@   RI   t   checkt   clone_with_new_inputsR{   R   (
   R5   RK   t
   cloned_outR   RI   RO   t   is_validt
   all_inputst   equiv_inputst   cloned_node(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR  Q  s8    	

(%
N(   R7   R8   R9   R   R6   R  (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR   2  s   
c         C` sE  g  t  |  j  D] \ } } | | k r | ^ q } t j j |  } g  } |  j } |  j |  j |  j } xP t	 |  D]B }	 t
 |  j d |	  }
 | |  j | | |
 !g 7} | |
 7} qy W| g  t |  j  D] } g  ^ q 7} | g  t |  j  D] } |  j | | g ^ q 7} t } g  | D] }	 d ^ q&} x | rt } x t  |  D]u \ } }	 | | rTt j g  | |	 D] } | | k ^ q{ rTd | | <| t j j |  j |	 g  7} t } qTqTWq;Wg  t  |  D]" \ } } | | d k r| ^ q} g  t  |  D]" \ } } | | d k r| ^ q} | | f S(   s  
    Looks at all outputs defined by indices ``out_idxs`` and see whom can be
    removed from the scan op without affecting the rest. Return two lists,
    the first one with the indices of outs that can be removed, the second
    with the outputs that can not be removed.

    t	   tap_arrayi   i    (   t	   enumerateR{   R	   Rj   RI   t   n_seqst	   n_mit_mott	   n_mit_sott	   n_sit_sotR   R   R|   R   t	   n_nit_sott   n_shared_outsR   Rw   R   t   any(   R"   t   out_idxsR   R   t   non_removablet   required_inputst   out_inst   offsett   limt   idxt   n_insRV   t   addedt   out_idxs_maskt   posR*   t   required_outst   not_required(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   scan_can_remove_outs  s4    	&4	
,
 5c         C` s  t    } g  | d <|  j d | d <d | d <d | d <g  | d <d | d <d | d <d | d	 <d | d
 <|  j d | d <|  j d | d <|  j d | d <|  j d | d <|  j d | d <|  j d | d <|  j d | d <|  j d | d <|  j |  j  } g  } | |  j d  } t    } d } |  j d }	 |  j }
 d } d } xQt |  j d  D]<} | | | k rd| | | | <| d 7} | d c d 7<| d c |  j | | g 7<| d c |  j | | g 7<x7 |  j | | D]$ } | |  j |
 g 7} |
 d 7}
 qWx7 |  j | | D]$ } | |  j | g 7} | d 7} q$W| | |	 | g 7} q^| t |  j | |  7} |
 t |  j | |  7}
 q^Wt |  | d <| |  j	 7} |	 |  j	 7}	 xt |  j d  D] } | | | k r| | | | <| d 7} | d c d 7<| d c |  j | | g 7<x7 |  j | | D]$ } | |  j |
 g 7} |
 d 7}
 qJW| |  j | g 7} | d 7} | | |	 | g 7} q| d 7} |
 t |  j | |  7}
 qW| |  j
 7} |	 |  j
 7}	 x t |  j d  D] } | | | k r| | | | <| d 7} | d c d 7<| d c |  j | | g 7<| |  j |
 g 7} |
 d 7}
 | |  j | g 7} | d 7} | | |	 | g 7} q| d 7} |
 d 7}
 qW| |  j 7} |	 |  j 7}	 g  } x t |  j d
  D] } | | | k rv| | | | <| d 7} | d
 c d 7<| |  j | g 7} | d 7} | | |	 | |  j g 7} q| d 7} qW| |  j 7} g  } x t |  j d	  D] } | | | k r=| | | | <| d 7} | d	 c d 7<| |  j | g 7} | d 7} | |  j |
 g 7} |
 d 7}
 | | |	 | g 7} q| d 7} |
 d 7}
 qW| | 7} | | 7} | |  j |
 7} | | |	 |  j |  j 7} |  j r| |  j | g 7} t |  d | | <n  | | | | | f S(   s  
    Helpful function that gets a Scan op, a list of indices indicating
    which outputs are not required anymore and should be removed, and
    a list of inputs to the apply node corresponding to the scan op and
    produces the list of inputs and outputs and the info dictionary where
    the indicated outputs are eliminated. Note that eliminating an output
    means removing its inputs from the inner funciton and from the
    node inputs, and changing the dictionary.

    R	  R  i    R  t   n_mit_mot_outst   mit_mot_out_slicesR  R  R  R  t   truncate_gradientR   t   gput   gpuat   modet   as_whilet   profilet   allow_gci   (   R   R|   RI   R  R   R	  R!  R{   R   R  R  R  R  R  R&  (   R"   R  RI   R|   t	   op_inputst
   op_outputst   node_inputst   map_old_newR  t	   ni_offsett   i_offsett   o_offsett   curr_posR  t   jdxt   nit_sot_inst
   shared_ins(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   compress_outs  s    	







		















	c         C` sU   t  |  t j  r |  j } n |  } t j j |  } t j j | |  } | | k S(   sM   
    Goes up in the graph and returns True if a node in nodes is found.

    (   R   R	   t   ApplyR{   Rj   RI   t   io_toposort(   t   l_nodet   f_nodet   l_outst   l_inst   nodes(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   find_upA  s    c   
      C` s   | d k r d } n  g  |  D] } t | |  ^ q } t   } x' t | |   D] \ } } | | | <qP Wt j j j |  } x3 | D]+ } t | t j	  r | j
   | | <q q Wt
 | d | }	 | |	 f S(   s   
    Different interface to clone, that allows you to pass inputs.
    Compared to clone, this method always replaces the inputs with
    new variables of the same type, and returns those (in the same
    order as the original inputs).

    R   R`   N(   R   R0   R   R   R   R	   Rj   RI   R   R   R   (
   RI   R{   R   R*   t	   nw_inputst   givensR.   t	   allinputsRO   t
   nw_outputs(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   reconstruct_graphO  s    	"	t	   scan_argsc           B` st   e  Z d  Z d   Z e d    Z e d    Z e d    Z e d    Z e d    Z	 d   Z
 d   Z RS(	   sQ   
    Parses the inputs and outputs of scan in an easy to manipulate format.

    c      	   C` s%  | d |  _  t | | d  } | d rN | d d g |  _ | d d  } n g  |  _ | d } | d } d }	 d }
 | d } | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 | d } | d } | d	 |  |  _ | d	 | | | !|  _ t d
   |  j D  } t d   |  j D  } | |
 |
 | !} g  |  _ d } xB |  j D]7 } |  j j	 | | | t
 |  ! | t
 |  7} qVW|
 | 7}
 | |
 |
 | !} g  |  _ d } xB |  j D]7 } |  j j	 | | | t
 |  ! | t
 |  7} qW|
 | 7}
 | |	 |	 | !|  _ |	 | 7}	 | |	 |	 | !|  _ |	 | 7}	 | d } | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 | d } | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 | d } | |	 |	 | !|  _ |	 | 7}	 | |	 |  _ | |
 |  _ d }	 d }
 | d |  _ | d } | |	 |	 | !|  _ | |
 |
 | !} g  |  _ d } xB |  j D]7 } |  j j	 | | | t
 |  ! | t
 |  7} quW|	 | 7}	 |
 | 7}
 | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 | |	 |	 | !|  _ | |
 |
 | !|  _ |	 | 7}	 |
 | 7}
 |	 t
 |  k st   |
 t
 |  k st   t!   |  _" x. d D]& } | | k r| | |  j" | <qqWd  S(   Ni    R   R&  i   iR  R  R  R	  c         s` s   |  ] } t  |  Vq d  S(   N(   R   (   R   t   s(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pys	   <genexpr>  s    c         s` s   |  ] } t  |  Vq d  S(   N(   R   (   R   RC  (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pys	   <genexpr>  s    R  R  R  R!  R   R"  R   R%  t   destroy_mapR#  R$  R'  R(  (	   s   truncate_gradients   names   modeRD  s   gpus   gpuas   as_whiles   profiles   allow_gc(#   t   n_stepsRA  t   condt   outer_in_seqst   inner_in_seqst   mit_mot_in_slicest   mit_sot_in_slicest   sumt   inner_in_mit_motR   R   t   inner_in_mit_sott   outer_in_mit_mott   outer_in_mit_sott   outer_in_sit_sott   inner_in_sit_sott   outer_in_sharedt   inner_in_sharedt   outer_in_nit_sott   outer_in_non_seqst   inner_in_non_seqsR!  t   outer_out_mit_mott   inner_out_mit_mott   outer_out_mit_sott   inner_out_mit_sott   outer_out_sit_sott   inner_out_sit_sott   outer_out_nit_sott   inner_out_nit_sott   outer_out_sharedt   inner_out_sharedR4   R   t
   other_info(   R5   Rs   t   outer_outputst   _inner_inputst   _inner_outputsR|   t   rvalRt   Rr   t   pt   qR  R  R  t   n_mit_mot_inst   n_mit_sot_inst   iimmt   qqt   slt   iimsR  R  R  R   t   iommRV   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyR6   l  s    
	






	!
	!











	!










c         C` s<   |  j  t |  j g   t |  j g   |  j |  j |  j S(   N(   RH  RK  RL  RM  RQ  RS  RV  (   R5   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   <lambda>  s    4c         C` s;   |  j  g |  j |  j |  j |  j |  j |  j |  j S(   N(   RE  RG  RN  RO  RP  RR  RT  RU  (   R5   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRo    s    3c         C` s3   t  |  j g   |  j |  j |  j |  j |  j S(   N(   RK  RX  RZ  R\  R^  R`  RF  (   R5   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRo    s    +c         C` s#   |  j  |  j |  j |  j |  j S(   N(   RW  RY  R[  R]  R_  (   R5   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRo    s    c         C` s   t  d t |  j  d t |  j  d t |  j  d |  j |  j d g g t |  j  d t |  j  d t |  j	  d t |  j
  d	 t d
   |  j D  d |  j |  j  	S(   NR  R  R  R	  iR  R  R  R   c         s` s   |  ] } t  |  Vq d  S(   N(   R   (   R   RC  (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pys	   <genexpr>  s    R!  (   R   R   RG  RN  RO  RI  RJ  RQ  RP  RT  RR  RK  R!  Ra  (   R5   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRo    s   c         C` s   t  j t |    } | j j |  j  x~ |  j D]s } | j d  s | j d  s | j d  s | j d  s | d	 k r2 t | | t j t |  |    q2 q2 W| S(
   Nt   inner_int	   inner_outt   outer_int	   outer_outR!  RI  RJ  Ra  (   s   mit_mot_out_slicess   mit_mot_in_slicess   mit_sot_in_slicess
   other_info(	   t   objectt   __new__R   t   __dict__R   t
   startswitht   setattrR   R   (   R5   t   rest   attr(    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   __copy__  s    	)c         C` s   t  j  |   } x{ |  j D]p } | j d  sg | j d  sg | j d  sg | j d  sg | d k r t | |  j t | |   q q W| S(	   NRp  Rq  Rr  Rs  R!  RI  RJ  (   s   mit_mot_out_slicess   mit_mot_in_slicess   mit_sot_in_slices(   R   Rv  Rw  R   R   (   R5   t   otherRy  Rz  (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   merge  s    	&(   R7   R8   R9   R6   t   propertyRr   Rs   Rt   Rb  R|   R{  R}  (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyRB  f  s   	t		c         C` s   |  d k r d St   } d d l m } |   } | j |   g  } x | r | j   } | | k rl qH n  | j |  t | g | g  r | j | | f  qH | j rH | j	 | j j
  qH qH Wt |  d k r |  St |  d | S(   s  
    Check all internal values of the graph that compute the variable ``out``
    for occurrences of values identical with ``x``. If such occurrences are
    encountered then they are replaced with variable ``y``.

    Parameters
    ----------
    out : Theano Variable
    x : Theano Variable
    y : Theano Variable

    Examples
    --------
    out := sigmoid(wu)*(1-sigmoid(wu))
    x := sigmoid(wu)
    forced_replace(out, x, y) := y*(1-y)

    Note
    ----
    When it find a match, it don't continue on the corresponding inputs.
    i    (   t   dequeR`   N(   R   R?   t   collectionsR  R   t   popleftR@   R   RG   t
   extendleftRI   R   R   (   RK   R*   Rd   RN   R  Rg  t
   to_replaceRj   (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   forced_replace"  s&    				(8   R9   t
   __future__R    R   R   t   __docformat__t   __authors__t   __copyright__t   __contact__R   t   loggingRY   R  R   R   R   t   theano.compatR   t   sixR   R   t	   six.movesR   t   theano.compile.pfuncR   R	   R
   R   R   t   theano.tensor.basicR   t	   getLoggert   _loggerR   R0   Rt  R1   RJ   RQ   RX   R   R   R   Rz   R   R   R   R   R   R   R  R4  R<  RA  RB  R  (    (    (    s=   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_utils.pyt   <module>   sT   G5		:u	[	v			5V	(		