@Override
  public IVertexSequence<V> next() {
    if (!hasNext()) throw new NoSuchElementException();
    // Generate a random walk starting at vertex order[current]
    int currVertexIdx = order[position++];
    int[] indices = new int[walkLength + 1];
    indices[0] = currVertexIdx;
    if (walkLength == 0) return new VertexSequence<>(graph, indices);

    Vertex<V> next;
    try {
      next = graph.getRandomConnectedVertex(currVertexIdx, rng);
    } catch (NoEdgesException e) {
      switch (mode) {
        case SELF_LOOP_ON_DISCONNECTED:
          for (int i = 1; i < walkLength; i++) indices[i] = currVertexIdx;
          return new VertexSequence<>(graph, indices);
        case EXCEPTION_ON_DISCONNECTED:
          throw e;
        default:
          throw new RuntimeException("Unknown/not implemented NoEdgeHandling mode: " + mode);
      }
    }
    indices[1] = next.vertexID();
    currVertexIdx = indices[1];

    for (int i = 2;
        i <= walkLength;
        i++) { // <= walk length: i.e., if walk length = 2, it contains 3 vertices etc
      next = graph.getRandomConnectedVertex(currVertexIdx, rng);
      currVertexIdx = next.vertexID();
      indices[i] = currVertexIdx;
    }
    return new VertexSequence<>(graph, indices);
  }
  @Override
  public IVertexSequence<V> next() {
    if (!hasNext()) throw new NoSuchElementException();
    // Generate a weighted random walk starting at vertex order[current]
    int currVertexIdx = order[position++];
    int[] indices = new int[walkLength + 1];
    indices[0] = currVertexIdx;
    if (walkLength == 0) return new VertexSequence<>(graph, indices);

    for (int i = 1; i <= walkLength; i++) {
      List<? extends Edge<? extends Number>> edgeList = graph.getEdgesOut(currVertexIdx);

      // First: check if there are any outgoing edges from this vertex. If not: handle the situation
      if (edgeList == null || edgeList.size() == 0) {
        switch (mode) {
          case SELF_LOOP_ON_DISCONNECTED:
            for (int j = i; j < walkLength; j++) indices[j] = currVertexIdx;
            return new VertexSequence<>(graph, indices);
          case EXCEPTION_ON_DISCONNECTED:
            throw new NoEdgesException(
                "Cannot conduct random walk: vertex "
                    + currVertexIdx
                    + " has no outgoing edges. "
                    + " Set NoEdgeHandling mode to NoEdgeHandlingMode.SELF_LOOP_ON_DISCONNECTED to self loop instead of "
                    + "throwing an exception in this situation.");
          default:
            throw new RuntimeException("Unknown/not implemented NoEdgeHandling mode: " + mode);
        }
      }

      // To do a weighted random walk: we need to know total weight of all outgoing edges
      double totalWeight = 0.0;
      for (Edge<? extends Number> edge : edgeList) {
        totalWeight += edge.getValue().doubleValue();
      }

      double d = rng.nextDouble();
      double threshold = d * totalWeight;
      double sumWeight = 0.0;
      for (Edge<? extends Number> edge : edgeList) {
        sumWeight += edge.getValue().doubleValue();
        if (sumWeight >= threshold) {
          if (edge.isDirected()) {
            currVertexIdx = edge.getTo();
          } else {
            if (edge.getFrom() == currVertexIdx) {
              currVertexIdx = edge.getTo();
            } else {
              currVertexIdx =
                  edge
                      .getFrom(); // Undirected edge: might be next--currVertexIdx instead of
                                  // currVertexIdx--next
            }
          }
          indices[i] = currVertexIdx;
          break;
        }
      }
    }
    return new VertexSequence<>(graph, indices);
  }
 /**
  * @param graph IGraph to conduct walks on
  * @param walkLength length of each walk. Walk of length 0 includes 1 vertex, walk of 1 includes 2
  *     vertices etc
  * @param rngSeed seed for randomization
  * @param mode mode for handling random walks from vertices with either no edges, or no outgoing
  *     edges (for directed graphs)
  */
 public WeightedRandomWalkIterator(
     IGraph<V, ? extends Number> graph, int walkLength, long rngSeed, NoEdgeHandling mode) {
   this(graph, walkLength, rngSeed, mode, 0, graph.numVertices());
 }
 /**
  * @param graph IGraph to conduct walks on
  * @param walkLength length of each walk. Walk of length 0 includes 1 vertex, walk of 1 includes 2
  *     vertices etc
  * @param rngSeed seed for randomization
  * @param mode mode for handling random walks from vertices with either no edges, or no outgoing
  *     edges (for directed graphs)
  */
 public RandomWalkIterator(IGraph<V, ?> graph, int walkLength, long rngSeed, NoEdgeHandling mode) {
   this(graph, walkLength, rngSeed, mode, 0, graph.numVertices());
 }