docs: def portTryReduce(root: LNode, port: LPort):
      """
      Check if majority of children is connected to same port
      if it is the case reduce children and connect this port instead children
  
      :note: use reduceUselessAssignments, extractSplits, flattenTrees before this function
          to maximize it's effect
      """
      if not port.children:
          return
  
      for p in port.children:
          portTryReduce(root, p)
  
      target_nodes = {}
      ch_cnt = countDirectlyConnected(port, target_nodes)
      if not target_nodes:
          # disconnected port
          return
  
      new_target, children_edge_to_destroy = max(target_nodes.items(),
                                                 key=lambda x: len(x[1]))
      cnt = len(children_edge_to_destroy)
      if cnt < ch_cnt / 2 or cnt == 1 and ch_cnt == 2:
          # too small to few shared connection to reduce
          return
  
      children_to_destroy = set()
      on_target_children_to_destroy = set()
      for child, edge in children_edge_to_destroy:
          if child.direction == PortType.OUTPUT:
              target_ch = edge.dsts
          elif child.direction == PortType.INPUT:
              target_ch = edge.srcs
          else:
              raise ValueError(child.direction)
          if len(target_ch) != 1:
              raise NotImplementedError("multiple connected nodes", target_ch)
          target_ch = target_ch[0]
  
          try:
              assert target_ch.parent is new_target, (
                  target_ch,
                  target_ch.parent,
                  new_target)
          except AssertionError:
              print('Wrong target:\n', edge.src, "\n", edge.dst,
                    "\n", target_ch.parent, "\n", new_target)
              raise
  
          if child.direction == PortType.OUTPUT:
              edge.removeTarget(target_ch)
          elif child.direction == PortType.INPUT:
              edge.removeTarget(child)
  
          if not edge.srcs or not edge.dsts:
              edge.remove()
  
          if not target_ch.incomingEdges and not target_ch.outgoingEdges:
              # disconnect selected children from this port and target
              on_target_children_to_destroy.add(target_ch)
  
          if not child.incomingEdges and not child.outgoingEdges:
              children_to_destroy.add(child)
  
      # destroy children of new target and this port if possible
      port.children = [
          ch for ch in port.children if ch not in children_to_destroy]
      new_target.children = [
          ch for ch in new_target.children if ch not in on_target_children_to_destroy]
  
      # connect this port to new target as it was connected by children before
      # [TODO] names for new edges
      if port.direction == PortType.OUTPUT:
          root.addEdge(port, new_target)
      elif port.direction == PortType.INPUT:
          root.addEdge(new_target, port)
      else:
          raise NotImplementedError(port.direction)