class_docstr: Build indices for a sparse CSC matrix that could implement A
  (convolve) B.
  
     This generates a sparse matrix M, which generates a stack of
     image patches when computing the dot product of M with image
     patch. Convolution is then simply the dot product of (img x M)
     and the kernels.
class_docstr_tok: ["Build","indices","for","a","sparse","CSC","matrix","that","could","implement","A","(","convolve",")","B",".","This","generates","a","sparse","matrix","M",",","which","generates","a","stack","of","image","patches","when","computing","the","dot","product","of","M","with","image","patch",".","Convolution","is","then","simply","the","dot","product","of","(","img","x","M",")","and","the","kernels","."]
docstr: Build a sparse matrix which can be used for performing...
  * convolution: in this case, the dot product of this matrix
  with the input images will generate a stack of images
  patches. Convolution is then a tensordot operation of the
  filters and the patch stack.
  * sparse local connections: in this case, the sparse matrix
  allows us to operate the weight matrix as if it were
  fully-connected. The structured-dot with the input image gives
  the output for the following layer.
  
  :param ker_shape: shape of kernel to apply (smaller than image)
  :param img_shape: shape of input images
  :param mode: 'valid' generates output only when kernel and
               image overlap overlap fully. Convolution obtained
               by zero-padding the input
  :param ws: must be always True
  :param (dx,dy): offset parameter. In the case of no weight sharing,
                  gives the pixel offset between two receptive fields.
                  With weight sharing gives the offset between the
                  top-left pixels of the generated patches
  
  :rtype: tuple(indices, indptr, logical_shape, sp_type, out_img_shp)
  :returns: the structure of a sparse matrix, and the logical dimensions
            of the image which will be the result of filtering.
docstr_tok: ["Build","a","sparse","matrix","which","can","be","used","for","performing","...","*","convolution",":","in","this","case",",","the","dot","product","of","this","matrix","with","the","input","images","will","generate","a","stack","of","images","patches",".","Convolution","is","then","a","tensordot","operation","of","the","filters","and","the","patch","stack",".","*","sparse","local","connections",":","in","this","case",",","the","sparse","matrix","allows","us","to","operate","the","weight","matrix","as","if","it","were","fully-connected",".","The","structured-dot","with","the","input","image","gives","the","output","for","the","following","layer",".",":","param","ker_shape",":","shape","of","kernel","to","apply","(","smaller","than","image",")",":","param","img_shape",":","shape","of","input","images",":","param","mode",":","'valid","'","generates","output","only","when","kernel","and","image","overlap","overlap","fully",".","Convolution","obtained","by","zero-padding","the","input",":","param","ws",":","must","be","always","True",":","param","(","dx",",","dy",")",":","offset","parameter",".","In","the","case","of","no","weight","sharing",",","gives","the","pixel","offset","between","two","receptive","fields",".","With","weight","sharing","gives","the","offset","between","the","top-left","pixels","of","the","generated","patches",":","rtype",":","tuple","(","indices",",","indptr",",","logical_shape",",","sp_type",",","out_img_shp",")",":","returns",":","the","structure","of","a","sparse","matrix",",","and","the","logical","dimensions","of","the","image","which","will","be","the","result","of","filtering","."]
code: def evaluate(
      inshp, kshp, strides=(1, 1), nkern=1, mode="valid", ws=True
  ):
      """Build a sparse matrix which can be used for performing...
      * convolution: in this case, the dot product of this matrix
      with the input images will generate a stack of images
      patches. Convolution is then a tensordot operation of the
      filters and the patch stack.
      * sparse local connections: in this case, the sparse matrix
      allows us to operate the weight matrix as if it were
      fully-connected. The structured-dot with the input image gives
      the output for the following layer.
  
      :param ker_shape: shape of kernel to apply (smaller than image)
      :param img_shape: shape of input images
      :param mode: 'valid' generates output only when kernel and
                   image overlap overlap fully. Convolution obtained
                   by zero-padding the input
      :param ws: must be always True
      :param (dx,dy): offset parameter. In the case of no weight sharing,
                      gives the pixel offset between two receptive fields.
                      With weight sharing gives the offset between the
                      top-left pixels of the generated patches
  
      :rtype: tuple(indices, indptr, logical_shape, sp_type, out_img_shp)
      :returns: the structure of a sparse matrix, and the logical dimensions
                of the image which will be the result of filtering.
      """
      if not ws:
          raise Exception("ws is obsolete and it must be always True")
  
      (dx, dy) = strides
  
      # inshp contains either 2 entries (height,width) or 3 (nfeatures,h,w)
      # in the first case, default nfeatures to 1
      if np.size(inshp) == 2:
          inshp = (1,) + inshp
  
      inshp = np.array(inshp)
      kshp = np.array(kshp)
      ksize = np.prod(kshp)
  
      kern = ksize - 1 - np.arange(ksize)
  
      # size of output image if doing proper convolution
      # (mode='full',dx=dy=0) outshp is the actual output shape
      # given the parameters
      fulloutshp = inshp[1:] + kshp - 1
      if mode == "valid":
          s = -1
      else:
          s = 1
      outshp = np.int64(
          np.ceil(
              (inshp[1:] + s * kshp - s * 1)
              / np.array([dy, dx], dtype="float")
          )
      )
      if any(outshp <= 0):
          err = (
              "Invalid kernel",
              kshp,
              "and/or step size",
              (dx, dy),
              "for given input shape",
              inshp,
          )
          raise ValueError(err)
  
      outsize = np.prod(outshp)
      insize = np.prod(inshp)
  
      # range of output units over which to iterate
      if mode == "valid":
          lbound = np.array([kshp[0] - 1, kshp[1] - 1])
          ubound = lbound + (inshp[1:] - kshp + 1)
      else:
          lbound = np.zeros(2)
          ubound = fulloutshp
  
      # coordinates of image in "fulloutshp" coordinates
      topleft = np.array([kshp[0] - 1, kshp[1] - 1])
      # bound when counting the receptive field
      botright = topleft + inshp[1:]
  
      # sparse matrix specifics...
      if ws:
          spmatshp = (outsize * np.prod(kshp) * inshp[0], insize)
      else:
          spmatshp = (nkern * outsize, insize)
      spmat = scipy_sparse.lil_matrix(spmatshp)
  
      # loop over output image pixels
      z, zz = 0, 0
  
      # incremented every time we write something to the sparse
      # matrix this is used to track the ordering of filter tap
      # coefficient in sparse column ordering
      tapi, ntaps = 0, 0
  
      # Note: looping over the number of kernels could've been done
      # more efficiently as the last step (when writing to
      # spmat). However, this messes up the ordering of the column
      # values (order in which you write the values determines how
      # the vectorized data will get used later one)
  
      for fmapi in xrange(inshp[0]):  # loop over input features
          # loop over number of kernels (nkern=1 for weight sharing)
          for n in xrange(nkern):
              # FOR EACH OUTPUT PIXEL...
              # loop over output image height
              for oy in np.arange(lbound[0], ubound[0], dy):
                  # loop over output image width
                  for ox in np.arange(lbound[1], ubound[1], dx):
                      # kern[l] is filter value to apply at (oj,oi)
                      # for (iy,ix)
                      l = 0
  
                      # ... ITERATE OVER INPUT UNITS IN RECEPTIVE FIELD
                      for ky in oy + np.arange(kshp[0]):
                          for kx in ox + np.arange(kshp[1]):
                              # verify if we are still within image
                              # boundaries. Equivalent to
                              # zero-padding of the input image
                              if all((ky, kx) >= topleft) and all(
                                  (ky, kx) < botright
                              ):
                                  # convert to "valid" input space
                                  # coords used to determine column
                                  # index to write to in sparse mat
                                  iy, ix = np.array((ky, kx)) - topleft
                                  # determine raster-index of input pixel...
  
                                  # taking into account multiple
                                  # input features
                                  col = (
                                      iy * inshp[2]
                                      + ix
                                      + fmapi * np.prod(inshp[1:])
                                  )
  
                                  # convert oy,ox values to output
                                  # space coordinates
                                  if mode == "full":
                                      (y, x) = (oy, ox)
                                  else:
                                      (y, x) = (oy, ox) - topleft
                                  # taking into account step size
                                  (y, x) = np.array([y, x]) / (dy, dx)
  
                                  # convert to row index of sparse matrix
                                  if ws:
                                      row = (
                                          (y * outshp[1] + x)
                                          * inshp[0]
                                          * ksize
                                          + l
                                          + fmapi * ksize
                                      )
                                  else:
                                      row = y * outshp[1] + x
  
                                  # Store something at that location
                                  # in sparse matrix.  The written
                                  # value is only useful for the
                                  # sparse case. It will determine
                                  # the way kernel taps are mapped
                                  # onto the sparse columns (idea of
                                  # kernel map)
                                  # n*... only for sparse
                                  spmat[row + n * outsize, col] = (
                                      tapi + 1
                                  )
  
                                  # total number of active taps
                                  # (used for kmap)
                                  ntaps += 1
  
                              # absolute tap index (total number of taps)
                              tapi += 1
                              # move on to next filter tap l=(l+1)%ksize
                              l += 1
  
      if spmat.format != "csc":
          spmat = spmat.tocsc().sorted_indices()
      else:
          # BUG ALERT: scipy0.6 has bug where data and indices are written in
          # reverse column ordering.
          # Explicit call to sorted_indices removes this problem.
          spmat = spmat.sorted_indices()
  
      if ws:
          kmap = None
      else:
          kmap = np.zeros(ntaps, dtype="int")
          k = 0
          # print 'TEMPORARY BUGFIX: REMOVE !!!'
          for j in xrange(spmat.shape[1]):
              for i_idx in xrange(spmat.indptr[j], spmat.indptr[j + 1]):
                  if spmat.data[i_idx] != 0:
                      # this is == spmat[i,j] - 1
                      kmap[k] = spmat.data[i_idx] - 1
                      k += 1
  
      # when in valid mode, it is more efficient to store in sparse row
      # TODO: need to implement structured dot for csr matrix
      assert spmat.format == "csc"
      sptype = "csc"
      # sptype = 'csr' if mode=='valid' else 'csc'
      if 0 and mode == "valid":
          spmat = spmat.tocsr()
  
      rval = (
          spmat.indices[: spmat.size],
          spmat.indptr,
          spmatshp,
          sptype,
          outshp,
      )
      if kmap is not None:
          rval += (kmap,)
  
      return rval
  
file_path: Theano/theano/sparse/sandbox/sp.py
imports: from __future__ import absolute_import, print_function, division
  import numpy
  import scipy
  from scipy import sparse
  from six.moves import xrange
  import theano
  import theano.sparse
  from theano import sparse, gof, Op, tensor
  from theano.sparse.basic import Remove0, remove0
  from theano.sparse import SpSum, sp_sum, ColScaleCSC, RowScaleCSC, col_scale, row_scale, Diag, diag, SquareDiagonal, square_diagonal, EnsureSortedIndices, ensure_sorted_indices, clean
label_desc: Use image node_id 2 for calling the ConvolutionIndices obj's underlying member method code with example usage: obj.evaluate(inshp, kshp, strides, nkern, mode, ws) and returns: rval