code: def adjoint_contract(
      adj_sum_op,
      adj_prod_op,
      out_adj,
      sum_op,
      prod_op,
      reduced_vars,
      lhs,
      rhs,
  ):
      if prod_op is adj_prod_op and sum_op in (ops.null, adj_sum_op):
          # the only change is here:
          out_adj = Approximate(
              adj_sum_op,
              out_adj,
              adj_prod_op(out_adj, adj_prod_op(lhs, rhs)),
              reduced_vars,
          )
  
          lhs_adj = adj_prod_op(out_adj, rhs)
          rhs_adj = adj_prod_op(lhs, out_adj)
          return ((lhs, lhs_adj), (rhs, rhs_adj))
  
      elif prod_op is adj_sum_op:
          if reduced_vars:
              raise NotImplementedError(
                  "TODO implement sum Contraction"
              )
          return ((lhs, out_adj), (rhs, out_adj))
  
      raise ValueError("should not be here!")
  
imports: from collections import defaultdict
  from collections.abc import Hashable
  from funsor.cnf import Contraction
  from funsor.interpretations import Interpretation, reflect
  from funsor.interpreter import stack_reinterpret
  from funsor.ops import AssociativeOp
  from funsor.registry import KeyedRegistry
  from funsor.terms import Approximate, Binary, Cat, Funsor, Reduce, Scatter, Slice, Subs, substitute, to_funsor
  from .None import instrument, interpreter, ops
label_desc: Use image node_id 9 for calling a global function with example usage: adjoint_contract(adj_sum_op, adj_prod_op, out_adj, sum_op, prod_op, reduced_vars, lhs, rhs) and returns: lhs,  lhs_adj,  rhs,  rhs_adj, lhs,  out_adj,  rhs,  out_adj