code: def absorb(self, sepset, target):
      # Assign a new potential tt to
      # Y (the target)
      logging.debug(
          "Absorb potentails from sepset node %s into clique %s",
          sepset.name,
          target.name,
      )
      tt = {}
  
      for k, v in list(target.potential_tt.items()):
          # For each entry we multiply by
          # sepsets new value and divide
          # by sepsets old value...
          # Note that nowhere in H&D is
          # division on potentials defined.
          # However in Barber page 12
          # an equation implies that
          # the the division is equivalent
          # to the original assignment.
          # For now we will assume entry-wise
          # division which seems logical.
          entry = transform(
              k, target.variable_names, sepset.variable_names
          )
          if target.potential_tt[k] == 0:
              tt[k] = 0
          else:
              tt[k] = target.potential_tt[k] * (
                  sepset.potential_tt[entry]
                  / sepset.potential_tt_old[entry]
              )
      # assign the new potentials to the node
      target.potential_tt = tt
  
imports: import copy
  import heapq
  import logging
  from collections import defaultdict
  from io import StringIO
  from itertools import combinations, product
  from random import choice, random
  from .exceptions import VariableNotInGraphError, VariableValueNotInDomainError
  from .graph import Node, UndirectedGraph, UndirectedNode, connect
  from .utils import get_args, get_original_factors
label_desc: Use image node_id 6 for calling the JoinTreeCliqueNode obj's underlying member method code with example usage: obj.absorb(sepset, target) without return types