All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrapht.alg.TransitiveReduction Maven / Gradle / Ivy

/*
 * (C) Copyright 2015-2021, by Christophe Thiebaud and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * See the CONTRIBUTORS.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the
 * GNU Lesser General Public License v2.1 or later
 * which is available at
 * http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
 */
package org.jgrapht.alg;

import org.jgrapht.*;

import java.util.*;

/**
 * An implementation of Harry Hsu's
 * transitive reduction algorithm.
 *
 * 

* cf. Harry Hsu. "An * algorithm for finding a minimal equivalent graph of a digraph.", Journal of the ACM, 22(1):11-16, * January 1975. *

* *

* This is a port from a python example by Michael Clerx, posted as an answer to a question about * * transitive reduction algorithm pseudocode on Stack * Overflow *

* * @author Christophe Thiebaud */ public class TransitiveReduction { /** * Singleton instance. */ public static final TransitiveReduction INSTANCE = new TransitiveReduction(); /** * Private Constructor. */ private TransitiveReduction() { } /** * The matrix passed as input parameter will be transformed into a path matrix. * *

* This method is package visible for unit testing, but it is meant as a private method. *

* * @param matrix the original matrix to transform into a path matrix */ static void transformToPathMatrix(BitSet[] matrix) { // compute path matrix for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix.length; j++) { if (i == j) { continue; } if (matrix[j].get(i)) { for (int k = 0; k < matrix.length; k++) { if (!matrix[j].get(k)) { matrix[j].set(k, matrix[i].get(k)); } } } } } } /** * The path matrix passed as input parameter will be transformed into a transitively reduced * matrix. * *

* This method is package visible for unit testing, but it is meant as a private method. *

* * @param pathMatrix the path matrix to reduce */ static void transitiveReduction(BitSet[] pathMatrix) { // transitively reduce for (int j = 0; j < pathMatrix.length; j++) { for (int i = 0; i < pathMatrix.length; i++) { if (pathMatrix[i].get(j)) { for (int k = 0; k < pathMatrix.length; k++) { if (pathMatrix[j].get(k)) { pathMatrix[i].set(k, false); } } } } } } /** * This method will remove all transitive edges from the graph passed as input parameter. * *

* You may want to clone the graph before, as transitive edges will be pitilessly removed. *

* * e.g. * *
     * {
     *     @code DirectedGraph<V, T> soonToBePrunedDirectedGraph;
     *
     *     TransitiveReduction.INSTANCE.reduce(soonToBePrunedDirectedGraph);
     *
     *     // pruned !
     * }
     * 
* * @param directedGraph the directed graph that will be reduced transitively * @param the graph vertex type * @param the graph edge type */ public void reduce(final Graph directedGraph) { GraphTests.requireDirected(directedGraph, "Graph must be directed"); final List vertices = new ArrayList<>(directedGraph.vertexSet()); final int n = vertices.size(); BitSet[] originalMatrix = new BitSet[n]; for (int i = 0; i < originalMatrix.length; i++) { originalMatrix[i] = new BitSet(n); } // initialize matrix with zeros // 'By default, all bits in the set initially have the value false.' // cf. http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html // initialize matrix with edges for (final E edge : directedGraph.edgeSet()) { final V v1 = directedGraph.getEdgeSource(edge); final V v2 = directedGraph.getEdgeTarget(edge); final int i1 = vertices.indexOf(v1); final int i2 = vertices.indexOf(v2); originalMatrix[i1].set(i2); } // create path matrix from original matrix final BitSet[] pathMatrix = originalMatrix; transformToPathMatrix(pathMatrix); // create reduced matrix from path matrix final BitSet[] transitivelyReducedMatrix = pathMatrix; transitiveReduction(transitivelyReducedMatrix); // remove edges from the DirectedGraph which are not in the reduced // matrix for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (!transitivelyReducedMatrix[i].get(j)) { directedGraph .removeEdge(directedGraph.getEdge(vertices.get(i), vertices.get(j))); } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy