annotate _FullBNT/BNT/learning/learn_struct_pdag_ic_star.m @ 9:4ea6619cb3f5 tip

removed log files
author matthiasm
date Fri, 11 Apr 2014 15:55:11 +0100
parents b5b38998ef3b
children
rev   line source
matthiasm@8 1 function [pdag, G] = learn_struct_pdag_ic_star(cond_indep, n, k, varargin)
matthiasm@8 2 % LEARN_STRUCT_PDAG_IC_STAR Learn a partially oriented DAG (pattern) with latent
matthiasm@8 3 % variables using the IC* algorithm
matthiasm@8 4 % P = learn_struct_pdag_ic_star(cond_indep, n, k, ...)
matthiasm@8 5 %
matthiasm@8 6 % n is the number of nodes.
matthiasm@8 7 % k is an optional upper bound on the fan-in (default: n)
matthiasm@8 8 % cond_indep is a boolean function that will be called as follows:
matthiasm@8 9 % feval(cond_indep, x, y, S, ...)
matthiasm@8 10 % where x and y are nodes, and S is a set of nodes (positive integers),
matthiasm@8 11 % and ... are any optional parameters passed to this function.
matthiasm@8 12 %
matthiasm@8 13 % The output P is an adjacency matrix, in which
matthiasm@8 14 % P(i,j) = -1 if there is either a latent variable L such that i <-L-> j
matthiasm@8 15 % OR there is a directed edge from i->j.
matthiasm@8 16 % P(i,j) = -2 if there is a marked directed i-*>j edge.
matthiasm@8 17 % P(i,j) = P(j,i) = 1 if there is and undirected edge i--j
matthiasm@8 18 % P(i,j) = P(j,i) = 2 if there is a latent variable L such that i<-L->j.
matthiasm@8 19 %
matthiasm@8 20 % The IC* algorithm learns a latent structure associated with a set of observed
matthiasm@8 21 % variables.
matthiasm@8 22 % The latent structure revealed is the projection in which every latent variable is
matthiasm@8 23 % 1) a root node
matthiasm@8 24 % 2) linked to exactly two observed variables.
matthiasm@8 25 % Latent variables in the projection are represented using a bidirectional graph,
matthiasm@8 26 % and thus remain implicit.
matthiasm@8 27 %
matthiasm@8 28 % See Pearl, "Causality: Models, Reasoning, and Inference", 2000, p52 for more details.
matthiasm@8 29 % Written by Tamar Kushnir, 2000
matthiasm@8 30
matthiasm@8 31 sep = cell(n,n);
matthiasm@8 32 ord = 0;
matthiasm@8 33 done = 0;
matthiasm@8 34 G = ones(n,n);
matthiasm@8 35 G = setdiag(G,0);
matthiasm@8 36 while ~done
matthiasm@8 37 done = 1;
matthiasm@8 38 [X,Y] = find(G);
matthiasm@8 39 for i=1:length(X)
matthiasm@8 40 x = X(i); y = Y(i);
matthiasm@8 41 nbrs = mysetdiff(myunion(neighbors(G, x), neighbors(G,y)), [x y]);
matthiasm@8 42 if length(nbrs) >= ord & G(x,y) ~= 0
matthiasm@8 43 done = 0;
matthiasm@8 44 SS = subsets(nbrs, ord, ord); % all subsets of size ord
matthiasm@8 45 for si=1:length(SS)
matthiasm@8 46 S = SS{si};
matthiasm@8 47 if feval(cond_indep, x, y, S, varargin{:})
matthiasm@8 48 G(x,y) = 0;
matthiasm@8 49 G(y,x) = 0;
matthiasm@8 50 sep{x,y} = myunion(sep{x,y}, S);
matthiasm@8 51 sep{y,x} = myunion(sep{y,x}, S);
matthiasm@8 52 break; % no need to check any more subsets
matthiasm@8 53 end
matthiasm@8 54 end
matthiasm@8 55 end
matthiasm@8 56 end
matthiasm@8 57 ord = ord + 1;
matthiasm@8 58 end
matthiasm@8 59
matthiasm@8 60 % Create the minimal pattern,
matthiasm@8 61 % i.e., the only directed edges are V structures.
matthiasm@8 62 pdag = G;
matthiasm@8 63 [X, Y] = find(G);
matthiasm@8 64 % We want to generate all unique triples x,y,z
matthiasm@8 65 % where y is a common neighbor to x and z
matthiasm@8 66 for i=1:length(X)
matthiasm@8 67 x = X(i);
matthiasm@8 68 y = Y(i);
matthiasm@8 69 Z = find(G(y,:));
matthiasm@8 70 Z = mysetdiff(Z, x);
matthiasm@8 71 for z=Z(:)'
matthiasm@8 72 if G(x,z)==0 & ~ismember(y, sep{x,z}) & ~ismember(y, sep{z,x})
matthiasm@8 73 pdag(x,y) = -1; pdag(y,x) = 0;
matthiasm@8 74 pdag(z,y) = -1; pdag(y,z) = 0;
matthiasm@8 75 end
matthiasm@8 76 end
matthiasm@8 77 end
matthiasm@8 78
matthiasm@8 79 % Convert the minimal pattern to a complete one using the following rules:
matthiasm@8 80 % Rule 1:
matthiasm@8 81 % if a and b are non-adjacent nodes with a common neighbor c,
matthiasm@8 82 % if a->c and not b->c then c-*>b (marked arrow).
matthiasm@8 83 % Rule 2:
matthiasm@8 84 % if a and b are adjacent and there is a directed path (marked links) from a to b
matthiasm@8 85 % then a->b (add arrowhead).
matthiasm@8 86 %Pearl (2000)
matthiasm@8 87
matthiasm@8 88 arrowin = [-1 -2 2];
matthiasm@8 89 old_pdag = zeros(n);
matthiasm@8 90 iter = 0;
matthiasm@8 91 while ~isequal(pdag, old_pdag)
matthiasm@8 92 iter = iter + 1;
matthiasm@8 93 old_pdag = pdag;
matthiasm@8 94 % rule 1
matthiasm@8 95 [X, Y] = find(pdag);
matthiasm@8 96 for i=1:length(X)
matthiasm@8 97 x = X(i);
matthiasm@8 98 y = Y(i);
matthiasm@8 99 Z = find(pdag(y,:));
matthiasm@8 100 Z = mysetdiff(Z, x);
matthiasm@8 101 for z=Z(:)'
matthiasm@8 102 if G(x,z)==0 & ismember(pdag(x,y),arrowin) & ~ismember(pdag(z,y),arrowin)
matthiasm@8 103 pdag(y,z) = -2; pdag(z,y) = 0;
matthiasm@8 104 end
matthiasm@8 105 end
matthiasm@8 106 end
matthiasm@8 107 % rule 2
matthiasm@8 108 [X, Y] = find(G);
matthiasm@8 109 %check all adjacent nodes because if pdag(x,y) = -1
matthiasm@8 110 %and pdag(y,x) = 0 there could still be an bidirected edge between x & y.
matthiasm@8 111 for i=1:length(X)
matthiasm@8 112 x = X(i);
matthiasm@8 113 y = Y(i);
matthiasm@8 114 if ~ismember(pdag(x,y), arrowin) %x->y doesn't exist yet
matthiasm@8 115 %find marked path from x to y
matthiasm@8 116 add_arrow = marked_path(x,y,pdag);
matthiasm@8 117 if add_arrow
matthiasm@8 118 if pdag(y,x)==-1 %bidirected edge
matthiasm@8 119 pdag(x,y) = 2; pdag(y,x) = 2;
matthiasm@8 120 else
matthiasm@8 121 pdag(x,y) = -1;pdag(y,x) = 0;
matthiasm@8 122 end
matthiasm@8 123 end
matthiasm@8 124 end
matthiasm@8 125 end
matthiasm@8 126 end
matthiasm@8 127
matthiasm@8 128
matthiasm@8 129 %%%%%%%%%%%%%
matthiasm@8 130
matthiasm@8 131 function t = marked_path(x,y,L)
matthiasm@8 132 % MARKED_PATH is a boolean function which returns 1 if a marked path
matthiasm@8 133 % between nodes x and y exists in the partially directed latent structure L.
matthiasm@8 134 %
matthiasm@8 135 % t = marked_path(x,y,L)
matthiasm@8 136 %
matthiasm@8 137 % x and y are the starting and ending nodes in the path, respectively.
matthiasm@8 138 % L is a latent structure (partially directed graph with possible latent variables).
matthiasm@8 139 %
matthiasm@8 140 % Rule 2 of IC* algorithm (see Pearl, 2000)
matthiasm@8 141
matthiasm@8 142 t=0;
matthiasm@8 143
matthiasm@8 144 %find set of marked links from x
matthiasm@8 145 marked = find(L(x,:)==-2);
matthiasm@8 146 if ismember(y,marked)
matthiasm@8 147 t=1; %marked path found
matthiasm@8 148 else
matthiasm@8 149 for m=marked(:)'
matthiasm@8 150 t = marked_path(m,y,L);
matthiasm@8 151 if t==1
matthiasm@8 152 break; %stop when marked path found
matthiasm@8 153 end
matthiasm@8 154 end
matthiasm@8 155 end