/* * 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. */ package edu.uci.ics.jung.algorithms.transformation; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.collections15.Factory; import org.apache.commons.collections15.Transformer; import org.apache.commons.collections15.functors.MapTransformer; import edu.uci.ics.jung.algorithms.blockmodel.VertexPartition; import edu.uci.ics.jung.graph.Graph; /** * This class transforms a graph with a known vertex partitioning into a graph * whose vertices correspond to the input graph's partitions. Two vertices in * the output graph are connected if and only if there exists at least one edge * between vertices in the corresponding partitions of the input graph. If the * output graph permits parallel edges, there will be an edge connecting two * vertices in the new graph for each such edge connecting constituent vertices * in the input graph. * * <p> * Concept based on Danyel Fisher's <code>GraphCollapser</code> in JUNG 1.x. * */ public class VertexPartitionCollapser<V, E, CV, CE> { protected Factory<Graph<CV, CE>> graph_factory; protected Factory<CV> vertex_factory; protected Factory<CE> edge_factory; protected Map<Set<V>, CV> set_collapsedv; /** * Creates an instance with the specified graph and element factories. * * @param vertex_factory * used to construct the vertices of the new graph * @param edge_factory * used to construct the edges of the new graph * @param graph_factory * used to construct the new graph */ public VertexPartitionCollapser(Factory<Graph<CV, CE>> graph_factory, Factory<CV> vertex_factory, Factory<CE> edge_factory) { this.graph_factory = graph_factory; this.vertex_factory = vertex_factory; this.edge_factory = edge_factory; this.set_collapsedv = new HashMap<Set<V>, CV>(); } /** * Creates a new graph whose vertices correspond to the partitions of the * supplied graph. * * @param partitioning * @return a new graph whose vertices correspond to the partitions of the * supplied graph */ public Graph<CV, CE> collapseVertexPartitions( VertexPartition<V, E> partitioning) { Graph<V, E> original = partitioning.getGraph(); Graph<CV, CE> collapsed = graph_factory.create(); // create vertices in new graph corresponding to equivalence sets in the // original graph for (Set<V> set : partitioning.getVertexPartitions()) { CV cv = vertex_factory.create(); collapsed.addVertex(vertex_factory.create()); set_collapsedv.put(set, cv); } // create edges in new graph corresponding to edges in original graph for (E e : original.getEdges()) { Collection<V> incident = original.getIncidentVertices(e); Collection<CV> collapsed_vertices = new HashSet<CV>(); Map<V, Set<V>> vertex_partitions = partitioning .getVertexToPartitionMap(); // collect the collapsed vertices corresponding to the original // incident vertices for (V v : incident) { collapsed_vertices .add(set_collapsedv.get(vertex_partitions.get(v))); } // if there's only one collapsed vertex, continue (no edges to // create) if (collapsed_vertices.size() > 1) { CE ce = edge_factory.create(); collapsed.addEdge(ce, collapsed_vertices); } } return collapsed; } /** * Returns a transformer from vertex sets in the original graph to collapsed * vertices in the transformed graph. */ public Transformer<Set<V>, CV> getSetToCollapsedVertexTransformer() { return MapTransformer.getInstance(set_collapsedv); } }