/* * 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.algorithms.filters.Filter; 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 implements Filter { /** * The type of edge to follow for defining the neighborhood. */ public static enum EdgeType { IN_OUT, IN, OUT } private Set 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 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(); this.rootNodes.add(rootNode); this.radiusK = radiusK; this.edgeType = edgeType; } /** * Constructs an unassembled graph containing the k-neighborhood around the root node(s). */ @SuppressWarnings("unchecked") public Graph transform(Graph graph) { // generate a Set of Vertices we want // add all to the UG int currentDepth = 0; List currentVertices = new ArrayList(); Set visitedVertices = new HashSet(); Set visitedEdges = new HashSet(); Set acceptedVertices = new HashSet(); //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 newVertices = null; //Use BFS to locate the neighborhood around the root nodes within distance k while (currentDepth < radiusK) { newVertices = new ArrayList(); for (V currentVertex : currentVertices) { Collection edges = null; switch (edgeType) { 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 ug = null; try { ug = graph.getClass().newInstance(); for(E edge : graph.getEdges()) { Pair endpoints = graph.getEndpoints(edge); if(acceptedVertices.containsAll(endpoints)) { ug.addEdge(edge, endpoints.getFirst(), endpoints.getSecond()); } } } catch (InstantiationException e) { throw new RuntimeException("Unable to create copy of existing graph: ", e); } catch (IllegalAccessException e) { throw new RuntimeException("Unable to create copy of existing graph: ", e); } return ug; } }