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

com.ibm.wala.util.graph.traverse.FloydWarshall Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2002-2010 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.util.graph.traverse;

import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Floyd-Warshall algorithm to compute all-pairs shortest path in graph with no negative cycles.
 *
 * 

TODO: this API should be cleaned up. * * @param node type in the graph */ public class FloydWarshall { public interface GetPath { List getPath(T from, T to); } public interface GetPaths { Set> getPaths(T from, T to); } protected final NumberedGraph G; public FloydWarshall(NumberedGraph g) { G = g; } protected int edgeCost() { return 1; } @SuppressWarnings("unused") protected void pathCallback(int i, int j, int k) {} public int[][] allPairsShortestPaths() { final int[][] result = new int[G.getNumberOfNodes()][G.getNumberOfNodes()]; for (int[] ints : result) { Arrays.fill(ints, Integer.MAX_VALUE); } for (T from : G) { final int fn = G.getNumber(from); IntSet tos = G.getSuccNodeNumbers(from); tos.foreach(x -> result[fn][x] = edgeCost()); } for (T kn : G) { int k = G.getNumber(kn); for (T in : G) { int i = G.getNumber(in); for (T jn : G) { int j = G.getNumber(jn); long newLen = (long) result[i][k] + (long) result[k][j]; if (newLen <= result[i][j]) { pathCallback(i, j, k); } if (newLen < result[i][j]) { result[i][j] = (int) newLen; } } } } return result; } public static int[][] shortestPathLengths(NumberedGraph G) { return new FloydWarshall<>(G).allPairsShortestPaths(); } public static GetPath allPairsShortestPath(final NumberedGraph G) { return new FloydWarshall<>(G) { final int[][] next = new int[G.getNumberOfNodes()][G.getNumberOfNodes()]; @Override protected void pathCallback(int i, int j, int k) { next[i][j] = k; } private GetPath doit() { for (int[] ints : next) { Arrays.fill(ints, -1); } final int[][] paths = allPairsShortestPaths(); return new GetPath<>() { @Override public String toString() { final StringBuilder s = new StringBuilder(); for (int i = 0; i <= G.getMaxNumber(); i++) { for (int j = 0; j <= G.getMaxNumber(); j++) { try { s.append(getPath(G.getNode(i), G.getNode(j))); } catch (UnsupportedOperationException e) { } } } return s.toString(); } @Override public List getPath(T from, T to) { int fn = G.getNumber(from); int tn = G.getNumber(to); if (paths[fn][tn] == Integer.MAX_VALUE) { throw new UnsupportedOperationException("no path from " + from + " to " + to); } else { int intermediate = next[fn][tn]; if (intermediate == -1) { return Collections.emptyList(); } else { T in = G.getNode(intermediate); List result = new ArrayList<>(getPath(from, in)); result.add(in); result.addAll(getPath(in, to)); return result; } } } }; } }.doit(); } public static GetPaths allPairsShortestPaths(final NumberedGraph G) { return new FloydWarshall<>(G) { final MutableIntSet[][] next = new MutableIntSet[G.getNumberOfNodes()][G.getNumberOfNodes()]; @Override protected void pathCallback(int i, int j, int k) { if (next[i][j] == null) { next[i][j] = IntSetUtil.make(); } next[i][j].add(k); } private GetPaths doit() { final int[][] paths = allPairsShortestPaths(); return new GetPaths<>() { @Override public String toString() { List>> x = new ArrayList<>(); for (int i = 0; i <= G.getMaxNumber(); i++) { for (int j = 0; j <= G.getMaxNumber(); j++) { try { x.add(getPaths(G.getNode(i), G.getNode(j))); } catch (UnsupportedOperationException e) { } } } return x.toString(); } @Override public Set> getPaths(final T from, final T to) { int fn = G.getNumber(from); int tn = G.getNumber(to); if (paths[fn][tn] == Integer.MAX_VALUE) { throw new UnsupportedOperationException("no path from " + from + " to " + to); } else { MutableIntSet intermediate = next[fn][tn]; if (intermediate == null) { List none = Collections.emptyList(); return Collections.singleton(none); } else { final Set> result = new HashSet<>(); intermediate.foreach( x -> { T in = G.getNode(x); for (List pre : getPaths(from, in)) { for (List post : getPaths(in, to)) { List path = new ArrayList<>(pre); path.add(in); path.addAll(post); result.add(path); } } }); return result; } } } }; } }.doit(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy