class_docstr: Check if variables can be expressed without using variables in invalid.
  
  Parameters
  ----------
  valid_equivalent
      Provides a dictionary mapping some invalid variables to valid ones that
      can be used instead.
class_docstr_tok: ["Check","if","variables","can","be","expressed","without","using","variables","in","invalid",".","Parameters","--","--","--","--","--","valid_equivalent","Provides","a","dictionary","mapping","some","invalid","variables","to","valid","ones","that","can","be","used","instead","."]
docstr: Go backwards in the graph, from out, and check if out is valid.
  
  If out is a valid node, (out, True) is returned.
  If out is not valid, but has an equivalent e, (e, False) is returned.
  If out is not valid and has no equivalent, None is returned.
docstr_tok: ["Go","backwards","in","the","graph",",","from","out",",","and","check","if","out","is","valid",".","If","out","is","a","valid","node",",","(","out",",","True",")","is","returned",".","If","out","is","not","valid",",","but","has","an","equivalent","e",",","(","e",",","False",")","is","returned",".","If","out","is","not","valid","and","has","no","equivalent",",","None","is","returned","."]
code: def check(self, out):
      """
      Go backwards in the graph, from out, and check if out is valid.
  
      If out is a valid node, (out, True) is returned.
      If out is not valid, but has an equivalent e, (e, False) is returned.
      If out is not valid and has no equivalent, None is returned.
  
      """
  
      def get_value(out):
          if out in self.valid:
              return out, True
          elif out in self.valid_equivalent:
              return self.valid_equivalent[out], False
          elif out in self.invalid:
              return None
          else:
              raise RuntimeError("This should not happen")
  
      q = [out]
      while q:
          out = q.pop()
          if out in self.valid:
              continue
          elif out in self.invalid:
              continue
  
          if out.owner is None:
              if isinstance(out, TensorConstant):
                  self.valid.add(out)
                  continue
              else:
                  # This is an input node and it has not been
                  # explicitly marked as invalid so we can use it
                  self.valid.add(out)
                  continue
  
          # Process the input if needed
          continue_while = False
          for inp in out.owner.inputs:
              if inp not in self.valid and inp not in self.invalid:
                  q.append(out)
                  q.extend(out.owner.inputs)
                  continue_while = True
                  break
          if continue_while:
              continue
          inputs = [get_value(i) for i in out.owner.inputs]
  
          # If some inputs are invalid without equivalent, so is out
          if None in inputs:
              self.invalid.add(out)
              continue
  
          # If some inputs are invalid with equivalent,
          # an equivalent out should be built and returned
          all_inputs = [inp for (inp, is_valid) in inputs]
          equiv_inputs = [
              inp for (inp, is_valid) in inputs if not is_valid
          ]
          if equiv_inputs:
              cloned_node = out.owner.clone_with_new_inputs(all_inputs)
              cloned_out = cloned_node.outputs[out.index]
              self.invalid.add(out)
              self.valid.add(cloned_out)
              self.valid_equivalent[out] = cloned_out
              continue
  
          # All inputs are valid, so is out
          self.valid.add(out)
  
      return get_value(out)
  
imports: import copy
  import dataclasses
  import logging
  from collections import OrderedDict, namedtuple
  from collections.abc import Sequence
  from itertools import chain
  from typing import TYPE_CHECKING, Callable, Optional, Union
  from typing import cast
  import numpy
  from pytensor import scalar
  from pytensor import tensor
  from pytensor.compile.profiling import ProfileStats
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Constant, Variable, equal_computations, graph_inputs
  from pytensor.graph.op import get_test_value
  from pytensor.graph.replace import clone_replace
  from pytensor.graph.type import HasDataType
  from pytensor.graph.utils import TestValueError
  from pytensor.tensor.basic import AllocEmpty, cast
  from pytensor.tensor.subtensor import set_subtensor
  from pytensor.tensor.variable import TensorConstant
label_desc: Use image node_id 2 for calling the Validator obj's underlying member method code with example usage: obj.check(out) and returns: get_value, out,  True, self,  False, None