wolffd@0
|
1 function [D,P] = dijk(A,s,t)
|
wolffd@0
|
2 %DIJK Shortest paths from nodes 's' to nodes 't' using Dijkstra algorithm.
|
wolffd@0
|
3 % [D,p] = dijk(A,s,t)
|
wolffd@0
|
4 % A = n x n node-node weighted adjacency matrix of arc lengths
|
wolffd@0
|
5 % (Note: A(i,j) = 0 => Arc (i,j) does not exist;
|
wolffd@0
|
6 % A(i,j) = NaN => Arc (i,j) exists with 0 weight)
|
wolffd@0
|
7 % s = FROM node indices
|
wolffd@0
|
8 % = [] (default), paths from all nodes
|
wolffd@0
|
9 % t = TO node indices
|
wolffd@0
|
10 % = [] (default), paths to all nodes
|
wolffd@0
|
11 % D = |s| x |t| matrix of shortest path distances from 's' to 't'
|
wolffd@0
|
12 % = [D(i,j)], where D(i,j) = distance from node 'i' to node 'j'
|
wolffd@0
|
13 % P = |s| x n matrix of predecessor indices, where P(i,j) is the
|
wolffd@0
|
14 % index of the predecessor to node 'j' on the path from 's(i)' to 'j'
|
wolffd@0
|
15 % (use PRED2PATH to convert P to paths)
|
wolffd@0
|
16 % = path from 's' to 't', if |s| = |t| = 1
|
wolffd@0
|
17 %
|
wolffd@0
|
18 % (If A is a triangular matrix, then computationally intensive node
|
wolffd@0
|
19 % selection step not needed since graph is acyclic (triangularity is a
|
wolffd@0
|
20 % sufficient, but not a necessary, condition for a graph to be acyclic)
|
wolffd@0
|
21 % and A can have non-negative elements)
|
wolffd@0
|
22 %
|
wolffd@0
|
23 % (If |s| >> |t|, then DIJK is faster if DIJK(A',t,s) used, where D is now
|
wolffd@0
|
24 % transposed and P now represents successor indices)
|
wolffd@0
|
25 %
|
wolffd@0
|
26 % (Based on Fig. 4.6 in Ahuja, Magnanti, and Orlin, Network Flows,
|
wolffd@0
|
27 % Prentice-Hall, 1993, p. 109.)
|
wolffd@0
|
28
|
wolffd@0
|
29 % Copyright (c) 1998-2001 by Michael G. Kay
|
wolffd@0
|
30 % Matlog Version 5 22-Aug-2001
|
wolffd@0
|
31
|
wolffd@0
|
32 % Input Error Checking ******************************************************
|
wolffd@0
|
33 error(nargchk(1,3,nargin));
|
wolffd@0
|
34
|
wolffd@0
|
35 [n,cA] = size(A);
|
wolffd@0
|
36
|
wolffd@0
|
37 if nargin < 2 | isempty(s), s = (1:n)'; else s = s(:); end
|
wolffd@0
|
38 if nargin < 3 | isempty(t), t = (1:n)'; else t = t(:); end
|
wolffd@0
|
39
|
wolffd@0
|
40 if ~any(any(tril(A) ~= 0)) % A is upper triangular
|
wolffd@0
|
41 isAcyclic = 1;
|
wolffd@0
|
42 elseif ~any(any(triu(A) ~= 0)) % A is lower triangular
|
wolffd@0
|
43 isAcyclic = 2;
|
wolffd@0
|
44 else % Graph may not be acyclic
|
wolffd@0
|
45 isAcyclic = 0;
|
wolffd@0
|
46 end
|
wolffd@0
|
47
|
wolffd@0
|
48 if n ~= cA
|
wolffd@0
|
49 error('A must be a square matrix');
|
wolffd@0
|
50 elseif ~isAcyclic & any(any(A < 0))
|
wolffd@0
|
51 error('A must be non-negative');
|
wolffd@0
|
52 elseif any(s < 1 | s > n)
|
wolffd@0
|
53 error(['''s'' must be an integer between 1 and ',num2str(n)]);
|
wolffd@0
|
54 elseif any(t < 1 | t > n)
|
wolffd@0
|
55 error(['''t'' must be an integer between 1 and ',num2str(n)]);
|
wolffd@0
|
56 end
|
wolffd@0
|
57 % End (Input Error Checking) ************************************************
|
wolffd@0
|
58
|
wolffd@0
|
59 A = A'; % Use transpose to speed-up FIND for sparse A
|
wolffd@0
|
60
|
wolffd@0
|
61 D = zeros(length(s),length(t));
|
wolffd@0
|
62 if nargout > 1, P = zeros(length(s),n); end
|
wolffd@0
|
63
|
wolffd@0
|
64 for i = 1:length(s)
|
wolffd@0
|
65 j = s(i);
|
wolffd@0
|
66
|
wolffd@0
|
67 Di = Inf*ones(n,1); Di(j) = 0;
|
wolffd@0
|
68
|
wolffd@0
|
69 isLab = logical(zeros(length(t),1));
|
wolffd@0
|
70 if isAcyclic == 1
|
wolffd@0
|
71 nLab = j - 1;
|
wolffd@0
|
72 elseif isAcyclic == 2
|
wolffd@0
|
73 nLab = n - j;
|
wolffd@0
|
74 else
|
wolffd@0
|
75 nLab = 0;
|
wolffd@0
|
76 UnLab = 1:n;
|
wolffd@0
|
77 isUnLab = logical(ones(n,1));
|
wolffd@0
|
78 end
|
wolffd@0
|
79
|
wolffd@0
|
80 while nLab < n & ~all(isLab)
|
wolffd@0
|
81 if isAcyclic
|
wolffd@0
|
82 Dj = Di(j);
|
wolffd@0
|
83 else % Node selection
|
wolffd@0
|
84 [Dj,jj] = min(Di(isUnLab));
|
wolffd@0
|
85 j = UnLab(jj);
|
wolffd@0
|
86 UnLab(jj) = [];
|
wolffd@0
|
87 isUnLab(j) = 0;
|
wolffd@0
|
88 end
|
wolffd@0
|
89
|
wolffd@0
|
90 nLab = nLab + 1;
|
wolffd@0
|
91 if length(t) < n, isLab = isLab | (j == t); end
|
wolffd@0
|
92
|
wolffd@0
|
93 [jA,kA,Aj] = find(A(:,j));
|
wolffd@0
|
94 Aj(isnan(Aj)) = 0;
|
wolffd@0
|
95
|
wolffd@0
|
96 if isempty(Aj), Dk = Inf; else Dk = Dj + Aj; end
|
wolffd@0
|
97
|
wolffd@0
|
98 if nargout > 1, P(i,jA(Dk < Di(jA))) = j; end
|
wolffd@0
|
99 Di(jA) = min(Di(jA),Dk);
|
wolffd@0
|
100
|
wolffd@0
|
101 if isAcyclic == 1 % Increment node index for upper triangular A
|
wolffd@0
|
102 j = j + 1;
|
wolffd@0
|
103 elseif isAcyclic == 2 % Decrement node index for lower triangular A
|
wolffd@0
|
104 j = j - 1;
|
wolffd@0
|
105 end
|
wolffd@0
|
106 end
|
wolffd@0
|
107 D(i,:) = Di(t)';
|
wolffd@0
|
108 end
|
wolffd@0
|
109
|
wolffd@0
|
110 if nargout > 1 & length(s) == 1 & length(t) == 1
|
wolffd@0
|
111 P = pred2path(P,s,t);
|
wolffd@0
|
112 end
|