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 an PyTensor function.
  The inputs list should contain all the inputs on which the outputs depend.
  `Variable`\s 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 PyTensor.
  
  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 `Variable`\s are used) and for tracking the `Variable`\s with
  a :attr:`FunctionGraph.clients` ``dict`` that specifies which `Apply` nodes
  use the `Variable`.  The :attr:`FunctionGraph.clients` field, combined with
  the :attr:`Variable.owner` and each :attr:`Apply.inputs`, allows the graph
  to be traversed in both directions.
  
  It can also be extended with new features using
  :meth:`FunctionGraph.attach_feature`.  See `Feature` for event types and
  documentation.  Extra features allow the `FunctionGraph` to verify new
  properties of a graph as it is optimized.
  
  The constructor creates a `FunctionGraph` which operates on the subgraph
  bound by the inputs and outputs sets.
  
  This class keeps lists for the inputs and outputs and modifies them
  in-place.
docstr: Remove the output at index `idx` and update the indices in the clients entries.
  
  `FunctionGraph.clients` contains entries like ``("output", i)`` under
  each output variable in `FunctionGraph.outputs`.  The ``i`` values
  correspond to each output's location within the `FunctionGraph.outputs`
  list, so, when an output is removed from the graph, all these entries
  need to be updated.  This method performs those updates.
  
  TODO: We could track these entries in a new instance attribute and make
  them lists, then each could be updated in-place very easily.  This
  seems fine, because the `FunctionGraph.clients` ``dict`` and list in
  which they're contained are already being updated in-place.
docstr_tok: ["Remove","the","output","at","index","`","idx","`","and","update","the","indices","in","the","clients","entries",".","`","FunctionGraph.clients","`","contains","entries","like","``","(","``","output","''",",","i",")","``","under","each","output","variable","in","`","FunctionGraph.outputs","`",".","The","``","i","``","values","correspond","to","each","output","'s","location","within","the","`","FunctionGraph.outputs","`","list",",","so",",","when","an","output","is","removed","from","the","graph",",","all","these","entries","need","to","be","updated",".","This","method","performs","those","updates",".","TODO",":","We","could","track","these","entries","in","a","new","instance","attribute","and","make","them","lists",",","then","each","could","be","updated","in-place","very","easily",".","This","seems","fine",",","because","the","`","FunctionGraph.clients","`","``","dict","``","and","list","in","which","they","'re","contained","are","already","being","updated","in-place","."]
code: def _remove_output(self, idx: int):
      """Remove the output at index `idx` and update the indices in the clients entries.
  
      `FunctionGraph.clients` contains entries like ``("output", i)`` under
      each output variable in `FunctionGraph.outputs`.  The ``i`` values
      correspond to each output's location within the `FunctionGraph.outputs`
      list, so, when an output is removed from the graph, all these entries
      need to be updated.  This method performs those updates.
  
      TODO: We could track these entries in a new instance attribute and make
      them lists, then each could be updated in-place very easily.  This
      seems fine, because the `FunctionGraph.clients` ``dict`` and list in
      which they're contained are already being updated in-place.
      """
      old_idx_mappings = tuple(
          (out, i) for i, out in enumerate(self.outputs)
      )
      self.outputs.pop(idx)
  
      new_idx = 0
      for out, old_idx in old_idx_mappings:
          if old_idx == idx:
              continue
          out_clients = self.clients[out]
          arrow: ClientType = ("output", old_idx)
          arrow_idx = out_clients.index(arrow)
          out_clients[arrow_idx] = ("output", new_idx)
          new_idx += 1
  
imports: import time
  from collections import OrderedDict
  from collections.abc import Iterable, Sequence
  from typing import TYPE_CHECKING, Any, Literal, Optional, Union, cast
  import pytensor
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, AtomicVariable, Variable, applys_between, clone_get_equiv, graph_inputs, io_toposort, vars_between
  from pytensor.graph.basic import as_string
  from pytensor.graph.features import AlreadyThere, Feature, ReplaceValidate
  from pytensor.graph.utils import MetaObject, MissingInputError, TestValueError
  from pytensor.misc.ordered_set import OrderedSet
label_desc: Use image node_id 13 for calling the FunctionGraph obj's underlying member method code with example usage: obj._remove_output(idx) without return types