-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathcombine_visitors.m
104 lines (86 loc) · 2.98 KB
/
combine_visitors.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
104
function cv = combine_visitors(varargin)
% COMBINE_VISITORS Generate a new visitor by combining existing visitors
%
% cv = combine_visitors(v1, v2, ...) generates a new algorithm visitor that
% works by calling the functions in v1 followed by the functions in v2, and
% so on.
%
% The value returned by the combined visitor function is the bitwise & of
% all the individual return values. So, if any visitor requests the
% algorithm to halt, then the algorithm will halt.
%
% Note: using a combined visitor is somewhat slower than writing a custom
% combined visitor yourself.
%
% Example:
% vis1 = struct();
% vis1.examine_vertex = @(u) fprintf('vis1: examine_vertex(%i)\n', u);
% vis2 = struct();
% vis2.examine_vertex = @(u) fprintf('vis2: examine_vertex(%i)\n', u);
% combined_vis = combine_visitors(vis1, vis2);
% load graphs/bfs_example.mat
% breadth_first_search(A,1,combined_vis);
% David Gleich
% Copyright, Stanford University, 2006-2008
% trivial output
if isempty(varargin)
error('matlab_bgl:invalidParameter', 'combine_visitors requires at least one argument');
end
if length(varargin) == 1, cv = varargin{1}; return; end
cv_fn = struct();
for ii = 1:length(varargin)
fn = fieldnames(varargin{ii});
for jj = 1:length(fn)
if ~isfield(cv_fn,fn{jj})
cv_fn.(fn{jj}) = 1;
else
cv_fn.(fn{jj}) = cv_fn.(fn{jj}) + 1;
end
end
end
function cfunc=combine_function(name,count)
used_visitors = cell(count,1);
cur_used = 1;
for kk = 1:length(varargin)
if isfield(varargin{kk}, name)
used_visitors{cur_used} = varargin{kk}.(name);
cur_used = cur_used + 1;
end
end
function rval = combine_function_impl(varargin)
rval = 1;
for ll=1:length(used_visitors)
try
stop = feval(used_visitors{ll}, varargin{:});
rval = rval & double(stop);
catch
[lastmsg,lastid] = lasterr;
if ~strcmp(lastid, 'MATLAB:TooManyOutputs')
rethrow(lasterr);
else
feval(used_visitors{ll}, varargin{:});
end
end
end
end
cfunc = @combine_function_impl;
end
cv = struct();
% specify only the visitors functions that only occured once
for ii = 1:length(varargin)
fn = fieldnames(varargin{ii});
for jj = 1:length(fn)
if (cv_fn.(fn{jj}) == 1)
cv.(fn{jj}) = varargin{ii}.(fn{jj});
end
end
end
% specify all visitors that occured more than once
fn = fieldnames(cv_fn);
for jj=1:length(fn)
if (cv_fn.(fn{jj}) > 1)
cv.(fn{jj}) = combine_function(fn{jj}, cv_fn.(fn{jj}));
end
end
% overall function end
end