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}