Create a random graph.
    
    @type  num_nodes: number
    @param num_nodes: Number of nodes.
    
    @type  num_edges: number
    @param num_edges: Number of edges.
    
    @type  directed: bool
    @param directed: Whether the generated graph should be directed or not.  

    @type  weight_range: tuple
    @param weight_range: tuple of two integers as lower and upper limits on randomly generated
    weights (uniform distribution).

def generate(num_nodes, num_edges, directed=False, weight_range=(1, 1)):
    """
    Create a random graph.
    
    @type  num_nodes: number
    @param num_nodes: Number of nodes.
    
    @type  num_edges: number
    @param num_edges: Number of edges.
    
    @type  directed: bool
    @param directed: Whether the generated graph should be directed or not.  

    @type  weight_range: tuple
    @param weight_range: tuple of two integers as lower and upper limits on randomly generated
    weights (uniform distribution).
    """
    # Graph creation
    if directed:
        random_graph = digraph()
    else:
        random_graph = graph()

    # Nodes
    nodes = range(num_nodes)
    random_graph.add_nodes(nodes)
    
    # Build a list of all possible edges
    edges = []
    edges_append = edges.append
    for x in nodes:
        for y in nodes:
            if ((directed and x != y) or (x > y)):
                edges_append((x, y))
    
    # Randomize the list
    shuffle(edges)
    
    # Add edges to the graph
    min_wt = min(weight_range)
    max_wt = max(weight_range)
    for i in range(num_edges):
        each = edges[i]
        random_graph.add_edge((each[0], each[1]), wt = randint(min_wt, max_wt))

    return random_graph