docs: def reachable_nodes(self, p_id, p_recursive=True, p_reverse=False):
          """
          Returns the set of all neighbors that the given node can reach.
  
          If recursive, it will also return the neighbor's neighbors, etc.
          If reverse, the arrows are reversed and then the reachable neighbors
          are located.
          """
          stack = [p_id]
          visited = set()
          result = set()
  
          while len(stack):
              current = stack.pop()
  
              if current in visited or current not in self._edges:
                  continue
  
              visited.add(current)
  
              if p_reverse:
                  parents = [node for node, neighbors in self._edges.items()
                             if current in neighbors]
  
                  stack = stack + parents
                  result = result.union(parents)
              else:
                  stack = stack + list(self._edges[current])
                  result = result.union(self._edges[current])
  
              if not p_recursive:
                  break
  
          return result