@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()); }