docs: def generate_random_graph(node_num, edge_num, self_loops=False, multi_edges=False):
      '''
      Generates and returns a :py:class:`~altgraph.Graph.Graph` instance with *node_num* nodes
      randomly connected by *edge_num* edges.
      '''
      g = Graph.Graph()
  
      if not multi_edges:
          if self_loops:
              max_edges = node_num * node_num
          else:
              max_edges = node_num * (node_num-1)
  
          if edge_num > max_edges:
              raise GraphError("inconsistent arguments to 'generate_random_graph'")
  
      nodes = range(node_num)
  
      for node in nodes:
          g.add_node(node)
  
      while 1:
          head = random.choice(nodes)
          tail = random.choice(nodes)
  
          # loop defense
          if head == tail and not self_loops:
              continue
  
          # multiple edge defense
          if g.edge_by_node(head,tail) is not None and not multi_edges:
              continue
  
          # add the edge
          g.add_edge(head, tail)
          if g.number_of_edges() >= edge_num:
              break
  
      return g