code: def local_useless_elemwise(fgraph, node):
      """
          eq(x, x) -> 1
          neq(x, x) -> 0
          mul(x) -> x
          add(x) -> x
          identity(x) -> x
          and(x, 1) -> x  (if x.dtype == 'bool')
          and(x, 0) -> zeros_like(x)
          or(x, 0) -> x
          or(x, 1) -> ones_like(x)  (if x.dtype == 'bool')
          xor(x, x) -> zeros_like(x)
  
      TODO: This implementation is painfully redundant.
  
      """
      if isinstance(node.op, Elemwise):
          # We call zeros_like and one_like with opt=True to generate a
          # cleaner graph.
          dtype = node.outputs[0].dtype
  
          if node.op.scalar_op == ps.eq and len(node.inputs) == 2:
              if node.inputs[0] == node.inputs[1]:
                  # it is the same var in the graph. That will always be true
                  ret = ones_like(node.inputs[0], dtype=dtype, opt=True)
  
                  # Copy stack trace from input to constant output
                  copy_stack_trace(node.outputs[0], ret)
                  return [ret]
          elif node.op.scalar_op == ps.neq and len(node.inputs) == 2:
              if node.inputs[0] == node.inputs[1]:
                  # it is the same var in the graph. That will always be false
                  ret = zeros_like(
                      node.inputs[0], dtype=dtype, opt=True
                  )
  
                  # Copy stack trace from input to constant output
                  copy_stack_trace(node.outputs[0], ret)
                  return [ret]
  
          elif node.op.scalar_op == ps.mul and len(node.inputs) == 1:
              # No need to copy over any stack trace
              return [node.inputs[0]]
  
          elif node.op.scalar_op == ps.add and len(node.inputs) == 1:
              # No need to copy over any stack trace
              return [node.inputs[0]]
          elif (
              node.op.scalar_op == ps.identity and len(node.inputs) == 1
          ):
              return [node.inputs[0]]
  
          elif (
              isinstance(node.op.scalar_op, ps.AND)
              and len(node.inputs) == 2
          ):
              if isinstance(node.inputs[0], TensorConstant):
                  const_val = extract_constant(
                      node.inputs[0], only_process_constants=True
                  )
                  if not isinstance(const_val, Variable):
                      if const_val == 0:
                          return [
                              zeros_like(
                                  node.inputs[1], dtype=dtype, opt=True
                              )
                          ]
                      elif node.outputs[0].dtype == "bool":
                          # If the output is not Boolean, it is the bitwise AND,
                          # and this rewrite would be wrong
                          return [
                              node.inputs[1].astype(
                                  node.outputs[0].dtype
                              )
                          ]
  
              if isinstance(node.inputs[1], TensorConstant):
                  const_val = extract_constant(
                      node.inputs[1], only_process_constants=True
                  )
                  if not isinstance(const_val, Variable):
                      if const_val == 0:
                          return [
                              zeros_like(
                                  node.inputs[0], dtype=dtype, opt=True
                              )
                          ]
                      elif node.outputs[0].dtype == "bool":
                          # If the output is not Boolean, it is the bitwise AND,
                          # and this rewrite would be wrong
                          return [
                              node.inputs[0].astype(
                                  node.outputs[0].dtype
                              )
                          ]
  
          elif (
              isinstance(node.op.scalar_op, ps.OR)
              and len(node.inputs) == 2
          ):
              if isinstance(node.inputs[0], TensorConstant):
                  const_val = extract_constant(
                      node.inputs[0], only_process_constants=True
                  )
                  if not isinstance(const_val, Variable):
                      if const_val == 0:
                          return [
                              node.inputs[1].astype(
                                  node.outputs[0].dtype
                              )
                          ]
                      elif node.outputs[0].dtype == "bool":
                          # If the output is not Boolean, it is the bitwise OR,
                          # and this rewrite would be wrong
                          return [
                              ones_like(
                                  node.inputs[1], dtype=dtype, opt=True
                              )
                          ]
  
              if isinstance(node.inputs[1], TensorConstant):
                  const_val = extract_constant(
                      node.inputs[1], only_process_constants=True
                  )
                  if not isinstance(const_val, Variable):
                      if const_val == 0:
                          return [
                              node.inputs[0].astype(
                                  node.outputs[0].dtype
                              )
                          ]
                      elif node.outputs[0].dtype == "bool":
                          # If the output is not Boolean, it is the bitwise OR,
                          # and this rewrite would be wrong
                          return [
                              ones_like(
                                  node.inputs[0], dtype=dtype, opt=True
                              )
                          ]
  
          elif (
              isinstance(node.op.scalar_op, ps.XOR)
              and len(node.inputs) == 2
          ):
              if node.inputs[0] is node.inputs[1]:
                  return [
                      zeros_like(node.inputs[0], dtype=dtype, opt=True)
                  ]
  
imports: import logging
  from typing import Union
  import numpy
  import pytensor.scalar.basic
  from pytensor import compile
  from pytensor.compile.ops import ViewOp
  from pytensor.graph import FunctionGraph
  from pytensor.graph.basic import Constant, Variable
  from pytensor.graph.rewriting.basic import NodeRewriter, RemovalNodeRewriter, Rewriter, copy_stack_trace, in2out, node_rewriter
  from pytensor.graph.rewriting.db import RewriteDatabase
  from pytensor.raise_op import Assert, CheckAndRaise, assert_op
  from pytensor.tensor.basic import Alloc, AllocEmpty, Join, MakeVector, ScalarFromTensor, Split, TensorFromScalar, alloc, as_tensor_variable, cast, extract_constant, fill, get_underlying_scalar_constant_value, join, ones_like, register_infer_shape, switch, tensor_copy, zeros, zeros_like
  from pytensor.tensor.elemwise import DimShuffle, Elemwise
  from pytensor.tensor.exceptions import NotScalarConstantError
  from pytensor.tensor.extra_ops import broadcast_arrays
  from pytensor.tensor.math import Sum, add, eq
  from pytensor.tensor.shape import Shape_i, shape_padleft
  from pytensor.tensor.sort import TopKOp
  from pytensor.tensor.type import DenseTensorType, TensorType
  from pytensor.tensor.variable import TensorConstant, TensorVariable
  from pytensor.utils import NoDuplicateOptWarningFilter
label_desc: Use image node_id 18 for calling a global function with example usage: local_useless_elemwise(fgraph, node) and returns: list, list, list, list, list, list, list, list, list, list, list, list, list, list