public G generate(int N, int k, double p) {
    G graph = ringLatticeGenerator.generate(N, k);

    Set<Edge> edges = new HashSet<Edge>();
    for (Edge edge : graph.getEdges()) {
      if (random.nextDouble() < p) {
        edges.add(edge);
      }
    }

    List<V> vertices = new ArrayList<V>(graph.getVertices().size());
    vertices.addAll((Collection<? extends V>) graph.getVertices());

    int doubleEdges = 0;

    for (Edge edge : edges) {
      V source;

      if (random.nextBoolean()) {
        source = (V) edge.getVertices().getFirst();
      } else {
        source = (V) edge.getVertices().getSecond();
      }

      builder.removeEdge(graph, (E) edge);
      V target = null;
      while (target == null) {
        target = vertices.get(random.nextInt(vertices.size()));
        if (source == target) target = null;
      }

      if (builder.addEdge(graph, source, target) == null) doubleEdges++;
    }

    logger.debug(String.format("Rejected %1$s double edges.", doubleEdges));

    return graph;
  }
 /**
  * Returns a list of edge attributes stored in String-String-tuples. The returned list contains
  * two entries:
  *
  * <ul>
  *   <li>{@link GraphML#SOURCE_ATTR} - <tt>vertexIdx</tt>
  *   <li>{@link GraphML#TARGET_ATTR} - <tt>vertexIdx</tt>
  * </ul>
  *
  * @param e the edge the attributes are to be returned.
  * @return a list of edge attributes.
  */
 protected List<Tuple<String, String>> getEdgeAttributes(Edge e) {
   List<Tuple<String, String>> attrs = new LinkedList<Tuple<String, String>>();
   Vertex v1 = e.getVertices().getFirst();
   Vertex v2 = e.getVertices().getSecond();
   int idx1 = vertexTmpIds.get(v1);
   int idx2 = vertexTmpIds.get(v2);
   if (idx1 > 0 && idx2 > 0) {
     attrs.add(createTuple(GraphML.SOURCE_ATTR, idx1));
     attrs.add(createTuple(GraphML.TARGET_ATTR, idx2));
   } else {
     throw new IllegalArgumentException("Orphaned edges are not allowed!");
   }
   return attrs;
 }