wolffd@0
|
1 % ---
|
wolffd@0
|
2 % mother class for the directed clip graph classes
|
wolffd@0
|
3 % contains general purpose and graph-theorethical
|
wolffd@0
|
4 % functions
|
wolffd@0
|
5 % ---
|
wolffd@0
|
6 % we consider the similarity between clips
|
wolffd@0
|
7 % as symmetric, thus sim(a,b) = sim(b,a)
|
wolffd@0
|
8 % this makes the set of nodes much smaller
|
wolffd@0
|
9 % ---
|
wolffd@0
|
10
|
wolffd@0
|
11 % ---
|
wolffd@0
|
12 % TODO: change structure to
|
wolffd@0
|
13 % avoid using Vclips, mapping clip ids
|
wolffd@0
|
14 % into a node number 00id1..00id2,
|
wolffd@0
|
15 %
|
wolffd@0
|
16 % Enables full integration into Digraph / Graph class
|
wolffd@0
|
17 % ---
|
wolffd@0
|
18
|
wolffd@0
|
19 classdef ClipPairGraph < DiGraph
|
wolffd@0
|
20
|
wolffd@0
|
21 properties(Hidden)
|
wolffd@0
|
22
|
wolffd@0
|
23 max_clipid = 10^6;
|
wolffd@0
|
24 vid_map;
|
wolffd@0
|
25 vid_last = 0;
|
wolffd@0
|
26 end
|
wolffd@0
|
27
|
wolffd@0
|
28 methods
|
wolffd@0
|
29
|
wolffd@0
|
30 % ---
|
wolffd@0
|
31 % Constructor
|
wolffd@0
|
32 % ---
|
wolffd@0
|
33 function G = ClipPairGraph(comparison)
|
wolffd@0
|
34
|
wolffd@0
|
35 if nargin == 0
|
wolffd@0
|
36
|
wolffd@0
|
37 G.vid_map = containers.Map('KeyType', 'double', 'ValueType', 'double');
|
wolffd@0
|
38
|
wolffd@0
|
39 elseif nargin == 1
|
wolffd@0
|
40
|
wolffd@0
|
41 G = ClipPairGraph();
|
wolffd@0
|
42
|
wolffd@0
|
43 % ---
|
wolffd@0
|
44 % Add the input graph to the empty one
|
wolffd@0
|
45 % ---
|
wolffd@0
|
46 G.add_graph(comparison);
|
wolffd@0
|
47
|
wolffd@0
|
48 clas = cat(1, class(comparison), superclasses(comparison));
|
wolffd@0
|
49 if strcellfind(clas, 'ClipPairGraph')
|
wolffd@0
|
50
|
wolffd@0
|
51 G.vid_map = comparison.vid_map;
|
wolffd@0
|
52 end
|
wolffd@0
|
53 end
|
wolffd@0
|
54 end
|
wolffd@0
|
55
|
wolffd@0
|
56 % ---
|
wolffd@0
|
57 % Node id by clip
|
wolffd@0
|
58 % ---
|
wolffd@0
|
59 function Vid = node(G, a, b)
|
wolffd@0
|
60
|
wolffd@0
|
61 % did we get just one clip?
|
wolffd@0
|
62 if nargin == 2
|
wolffd@0
|
63 % ---
|
wolffd@0
|
64 % TODO: this is terribly ineffective
|
wolffd@0
|
65 % create all possible pairs and search if they exist
|
wolffd@0
|
66 % ---
|
wolffd@0
|
67 Vid = [];
|
wolffd@0
|
68 for b = G.clips()';
|
wolffd@0
|
69
|
wolffd@0
|
70 sm = min([a b]);
|
wolffd@0
|
71 bg = max([a b]);
|
wolffd@0
|
72 hash = G.max_clipid *bg + sm;
|
wolffd@0
|
73
|
wolffd@0
|
74 % ---
|
wolffd@0
|
75 % does this pair exist? if so: return Vid
|
wolffd@0
|
76 % ---
|
wolffd@0
|
77 if G.vid_map.isKey(hash)
|
wolffd@0
|
78 Vid(end+1) = G.vid_map(hash);
|
wolffd@0
|
79 end
|
wolffd@0
|
80 end
|
wolffd@0
|
81
|
wolffd@0
|
82 % Ah no, we got the 2 clips
|
wolffd@0
|
83 else
|
wolffd@0
|
84
|
wolffd@0
|
85 % ---
|
wolffd@0
|
86 % hash function for clip pair
|
wolffd@0
|
87 % ---
|
wolffd@0
|
88 % sort clip ids
|
wolffd@0
|
89 sm = min([a b]);
|
wolffd@0
|
90 bg = max([a b]);
|
wolffd@0
|
91
|
wolffd@0
|
92 % ---
|
wolffd@0
|
93 % get node code:
|
wolffd@0
|
94 % max_clipid * bg + sm
|
wolffd@0
|
95 % ---
|
wolffd@0
|
96 hash = G.max_clipid *bg + sm;
|
wolffd@0
|
97
|
wolffd@0
|
98 % ---
|
wolffd@0
|
99 % table lookup
|
wolffd@0
|
100 % ---
|
wolffd@0
|
101 if G.vid_map.isKey(hash)
|
wolffd@0
|
102
|
wolffd@0
|
103 Vid = G.vid_map(hash);
|
wolffd@0
|
104 else
|
wolffd@0
|
105
|
wolffd@0
|
106 % ---
|
wolffd@0
|
107 % create new psition in hash table and
|
wolffd@0
|
108 % assign this ID to the node
|
wolffd@0
|
109 % ---
|
wolffd@0
|
110 G.vid_last = G.vid_last + 1;
|
wolffd@0
|
111 Vid = G.vid_last;
|
wolffd@0
|
112
|
wolffd@0
|
113 G.vid_map(hash) = Vid;
|
wolffd@0
|
114
|
wolffd@0
|
115 % ---
|
wolffd@0
|
116 % NOTE: this is intended for maybe swithcingto
|
wolffd@0
|
117 % cell descriptions in future.
|
wolffd@0
|
118 % The node ids will be stored as well
|
wolffd@0
|
119 % ---
|
wolffd@0
|
120 G.Vlbl{Vid} = G.label(Vid);
|
wolffd@0
|
121 end
|
wolffd@0
|
122 end
|
wolffd@0
|
123 end
|
wolffd@0
|
124
|
wolffd@0
|
125 % ---
|
wolffd@0
|
126 % Returns all clip ids referenced in the Graph
|
wolffd@0
|
127 % ---
|
wolffd@0
|
128 function [a] = clips(G)
|
wolffd@0
|
129
|
wolffd@0
|
130 [sm, bg] = G.clipsN(G.nodes);
|
wolffd@0
|
131 a = unique([sm; bg]);
|
wolffd@0
|
132 end
|
wolffd@0
|
133
|
wolffd@0
|
134
|
wolffd@0
|
135 % ---
|
wolffd@0
|
136 % Clip ids for Node
|
wolffd@0
|
137 % ---
|
wolffd@0
|
138 function [sm, bg] = clipsN(G, Vid)
|
wolffd@0
|
139
|
wolffd@0
|
140 % get all clips referenced in this graph
|
wolffd@0
|
141 if numel(Vid) > 1
|
wolffd@0
|
142 sm = [];
|
wolffd@0
|
143 bg = [];
|
wolffd@0
|
144 for i = 1:numel(Vid);
|
wolffd@0
|
145 [sm(end+1), bg(end+1)] = G.clipsN(Vid(i));
|
wolffd@0
|
146 end
|
wolffd@0
|
147 else
|
wolffd@0
|
148
|
wolffd@0
|
149 % ---
|
wolffd@0
|
150 % TODO: There must be a more efficient way to do this
|
wolffd@0
|
151 % ---
|
wolffd@0
|
152 % get all hash data
|
wolffd@0
|
153
|
wolffd@0
|
154 all_hashs = G.vid_map.values();
|
wolffd@0
|
155 all_keys = G.vid_map.keys();
|
wolffd@0
|
156 % ---
|
wolffd@0
|
157 % search for this Node ID and return hash value
|
wolffd@0
|
158 % ---
|
wolffd@0
|
159 hash = all_keys{cell2mat(all_hashs) == Vid};
|
wolffd@0
|
160
|
wolffd@0
|
161 sm = mod(hash, G.max_clipid);
|
wolffd@0
|
162 bg = div(hash, G.max_clipid);
|
wolffd@0
|
163 end
|
wolffd@0
|
164 end
|
wolffd@0
|
165
|
wolffd@0
|
166
|
wolffd@0
|
167 % ---
|
wolffd@0
|
168 % Edge weight by clip id
|
wolffd@0
|
169 % ---
|
wolffd@0
|
170 function [weight, V1, V2] = edge(G, a, b, c)
|
wolffd@0
|
171
|
wolffd@0
|
172 if nargin == 4
|
wolffd@0
|
173 V1 = add_node(G, a, b);
|
wolffd@0
|
174 V2 = add_node(G, a, c);
|
wolffd@0
|
175
|
wolffd@0
|
176 elseif nargin == 3
|
wolffd@0
|
177 V1 = a;
|
wolffd@0
|
178 V2 = b;
|
wolffd@0
|
179 end
|
wolffd@0
|
180
|
wolffd@0
|
181 weight = edge@DiGraph(G, V1, V2);
|
wolffd@0
|
182 end
|
wolffd@0
|
183
|
wolffd@0
|
184 function [weight, varargout] = edges(G,a,b)
|
wolffd@0
|
185
|
wolffd@0
|
186 % all edges or from specified node ?
|
wolffd@0
|
187 if nargin >= 2
|
wolffd@0
|
188
|
wolffd@0
|
189 % is there a clip pair or node number input?
|
wolffd@0
|
190 if nargin == 3
|
wolffd@0
|
191 V1 = add_node(G, a, b);
|
wolffd@0
|
192
|
wolffd@0
|
193 elseif nargin == 2
|
wolffd@0
|
194 V1 = a;
|
wolffd@0
|
195 end
|
wolffd@0
|
196
|
wolffd@0
|
197 [weight, V1, V2] = edges@DiGraph(G, V1);
|
wolffd@0
|
198
|
wolffd@0
|
199 else
|
wolffd@0
|
200 % ---
|
wolffd@0
|
201 % ok, get ALL edges
|
wolffd@0
|
202 % ---
|
wolffd@0
|
203 [weight, V1, V2] = edges@DiGraph(G);
|
wolffd@0
|
204 end
|
wolffd@0
|
205
|
wolffd@0
|
206 % how to represent the output
|
wolffd@0
|
207 if nargout <= 3
|
wolffd@0
|
208 varargout{1} = V1;
|
wolffd@0
|
209 varargout{2} = V2;
|
wolffd@0
|
210 else
|
wolffd@0
|
211 % ---
|
wolffd@0
|
212 % get all the clips from the edges
|
wolffd@0
|
213 % ---
|
wolffd@0
|
214 ao = zeros(1,numel(V1));
|
wolffd@0
|
215 bo = zeros(1,numel(V1));
|
wolffd@0
|
216 co = zeros(1,numel(V1));
|
wolffd@0
|
217 for i =1:numel(V1)
|
wolffd@0
|
218 [ao(i), bo(i), co(i)] = G.clipsE(V1(i), V2(i));
|
wolffd@0
|
219 end
|
wolffd@0
|
220 varargout{1} = ao;
|
wolffd@0
|
221 varargout{2} = bo;
|
wolffd@0
|
222 varargout{3} = co;
|
wolffd@0
|
223 end
|
wolffd@0
|
224 end
|
wolffd@0
|
225
|
wolffd@0
|
226 % ---
|
wolffd@0
|
227 % add an edge saying sim(a,b) > sim(a,c)
|
wolffd@0
|
228 % ---
|
wolffd@0
|
229 function add_edge(G, a, b, c, weight)
|
wolffd@0
|
230
|
wolffd@0
|
231 if nargin == 5
|
wolffd@0
|
232 V1 = add_node(G, a, b);
|
wolffd@0
|
233 V2 = add_node(G, a, c);
|
wolffd@0
|
234
|
wolffd@0
|
235 elseif nargin == 4
|
wolffd@0
|
236 V1 = a;
|
wolffd@0
|
237 V2 = b;
|
wolffd@0
|
238 weight = c;
|
wolffd@0
|
239 end
|
wolffd@0
|
240
|
wolffd@0
|
241 % ---
|
wolffd@0
|
242 % call superclass
|
wolffd@0
|
243 % ---
|
wolffd@0
|
244 add_edge@DiGraph(G, V1, V2, weight);
|
wolffd@0
|
245
|
wolffd@0
|
246 end
|
wolffd@0
|
247
|
wolffd@0
|
248 function Vid = add_node(G, a, b)
|
wolffd@0
|
249
|
wolffd@0
|
250 if nargin == 3
|
wolffd@0
|
251 Vid = G.node(a,b);
|
wolffd@0
|
252 else
|
wolffd@0
|
253 Vid = a;
|
wolffd@0
|
254 end
|
wolffd@0
|
255
|
wolffd@0
|
256 % ---
|
wolffd@0
|
257 % call superclass
|
wolffd@0
|
258 % ---
|
wolffd@0
|
259 add_node@DiGraph(G, Vid);
|
wolffd@0
|
260 end
|
wolffd@0
|
261
|
wolffd@0
|
262 % ---
|
wolffd@0
|
263 % the pairgraph variant of add_graph also updates the
|
wolffd@0
|
264 % clip id hashmap
|
wolffd@0
|
265 % ----
|
wolffd@0
|
266 function add_graph(G, G2)
|
wolffd@0
|
267
|
wolffd@0
|
268 % determine if symmetric edges have to be added
|
wolffd@0
|
269 clas = cat(1, class(G2), superclasses(G2));
|
wolffd@0
|
270 if strcellfind(clas, 'Graph')
|
wolffd@0
|
271 add_symm = 1;
|
wolffd@0
|
272 else
|
wolffd@0
|
273 add_symm = 0;
|
wolffd@0
|
274 end
|
wolffd@0
|
275
|
wolffd@0
|
276 % ---
|
wolffd@0
|
277 % add all nodes and edges in G2
|
wolffd@0
|
278 % ---
|
wolffd@0
|
279 for V = G2.nodes();
|
wolffd@0
|
280
|
wolffd@0
|
281 [a, count] = sscanf(G2.label(V),'%u:%u');
|
wolffd@0
|
282
|
wolffd@0
|
283 if count == 2
|
wolffd@0
|
284 b = a(2);
|
wolffd@0
|
285 a = a(1);
|
wolffd@0
|
286
|
wolffd@0
|
287 G.add_node(a,b);
|
wolffd@0
|
288 else
|
wolffd@0
|
289 G.add_node(V);
|
wolffd@0
|
290 end
|
wolffd@0
|
291 end
|
wolffd@0
|
292
|
wolffd@0
|
293 % ---
|
wolffd@0
|
294 % NOTE / TODO:
|
wolffd@0
|
295 % this LABEL inheritance is far too expensive when
|
wolffd@0
|
296 % creating many copiesof the same graph
|
wolffd@0
|
297 % Its also unnessecary for lots of them
|
wolffd@0
|
298 % except for debugging :(.
|
wolffd@0
|
299 % ---
|
wolffd@0
|
300 G.Vlbl = cell(1, numel(G2.V));
|
wolffd@0
|
301 if G2.cardinality > 1
|
wolffd@0
|
302 G.Vlbl(G.nodes()) = G2.label(G2.nodes());
|
wolffd@0
|
303 else
|
wolffd@0
|
304 G.Vlbl(G.nodes()) = {G2.label(G2.nodes())};
|
wolffd@0
|
305 end
|
wolffd@0
|
306
|
wolffd@0
|
307 % ---
|
wolffd@0
|
308 % get all edges in G2
|
wolffd@0
|
309 % CAVE: if we added the edges above using
|
wolffd@0
|
310 % label clip indices, we have to address them
|
wolffd@0
|
311 % using these below!
|
wolffd@0
|
312 % ---
|
wolffd@0
|
313 [val, V1, V2] = edges(G2);
|
wolffd@0
|
314
|
wolffd@0
|
315 for i = 1:numel(val)
|
wolffd@0
|
316
|
wolffd@0
|
317 % ---
|
wolffd@0
|
318 % add edges to graph
|
wolffd@0
|
319 % NOTE: we assume either all or no edges
|
wolffd@0
|
320 % are labeled with clip indices
|
wolffd@0
|
321 % ---
|
wolffd@0
|
322 if count == 2
|
wolffd@0
|
323 % ---
|
wolffd@0
|
324 % ok, they were labeled above,
|
wolffd@0
|
325 % so index by clips.
|
wolffd@0
|
326 %
|
wolffd@0
|
327 % TODO:
|
wolffd@0
|
328 % 1. get rid of this sscanf stuff and use add_edge for
|
wolffd@0
|
329 % creating the nodes first, the only add single nodes
|
wolffd@0
|
330 % 2. use cell labels globally instead of hashmap here
|
wolffd@0
|
331
|
wolffd@0
|
332 [u, count] = sscanf(G2.label(V1(i)),'%u:%u');
|
wolffd@0
|
333 [v, count] = sscanf(G2.label(V2(i)),'%u:%u');
|
wolffd@0
|
334
|
wolffd@0
|
335 a = intersect(u,v);
|
wolffd@0
|
336 b = setdiff(u,a);
|
wolffd@0
|
337 c = setdiff(v,a);
|
wolffd@0
|
338
|
wolffd@0
|
339 G.add_edge(a, b, c, val(i));
|
wolffd@0
|
340
|
wolffd@0
|
341 if add_symm
|
wolffd@0
|
342 % ---
|
wolffd@0
|
343 % add symmetric edges to graph
|
wolffd@0
|
344 % ---
|
wolffd@0
|
345 G.add_edge(a, c, b, val(i));
|
wolffd@0
|
346 end
|
wolffd@0
|
347
|
wolffd@0
|
348 else
|
wolffd@0
|
349 G.add_edge(V1(i), V2(i), val(i));
|
wolffd@0
|
350
|
wolffd@0
|
351 if add_symm
|
wolffd@0
|
352 % ---
|
wolffd@0
|
353 % add symmetric edges to graph
|
wolffd@0
|
354 % ---
|
wolffd@0
|
355 G.add_edge(V2(i), V1(i), val(i));
|
wolffd@0
|
356 end
|
wolffd@0
|
357
|
wolffd@0
|
358 end
|
wolffd@0
|
359
|
wolffd@0
|
360
|
wolffd@0
|
361 end
|
wolffd@0
|
362
|
wolffd@0
|
363 end
|
wolffd@0
|
364
|
wolffd@0
|
365 function remove_node(G, a, b)
|
wolffd@0
|
366
|
wolffd@0
|
367 if nargin == 3
|
wolffd@0
|
368 Vid = G.node(a,b);
|
wolffd@0
|
369 else
|
wolffd@0
|
370 Vid = a;
|
wolffd@0
|
371 end
|
wolffd@0
|
372
|
wolffd@0
|
373 % ---
|
wolffd@0
|
374 % call superclass
|
wolffd@0
|
375 % ---
|
wolffd@0
|
376 remove_node@DiGraph(G, Vid);
|
wolffd@0
|
377 end
|
wolffd@0
|
378
|
wolffd@0
|
379 % ---
|
wolffd@0
|
380 % Clip ids for Edge
|
wolffd@0
|
381 % ---
|
wolffd@0
|
382 function [a,b,c] = clipsE(G, V1, V2)
|
wolffd@0
|
383
|
wolffd@0
|
384 [c1, c2] = clipsN(G, V1);
|
wolffd@0
|
385 [c3, c4] = clipsN(G, V2);
|
wolffd@0
|
386
|
wolffd@0
|
387 % common clip
|
wolffd@0
|
388 a = intersect([c1 c2],[c3 c4]);
|
wolffd@0
|
389
|
wolffd@0
|
390 % nearer (similar) clip
|
wolffd@0
|
391 b = setdiff([c1 c2],a);
|
wolffd@0
|
392
|
wolffd@0
|
393 % far clip
|
wolffd@0
|
394 c = setdiff([c3 c4],a);
|
wolffd@0
|
395
|
wolffd@0
|
396 if isempty(a)
|
wolffd@0
|
397 error 'clip similarity graph inconsistent'
|
wolffd@0
|
398 end
|
wolffd@0
|
399 end
|
wolffd@0
|
400
|
wolffd@0
|
401 % ---
|
wolffd@0
|
402 function out = label(G, Vid)
|
wolffd@0
|
403
|
wolffd@0
|
404 if nargin == 1
|
wolffd@0
|
405 out = cell(numel(G.V), 1);
|
wolffd@0
|
406 Vid = 1:numel(G.V);
|
wolffd@0
|
407 end
|
wolffd@0
|
408
|
wolffd@0
|
409 for i = 1:numel(Vid)
|
wolffd@0
|
410 if (numel(G.Vlbl) < Vid(i)) || isempty(G.Vlbl{Vid(i)})
|
wolffd@0
|
411
|
wolffd@0
|
412 [sm, bg] = G.clipsN(Vid(i));
|
wolffd@0
|
413
|
wolffd@0
|
414 if numel(Vid) > 1
|
wolffd@0
|
415 out{i} = sprintf('%d:%d', sm, bg);
|
wolffd@0
|
416 else
|
wolffd@0
|
417 out = sprintf('%d:%d', sm, bg);
|
wolffd@0
|
418 end
|
wolffd@0
|
419 else
|
wolffd@0
|
420 if numel(Vid) > 1
|
wolffd@0
|
421 out{i} = G.Vlbl{Vid(i)};
|
wolffd@0
|
422 else
|
wolffd@0
|
423 out = G.Vlbl{Vid(i)};
|
wolffd@0
|
424 end
|
wolffd@0
|
425 end
|
wolffd@0
|
426 end
|
wolffd@0
|
427 end
|
wolffd@0
|
428
|
wolffd@0
|
429 % ---
|
wolffd@0
|
430 % determines if Edges in G2 are the same as in G
|
wolffd@0
|
431 % ---
|
wolffd@0
|
432 function out = le(a,b)
|
wolffd@0
|
433 out = isSubgraph(a, b);
|
wolffd@0
|
434 end
|
wolffd@0
|
435
|
wolffd@0
|
436 function [out] = isSubgraph(G, G2)
|
wolffd@0
|
437
|
wolffd@0
|
438 [val, V1, V2] = G2.edges();
|
wolffd@0
|
439
|
wolffd@0
|
440 i = 1;
|
wolffd@0
|
441 while i <= numel(V1)
|
wolffd@0
|
442 % ---
|
wolffd@0
|
443 % Test if edge exists in other graph,
|
wolffd@0
|
444 % using clips as identifier
|
wolffd@0
|
445 % ---
|
wolffd@0
|
446 [a,b,c] = G2.clipsE(V1(i), V2(i));
|
wolffd@0
|
447
|
wolffd@0
|
448 if G.edge(a,b,c) ~= val(i)
|
wolffd@0
|
449 out = 0;
|
wolffd@0
|
450 return,
|
wolffd@0
|
451 end
|
wolffd@0
|
452 i = i + 1;
|
wolffd@0
|
453 end
|
wolffd@0
|
454 out = 1;
|
wolffd@0
|
455 end
|
wolffd@0
|
456
|
wolffd@0
|
457
|
wolffd@0
|
458 function [Gout] = minus(a, b)
|
wolffd@0
|
459 Gout = feval(class(a),a);
|
wolffd@0
|
460 Gout.remove_graph(b);
|
wolffd@0
|
461 end
|
wolffd@0
|
462
|
wolffd@0
|
463 function remove_graph(G, G2)
|
wolffd@0
|
464
|
wolffd@0
|
465 % ---
|
wolffd@0
|
466 % Get Edges in G2 and remove them
|
wolffd@0
|
467 % ---
|
wolffd@0
|
468 [~, V1, V2] = G2.edges();
|
wolffd@0
|
469 for i = 1:numel(V1)
|
wolffd@0
|
470 % ---
|
wolffd@0
|
471 % Test if edge exists in other graph,
|
wolffd@0
|
472 % using clips as identifier
|
wolffd@0
|
473 % ---
|
wolffd@0
|
474 [a,b,c] = G2.clipsE(V1(i), V2(i));
|
wolffd@0
|
475
|
wolffd@0
|
476 G.remove_edge(a,b,c);
|
wolffd@0
|
477 end
|
wolffd@0
|
478
|
wolffd@0
|
479 % ---
|
wolffd@0
|
480 % Note : we only remove nodes with no
|
wolffd@0
|
481 % remaining incoming edges
|
wolffd@0
|
482 % ---
|
wolffd@0
|
483 V = G2.nodes();
|
wolffd@0
|
484 for i = 1:numel(V)
|
wolffd@0
|
485
|
wolffd@0
|
486 % ---
|
wolffd@0
|
487 % get corresponding node in G via clips
|
wolffd@0
|
488 % ---
|
wolffd@0
|
489 [a,b] = G2.clipsN(V(i));
|
wolffd@0
|
490
|
wolffd@0
|
491 Vid = node(G, a, b);
|
wolffd@0
|
492 if G.degree(Vid) == 0
|
wolffd@0
|
493
|
wolffd@0
|
494 G.remove_node(Vid);
|
wolffd@0
|
495 end
|
wolffd@0
|
496 end
|
wolffd@0
|
497 end
|
wolffd@0
|
498 end
|
wolffd@0
|
499 end |