/* * Copyright (c) 2003, the JUNG Project and the Regents of the University * of California * All rights reserved. * * This software is open-source under the BSD license; see either * "license.txt" or * http://jung.sourceforge.net/license.txt for a description. */ /* * Created on Dec 26, 2001 * */ package edu.uci.ics.jung.algorithms.filters; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.util.Pair; /** * A filter used to extract the k-neighborhood around one or more root node(s). * The k-neighborhood is defined as the subgraph induced by the set of vertices * that are k or fewer hops (unweighted shortest-path distance) away from the * root node. * * @author Danyel Fisher */ public class KNeighborhoodFilter<V, E> implements Filter<V, E> { /** * The type of edge to follow for defining the neighborhood. */ public static enum EdgeType { IN_OUT, IN, OUT } private Set<V> rootNodes; private int radiusK; private EdgeType edgeType; /** * Constructs a new instance of the filter. * * @param rootNodes * the set of root nodes * @param radiusK * the neighborhood radius around the root set * @param edgeType * 0 for in/out edges, 1 for in-edges, 2 for out-edges */ public KNeighborhoodFilter(Set<V> rootNodes, int radiusK, EdgeType edgeType) { this.rootNodes = rootNodes; this.radiusK = radiusK; this.edgeType = edgeType; } /** * Constructs a new instance of the filter. * * @param rootNode * the root node * @param radiusK * the neighborhood radius around the root set * @param edgeType * 0 for in/out edges, 1 for in-edges, 2 for out-edges */ public KNeighborhoodFilter(V rootNode, int radiusK, EdgeType edgeType) { this.rootNodes = new HashSet<V>(); this.rootNodes.add(rootNode); this.radiusK = radiusK; this.edgeType = edgeType; } /** * Constructs an unassembled graph containing the k-neighborhood around the * root node(s). */ @Override public Graph<V, E> transform(Graph<V, E> graph) { // generate a Set of Vertices we want // add all to the UG int currentDepth = 0; List<V> currentVertices = new ArrayList<V>(); Set<V> visitedVertices = new HashSet<V>(); Set<E> visitedEdges = new HashSet<E>(); Set<V> acceptedVertices = new HashSet<V>(); // Copy, mark, and add all the root nodes to the new subgraph for (V currentRoot : rootNodes) { visitedVertices.add(currentRoot); acceptedVertices.add(currentRoot); currentVertices.add(currentRoot); } ArrayList<V> newVertices = null; // Use BFS to locate the neighborhood around the root nodes within // distance k while (currentDepth < radiusK) { newVertices = new ArrayList<V>(); for (V currentVertex : currentVertices) { Collection<E> edges = null; switch (edgeType) { default: case IN_OUT: edges = graph.getIncidentEdges(currentVertex); break; case IN: edges = graph.getInEdges(currentVertex); break; case OUT: edges = graph.getOutEdges(currentVertex); break; } for (E currentEdge : edges) { V currentNeighbor = graph.getOpposite(currentVertex, currentEdge); if (!visitedEdges.contains(currentEdge)) { visitedEdges.add(currentEdge); if (!visitedVertices.contains(currentNeighbor)) { visitedVertices.add(currentNeighbor); acceptedVertices.add(currentNeighbor); newVertices.add(currentNeighbor); } } } } currentVertices = newVertices; currentDepth++; } Graph<V, E> ug = null; try { ug = graph.newInstance(); for (E edge : graph.getEdges()) { Pair<V> endpoints = graph.getEndpoints(edge); if (acceptedVertices.containsAll(endpoints)) { ug.addEdge(edge, endpoints.getFirst(), endpoints.getSecond()); } } } catch (Exception e) { throw new RuntimeException( "Unable to create copy of existing graph: ", e); } return ug; } }