docs: def remove_node(self, node):
          """Removes a node and its attributes from the hypergraph. Removes
          every hyperedge that contains this node in either the head or the tail.
  
          :param node: reference to the node being added.
          :raises: ValueError -- No such node exists.
  
          Examples:
          ::
  
              >>> H = DirectedHypergraph()
              >>> H.add_node("A", label="positive")
              >>> H.remove_node("A")
  
          """
          if not self.has_node(node):
              raise ValueError("No such node exists.")
  
          # Remove every hyperedge which is in the forward star of the node
          forward_star = self.get_forward_star(node)
          for hyperedge_id in forward_star:
              self.remove_hyperedge(hyperedge_id)
  
          # Remove every hyperedge which is in the backward star of the node
          # but that is not also in the forward start of the node (to handle
          # overlapping hyperedges)
          backward_star = self.get_backward_star(node)
          for hyperedge_id in backward_star - forward_star:
              self.remove_hyperedge(hyperedge_id)
  
          # Remove node's forward and backward star
          del self._forward_star[node]
          del self._backward_star[node]
  
          # Remove node's attributes dictionary
          del self._node_attributes[node]