code: def collapse_algo(
      g: Plottable,
      child: Union[str, int],
      parent: Union[str, int],
      attribute: Union[str, int],
      column: Union[str, int],
      seen: dict,
  ):
      """Basically candy crush over graph properties in a topology aware manner
  
          Checks to see if child node has desired property from parent, we will need to check if (start_node=parent: has_attribute , children nodes: has_attribute) by case (T, T), (F, T), (T, F) and (F, F),we start recursive collapse (or not) on the children, reassigning nodes and edges.
  
          if (T, T), append children nodes to start_node, re-assign the name of the node, and update the edge table with new name,
  
          if (F, T) start k-(potentially new) super nodes, with k the number of children of start_node. Start node keeps k outgoing edges.
  
          if (T, F) it is the end of the cluster, and we keep new node as is; keep going
  
          if (F, F); keep going
  
      :param seen:
      :param g: graphistry instance
      :param child: child node to start traversal, for first traversal, set child=parent or vice versa.
      :param parent: parent node to start traversal, in main call, this is set to child.
      :param attribute: attribute to collapse by
      :param column: column in nodes dataframe to collapse over.
  
      :returns: graphistry instance with collapsed nodes.
      """
  
      compute_key = f"{parent} {child}"
  
      if (
          compute_key in seen
      ):  # it has already traversed this path, skip
          return g
      else:
          if has_property(g, parent, attribute, column):  # if (T, *)
              # add start node to super node index
              tkey = f"{parent} {parent}"  # it will reduce this to `parent` but can add to `seen`
              if tkey not in compute_key:  # its love!
                  seen[tkey] = 1
                  collapse_nodes_and_edges(g, parent, parent)
              if has_property(g, child, attribute, column):  # if (T, T)
                  if VERBOSE:
                      logger.info("-" * 80)
                      logger.info(
                          f" ** [ parent: {parent}, child: {child} ] both have property"
                      )
                  collapse_nodes_and_edges(
                      g, parent, child
                  )  # will make a new parent off of parent, child names
                  # add to seen
                  seen[compute_key] = 1
                  for e in get_edges_of_node(
                      g, parent, outgoing_edges=True, hops=1
                  ).values:  # False just includes the child node and goes into infinite loop when parent = child
                      collapse_algo(
                          g, e, child, attribute, column, seen
                      )  # now child is the parent, and the edges are the start node
          # else do nothing collapse-y to parent, move on to child
          else:  # if (F, *)
              #  do nothing to child, parent is child, and child is edge and recurse
              for e in get_edges_of_node(
                  g, child, outgoing_edges=True, hops=1
              ).values:
                  if VERBOSE:
                      logger.info(
                          f" -- Parent {parent} does not have property, looking at node <[ {e} from {child} ]>"
                      )
  
                  if (e == child) and (parent == child):
                      # get it unstuck
                      return g
  
                  collapse_algo(
                      g, e, child, attribute, column, seen
                  )  # now child is the parent, and the edges are the start node
      return g
  
imports: from typing import Union, Optional, List
  import copy, logging, pandas, numpy
  from graphistry.PlotterBase import Plottable
label_desc: Use image node_id 17 for calling a global function with example usage: collapse_algo(g, child, parent, attribute, column, seen) and returns: g, g, g