class_docstr: A FunctionGraph represents a subgraph bound by a set of input variables and
  a set of output variables, ie a subgraph that specifies a theano function.
  The inputs list should contain all the inputs on which the outputs depend.
  Variables of type Constant are not counted as inputs.
  
  The FunctionGraph supports the replace operation which allows to replace a
  variable in the subgraph by another, e.g. replace (x + x).out by (2
  * x).out. This is the basis for optimization in theano.
  
  This class is also responsible for verifying that a graph is valid
  (ie, all the dtypes and broadcast patterns are compatible with the
  way the the Variables are used) and for annotating the Variables with
  a .clients field that specifies which Apply nodes use the variable.
  The .clients field combined with the .owner field and the Apply nodes'
  .inputs field allows the graph to be traversed in both directions.
  
  It can also be extended with new features using
  FunctionGraph.attach_feature(<toolbox.Feature instance>).
  See toolbox.Feature for event types and documentation.
  Extra features allow the FunctionGraph to verify new properties of
  a graph as it is optimized.
  # TODO: are there other things features can do to the fgraph?
  
  Historically, the FunctionGraph was called an Env. Keep this in mind
  while reading out-of-date documentation, e-mail support threads, etc.
  
  The constructor creates a FunctionGraph which operates on the subgraph
  bound by the inputs and outputs sets.
  
  This class keeps a pointer to the inputs and outputs, and also modifies
  them.
  
  #TODO: document what variables are[not] set in the FunctionGraph when a
  feature is added via the constructor. How constructed is the
  FunctionGraph?
  
  Parameters
  ----------
  inputs
      Inputs nodes of the graph, usually declared by the user.
  outputs
      Outputs nodes of the graph.
  clone
      If true, we will clone the graph. This is useful to remove the constant
      cache problem.
  
  Notes
  -----
  The intermediate nodes between 'inputs' and 'outputs' are not explicitely
  passed.
class_docstr_tok: ["A","FunctionGraph","represents","a","subgraph","bound","by","a","set","of","input","variables","and","a","set","of","output","variables",",","ie","a","subgraph","that","specifies","a","theano","function",".","The","inputs","list","should","contain","all","the","inputs","on","which","the","outputs","depend",".","Variables","of","type","Constant","are","not","counted","as","inputs",".","The","FunctionGraph","supports","the","replace","operation","which","allows","to","replace","a","variable","in","the","subgraph","by","another",",","e.g",".","replace","(","x","+","x",")",".out","by","(","2","*","x",")",".out",".","This","is","the","basis","for","optimization","in","theano",".","This","class","is","also","responsible","for","verifying","that","a","graph","is","valid","(","ie",",","all","the","dtypes","and","broadcast","patterns","are","compatible","with","the","way","the","the","Variables","are","used",")","and","for","annotating","the","Variables","with","a",".clients","field","that","specifies","which","Apply","nodes","use","the","variable",".","The",".clients","field","combined","with","the",".owner","field","and","the","Apply","nodes'",".inputs","field","allows","the","graph","to","be","traversed","in","both","directions",".","It","can","also","be","extended","with","new","features","using","FunctionGraph.attach_feature","(","<","toolbox.Feature","instance",">",")",".","See","toolbox.Feature","for","event","types","and","documentation",".","Extra","features","allow","the","FunctionGraph","to","verify","new","properties","of","a","graph","as","it","is","optimized",".","#","TODO",":","are","there","other","things","features","can","do","to","the","fgraph","?","Historically",",","the","FunctionGraph","was","called","an","Env",".","Keep","this","in","mind","while","reading","out-of-date","documentation",",","e-mail","support","threads",",","etc",".","The","constructor","creates","a","FunctionGraph","which","operates","on","the","subgraph","bound","by","the","inputs","and","outputs","sets",".","This","class","keeps","a","pointer","to","the","inputs","and","outputs",",","and","also","modifies","them",".","#","TODO",":","document","what","variables","are","[","not","]","set","in","the","FunctionGraph","when","a","feature","is","added","via","the","constructor",".","How","constructed","is","the","FunctionGraph","?","Parameters","--","--","--","--","--","inputs","Inputs","nodes","of","the","graph",",","usually","declared","by","the","user",".","outputs","Outputs","nodes","of","the","graph",".","clone","If","true",",","we","will","clone","the","graph",".","This","is","useful","to","remove","the","constant","cache","problem",".","Notes","--","--","-","The","intermediate","nodes","between","'inputs","'","and","'outputs","'","are","not","explicitely","passed","."]
docstr: Create an FunctionGraph which operates on the subgraph bound by the
  inputs and outputs sets.
  
  Parameters
  ----------
  inputs : list of variables
      Inputs nodes of the graph, usually declared by the user
  outputs : list of variables
      Outputs nodes of the graph.
  clone : boolean
      If true, we will clone the graph. This is useful to remove the
      constant cache problem.
  update_mapping : dictionary
      Mapping between the inputs with updates and the outputs
      corresponding to their updates.
docstr_tok: ["Create","an","FunctionGraph","which","operates","on","the","subgraph","bound","by","the","inputs","and","outputs","sets",".","Parameters","--","--","--","--","--","inputs",":","list","of","variables","Inputs","nodes","of","the","graph",",","usually","declared","by","the","user","outputs",":","list","of","variables","Outputs","nodes","of","the","graph",".","clone",":","boolean","If","true",",","we","will","clone","the","graph",".","This","is","useful","to","remove","the","constant","cache","problem",".","update_mapping",":","dictionary","Mapping","between","the","inputs","with","updates","and","the","outputs","corresponding","to","their","updates","."]
code: def __init__(
      self,
      inputs,
      outputs,
      features=None,
      clone=True,
      update_mapping=None,
  ):
      """
      Create an FunctionGraph which operates on the subgraph bound by the
      inputs and outputs sets.
  
      Parameters
      ----------
      inputs : list of variables
          Inputs nodes of the graph, usually declared by the user
      outputs : list of variables
          Outputs nodes of the graph.
      clone : boolean
          If true, we will clone the graph. This is useful to remove the
          constant cache problem.
      update_mapping : dictionary
          Mapping between the inputs with updates and the outputs
          corresponding to their updates.
      """
  
      if clone:
          inputs, outputs = graph.clone(inputs, outputs)
  
      self.execute_callbacks_time = 0
      self.execute_callbacks_times = {}
  
      if features is None:
          features = []
  
      # XXX: Unless I'm missing something (but there's no documentation,
      # so I probably am) this should be a set.
      self._features = []
  
      # All apply nodes in the subgraph defined by inputs and
      # outputs are cached in this field
      self.apply_nodes = set()
  
      # Ditto for variable nodes.
      # It must contain all fgraph.inputs and all apply_nodes
      # outputs even if they aren't used in the graph.
      self.variables = set()
  
      self.inputs = list(inputs)
      self.outputs = outputs
  
      for f in features:
          self.attach_feature(f)
      self.attach_feature(toolbox.ReplaceValidate())
  
      for input in self.inputs:
          if input.owner is not None:
              raise ValueError(
                  "One of the provided inputs is the output of"
                  "an already existing node. "
                  "If that is okay, either discard that "
                  "input's owner or use graph.clone."
              )
          self.__setup_r__(input)
          self.variables.add(input)
  
      for output in outputs:
          self.__import_r__(output, reason="init")
      for i, output in enumerate(outputs):
          output.clients.append(("output", i))
  
      self.profile = None
      self.update_mapping = update_mapping
  
imports: from __future__ import absolute_import, print_function, division
  from collections import OrderedDict
  import time
  import theano
  from theano.gof import graph
  from theano.gof import utils
  from theano.gof import toolbox
  from theano import config
  from six import iteritems, itervalues
  from six.moves import StringIO
  from theano.gof.utils import get_variable_trace_string
  from theano.misc.ordered_set import OrderedSet
label_desc: Use image node_id 1 to create a new FunctionGraph object from inherited base classes: utils with example: obj = FunctionGraph(inputs, outputs, features, clone, update_mapping)