Mercurial > hg > camir-aes2014
comparison toolboxes/FullBNT-1.0.7/graph/mk_nbrs_of_digraph.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function [Gs, op, nodes, A] = my_mk_nbs_of_digraph(G0,A) | |
2 % MY_MK_NBRS_OF_DIGRAPH Make all digraphs that differ from G0 by a single edge deletion, addition or reversal, subject to acyclicity | |
3 % [Gs, op, nodes, A] = my_mk_nbrs_of_digraph(G0,<A>) | |
4 % | |
5 % G0 is an adj matrix s.t. G0(i,j)=1 iff i->j in graph | |
6 % A is the ancestor matrix for G0 (opt, creates if necessary) | |
7 % | |
8 % Gs(:,:,i) is the i'th neighbor | |
9 % op{i} = 'add', 'del', or 'rev' is the operation used to create the i'th neighbor. | |
10 % nodes(i,1:2) are the head and tail of the operated-on arc. | |
11 % Modified from mk_nbrs_of_digraph by Sonia Leach | |
12 % | |
13 % Modified by Sonia Leach Feb 02 | |
14 | |
15 if nargin ==1, A = reachability_graph(G0');, end | |
16 | |
17 n = length(G0); | |
18 [I,J] = find(G0); % I(k), J(k) is the k'th edge | |
19 E = length(I); % num edges present in G0 | |
20 | |
21 | |
22 % SINGLE EDGE DELETIONS | |
23 % all deletions are valid wrt acyclity | |
24 | |
25 Grep = repmat(G0(:), 1, E); % each column is a copy of G0 | |
26 % edge_ndx(k) is the scalar location of the k'th edge | |
27 edge_ndx = find(G0); | |
28 | |
29 % edge_ndx = subv2ind([n n], [I J]); % equivalent | |
30 % We set (ndx(k), k) to 0 for k=1:E in Grep | |
31 ndx = subv2ind(size(Grep), [edge_ndx(:) (1:E)']); | |
32 G1 = Grep; | |
33 G1(ndx) = 0; | |
34 Gdel = reshape(G1, [n n E]); | |
35 | |
36 | |
37 % SINGLE EDGE REVERSALS | |
38 | |
39 % SML: previously Kevin had that legal structure was if | |
40 % A(P,i)=1 for any P = { p | p in parents(j), p~=i} | |
41 % specifically he said | |
42 % "if any(A(ps,i)) then there is a path i -> parent of j -> j | |
43 % so reversing i->j would create a cycle" | |
44 % Thus put in another way: | |
45 % for each i,j if sum(G0(:,j)' * A(:,i)) > 0, reversing i->j | |
46 % is not legal. | |
47 % | |
48 % Ex. Suppose we want to check if 2->4 can be reversed in the | |
49 % following graph: | |
50 % G0 = A = | |
51 % 0 0 1 0 0 0 0 0 | |
52 % 0 0 1 1 0 0 0 0 | |
53 % 0 0 0 1 1 1 0 0 | |
54 % 0 0 0 0 1 1 1 0 | |
55 % | |
56 % Then parents(4) = G0(:,4) = [0 1 1 0]' | |
57 % and A(:,2) = [0 0 1 1]. Thus G0(:,4)'*A(:,2) = 1 b/c 3 is | |
58 % an ancestor of 4 and a child of 2. Note that this works b/c | |
59 % matrix multiplication has the effect of ANDing the two vectors | |
60 % and summing up the result (equiv. to the any(A(ps,i)) in kevin's code) | |
61 % | |
62 % So, we vectorize and check for all i,j pairs by looking for | |
63 % 1's in L = (G0'*A)' which has L(i,j)=1 if rev(i,j) not legal | |
64 % Note that this will give 1's where there are none in the G0 | |
65 % so we do a L=max(0, G0-L) to cancel out only the existing edges that | |
66 % aren't legal (subtracting where both are 1 and setting where | |
67 % G0=0 and A=1 back to 0). | |
68 | |
69 L = max(0, G0-(G0'*A)'); | |
70 [IL, JL] = find(L); % I(k), J(k) is the k'th legal edge to rev. | |
71 EL = length(IL); | |
72 | |
73 | |
74 % SML: First we have to DELETE THE EDGES WE ARE REVERSING | |
75 % We can't use G1 w/ reversed edges already deleted (as | |
76 % Kevin did) b/c the space of possible deletions are different | |
77 % now (some reverses aren't legal) | |
78 | |
79 Grep = repmat(G0(:), 1, EL); % each column is a copy of G0 | |
80 % edge_ndx(k) is the scalar location of the k'th edge | |
81 edge_ndx = subv2ind([n n], [IL JL]); | |
82 % We set (ndx(k), k) to 0 for k=1:E in Grep | |
83 ndx = subv2ind(size(Grep), [edge_ndx(:) (1:EL)']); | |
84 G1 = Grep; | |
85 G1(ndx) = 0; | |
86 | |
87 % SML: Now we add in our REVERSED EDGES | |
88 % rev_edge_ndx(k) is the scalar location of the k'th legal reversed edge | |
89 rev_edge_ndx = subv2ind([n n], [JL IL]); | |
90 | |
91 % We set (rev_edge_ndx(k), k) to 1 for k=1:EL in G1 | |
92 % We have already deleted i->j in the previous step | |
93 ndx = subv2ind(size(Grep), [rev_edge_ndx(:) (1:EL)']); | |
94 G1(ndx) = 1; | |
95 Grev = reshape(G1, [n n EL]); | |
96 | |
97 % SINGLE EDGE ADDITIONS | |
98 | |
99 % SML: previously Kevin had that any addition was legal if A(i,j)=0 | |
100 % however, you can not add i->j if j is a descendent of i. | |
101 % Thus, we create all possible additions in Gbar and then | |
102 % subtract the descendants of each edge as possible parents | |
103 % This means the potential parents of i (i.e. Gbar(:,i)) | |
104 % can not also be descendants if i i.e. (A(:,i)) which is accomplished | |
105 % by subtracting (Gbar-A == 1 iff Gbar=1 & A=0) | |
106 | |
107 Gbar = ~G0; % Gbar(i,j)=1 iff there is no i->j edge in G0 | |
108 Gbar = setdiag(Gbar, 0); % turn off self loops | |
109 | |
110 GbarL = Gbar-A; | |
111 [IbarL, JbarL] = find(GbarL); % I(k), J(k) is the k'th legal edge to add | |
112 EbarL = length(IbarL); | |
113 | |
114 bar_edge_ndx = find(GbarL); | |
115 | |
116 Grep = repmat(G0(:), 1, EbarL); % each column is a copy of G0 | |
117 ndx = subv2ind(size(Grep), [bar_edge_ndx(:) (1:EbarL)']); | |
118 Grep(ndx) = 1; | |
119 Gadd = reshape(Grep, [n n EbarL]); | |
120 | |
121 | |
122 Gs = cat(3, Gdel, Grev, Gadd); | |
123 | |
124 nodes = [I J; | |
125 IL JL; | |
126 IbarL JbarL]; | |
127 | |
128 op = cell(1, E+EL+EbarL); | |
129 op(1:E) = {'del'}; | |
130 op(E+(1:EL)) = {'rev'}; | |
131 op((E+EL+1):end) = {'add'}; | |
132 |