/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@gephi.org> Website : http://www.gephi.org This file is part of Gephi. Gephi is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gephi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Gephi. If not, see <http://www.gnu.org/licenses/>. */ package org.gephi.algorithms.shortestpath; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import org.gephi.data.attributes.type.TimeInterval; import org.gephi.dynamic.DynamicUtilities; import org.gephi.dynamic.api.DynamicController; import org.gephi.graph.api.Edge; import org.gephi.graph.api.Graph; import org.gephi.graph.api.Node; import org.openide.util.Lookup; /** * * @author Mathieu Bastian */ public class DijkstraShortestPathAlgorithm extends AbstractShortestPathAlgorithm { protected final Graph graph; protected final HashMap<Node, Edge> predecessors; protected TimeInterval timeInterval; public DijkstraShortestPathAlgorithm(Graph graph, Node sourceNode) { super(sourceNode); this.graph = graph; predecessors = new HashMap<Node, Edge>(); DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class); if (dynamicController != null) { timeInterval = DynamicUtilities.getVisibleInterval(dynamicController.getModel(graph.getGraphModel().getWorkspace())); } } public void compute() { graph.readLock(); Set<Node> nodes = new HashSet<Node>(); //Initialize int nodeCount = 0; for (Node node : graph.getNodes()) { distances.put(node, Double.POSITIVE_INFINITY); nodes.add(node); nodeCount++; } distances.put(sourceNode, 0d); while (!nodes.isEmpty()) { // find node with smallest distance value Double minDistance = Double.POSITIVE_INFINITY; Node minDistanceNode = null; for (Node k : nodes) { Double dist = distances.get(k); if (dist.compareTo(minDistance) < 0) { minDistance = dist; minDistanceNode = k; } } Node currentNode = minDistanceNode; nodes.remove(currentNode); for (Edge edge : graph.getEdges(currentNode)) { Node neighbor = graph.getOpposite(currentNode, edge); double dist = edgeWeight(edge) + distances.get(currentNode); if (distances.get(neighbor).equals(Double.POSITIVE_INFINITY)) { distances.put(neighbor, dist); maxDistance = Math.max(maxDistance, dist); predecessors.put(neighbor, edge); } else { if (dist < distances.get(neighbor)) { distances.put(neighbor, dist); maxDistance = Math.max(maxDistance, dist); predecessors.put(neighbor, edge); } } } } graph.readUnlock(); } @Override protected double edgeWeight(Edge edge) { if (timeInterval != null) { return edge.getWeight(timeInterval.getLow(), timeInterval.getHigh()); } return edge.getWeight(); } public Node getPredecessor(Node node) { Edge edge = predecessors.get(node); if (edge != null) { if (edge.getSource() != node) { return edge.getSource(); } else { return edge.getTarget(); } } return null; } public Edge getPredecessorIncoming(Node node) { return predecessors.get(node); } }