ó
àÆ÷Xc           @` sÓ   d  d l  m Z m Z m Z d  d l Z d  d l Z d  d l m Z m Z d  d l m	 Z	 d  d l
 m Z d e f d „  ƒ  YZ d e f d	 „  ƒ  YZ e e ƒ Z e e ƒ Z e e ƒ Z e e ƒ Z d
 „  Z d S(   i    (   t   absolute_importt   print_functiont   divisionN(   t   Opt   Apply(   t   discrete_dtypes(   t   grad_undefinedt   SparseBlockGemvc           B` sJ   e  Z d  Z d Z g  Z e d „ Z d „  Z d „  Z d „  Z	 d „  Z
 RS(   sÔ  
    This op computes the dot product of specified pieces of vectors
    and matrices, returning pieces of vectors::

        for b in range(batch_size):
            for j in range(o.shape[1]):
                for i in range(h.shape[1]):
                    o[b, j, :] += numpy.dot(h[b, i], W[iIdx[b, i], oIdx[b, j]])

    where b, h, W, o iIdx, oIdx are defined in the docstring of make_node.

    .. image:: ../../../images/blocksparse.png
        :scale: 50 %

    t   inplacec         C` s,   | |  _  |  j  r( i d g d 6|  _ n  d  S(   Ni    (   R   t   destroy_map(   t   selfR   (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt   __init__   s    		c         C` sH  t  j j | ƒ } t  j j | ƒ } t  j j | ƒ } t  j j | ƒ } t  j j | ƒ } | j d k rx t d ƒ ‚ n  | j d k r– t d ƒ ‚ n  | j d k r´ t d ƒ ‚ n  | j d k rÒ t d ƒ ‚ n  | j d k rð t d ƒ ‚ n  | j j t k st ‚ | j j t k s t ‚ t	 |  | | | | | g | j ƒ  g ƒ S(	   sB  
        Compute the dot product of the specified pieces of vectors
        and matrices.

        The parameter types are actually their expected shapes
        relative to each other.

        Parameters
        ----------
        o : batch, oWin, oSize
            output vector
        W : iBlocks, oBlocks, iSize, oSize
            weight matrix
        h : batch, iWin, iSize
            input from lower layer (sparse)
        inputIdx : batch, iWin
            indexes of the input blocks
        outputIdx : batch, oWin
            indexes of the output blocks

        Returns
        -------
        (batch, oWin, oSize)
            dot(W[i, j], h[i]) + o[j]

        Notes
        -----
        - `batch` is the number of examples in a minibatch (batch size).
        - `iBlocks` is the total number of blocks in the input (from lower
            layer).
        - `iSize` is the size of each of these input blocks.
        - `iWin` is the number of blocks that will be used as inputs. Which
           blocks will be used is specified in `inputIdx`.
        - `oBlocks` is the number or possible output blocks.
        - `oSize` is the size of each of these output blocks.
        - `oWin` is the number of output blocks that will actually be computed.
            Which blocks will be computed is specified in `outputIdx`.

        i   s    The output o must be a 2D tensori   s'   The weight matrix W must be a 4D tensors   The input h must be a 3D tensori   s.   The input indices inputIdx must be a 2D tensors0   The output indices outputIdx must be a 2D tensor(
   t   theanot   tensort   as_tensor_variablet   ndimt	   TypeErrort   typet   dtypeR   t   AssertionErrorR   (   R
   t   ot   Wt   ht   inputIdxt	   outputIdx(    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt	   make_node#   s$    (c      
   C` s  | d  \ } } } } } |  j  s1 | j ƒ  } n  x¼ t | j d ƒ D]§ }	 xž t | j d ƒ D]‰ }
 | |	 |
 f } xp t | j d ƒ D][ } | |	 | f } | | | f } | |	 |
 d  d  … f c t j | |	 | f | ƒ 7<q‰ Wq_ WqE W| | d d <d  S(   Ni   i    i   (   R   t   copyt   ranget   shapet   numpyt   dot(   R
   t   nodet   inpt   out_R   R   R   t   iIdxt   oIdxt   bt   jR   t   iR   t   w(    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt   performa   s    	Ac         C` s   | d g S(   Ni    (    (   R
   R   t   input_shapes(    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt   infer_shapep   s    c      	   C` s³   | \ } } } } } | d } t  |  j ƒ }	 t |  j ƒ }
 |	 | j ƒ  | | | | ƒ } |
 | j ƒ  | j d ƒ | | | ƒ } | | | t |  d | d ƒ t |  d | d ƒ g S(	   Ni    i   i   i   s   grad of inputIdx makes no sensei   s    grad of outputIdx makes no sense(   i   i    i   i   (   t   SparseBlockOuterR   R   t
   zeros_liket
   dimshuffleR   (   R
   t   inputst   gradsR   R   R   R   R   t   got	   outer_funt   gemv_funt   Wgradt   hgrad(    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt   grads   s    
	(   s   inplace(   t   __name__t
   __module__t   __doc__t	   __props__t   registered_optst   FalseR   R   R(   R*   R5   (    (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyR   
   s   	>		R+   c           B` sD   e  Z d  Z d Z g  Z e d „ Z d d „ Z d „  Z	 d „  Z
 RS(   s&  
    This computes the outer product of two sets of pieces of vectors
    updating a full matrix with the results::

        for b in range(batch_size):
            o[xIdx[b, i], yIdx[b, j]] += (alpha * outer(x[b, i], y[b, j]))

    This op is involved in the gradient of SparseBlockGemv.

    R   c         C` s,   | |  _  |  j  r( i d g d 6|  _ n  d  S(   Ni    (   R   R	   (   R
   R   (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyR   “   s    		c         C` s—   t  j j t j d d d ƒƒ } t  j j | ƒ } t  j j | ƒ } t  j j | ƒ } | d k rl | } n  t |  | | | | | | g | j ƒ  g ƒ S(   s“  
        Compute the dot product of the specified pieces of vectors
        and matrices.

        The parameter types are actually their expected shapes
        relative to each other.

        Parameters
        ----------
        o : xBlocks, yBlocks, xSize, ySize
        x : batch, xWin, xSize
        y : batch, yWin, ySize
        xIdx : batch, iWin
            indexes of the x blocks
        yIdx : batch, oWin
            indexes of the y blocks

        Returns
        -------
        (xBlocks, yBlocks, xSize, ySize)
            outer(x[i], y[j]) + o[i, j]

        Notes
        -----
        - `batch` is the number of examples in a minibatch (batch size).
        - `xBlocks` is the total number of blocks in x.
        - `xSize` is the size of each of these x blocks.
        - `xWin` is the number of blocks that will be used as x. Which blocks
          will be used is specified in `xIdx`.
        - `yBlocks` is the number or possible y blocks.
        - `ySize` is the size of each of these y blocks.
        - `yWin` is the number of y blocks that will actually be computed.
          Which blocks will be computed is specified in `yIdx`.

        g      ð?R   t   float32N(	   R   R   t   constantR   t   asarrayR   t   NoneR   R   (   R
   R   t   xt   yt   xIdxt   yIdxt   alphat   one(    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyR   ˜   s    $!	c         C` s   | d g S(   Ni    (    (   R
   R   R)   (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyR*   Ç   s    c         C` só   | d  \ } } } } } }	 |  j  s4 | j ƒ  } n  xª t | j d ƒ D]• }
 xŒ t | j d ƒ D]w } xn t | j d ƒ D]Y } | | |
 | f | |
 | f f c t j | |
 | f | |
 | d  d  … f ƒ 7<q| Wqb WqH W| | d d <d  S(   Ni   i    i   (   R   R   R   R   R   t   outer(   R
   R   R    R!   R   R@   RA   RB   RC   RD   R$   R&   R%   (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyR(   Ê   s    	7((   s   inplaceN(   R6   R7   R8   R9   R:   R;   R   R?   R   R*   R(   (    (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyR+   „   s   
/	c         C` s§   | j  | j  d k s t ‚ | j  | j  k s4 t ‚ | j  d k r | j d d d ƒ } | j d d ƒ } | j d d ƒ } n  t ƒ  | j | d d ƒ|  | | | ƒ S(   s  
    Compute the dot product (plus bias) of the specified pieces of vectors
    and matrices. See SparseBlockGemv to get more information.

    The parameter types are actually their expected shapes relative to
    each other.

    Parameters
    ----------
    W : iBlocks, oBlocks, iSize, oSize
        weight matrix
    h : batch, iWin, iSize
        input from lower layer (sparse)
    inputIdx : batch, iWin
        indexes of the input blocks
    b : oBlocks, oSize
        bias vector
    outputIdx : batch, oWin
        indexes of the output blocks

    Returns
    -------
    (batch, oWin, oSize)
        dot(W[i, j], h[i]) + b[j] but b[j] is only added once

    Notes
    -----
    - `batch` is the number of examples in a minibatch (batch size).
    - `iBlocks` is the total number of blocks in the input (from lower layer).
    - `iSize` is the size of each of these input blocks.
    - `iWin` is the number of blocks that will be used as inputs. Which blocks
       will be used is specified in `inputIdx`.
    - `oBlocks` is the number or possible output blocks.
    - `oSize` is the size of each of these output blocks.
    - `oWin` is the number of output blocks that will actually be computed.
       Which blocks will be computed is specified in `outputIdx`.

    i   i   R@   i    t   axis(   R   R   R-   R   t   take(   R   R   R   R$   R   (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt   sparse_block_dotÞ   s    '(   t
   __future__R    R   R   R   R   R   R   t   theano.tensorR   t   theano.gradientR   R   R+   R;   t   sparse_block_gemvt   Truet   sparse_block_gemv_inplacet   sparse_block_outert   sparse_block_outer_inplaceRI   (    (    (    s>   /tmp/pip-build-X4mzal/theano/theano/tensor/nnet/blocksparse.pyt   <module>   s   zT