-
Notifications
You must be signed in to change notification settings - Fork 16
/
pathbetweennodes.m
103 lines (81 loc) · 2.18 KB
/
pathbetweennodes.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
function pth = pathbetweennodes(adj, src, snk, verbose)
%PATHBETWEENNODES Return all paths between two nodes of a graph
%
% pth = pathbetweennodes(adj, src, snk)
% pth = pathbetweennodes(adj, src, snk, vflag)
%
%
% This function returns all simple paths (i.e. no cycles) between two nodes
% in a graph. Not sure this is the most efficient algorithm, but it seems
% to work quickly for small graphs, and isn't too terrible for graphs with
% ~50 nodes.
%
% Input variables:
%
% adj: adjacency matrix
%
% src: index of starting node
%
% snk: index of target node
%
% vflag: logical scalar for verbose mode. If true, prints paths to
% screen as it traverses them (can be useful for larger,
% time-consuming graphs). [false]
%
% Output variables:
%
% pth: cell array, with each cell holding the indices of a unique path
% of nodes from src to snk.
% Copyright 2014 Kelly Kearney
if nargin < 4
verbose = false;
end
n = size(adj,1);
stack = src;
stop = false;
pth = cell(0);
cycles = cell(0);
next = cell(n,1);
for in = 1:n
next{in} = find(adj(in,:));
end
visited = cell(0);
pred = src;
while 1
visited = [visited; sprintf('%d,', stack)];
[stack, pred] = addnode(stack, next, visited, pred);
if verbose
fprintf('%2d ', stack);
fprintf('\n');
end
if isempty(stack)
break;
end
if stack(end) == snk
pth = [pth; {stack}];
visited = [visited; sprintf('%d,', stack)];
stack = popnode(stack);
elseif length(unique(stack)) < length(stack)
cycles = [cycles; {stack}];
visited = [visited; sprintf('%d,', stack)];
stack = popnode(stack);
end
end
function [stack, pred] = addnode(stack, next, visited, pred)
newnode = setdiff(next{stack(end)}, pred);
possible = arrayfun(@(x) sprintf('%d,', [stack x]), newnode, 'uni', 0);
isnew = ~ismember(possible, visited);
if any(isnew)
idx = find(isnew, 1);
stack = str2num(possible{idx});
pred = stack(end-1);
else
[stack, pred] = popnode(stack);
end
function [stack, pred] = popnode(stack)
stack = stack(1:end-1);
if length(stack) > 1
pred = stack(end-1);
else
pred = [];
end