code: def perform_sigm_times_exp(
      tree,
      exp_x=None,
      exp_minus_x=None,
      sigm_x=None,
      sigm_minus_x=None,
      parent=None,
      child_idx=None,
      full_tree=None,
  ):
      """
      Core processing of the `local_sigm_times_exp` optimization.
  
      This recursive function operates on a multiplication tree as output by
      `parse_mul_tree`. It walks through the tree and modifies it in-place
      by replacing matching pairs (exp, sigmoid) with the desired optimized
      version.
  
      Parameters
      ----------
      tree
          The sub-tree to operate on.
      exp_x
          List of arguments x so that `exp(x)` exists somewhere in the whole
          multiplication tree. Each argument is a pair (x, leaf) with `x` the
          argument of the exponential, and `leaf` the corresponding leaf in the
          multiplication tree (of the form [n, exp(x)] -- see `parse_mul_tree`).
          If None, this argument is initialized to an empty list.
      exp_minus_x
          Similar to `exp_x`, but for `exp(-x)`.
      sigm_x
          Similar to `exp_x`, but for `sigmoid(x)`.
      sigm_minus_x
          Similar to `exp_x`, but for `sigmoid(-x)`.
      parent
          Parent of `tree` (None if `tree` is the global root).
      child_idx
          Index of `tree` in its parent's inputs (None if `tree` is the global
          root).
      full_tree
          The global multiplication tree (should not be set except by recursive
          calls to this function). Used for debugging only.
  
      Returns
      -------
      bool
          True if a modification was performed somewhere in the whole multiplication
          tree, or False otherwise.
  
      """
      if exp_x is None:
          exp_x = []
      if exp_minus_x is None:
          exp_minus_x = []
      if sigm_x is None:
          sigm_x = []
      if sigm_minus_x is None:
          sigm_minus_x = []
      if full_tree is None:
          full_tree = tree
      if False:  # Debug code.
          print("<perform_sigm_times_exp>")
          print("  full_tree   = %s" % full_tree)
          print("  tree        = %s" % tree)
          print("  exp_x       = %s" % exp_x)
          print("  exp_minus_x = %s" % exp_minus_x)
          print("  sigm_x      = %s" % sigm_x)
          print("  sigm_minus_x= %s" % sigm_minus_x)
      neg, inputs = tree
      if isinstance(inputs, list):
          # Recurse through inputs of the multiplication.
          rval = False
          for sub_idx, sub_tree in enumerate(inputs):
              rval |= perform_sigm_times_exp(
                  tree=sub_tree,
                  parent=tree,
                  child_idx=sub_idx,
                  exp_x=exp_x,
                  exp_minus_x=exp_minus_x,
                  sigm_x=sigm_x,
                  sigm_minus_x=sigm_minus_x,
                  full_tree=full_tree,
              )
          return rval
      else:
          # Reached a leaf: if it is an exponential or a sigmoid, then we
          # first attempt to find a match in leaves already visited.
          # If there is such a match, we modify the already-visited leaf
          # accordingly: for instance if we visited a leaf sigmoid(x), then
          # find later a -exp(-x), we replace the previous leaf by
          # -sigmoid(-x) and remove the -exp(-x) from the tree.
          # If no match is found, then we register this leaf so that it can
          # be found later while walking the tree.
          var = inputs
          keep_it = False
          exp_info = is_exp(var)
          if exp_info is not None:
              exp_neg, exp_arg = exp_info
              neg ^= exp_neg
              neg_arg = is_neg(exp_arg)
              if neg_arg is None:
                  if not replace_leaf(
                      exp_arg, sigm_minus_x, sigm_x, sigmoid, neg
                  ):
                      exp_x.append((exp_arg, tree))
                      keep_it = True
              else:
                  if not replace_leaf(
                      neg_arg,
                      sigm_x,
                      sigm_minus_x,
                      lambda x: sigmoid(-x),
                      neg,
                  ):
                      exp_minus_x.append((neg_arg, tree))
                      keep_it = True
          elif var.owner and var.owner.op == sigmoid:
              sigm_arg = var.owner.inputs[0]
              neg_arg = is_neg(sigm_arg)
              if neg_arg is None:
                  if not replace_leaf(
                      sigm_arg,
                      exp_minus_x,
                      sigm_minus_x,
                      lambda x: sigmoid(-x),
                      neg,
                  ):
                      sigm_x.append((sigm_arg, tree))
                      keep_it = True
              else:
                  if not replace_leaf(
                      neg_arg, exp_x, sigm_x, sigmoid, neg
                  ):
                      sigm_minus_x.append((neg_arg, tree))
                      keep_it = True
          else:
              # It is not an exponential nor a sigmoid.
              keep_it = True
          if not keep_it:
              # Delete this leaf, i.e. replace it by [False, None] (corresponding
              # to a multiplication by 1).
              assert parent is not None
              parent[1][child_idx] = [False, None]
          return not keep_it
  
imports: from __future__ import absolute_import, print_function, division
  import warnings
  import numpy
  import theano
  from theano import config, gof, printing, scalar
  from theano.compat import imap
  from theano.printing import pprint
  from theano.tensor import basic
  from theano.tensor import elemwise, opt, NotScalarConstantError
  from theano.tensor.type import values_eq_approx_remove_inf
  from theano.gof.opt import copy_stack_trace
label_desc: Use image node_id 16 for calling a global function with example usage: perform_sigm_times_exp(tree, exp_x, exp_minus_x, sigm_x, sigm_minus_x, parent, child_idx, full_tree) and returns: rval, unknown