class_docstr: Parameters
  ----------
  inputs
      Inputs of the inner function of scan.
  outputs
      Outputs of the inner function of scan.
  info
      Dictionary containing different properties of the scan op (like number
      of different types of arguments, name, mode, if it should run on GPU or
      not, etc.).
  typeConstructor
      Function that constructs an equivalent to Theano TensorType.
  
  Notes
  -----
  ``typeConstructor`` had been added to refactor how
  Theano deals with the GPU. If it runs on the GPU, scan needs
  to construct certain outputs (those who reside in the GPU
  memory) as the GPU-specific type.  However we can not import
  gpu code in this file (as it is in sandbox, and not available
  on each machine) so the workaround is that the GPU
  optimization passes to the constructor of this class a
  function that is able to construct a GPU type. This way the
  class Scan does not need to be aware of the details for the
  GPU, it just constructs any tensor using this function (which
  by default constructs normal tensors).
class_docstr_tok: ["Parameters","--","--","--","--","--","inputs","Inputs","of","the","inner","function","of","scan",".","outputs","Outputs","of","the","inner","function","of","scan",".","info","Dictionary","containing","different","properties","of","the","scan","op","(","like","number","of","different","types","of","arguments",",","name",",","mode",",","if","it","should","run","on","GPU","or","not",",","etc.",")",".","typeConstructor","Function","that","constructs","an","equivalent","to","Theano","TensorType",".","Notes","--","--","-","``","typeConstructor","``","had","been","added","to","refactor","how","Theano","deals","with","the","GPU",".","If","it","runs","on","the","GPU",",","scan","needs","to","construct","certain","outputs","(","those","who","reside","in","the","GPU","memory",")","as","the","GPU-specific","type",".","However","we","can","not","import","gpu","code","in","this","file","(","as","it","is","in","sandbox",",","and","not","available","on","each","machine",")","so","the","workaround","is","that","the","GPU","optimization","passes","to","the","constructor","of","this","class","a","function","that","is","able","to","construct","a","GPU","type",".","This","way","the","class","Scan","does","not","need","to","be","aware","of","the","details","for","the","GPU",",","it","just","constructs","any","tensor","using","this","function","(","which","by","default","constructs","normal","tensors",")","."]
docstr: Compute and return dictionary mappings between the inputs and
  outputs of the inner function and the inputs and outputs of the Scan
  node in the outer graph.
  
  The return value is a dictionary in which the keys are the names of
  the individual mappings and the values are the mapping dictionaries
  themselves. In dictionaries representing mappings to outer variables,
  the values are individual integer indices. In dictionaries
  representing mappings to inner variables, the values are sequences of
  indices because multiple inner variables can be associated with the
  same state.
docstr_tok: ["Compute","and","return","dictionary","mappings","between","the","inputs","and","outputs","of","the","inner","function","and","the","inputs","and","outputs","of","the","Scan","node","in","the","outer","graph",".","The","return","value","is","a","dictionary","in","which","the","keys","are","the","names","of","the","individual","mappings","and","the","values","are","the","mapping","dictionaries","themselves",".","In","dictionaries","representing","mappings","to","outer","variables",",","the","values","are","individual","integer","indices",".","In","dictionaries","representing","mappings","to","inner","variables",",","the","values","are","sequences","of","indices","because","multiple","inner","variables","can","be","associated","with","the","same","state","."]
code: def get_oinp_iinp_iout_oout_mappings(self):
      """
      Compute and return dictionary mappings between the inputs and
      outputs of the inner function and the inputs and outputs of the Scan
      node in the outer graph.
  
      The return value is a dictionary in which the keys are the names of
      the individual mappings and the values are the mapping dictionaries
      themselves. In dictionaries representing mappings to outer variables,
      the values are individual integer indices. In dictionaries
      representing mappings to inner variables, the values are sequences of
      indices because multiple inner variables can be associated with the
      same state.
  
      """
      # Lists for outer variables contain individual indices, lists for
      # inner variables contain sequences of indices because many inner
      # variables can be associated with the same outer variable. The list
      # and indices are initialized already containing the data associated
      # with the timestep index, the first outer input.
      outer_input_indices = [0]
      inner_input_indices = [[]]
      inner_output_indices = [[]]
      outer_output_indices = [-1]
  
      outer_iidx = 1
      inner_iidx = 0
      inner_oidx = 0
      outer_oidx = 0
  
      # Handle sequences inputs
      for i in xrange(self.info["n_seqs"]):
          outer_input_indices.append(outer_iidx)
          inner_input_indices.append([inner_iidx])
          inner_output_indices.append([])
          outer_output_indices.append(-1)
  
          outer_iidx += 1
          inner_iidx += 1
          inner_oidx += 0
          outer_oidx += 0
  
      # Handle mitmots, mitsots and sitsots variables
      for i in xrange(len(self.info["tap_array"])):
          nb_input_taps = len(self.info["tap_array"][i])
  
          if i < self.n_mit_mot:
              nb_output_taps = len(self.mit_mot_out_slices[i])
          else:
              nb_output_taps = 1
  
          outer_input_indices.append(outer_iidx)
          inner_input_indices.append(
              list(range(inner_iidx, inner_iidx + nb_input_taps))
          )
          inner_output_indices.append(
              list(range(inner_oidx, inner_oidx + nb_output_taps))
          )
          outer_output_indices.append(outer_oidx)
  
          outer_iidx += 1
          inner_iidx += nb_input_taps
          inner_oidx += nb_output_taps
          outer_oidx += 1
  
      # This is needed because, for outer inputs (and for outer inputs only)
      # nitsots come *after* shared variables.
      outer_iidx += self.info["n_shared_outs"]
  
      # Handle nitsots variables
      for i in xrange(self.n_nit_sot):
          outer_input_indices.append(outer_iidx)
          inner_input_indices.append([])
          inner_output_indices.append([inner_oidx])
          outer_output_indices.append(outer_oidx)
  
          outer_iidx += 1
          inner_iidx += 0
          inner_oidx += 1
          outer_oidx += 1
  
      # This is needed because, for outer inputs (and for outer inputs only)
      # nitsots come *after* shared variables.
      outer_iidx -= self.info["n_shared_outs"] + self.n_nit_sot
  
      # Handle shared states
      for i in xrange(self.info["n_shared_outs"]):
          outer_input_indices.append(outer_iidx)
          inner_input_indices.append([inner_iidx])
          inner_output_indices.append([inner_oidx])
          outer_output_indices.append(outer_oidx)
  
          outer_iidx += 1
          inner_iidx += 1
          inner_oidx += 1
          outer_oidx += 1
  
      # This is needed because, for outer inputs (and for outer inputs only)
      # nitsots come *after* shared variables.
      outer_iidx += self.n_nit_sot
  
      # Handle non-sequence inputs
      # Note : the number of non-sequence inputs is not stored in self.info
      # so it has to be inferred from the number of inner inputs that remain
      # to be handled
      for i in xrange(len(self.inputs) - inner_iidx):
          outer_input_indices.append(outer_iidx)
          inner_input_indices.append([inner_iidx])
          inner_output_indices.append([])
          outer_output_indices.append(-1)
  
          outer_iidx += 1
          inner_iidx += 1
          inner_oidx += 0
          outer_oidx += 0
  
      # With the global mapping inferred, the individual mappings
      # can be produced
      mappings = {
          "outer_inp_from_outer_out": {},
          "inner_inp_from_outer_out": {},
          "inner_out_from_outer_out": {},
          "inner_inp_from_outer_inp": {},
          "inner_out_from_outer_inp": {},
          "outer_out_from_outer_inp": {},
          "outer_inp_from_inner_inp": {},
          "inner_out_from_inner_inp": {},
          "outer_out_from_inner_inp": {},
          "outer_inp_from_inner_out": {},
          "inner_inp_from_inner_out": {},
          "outer_out_from_inner_out": {},
      }
  
      for oinp, iinp, iout, oout in izip(
          outer_input_indices,
          inner_input_indices,
          inner_output_indices,
          outer_output_indices,
      ):
          if oout != -1:
              mappings["outer_inp_from_outer_out"][oout] = oinp
              mappings["inner_inp_from_outer_out"][oout] = iinp
              mappings["inner_out_from_outer_out"][oout] = iout
  
          if oinp != -1:
              mappings["inner_inp_from_outer_inp"][oinp] = iinp
              mappings["inner_out_from_outer_inp"][oinp] = iout
              mappings["outer_out_from_outer_inp"][oinp] = oout
  
          for idx in iinp:
              mappings["outer_inp_from_inner_inp"][idx] = oinp
              mappings["inner_out_from_inner_inp"][idx] = iout
              mappings["outer_out_from_inner_inp"][idx] = oout
  
          for idx in iout:
              mappings["outer_inp_from_inner_out"][idx] = oinp
              mappings["inner_inp_from_inner_out"][idx] = iinp
              mappings["outer_out_from_inner_out"][idx] = oout
  
      return mappings
  
imports: from __future__ import absolute_import, print_function, division
  import copy
  import itertools
  import logging
  import time
  from collections import OrderedDict
  import numpy
  from six import iteritems, integer_types, raise_from
  from six.moves import xrange
  import theano
  from theano.compile import function, In, Out
  from theano.compile.mode import AddFeatureOptimizer
  from theano import compile, config, gradient, gof, tensor
  from theano.gof import PureOp, Apply
  from theano.gof.graph import io_connection_pattern
  from theano.gof.toolbox import NoOutputFromInplace
  from theano.compat import izip
  from theano.tensor import as_tensor_variable, TensorType
  from theano.tensor.opt import Shape_i
  from theano.gradient import grad_undefined, DisconnectedType, NullType
  from six import string_types
  from theano.compile.profiling import ScanProfileStats
  from theano.scan_module import scan_utils
  from theano.scan_module.scan_utils import safe_new, forced_replace
label_desc: Use image node_id 38 for calling the Scan obj's underlying member method code with example usage: obj.get_oinp_iinp_iout_oout_mappings() and returns: mappings