annotate core/magnatagatune/ClipPairGraph.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
rev   line source
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