ó
àÆ÷Xc           @` sZ   d  d l  m Z m Z m Z d  d l Z d  d l m Z g  d g  d d d e d „ Z	 d S(   i    (   t   absolute_importt   print_functiont   divisionN(   t   Joint   checkpointscan_fni
   c         ` sÂ  t  | t ƒ s | g } n  t  | t ƒ s6 | g } n  t  | t ƒ sQ | g } n  x8 | D]0 } t  | t ƒ rX d | k rX t d ƒ ‚ qX qX W| d k r¬ | d j d } n  t j j t j j	 | | ƒ d ƒ }	 | t j j
 |	 f d ƒ }
 | | } t j j t j j | d ƒ | | ƒ } t j j |
 d | ƒ }
 | r¾t d d ƒ } xo t | ƒ D]^ \ } } | j d | } t j j | | j d f d | j ƒ} | d | | g ƒ | | <qYWn  g  | D]Z } | j | j d | | g g  t d | j ƒ D] } | j | ^ qø| j d ƒ ^ qÅ‰ ˆ j |
 ƒ g  | D] } | d k r9| ^ q9‰ | ‰ ‡  ‡ ‡ ‡ ‡ f d	 †  } t j d
 | d ˆ d | d ˆ d ˆ d d |	 d t ƒ \ } } | | f S(   sM  Scan function that uses less memory, but is more restrictive.

    In :func:`~theano.scan`, if you compute the gradient of the output
    with respect to the input, you will have to store the intermediate
    results at each time step, which can be prohibitively huge. This
    function allows to do ``save_every_N`` steps of forward computations
    without storing the intermediate results, and to recompute them during
    the gradient computation.

    Notes
    -----
    Current assumptions:

    * Every sequence has the same length.
    * If ``n_steps`` is specified, it has the same value as the length of
      any sequence.
    * The value of ``save_every_N`` divides the number of steps the scan
      will run without remainder.
    * Only singly-recurrent and non-recurrent outputs are used.
      No multiple recurrences.
    * Only the last timestep of any output will ever be used.

    Parameters
    ----------
    fn
        ``fn`` is a function that describes the operations involved in one
        step of ``scan``. See the documentation of :func:`~theano.scan`
        for more information.

    sequences
        ``sequences`` is the list of Theano variables or dictionaries
        describing the sequences ``scan`` has to iterate over. All
        sequences must be the same length in this version of ``scan``.

    outputs_info
        ``outputs_info`` is the list of Theano variables or dictionaries
        describing the initial state of the outputs computed
        recurrently.

    non_sequences
        ``non_sequences`` is the list of arguments that are passed to
        ``fn`` at each steps. One can opt to exclude variable
        used in ``fn`` from this list as long as they are part of the
        computational graph, though for clarity we encourage not to do so.

    n_steps
        ``n_steps`` is the number of steps to iterate given as an int
        or Theano scalar (> 0). If any of the input sequences do not have
        enough elements, scan will raise an error. If n_steps is not provided,
        ``scan`` will figure out the amount of steps it should run given its
        input sequences.

    save_every_N
        ``save_every_N`` is the number of steps to go without storing
        the computations of ``scan`` (ie they will have to be recomputed
        during the gradient computation).

    padding
        If the length of the sequences is not a multiple of ``save_every_N``,
        the sequences will be zero padded to make this version of ``scan``
        work properly, but will also result in a memory copy. It can be
        avoided by setting ``padding`` to False, but you need to make
        sure the length of the sequences is a multple of ``save_every_N``.

    Returns
    -------
    tuple
        Tuple of the form ``(outputs, updates)`` as in :func:`~theano.scan`, but
        with a small change: It only contain the output at each
        ``save_every_N`` step. The time steps that are not returned by
        this function will be recomputed during the gradient computation
        (if any).

    See Also
    --------
    :func:`~theano.scan`: Looping in Theano.

    t   tapss(   scan_checkpoints doesn't work with taps.i    t   int64iÿÿÿÿt   viewi   t   dtypec          ` s  t  |  t ˆ ƒ  ƒ } t  |  t ˆ ƒ t ˆ ƒ !ƒ } t  |  t ˆ ƒ ƒ } | d  g t ˆ ƒ } t j d ˆ  d | d  d | d | d ˆ d d | d ƒ \ } } t | t  ƒ sÁ | g } n  t | t  ƒ sÞ | d | f Sg  | D] } | d ^ qå | f Sd  S(	   Nt   fnt	   sequencesiÿÿÿÿt   outputs_infot   non_sequencest   namet   _innert   n_steps(   t   listt   lent   Nonet   theanot   scant
   isinstance(   t   argst   i_sequencest   i_prev_outputst   i_non_sequencest   i_outputs_infost   resultst   updatest   r(   R	   R   t   new_nitsotst   o_nonsequencest   o_sequences(    sC   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_checkpoints.pyt
   outer_step…   s     

R	   R
   R   R   R   t   _outerR   t   allow_gcN(   R   R   t   dictt   RuntimeErrorR   t   shapeR   t   tensort   castt   ceilt   onest   switcht   eqt   set_subtensorR   t	   enumeratet   zerosR   t   reshapet   ranget   ndimt   appendR   t   True(   R	   R
   R   R   R   R   t   save_every_Nt   paddingt   elementt	   o_n_stepst	   i_n_stepst   modt   last_n_stepst   joint   it   st   nt   zR!   R   R   (    (   R	   R   R   R   R    sC   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_checkpoints.pyt   scan_checkpoints   sJ    R	
( d%
(
   t
   __future__R    R   R   R   t   theano.tensor.basicR   R   R4   RA   (    (    (    sC   /tmp/pip-build-X4mzal/theano/theano/scan_module/scan_checkpoints.pyt   <module>   s
   		