
Xc           @` s  d  Z  d d l m Z m Z m Z d d l m Z m Z d d l m Z d d l Z d d l	 Z	 d d l
 Z d d l Z d d l m Z d d l m Z d d l m Z d d	 l m Z d d
 l m Z d d l m Z d d l m Z e j Z e j d  Z d   Z e e _ d d d d  Z d e  f d     YZ! d e  f d     YZ" d d  Z# d d e$ d  Z% d e! f d     YZ& d   Z' d e& f d     YZ( d   Z) d e! f d     YZ* d   Z+ d S(    s
   
WRITEME

i    (   t   absolute_importt   print_functiont   division(   t   copyt   deepcopy(   t	   getsizeofN(   t   izip(   t   reraise(   t   StringIO(   t   utils(   t   graph(   t   Typei   (   t   undefc         ` s     f d   } t  |  d  r |  j } | d  | d	 k r^ | d  | d  | d  q | r | d  x! t j |  D] } | |  q~ W| d  q n  d	 S(
   s\   
    Log Theano's diagnostic stack trace for an exception
    raised by raise_with_op.

    c         ` s   t  d |  j   d   d  S(   Ns   log_thunk_trace: %st   file(   t   printt   strip(   t   msg(   t   f(    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   write!   s    t   __thunk_trace__s$   There was a problem executing an Op.s)   Could not find where this Op was defined.sO    * You might have instantiated this Op directly instead of using a constructor.sS    * The Op you constructed might have been optimized. Try turning off optimizations.s   Definition in: sN   For the full definition stack trace set the Theano flags traceback.limit to -1N(   t   hasattrR   t   Nonet	   tracebackt   format_list(   t   valueR   R   t   trace2t   line(    (   R   s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   log_thunk_trace   s    	



c         C` s   t  |  t |  | |  d S(   s6  
    This function is meant to replace excepthook and do some
    special work if the exception value has a __thunk_trace__
    field.
    In that case, it retrieves the field, which should
    contain a trace as returned by L{traceback.extract_stack},
    and prints it out on L{stderr}.

    The normal excepthook is then called.

    Parameters:
    ----------
    type
        Exception class
    value
        Exception instance
    trace
        Traceback object

    Notes
    -----
    This hook replaced by nosetests, so it does not run in nose tests.

    N(   R   t   __excepthook(   t   typeR   t   trace(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt
   thunk_hook5   s    
c   *   
   C` s	  | d> k r t j   } n  | \ } } } | t k rI t | | |  n  y |  j d j j } Wn> t k
 r y |  j	 j j } Wq t k
 r d? } q Xn X| | _
 |  | _ |  j j   } |  | k r | j |   }	 n d> }	 |	 | _ g  }
 d t |   } | j d> k	 r%| d |	 7} n  g  |  j D] } t | d d  ^ q/} | d | 7} | d> k	 r)t | d  r(g  | j D] } t | d d d	  ^ q} g  | j D] } t | d d
 d  ^ q} g  } xc | j D]C } t | d d d  d k r| j | d  q| j d  qWn d } d } d } g  |  j D]& } g  | j D] } | d ^ qT^ qD} | d | d | d | 7} t j j d k r| d t g  | j D]( } t t | d d d  d d  ^ q 7} n  t |  j	 d  r| d t |  j	 j  7} n  | d | 7} n |
 j d  t |  j d j d g   } t | t  rt |  d k r| d  7} t   } x | D] } t j | |  qW| t | j     7} n |
 j d!  t j j d k r't   } t j! j" |  d" | d# t# d$ t# | d% 7} | | j    7} n  t j j d k rU	| d> k	 rU	| d& 7} g  |  j j D]! } t | t j$ j%  r\| ^ q\} g  |  j j D]! } t | t j$ j%  s| ^ q} g  } d } d } x7| D]/} g  }  |  j t |   d> }! t | | d d  rR| | d j& }! t |!  d k r?|  j |!  q_|  j t'    n |  j d>  t | | d d  r| | d j( }" |  j t) j( |"  j*  |! d> k r|  j d  qt) j( |"  j* t) j+ |!  }# |  j |#  | |# 7} | j, s| |# 7} qt | j, j	 d' d>  r| j, j	 j- }$ | j, j j |  }% | | d }& |% |$ k rt |$ |%  d( k szt.  | | j, j |$ |% d d }' | j/ j0 |& |'  r| |# 8} qqn  t | j, j	 d) d>  r| j, j	 j1 }$ | j, j j |  }% | | d }& |% |$ k r|t |$ |%  d( k s4t.  | | j, j |$ |% d d }' | j/ j0 |& |'  ry| |# 8} qyq|qn. t2 | | d  }( |  j |(  |  j d  | | k r|  j t#  n) | | k r|  j t3  n |  j d>  | j |   qWd d* l4 m5 }) | j6 d+ |) d,  d- t#  x | D] } | d, d k rRq6n  | d. | d d/ 7} | d0 t# k r| d1 7} n | d0 t3 k r| d2 7} n  | d( d> k	 r| d3 t | d(  7} n  | d4 | d5 7} | d, d> k	 r	| d6 | d, 7} q6| d7 7} q6W| d8 | | d9 d: d: f 7} | d; | | d9 d: d: f 7} n |
 j d<  y+ | t |  | d7 d7 j7 |
   } Wn% t8 k
 r	t9 d= t |   n Xt | | |  d> S(@   s  
    Re-raise an exception while annotating the exception object with
    debug info.

    Parameters
    ----------
    node : Apply node
        The Apply node object that resulted in the raised exception.
    exc_info : tuple, optional
        A tuple containing the exception type, exception object and
        associated traceback, as would be returned by a call to
        `sys.exc_info()` (which is done if `None` is passed).
    storage_map: dict, optional
        storage map of the theano function that resulted in the
        raised exception.

    Notes
    -----
    This re-raises the exception described by `exc_info` (or the last
    one raised, if `exc_info` is omitted) and annotates the exception
    object with several new members which may be helpful for debugging
    Theano graphs. They are:

     * __op_instance__: The Op that is responsible for the exception
       being raised.
     * __thunk_trace__: A traceback corresponding to the code that
       actually generated the exception, if it is available.
     * __applynode_index__: The index of the Apply node corresponding
       to this op in `op.fgraph.toposort()`.

    The exception is not annotated if it is of type `KeyboardInterrupt`.

    i    s#   
Apply node that caused the error: s   
Toposort index: %dR   s   No types   
Inputs types: %s
t   inputst   shapes	   No shapest   stridess
   No stridest   sizeii   s	   not showns*   The thunk don't have an inputs attributes.s/   So we can't access the strides of inputs valuess'   And can't print its inputs scalar values   Inputs shapes: %ss   
Inputs strides: %ss   
Inputs values: %st   highs   
Inputs type_num: %st   dtypet    t   numt   __input_name__s   
Inputs name: %s
s   
Outputs clients: %s
sY   HINT: Use another linker then the c linker to have the inputs shapes and strides printed.R   sZ   
Backtrace when the node is created(use Theano flag traceback.limit=N to make it longer):
s  HINT: Re-running with most Theano optimization disabled could give you a back-trace of when this node was created. This can be done with by setting the Theano flag 'optimizer=fast_compile'. If that does not work, Theano optimizations can be disabled with 'optimizer=None'.R   t   stop_on_namet
   print_types    
Debugprint of the apply node: 
s   
Storage map footprint:
t   view_mapi   t   destroy_map(   t
   itemgettert   keyi   t   reverses    - s   , i   s   Shared Input, s   Input, s   Shape: %s, s   ElemSize: %s Byte(s)i   s   , TotalSize: %s Byte(s)
s   
s    TotalSize: %s Byte(s) %.3f GB
g      @i   s&    TotalSize inputs: %s Byte(s) %.3f GB
ss   HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storage map footprint of this apply node.s>   WARNING: %s error does not allow us to add extra error messageN(    (:   R   t   syst   exc_infot   KeyboardInterruptR   t   outputst   tagR   t   AttributeErrort   opR   t   __op_instance__t   fgrapht   toposortt   indext   __applynode_index__t   strR    t   getattrR   t   appendt   clientst   theanot   configt   exception_verbosityR(   t
   isinstancet   listt   lenR   R   t
   print_listt   getvaluet   printingt
   debugprintt   Truet   compilet   SharedVariableR!   t   tupleR%   t   npt   itemsizet   prodt   ownerR+   t   AssertionErrorR   t   may_share_memoryR,   R   t   Falset   operatorR-   t   sortt   joint	   TypeErrorR   (*   t   nodet   thunkR1   t   storage_mapt   exc_typet	   exc_valuet	   exc_traceR   t   topot
   node_indext   hintst   detailed_err_msgt   iptt   typest   shapesR"   t   scalar_valuest   vart   cR?   t   it   trt   siot   subtrR   t   itemt   shared_input_listt   nonshared_input_listt   storage_map_listt
   total_sizet   total_size_inputst   kt   storage_map_itemt	   shapeinfoR%   t   szt   vmapt   out_idxt   datat
   input_datat   bytesR-   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   raise_with_opT   s4   "			())6	@!
		

!!
	(t   Linkerc           B` s8   e  Z d  Z e d  Z d   Z e d  Z d   Z RS(   s   
    WRITEME

    c         C` s(   t  |   } | t k	 r$ | | _ n  | S(   N(   R   R   t   allow_gc(   t   selfR~   t   new(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   cloneN  s    c         C` s%   t  j d t |   |  j j   d S(   s  
        This function must return a triplet (function, input_variables,
        output_variables) where function is a thunk that operates on the
        returned variables. If inplace is True, the input_variables and
        output_variables lists will be the same as the inputs and outputs
        of the graph provided to the L{Linker}. Else, independent
        variables will be returned.

        Examples
        --------
        x, y = Variable(Double), Variable(Double)
        e = x + y
        fgraph = FunctionGraph([x, y], [e])
        fn, (new_x, new_y), (new_e, ) = MyLinker(fgraph).make_thunk(inplace)
        new_x.data = 1.0
        new_y.data = 2.0
        fn()
        print new_e.data # 3.0
        print e.data # 3.0 iff inplace == True (else unknown)

        t
   make_thunkN(   R	   t   MethodNotDefinedR   t	   __class__t   __name__(   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR   T  s    c         ` sO   |  j  |   \          f d   }  | _   | _  | _ | S(   s  
        Returns a function that takes values corresponding to the inputs of the
        fgraph used by this L{Linker} and returns values corresponding the the
        outputs of that fgraph. If inplace is True, the calculations will
        operate in the same storage the fgraph uses, else independent storage
        will be allocated for the function.

        Example
        -------
        e = x + y
        fgraph = FunctionGraph([x, y], [e])
        fn = MyLinker(fgraph).make_function(inplace)
        print fn(1.0, 2.0) # 3.0
        print e.data # 3.0 iff inplace == True (else unknown)

        If unpack_single is True (default) and that the function has only one
        output, then that output will be returned. Else, a list or tuple of
        length 1 will be returned.

        c          ` s   d   } t  |   t     k rE t | t     t  |      n  x& t |     D] \ } } | | _ qU W    r t j g   D] } | j ^ q  Sg   D] } | j ^ q Sd  S(   Nc         S` s!   d |  d d g |  d k | f S(   Ns,   Function call takes exactly %i %s (%i given)t   argumentt	   argumentsi   (    (   t   takest   got(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   e_arity  s    (   RE   RX   R   Ry   R	   t   to_return_values(   t   argsR   t   argt   variable(   R    R3   RZ   t   unpack_single(    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   execute  s    	$	(   R   RZ   R    R3   (   R   R   t   kwargsR   (    (   R    R3   RZ   R   s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   make_functionn  s    			c         C` s
   | j    S(   N(   R9   (   R   R8   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   schedule  s    (	   R   t
   __module__t   __doc__R   R   R   RJ   R   R   (    (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR}   H  s
   	+t	   Containerc           B` sn   e  Z d  Z e e d d d  Z d   Z d   Z e e e  Z	 e e e  Z
 d   Z d   Z d   Z RS(   s  
    This class joins a variable with its computed value.

    It is used in linkers, especially for the inputs and outputs of a Function.

    Parameters
    ----------
    r : a Variable or a Type
    storage
        A list of length 1, whose element is the value for `r`.
    readonly : bool
        True indicates that this should not be setable by Function[r] = val.
    strict : bool
        If True, we don't allow type casting.
    allow_downcast
        If True (and `strict` is False), allow upcasting of type, but not
        downcasting. If False, prevent it. If None (default), allows only
        downcasting of float to floatX scalar.
    name : str
        A string (for pretty-printing?)

    c         C` s   t  | t  s# t |  d k r2 t d   n  t  | t  rM | |  _ n | j |  _ | d  k r} t | d d   |  _ n	 | |  _ | |  _	 | |  _
 | |  _ | |  _ d  S(   Ni   s-   storage must be a list of length at least onet   name(   RC   RD   RE   RX   R   R   R   R=   R   t   storaget   readonlyt   strictt   allow_downcast(   R   t   rR   R   R   R   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __init__  s    #				c         C` s   |  j  d S(   Ni    (   R   (   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __get__  s    c         C` s	  |  j  r t d |  j   n  y | d  k r? d  |  j d <d  Si  } |  j r[ t | d <n  |  j d  k	 rz |  j | d <n  t |  j	 d  r |  j	 j
 | |  j d |  |  j d <n |  j	 j | |  |  j d <Wn0 t k
 r} | j d |  j f | _   n Xd  S(   Ns   Cannot set readonly storage: %si    R   R   t   filter_inplaces   Container name "%s"(   R   t	   ExceptionR   R   R   R   RJ   R   R   R   R   t   filterR   (   R   R   R   t   e(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __set__  s&    		
 c         C` s   d t  |  j d  d S(   Nt   <i    t   >(   R<   R   (   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __str__  s    c         C` s   d t  |  j d  d S(   NR   i    R   (   t   reprR   (   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __repr__  s    c      
   C` s>  t  |  j d  | k } t |   t |  j d | t |  j d | t |  j d | t |  j d | t |  j d | t |  j d |  } | j d d  k	 r:|  j j	 | j d  r:| s t
  |  j j	 |  j d  s t
  |  j j | j d d t d t | j d <| j d | t  |  j d  <n  | S(   Ni    t   memoR   R   (   t   idR   R   R   R   R   R   R   R   t   is_valid_valueRR   R   RT   (   R   R   t   data_was_in_memoR   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __deepcopy__  s"    	!N(   R   R   R   RT   R   R   R   R   t   propertyRy   R   R   R   R   (    (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s   				c   	      C` sb  | d k r i  } n  | d k rC g  |  j D] } d g ^ q+ } n! t |  j  t |  k sd t  xe t |  j |  D]Q \ } } | | k r | | | k s t d | d | | f   qw | | | <qw W| d k	 rdt |  j  t |  k s t  xh t |  j |  D]Q \ } } | | k rS| | | k s]t d | d | | f   q| | | <qWn  x | D]x } xH | j D]= } | | k r{t | t j  st  | j	 g | | <q{q{Wx$ | j D] } | j
 | d g  qWqkWx< |  j D]1 } t | t j  r| j
 | | j	 g  qqW| d k rUg  |  j D] } | | ^ q<} n  | | | f S(   s  Ensure there is storage (a length-1 list) for inputs, outputs, and interior nodes.

    :param fgraph: The current fgraph.  This function uses the inputs and outputs attributes.
    :param order: an iterable over Apply instances (in program running order)
    :param input_storage: None or existing input storage (see below)
    :param output_storage: None or existing output storage (see below)

    :rtype: 3-tuple
    :returns: (list of storage for inputs, list of storage for outputs, and the `storage_map`)

    Parameters
    ----------
    fgraph
        The current fgraph. This function uses the inputs and outputs
        attributes.
    order
        An iterable over Apply instances (in program running order).
    input_storage
        None or existing input storage (see below).
    output_storage
        None or existing output storage (see below).

    Returns
    -------
    3-tuple
        List of storage for inputs, list of storage for outputs, and
        the `storage_map`.

    Extended summary
    ----------------
    This function iterates over the nodes in `order` and ensures that for every
    input and output `Variable`, there is a unique storage container. This is
    returned as a dictionary Variable -> storage called the `storage_map`.

    This function also returns `input_storage`, which is a list of storages
    corresponding to fgraph.inputs.
    This function also returns `output_storage`, which is a list of storages
    corresponding to fgraph.outputs.

    sV   Given input_storage conflicts with storage in given storage_map. Given input_storage: s   Storage in storage_map: sX   Given output_storage conflicts with storage in given storage_map. Given output_storage: N(   R   R    RE   RR   t   zipR3   RC   R
   t   ConstantRy   t
   setdefault(	   R8   t   ordert   input_storaget   output_storageR[   t   inputR   R   RY   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   map_storage  s@    +	"!!#c   
      ` s     d k r g    n  t   t   k rQ t d t   t   f   n   r t   t   k r t d t   t   f   n       f d   } | } n< | r     f d   } | } n    f d   }	 |	 } | S(   s  
    WRITEME

    Parameters
    ----------
    fgraph
    thunks
        The list of program instructions.
    order
        The list of apply instances that gave rise to the thunks
        (same order as thunks).
    post_thunk_old_storage
        A list (corresponding to thunks, order) whose elements are lists of
        storage cells, that should be cleared after running thecorresponding
        thunk. A value of None disables this functionality.
    no_recycling
        Storage elements that cannot be 'recycled' by repeatedly executing the
        program. These storage elements are cleared before re-running.
    nice_errors
        Run in such a way that the double-traceback is printed. This costs a
        bit of performance in the inner python loop.

    s%   Length of thunks and order must matchs6   Length of thunks and post_thunk_old_storage must matchc          ` s   x   D] }  d  |  d <q WyL xE t     D]1 \ } } } |   x | D] } d  | d <qN Wq1 WWn t k
 r t | |  n Xd  S(   Ni    (   R   R   R   R|   (   t   xRZ   RY   t   old_storaget   old_s(   t   no_recyclingR   t   post_thunk_old_storaget   thunks(    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   streamline_default_f  s    c          ` sk   x   D] }  d  |  d <q Wy+ x$ t    D] \ } } |   q. WWn t k
 rf t | |  n Xd  S(   Ni    (   R   R   R   R|   (   R   RZ   RY   (   R   R   R   (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   streamline_nice_errors_f  s    c          ` s7   x   D] }  d  |  d <q Wx  D] } |   q" Wd  S(   Ni    (   R   (   R   RZ   (   R   R   (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   streamline_fast_f  s    N(   R   RE   t
   ValueError(
   R8   R   R   R   R   t   nice_errorsR   R   R   R   (    (   R   R   R   R   s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt
   streamlinei  s$    			t   LocalLinkerc           B` s)   e  Z d  Z d d d d  Z d   Z RS(   s}   
    Useful base class for L{Linker}s which keep all nodes in the graph, and run
    a thunk associated with each node.

    c         C` s    |  j  d | d | d |  d  S(   NR   R   R[   i   (   t   make_all(   R   R   R   R[   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    c         C` s%   t  j d t |   |  j j   d  S(   NR   (   R	   R   R   R   R   (   R   R   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    	N(   R   R   R   R   R   R   (    (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s   c         C` si   i  } t    } xM |  D]E } x | j D] } | | | <q& Wx | j D] } | j |  qD Wq W| | f S(   s  
    Return the set of Variable instances which are computed by node_list.
    Parameters
    ----------
    node_list
        List of Apply instances in program execution order.

    Returns
    -------
    2-tuple
        FIRST, the set of Variable instances which are computed by node_list,
        and SECOND a dictionary that maps each Variable instance to a the last
        node to use Variable as an input.

    Extended Summary
    ----------------
    This is used to allow garbage collection within graphs.

    It ignores view_map and destroy_map. This isn't needed as python
    have reference count. In Theano gc, we should not take into
    account view_map and destroy_map as if the thunk decided to create
    a new output, we would delay uselessly its gc by Python.

    (   t   setR    R3   t   add(   t	   node_listt	   last_usert   computedRY   R   t   output(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt	   gc_helper  s    	t   PerformLinkerc           B` s>   e  Z d  Z d d d  Z d d d  Z d d d d  Z RS(   s   
    Basic L{Linker} subclass that calls the perform method on each L{Op} in
    the L{FunctionGraph} in the order given by L{Linker.schedule}.

    c         C` sC   | d  k r t j j } n  d  |  _ | |  _ | r? | |  _ n  d  S(   N(   R   R@   RA   R~   R8   R   (   R   R~   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    		c         C` sn   | d k r g  } n  |  j d k	 rX |  j | k	 rX t |   d |  j  j | | |  S| |  _ | |  _ |  S(   s$  

        Parameters
        ----------
        fgraph
            A PerformLinker can have accepted one FunctionGraph instance at a time.
        no_recycling
            WRITEME

        Returns
        -------
        object
            self (TODO: WHY? Who calls this function?)

        R~   N(   R   R8   R   R~   t   acceptR   (   R   R8   R   t   profile(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    			c         C` s  |  j  } |  j |  } |  j } t | | | | |  \ } } } i  } x$ | D] } | j d k g | | <qO Wg  }	 x | D]y }
 |	 |
 j j |
 | | | d  g 7}	 g  |
 j D] } | | ^ q |	 d _ g  |
 j	 D] } | | ^ q |	 d _	 q| Wt
 |  \ } } |  j rg  } n d } xl | D]d }
 |  j r*| j g  |
 j D]; } | | k rI| | j	 k rI|
 | | k rI| | ^ qI q*q*W| t k rt | j    } t j | |  } n, g  | D] } | | j k r| | ^ q} t | |	 | | d | } |  j | _ t | | |  | | _ | g  t | j |  D] \ } } t | |  ^ qGg  t | j	 |  D] \ } } t | | t  ^ qx|	 | f S(   s  
        Returns Function to run all nodes, list of input containers, list of outputs

        Parameters
        ----------
        input_storage
            list of storages corresponding to fgraph.inputs
        output_storage
            list of storages corresponding to fgraph.outputs

        Returns
        -------
        object
            Function to run all nodes, list of input containers, list of output
            containers, list of thunks (for all programs), list of nodes
            (for all programs).

        t   pyiR   N(   R8   R   R   R   RQ   R   R6   R   R    R3   R   R~   R>   RJ   RD   t   valuesR	   t
   differenceR   t   add_clear_storageR[   R   R   (   R   R   R   R[   R8   R   R   t   compute_mapRs   R   RY   t   vR   R   R   R   R   R   R   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     sX    		!'+			(,		.1N(   R   R   R   R   R   R   R   (    (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s   c         ` s      f d   } | |  _  d  S(   Nc          ` s#   x   D] }  d   |  d <q Wd  S(   Ni    (   R   (   Rh   (   R   R[   (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   clear_storagek  s    (   R   (   R   R   R[   R   (    (   R   R[   s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR   j  s    t
   WrapLinkerc           B` sM   e  Z d  Z d   Z d   Z e d  Z d d d  Z d   Z	 d   Z
 RS(   s  
    This class makes it easier to run several L{LocalLinker}s in parallel, and
    offers some control over how each thunk is run.

    A wrapper function must be provided, and it can be used to execute the
    thunks, inspect the nodes, print stuff out, etc.

    The constructor initializes a WrapLinker.

    Parameters
    ----------
    linkers : list of L{LocalLinker} subclasses, whose make_all() method returns
        thunks in the same order.
        For each node in the graph, each linker will provide a
        thunk.  This class makes it possible to iterate over each linker's
        program in parallel.
    wrapper : lambda (i, i_node, i_thunk1, i_thunk2, ...) : None
        Does some user-defined action for the i'th element of the program.
        i_thunk<n> is the thunk returned by the n'th linker. (If you want
        to run the program, make sure to call the necessary thunks in this
        function.)

    Notes
    -----
    The outputs of the first linker will be returned.

    This linker ensures that each linker has its own storage for inputs and
    outputs and intermediate variables. There is no interference between
    linkers.

    c         C` s   d  |  _ | |  _ | |  _ d  S(   N(   R   R8   t   linkerst   wrapper(   R   R   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    		c         C` s;   |  j  d g  |  j D] } t |  ^ q d |  j  } | S(   s  
        Shallow copy of a WrapLinker.

        Returns
        -------
        object
            A copy of self, where each of the linkers in self.linkers
            have been shallow-copied.

        It is useful because in FunctionMaker, copy.copy is called on the
        Mode's linker, so that it is not modified inplace when linker.accept()
        is called. In this case, we want the wrapped linkers to be copied too.

        R   R   (   R   R   R   R   (   R   t   lt   other(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   __copy__  s    	"c         C` s;   |  j  d g  |  j D] } | j d |  ^ q d |  j  S(   NR   R~   R   (   R   R   R   R   (   R   R~   R   (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    	(c         C` s   | d k r g  } n  |  j d k	 rX |  j | k	 rX t |   |  j |  j  j | |  S| |  _ | |  _ g  |  j D] } | j | |  ^ qt |  _ |  S(   s  

        Parameters
        ----------
        fgraph : gof.FunctionGraph
            The fgraph which we will link.
        no_recycling : a list of Variables that belong to fgraph.
            If a Variable is in no_recycling, L{WrapLinker} will clear
            the output storage associated to it (for each linker in linkers)
            during the computation to avoid reusing it.

        N(   R   R8   R   R   R   R   R   (   R   R8   R   R   t   linker(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    			(c         C` s   d  S(   N(    (   R   R   R    R   t   thunk_groups(    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   pre  s    c         ` s   j  }  j d j |   g } | j d d   | g   j d D] } | j |   ^ qC 7} t |   \ }   } } } | d }	 x- | d D]! }
 |	 |
 k s t d   q q W  d  | d } t t |     g  t |   D] } | d ^ q  g   xq t    D]` \ } } xQ t	 | j
  D]@ \ } } | | k r/x% | D] }  j | j
 |  qNWq/q/WqW j   j           f d   }  | _ |  | f S(   Ni    R   i   sF   All linkers to WrapLinker should execute operations in the same order.c          ` s   xL   d D]@ }  x7 t   |   D]& \ } } t | j d  | j d <q! Wq Wx  D] } d  | d <qV W  g    d D] } | j ^ q{    x^ t t      D]G \ } \ } } y  | | |  Wq t k
 r t | |  q Xq Wd  S(   Ni   i    (   R   R   R   R   Ry   t	   enumerateR   R|   (   R    t   input1t   input2R   R   Ri   R   RY   (   t   input_listst   inputs0R   R   R   R   t   to_resetR   (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    "#
((   R   R   R   t   popR   R   R   RD   R   R   R3   R>   R   R   R   (   R   R   R   R   R   t   fnst   output_listst   thunk_listst   order_listst   order_list0t
   order_listt   outputs0R   R   RY   t   jR   RZ   R   (    (   R   R   R   R   R   R   R   R   s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s2    	-


##		$	N(   R   R   R   R   R   R   R   R   R   R   R   (    (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR   q  s   			c         ` s     f d   } t  |  |  S(   sa   
    Variant on WrapLinker that runs a series of wrapper functions instead of
    just one.

    c          ` s   x   D] } | |    q Wd  S(   N(    (   R   R   (   t   wrappers(    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyR     s    (   R   (   R   R   R   (    (   R   s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   WrapLinkerMany  s    (,   R   t
   __future__R    R   R   R   R   R0   R   R   t   numpyRN   R@   t   theano.compatR   t   sixR   t	   six.movesR   t
   theano.gofR	   R
   t   theano.gof.typeR   R   t
   excepthookR   t   stderrR   R   R   R|   t   objectR}   R   R   RJ   R   R   R   R   R   R   R   (    (    (    s/   /tmp/pip-build-X4mzal/theano/theano/gof/link.pyt   <module>   s<   			VgdG	$|	