001/* Computation of transitive closure of a directed graph using the 002 Floyd-Warshall algorithm. 003 004 Copyright (c) 2003-2014 The University of Maryland. All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF MARYLAND BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF MARYLAND HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF MARYLAND SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 MARYLAND HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 025 */ 026package ptolemy.graph.analysis.strategy; 027 028import java.util.Arrays; 029import java.util.Iterator; 030 031import ptolemy.graph.DirectedGraph; 032import ptolemy.graph.Edge; 033import ptolemy.graph.Graph; 034import ptolemy.graph.Node; 035import ptolemy.graph.analysis.analyzer.TransitiveClosureAnalyzer; 036 037/////////////////////////////////////////////////////////////////// 038//// FloydWarshallTransitiveClosureStrategy 039 040/** 041 Computation of transitive closure of a directed graph using the 042 Floyd-Warshall algorithm described in: 043 Thomas H. Cormen, Charles E. Leiserson and Ronald L. Rivest: 044 Introduction to Algorithms. Cambridge: MIT Press, 1990. 045 <p> 046 The complexity of this algorithm is O(N^3), where N is the number of nodes. 047 <p> 048 @see ptolemy.graph.Graph#nodeLabel 049 @see ptolemy.graph.analysis.TransitiveClosureAnalysis 050 @since Ptolemy II 4.0 051 @Pt.ProposedRating Red (shahrooz) 052 @Pt.AcceptedRating Red (ssb) 053 @author Shahrooz Shahparnia based on an initial implementation by Ming Yung Ko. 054 @version $Id$ 055 */ 056public class FloydWarshallTransitiveClosureStrategy 057 extends FloydWarshallStrategy implements TransitiveClosureAnalyzer { 058 /** Construct a transitive closure analysis for a given directed graph. 059 * @param graph The given directed graph. 060 */ 061 public FloydWarshallTransitiveClosureStrategy(Graph graph) { 062 super(graph); 063 } 064 065 /////////////////////////////////////////////////////////////////// 066 //// public methods //// 067 068 /** Check if there exist a path between a starting node and an ending node 069 * on the analyzer's graph. 070 * 071 * @param startNode The starting node. 072 * @param endNode The ending node. 073 * @return True if such a path exists. 074 */ 075 @Override 076 public boolean pathExistence(Node startNode, Node endNode) { 077 return _transitiveClosure[graph().nodeLabel(startNode)][graph() 078 .nodeLabel(endNode)]; 079 } 080 081 /** Return a description of the analyzer. 082 * 083 * @return Return a description of the analyzer.. 084 */ 085 @Override 086 public String toString() { 087 return "Transitive closure analyzer" 088 + " based on the Floyd-Warshall algorithm."; 089 } 090 091 /** Compute the transitive closure of the graph under analysis in the 092 * form of two dimensional array. The first dimension represents 093 * source node label while the second one represents sink node label. 094 * Assume i and j are labels of two nodes. 095 * transitiveClosureMatrix()[i][j] is true if there is a path on the graph 096 * from "i" to "j". 097 * 098 * @return The transitive closure in the form of 2D array. 099 */ 100 @Override 101 public boolean[][] transitiveClosureMatrix() { 102 return (boolean[][]) _result(); 103 } 104 105 /** Check for validity of this strategy. 106 * A graph needs to be an instance of a {@link DirectedGraph} in order 107 * to use this algorithm. 108 * 109 * @return True if the graph is a directed graph. 110 */ 111 @Override 112 public boolean valid() { 113 return graph() instanceof DirectedGraph; 114 } 115 116 /////////////////////////////////////////////////////////////////// 117 //// protected methods //// 118 119 /** The computation associated with the Floyd-Warshall algorithm. 120 * 121 * @return Return the transitive closure matrix as an {@link Object} 122 * in order to be stored in the result-cache. 123 */ 124 @Override 125 protected Object _compute() { 126 int size = graph().nodeCount(); 127 128 // Initialize transitiveClosure to the adjacency matrix 129 _transitiveClosure = new boolean[size][size]; 130 131 for (int i = 0; i < size; i++) { 132 133 // For graphs of 300 nodes, Arrays.fill() is about 3% 134 // faster than iterating through the row. 135 Arrays.fill(_transitiveClosure[i], false); 136 137 Node node = graph().node(i); 138 Iterator outputEdges = ((DirectedGraph) graph()).outputEdges(node) 139 .iterator(); 140 141 while (outputEdges.hasNext()) { 142 int sinkLabel = ((DirectedGraph) graph()) 143 .nodeLabel(((Edge) outputEdges.next()).sink()); 144 _transitiveClosure[i][sinkLabel] = true; 145 } 146 } 147 148 super._compute(); 149 return _transitiveClosure; 150 } 151 152 /** Overrides the computation associated with the implementation of the 153 * Floyd-Warshall algorithm, for the purpose of computing the transitive 154 * closure. 155 */ 156 @Override 157 protected void _floydWarshallComputation(int k, int i, int j) { 158 _transitiveClosure[i][j] |= _transitiveClosure[i][k] 159 & _transitiveClosure[k][j]; 160 } 161 162 /////////////////////////////////////////////////////////////////// 163 //// private variables //// 164 // A reference to the result of the computation to be shared between the 165 // two protected methods. 166 private boolean[][] _transitiveClosure; 167}