wolffd@0: % --- wolffd@0: % class ClipSimGraphMulti wolffd@0: % Directed MultiGraph representing comparative clip similarities. wolffd@0: % EACH pair of vertices has multiple directed edges connecting them wolffd@0: % wolffd@0: % each node represents a pair of clips, wolffd@0: % an edge (a,b) -> (a,c) is present if there is at least one wolffd@0: % users judging clip a more similar to clip b than to clip c wolffd@0: % wolffd@0: % Each edge thus represent a single (are nearer to each othen than) wolffd@0: % expression wolffd@0: % --- wolffd@0: wolffd@0: classdef ClipSimGraphMulti < ClipSimGraph & handle wolffd@0: wolffd@0: wolffd@0: properties wolffd@0: wolffd@0: end wolffd@0: wolffd@0: % --- wolffd@0: % the methods wolffd@0: % --- wolffd@0: methods wolffd@0: wolffd@0: % constructor of the graph wolffd@0: function G = ClipSimGraphMulti(comparison, comparison_ids) wolffd@0: wolffd@0: if nargin == 0 wolffd@0: % --- wolffd@0: % empty constructor wolffd@0: % --- wolffd@0: wolffd@0: elseif nargin == 1 wolffd@0: % todo: copy graph if same class wolffd@0: wolffd@0: % --- wolffd@0: % this uses an imput grpaph wolffd@0: % to create a new MD graph wolffd@0: % --- wolffd@0: wolffd@0: G = ClipSimGraphMulti(); wolffd@0: wolffd@0: % --- wolffd@0: % Add the input graph to the empty one wolffd@0: % --- wolffd@0: G.add_graph(comparison); wolffd@0: wolffd@0: elseif nargin == 2 wolffd@0: wolffd@0: wolffd@0: % --- wolffd@0: % handle automatic or manual input wolffd@0: % --- wolffd@0: for i = 1:size(comparison,1) wolffd@0: wolffd@0: % get clips and votes wolffd@0: clips = comparison_ids(comparison(i,1:3)); wolffd@0: votes = comparison(i,4:6); wolffd@0: wolffd@0: % for each triplet position create an edge reflecting the wolffd@0: % absolute and relative voting for this position wolffd@0: wolffd@0: % --- wolffd@0: % NOTE: we index 0 - 2 to ease the mod wolffd@0: % calculaton for the remaining indices wolffd@0: % --- wolffd@0: for v = 0:2 wolffd@0: wolffd@0: % --- wolffd@0: % has at least one user voted this clip out? wolffd@0: % If so, treat it as an outlier and determine score wolffd@0: % --- wolffd@0: if votes(v+1) > 0 wolffd@0: wolffd@0: a = mod(v+1, 3)+1; wolffd@0: b = mod(v+2, 3)+1; wolffd@0: c = v+1; wolffd@0: wolffd@0: wolffd@0: % --- wolffd@0: % every outlier vote results in two wolffd@0: % dissimilarity equations, favored by wolffd@0: % the people who voted for the outlier wolffd@0: % --- wolffd@0: wolffd@0: % edge 1 wolffd@0: add_edge(G, clips(a), clips(b), clips(c), votes(v+1)); wolffd@0: wolffd@0: % edge 2 wolffd@0: add_edge(G, clips(b), clips(a), clips(c), votes(v+1)); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: % end constructor function wolffd@0: end wolffd@0: wolffd@0: function out = order(G) wolffd@0: wolffd@0: out = sum(G.V); wolffd@0: end wolffd@0: wolffd@0: function out = num_edges_multi(G) wolffd@0: out = sum(sum(G.E)); wolffd@0: end wolffd@0: wolffd@0: function out = num_edges(G) wolffd@0: out = sum(sum(G.E ~= 0)); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: % --- wolffd@0: % NOTE: the weight explains the multiplicity of each wolffd@0: % edge, to correctily describe this, wolffd@0: % we just count the votes wolffd@0: % --- wolffd@0: function join_edge(G, a, b, c, weight) wolffd@0: wolffd@0: if nargin == 5 wolffd@0: V1 = G.node(a, b); wolffd@0: V2 = G.node(a, c); wolffd@0: elseif nargin == 4 wolffd@0: V1 = a; wolffd@0: V2 = b; wolffd@0: weight = c; wolffd@0: end wolffd@0: wolffd@0: if G.edge(V1, V2) ~= 0 wolffd@0: wolffd@0: % set add number to Edge index wolffd@0: G.E(V1, V2) = (G.E(V1, V2) + weight); wolffd@0: wolffd@0: cprint(3, 'edge weight %d %d %d updated \n',a ,b , c) ; wolffd@0: else wolffd@0: wolffd@0: error 'nodes not found'; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: % --- wolffd@0: % This eliminates any order-2 cycles, wolffd@0: % by substracting opposing edge counts wolffd@0: % --- wolffd@0: function remove_cycles_length2(G) wolffd@0: wolffd@0: G.E = max(0, G.E - G.E'); wolffd@0: end wolffd@0: % --- wolffd@0: % TODO: this back-and forth transform is a workaround wolffd@0: % avoiding some costly other transformation which would wolffd@0: % happen during the direct digraph call wolffd@0: % --- wolffd@0: wolffd@0: function [Gs, s, id] = connected_components(G, varargin) wolffd@0: % --- wolffd@0: % get all connected subgraphs: wolffd@0: % --- wolffd@0: G2 = DiGraph(G); wolffd@0: wolffd@0: [GsDiGraph, s, id] = connected_components@DiGraph(G2, varargin{:}); wolffd@0: wolffd@0: for i = 1:numel(GsDiGraph) wolffd@0: Gs(i) = ClipSimGraphMulti(GsDiGraph(i)); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: end wolffd@0: wolffd@0: methods (Hidden) wolffd@0: wolffd@0: end wolffd@0: end