package iiuf.util.graph;
import java.util.HashMap;
import java.util.LinkedList;
import iiuf.util.AttributeFactory;
import iiuf.util.Attributable;
/**
Various graph utilities.
(c) 2000, 2001, IIUF, DIUF<p>
@author $Author: ohitz $
@version $Name: $ $Revision: 1.1 $
*/
public class Utilities {
public static void breadthFirst(GraphModel graph, DefaultGraphNode start, Object userobject, GraphWalk walker) {
breadthFirst(graph, start, userobject, false, walker);
}
private static void updateNode(GraphModel graph, DefaultGraphNode node, int color, double distance, DefaultGraphNode parent,
GraphWalk walker, Object userobject, int component) {
node.color = node.GRAY;
node.distance = distance;
node.parent = parent;
walker.node(graph, node, userobject, component);
}
public static void breadthFirst(GraphModel graph, DefaultGraphNode start, Object userobject, boolean all,
GraphWalk walker) {
synchronized(graph) {
LinkedList queue = new LinkedList();
Object[] nodes = graph.nodes().toArray();
for(int i = 0; i < nodes.length; i++) {
DefaultGraphNode gn = (DefaultGraphNode)nodes[i];
gn.color = gn.WHITE;
gn.distance = gn.INF;
gn.parent = null;
}
for(int component = 0;; component++) {
updateNode(graph, start, DefaultGraphNode.GRAY, 0, null, walker, userobject, component);
queue.add(start);
while(!queue.isEmpty()) {
DefaultGraphNode u = (DefaultGraphNode)queue.getFirst();
GraphEdge[] adj = u.getEdges();
for(int i = 0; i < adj.length; i++) {
DefaultGraphNode v = (DefaultGraphNode)adj[i].getAdjacent(u);
if(v.color == v.WHITE) {
updateNode(graph, v, v.GRAY, u.distance + 1, u, walker, userobject, component);
queue.add(v);
}
}
queue.removeFirst();
u.color = u.BLACK;
start = null;
if(all) {
for(int i = 0; i < nodes.length; i++)
if(((DefaultGraphNode)nodes[i]).color == DefaultGraphNode.WHITE) {
start = (DefaultGraphNode)nodes[i];
break;
}
}
if(start == null) return;
}
}
}
}
public static class ShortestPath {
GraphNode[] nodes;
GraphEdge[][] edges;
HashMap nodeIndex = new HashMap();
int[][] P;
ShortestPath(GraphNode[] n_) {
nodes = n_;
int nnodes = nodes.length;
double[][] D0 = new double[nnodes][nnodes];
double[][] D1 = new double[nnodes][nnodes];
int[][] P0 = new int[nnodes][nnodes];
int[][] P1 = new int[nnodes][nnodes];
edges = new GraphEdge[nnodes][nnodes];
for(int i = 0; i < nnodes; i++)
nodeIndex.put(nodes[i], new Integer(i));
// init weight matrix
for(int i = 0; i < nnodes; i++) {
nodeloop:
for(int j = 0; j < nnodes; j++) {
if(i == j) D1[i][j] = 0;
else {
GraphEdge[] outs = nodes[i].getOut();
for(int k = 0; k < outs.length; k++)
if(outs[k].getToNode() == nodes[j]) {
edges[i][j] = outs[k];
D1[i][j] = outs[k].getWeight();
continue nodeloop;
}
D1[i][j] = Double.POSITIVE_INFINITY;
}
}
}
// floyd-wharshall
// init
for(int i = 0; i < nnodes; i++)
for(int j = 0; j < nnodes; j++)
P1[i][j] = i != j && D1[i][j] != Double.POSITIVE_INFINITY ? i : -1;
for(int k = 1; k <= nnodes; k++) { // as both i and j run from 0 upwards, but k starts from 1
int kdec = k - 1; // there is a need to adjust k, i.e. create and use kdec.
for(int i = 0;i < nnodes; i++)
for(int j = 0; j < nnodes; j++) {
if (D1[i][j] > D1[i][kdec] + D1[kdec][j]) {
D0[i][j] = D1[i][kdec] + D1[kdec][j];
P0[i][j] = P1[kdec][j];
} else {
D0[i][j] = D1[i][j];
P0[i][j] = P1[i][j];
}
}
P1 = P0;
D1 = D0;
}
P = P0;
/*
System.out.println("D");
for(int i = 0; i < nnodes; i++) {
for(int j = 0; j < nnodes; j++)
System.out.print((D0[i][j] == Double.POSITIVE_INFINITY ? "INF" : D0[i][j] + "")+ "\t");
System.out.println();
}
System.out.println("P");
for(int i = 0; i < nnodes; i++) {
for(int j = 0; j < nnodes; j++)
System.out.print((P[i][j] == Double.POSITIVE_INFINITY ? "INF" : P[i][j] + "")+ "\t");
System.out.println();
}
*/
}
private LinkedList shortestPath(LinkedList l, GraphNode from, GraphNode to) {
if(from == to) {
l.add(to);
return l;
}
int i = ((Integer)nodeIndex.get(from)).intValue();
int j = ((Integer)nodeIndex.get(to)).intValue();
if(P[i][j] == -1) return l;
else {
shortestPath(l, from, nodes[P[i][j]]);
l.add(to);
}
return l;
}
public GraphEdge[] shortestPath(GraphNode from, GraphNode to) {
LinkedList nodes = shortestPath(new LinkedList(), from, to);
if(nodes.size() < 2) return null;
GraphEdge[] result = new GraphEdge[nodes.size() - 1];
for(int k = 1; k < nodes.size(); k++) {
int i = ((Integer)nodeIndex.get(nodes.get(k - 1))).intValue();
int j = ((Integer)nodeIndex.get(nodes.get(k))).intValue();
result[k - 1] = edges[i][j];
}
return result;
}
}
public static ShortestPath shortestPath(GraphModel m) {
return shortestPath(m.nodesArray());
}
public static ShortestPath shortestPath(GraphNode[] n) {
return new ShortestPath(n);
}
public static void main(String[] argv) {
GraphModel m = new DefaultGraphModel();
DefaultGraphNode[] n = new DefaultGraphNode[6];
for(int i = 1; i < 6; i++){
n[i] = new DefaultGraphNode();
n[i].color = i;
m.add(n[i]);
}
m.add(new DefaultGraphEdge(n[1], n[2], 3));
m.add(new DefaultGraphEdge(n[1], n[3], 8));
m.add(new DefaultGraphEdge(n[1], n[5], -4));
m.add(new DefaultGraphEdge(n[2], n[4], 1));
m.add(new DefaultGraphEdge(n[2], n[5], 7));
m.add(new DefaultGraphEdge(n[3], n[2], 4));
m.add(new DefaultGraphEdge(n[4], n[1], 2));
m.add(new DefaultGraphEdge(n[4], n[3], -5));
m.add(new DefaultGraphEdge(n[5], n[4], 6));
DefaultGraphNode[] tmp = n;
n = new DefaultGraphNode[tmp.length - 1];
System.arraycopy(tmp, 1, n, 0, n.length);
ShortestPath sp = shortestPath(n);
for(int i = 0; i < n.length; i++)
for(int j = 0; j < n.length; j++) {
GraphEdge[] e = sp.shortestPath(n[i], n[j]);
if(e != null) {
System.out.print(n[i].color + "->" + n[j].color + ":");
for(int k = 0; k < e.length; k++)
System.out.print(" " + ((DefaultGraphNode)e[k].getFromNode()).color + "->" +
((DefaultGraphNode)e[k].getToNode()).color);
System.out.println();
}
}
}
}
/*
$Log: Utilities.java,v $
Revision 1.1 2002/07/11 12:00:11 ohitz
Initial checkin
Revision 1.4 2001/07/30 15:27:04 schubige
adapted for sample based timing
Revision 1.3 2001/05/11 11:30:26 schubige
fns demo final
Revision 1.2 2001/01/04 16:28:43 schubige
Header update for 2001 and DIUF
Revision 1.1 2000/11/10 10:11:54 schubige
iiuf tree cleanup iter 3
*/