about summary refs log tree commit diff
path: root/sourcecodes/bnt-master/SLP/learning/learn_struct_bnpc.m
diff options
context:
space:
mode:
Diffstat (limited to 'sourcecodes/bnt-master/SLP/learning/learn_struct_bnpc.m')
-rw-r--r--sourcecodes/bnt-master/SLP/learning/learn_struct_bnpc.m725
1 files changed, 725 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/SLP/learning/learn_struct_bnpc.m b/sourcecodes/bnt-master/SLP/learning/learn_struct_bnpc.m
new file mode 100644
index 00000000..bddce565
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/learn_struct_bnpc.m
@@ -0,0 +1,725 @@
+function [Phase_3, Phase_2, Phase_1, UPhase_3] = learn_struct_bnpc(data,node_sizes,epsilon,star)
+% G = learn_struct_bnpc(Data,node_sizes,epsilon,star)
+%
+% Data(i,m) is node i in case m.
+% node_sizes and epsilon are optionnals.
+% star = 0 to use try_to_separate_B instead of try_to_separate_B_star
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+%
+% Things to do : rewrite function orient_edges !
+%                ! sometimes it causes crashes !
+%
+% V0.91 : 18 sept 2003 (olivier.francois@insa-rouen.fr)
+
+verbose=1;
+%if nargin < 5, mwst=0; end
+if nargin < 4, star=1; end
+if nargin < 3, epsilon=0.05; end
+if nargin < 2, node_sizes=max(data'); end
+
+if verbose
+  fprintf('================== phase I : \n');
+end
+tmp1=cputime;
+[Phase_1 II JJ score_mat score_mat2] = phaseI(data, node_sizes, epsilon);
+tmp1=cputime-tmp1;
+
+if verbose
+  fprintf('Execution time : %2.5f\n',tmp1);
+  fprintf('\n================== phase II : \n');
+end
+tmp1=cputime;
+Phase_2 = phaseII(Phase_1, data, node_sizes, epsilon, II, JJ, score_mat);
+tmp1=cputime-tmp1;
+
+if verbose
+  fprintf('Execution time : %2.5f\n',tmp1);
+  fprintf('\n================== phase III : \n');
+end
+tmp1=cputime;
+[Phase_3 UPhase_3]  = phaseIII(Phase_2, data, node_sizes, epsilon, score_mat2, star);
+tmp1=cputime-tmp1;
+if verbose
+  fprintf('Execution time : %2.5f\n',tmp1);
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [G, II, JJ, score_mat, sc2] = phaseI(data,node_sizes,alpha)
+% [G, II , JJ, score_mat, s2] = phaseI(data,node_sizes,epsilon)
+%
+% G is an acyclic graph
+% [II JJ] is the list of important edges not processed in phase I (for phase II)
+% score_mat is the mutual information score matrix
+%
+% data(i,m) is node i in case m.
+% alpha is the significant level for CI tests ( default=0.05 ).
+% node_sizes is the vector of sizes ( default=max(data') ).
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+% 0.
+if nargin < 3, alpha=0.05; end
+if nargin < 2, node_sizes=max(data'); end
+[N m] = size(data);
+score_mat = zeros(N);
+edges=0;
+
+% 1.
+G = zeros(N);
+L=[];
+
+% 2. Use of Chi2 instead of MI ... allow using a confidence level alpha instead of an arbitrary epsilon
+for i=1:(N-1)
+  for j=(i+1):N
+    [I score_mat(i,j)] = cond_indep_chisquare(i,j,[],data,'LRT',alpha,node_sizes);
+  end
+end
+sc2=score_mat;
+
+
+[tmp ordre]=sort(-score_mat(:));
+ordre2=ordre(find(-tmp>alpha));
+[II JJ]=ind2sub([N N],ordre2);
+
+pointer=1 ;
+fini=length(II);
+
+% 3.
+edges=2;
+for pointer=1:min(2,fini),
+  %fprintf('%d-%d\n',II(pointer),JJ(pointer));
+  G(II(pointer),JJ(pointer))=1;
+  G(JJ(pointer),II(pointer))=1;
+  score_mat(II(pointer),JJ(pointer))=-inf;
+end
+
+pointer=min(2,fini);
+arret=0;
+
+while pointer<fini & ~arret
+  % 4.
+  pointer=pointer+1;
+  C = ~reachability_graph(G);
+  if C(II(pointer),JJ(pointer))
+    %fprintf('%d-%d\n',II(pointer),JJ(pointer));
+    G(II(pointer),JJ(pointer))=1;
+    G(JJ(pointer),II(pointer))=1;
+    score_mat(II(pointer),JJ(pointer))=-inf;
+    edges=edges+1;
+    if edges==N-1
+      arret=1;
+    end
+  end
+
+  % 5.
+end
+
+[tmp ordre]=sort(-score_mat(:));
+ordre2=ordre(find(-tmp>alpha));
+[II JJ]=ind2sub([N N],ordre2);
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function G = phaseII(G1,data,node_sizes,alpha,II, JJ, score_mat)
+% G = phaseII(G1,data,node_sizes,epsilon,II,JJ, score_mat)
+%
+% G1, II, JJ,score_mat are given by phaseI.
+% data(i,m) is node i in case m.
+% node_sizes is the vector of sizes ( default=max(data') ).
+% alpha is the significant level for CI tests ( default=0.05 ).
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+st{1}='added';
+st{2}='';
+% 0.
+[N m] = size(data);
+
+G=G1;
+
+% 6.
+II=II(end:-1:1);
+JJ=JJ(end:-1:1);
+
+pointer=length(II);
+
+while pointer>0
+  % 7.
+  trysep = try_to_separate_A(G,II(pointer),JJ(pointer),data,alpha,node_sizes);
+  %fprintf('Try to separate %d and %d : %s\n',II(pointer),JJ(pointer),st{trysep+1});
+  if ~trysep
+    G(II(pointer),JJ(pointer))=1;
+    G(JJ(pointer),II(pointer))=1;
+    %fprintf('%d-%d\n',II(pointer),JJ(pointer));
+  end
+  % 8.
+  pointer=pointer-1;
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [G,U] = phaseIII(G1,data,node_sizes,alpha,s2,star)
+% [G] = phaseIII(G1,data,node_sizes,alpha,s2,star)
+%
+% data(i,m) is node i in case m.
+% if star~=0, use try_to_separate_B_star instead of try_to_separate_B (default star=1).
+% G is the non-oriented graph and G1 the oriented result.
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+% 0.
+if nargin < 2, disp('Not enough arguments');return; end
+if nargin < 3, node_sizes=max(data'); end
+if nargin < 4, alpha = 0.05; end
+if nargin < 5, star=1; end
+G=G1;
+N=length(G);
+% reachability_matrix of G
+M = expm(full(G)) - eye(length(G)); M = (M>0);
+
+% 9.
+fprintf('Thinning - separateA\n');
+
+% Edges are examined in the inverse order of their Chi2 (or MI) score
+s2(find(~G))=0;
+[tmp ordre]=sort(s2(:));
+ordre2=ordre(find(tmp>0));
+[I J]=ind2sub([N N],ordre2);
+ii=1:length(I);
+for i=ii,
+  %fprintf('%d-%d : ',I(i),J(i));
+  G(I(i),J(i))=0;
+  G(J(i),I(i))=0;
+  trysep = try_to_separate_A(G,I(i),J(i),data,alpha,node_sizes);
+
+  if ~trysep,
+    G(I(i),J(i))=1;
+    G(J(i),I(i))=1;
+    %fprintf(' keep\n');
+    %else
+    %fprintf('delete\n');
+  end
+end
+
+% 10.
+fprintf('Thinning - separateB'); if star; fprintf('star'); end; fprintf('\n');
+s2(find(~G))=0;
+[tmp ordre]=sort(s2(:));
+ordre2=ordre(find(tmp>0));
+[I J]=ind2sub([N N],ordre2);
+ii=1:length(I);
+for i=ii,
+  %fprintf('%d-%d : ',I(i),J(i));
+  G(I(i),J(i))=0; G(J(i),I(i))=0;
+  if star==0
+    trysep = try_to_separate_B(G,I(i),J(i),data,node_sizes,alpha);
+  else
+    trysep = try_to_separate_B_star(G,I(i),J(i),data,node_sizes,alpha);
+  end
+  if ~trysep,
+    G(I(i),J(i))=1; G(J(i),I(i))=1;
+    %fprintf(' keep\n');
+    %else
+    %fprintf('delete\n');
+  end
+end
+
+%11.
+fprintf('Thinning - orient_edges\n');
+U=G;
+G=orient_edges(U,data,node_sizes,alpha);
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [I, N1, N2] = try_to_separate_A(G,node1,node2,data,alpha,node_sizes)
+% [I, N1, N2] = try_to_separate_A(G,node1,node2,data,alpha,node_sizess)
+%
+% G is the current partially directed graph.
+% I is a boolean : I=1 <==> separated.
+% N1 : neighbors of node1 that are on an adjacency path between node1 and node2 (ditto for N2).
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+% 0.
+if node1==node2 | length(G)<2
+  disp('Error: Check your arguments in try_to_separate_A.');I=0; return
+end
+N=size(data,1);
+if nargin==4, alpha=0.05; node_sizes=max(data'); end
+if nargin==5, node_sizes=max(data'); end
+
+% 1.
+N1=find(G(node1,:)==1);N01=N1;
+GG1=G(setdiff(1:N,node1),setdiff(1:N,node1));
+node22=node2-(node2>node1);
+% reachability_matrix of GG1
+M = expm(full(GG1)) - eye(length(GG1)); M = (M>0);
+% N1 is the neighbors of node1 that are on the adjacency between node1 and node2
+for i=N1
+  j=i-(i>node1);
+  if M(j,node22)~=1, N01=setdiff(N01,i); N1=setdiff(N1,i); end
+  % 2.
+  if ~G(node1,i), N1=setdiff(N1,i); end
+end
+
+N2=find(G(node2,:)==1);N02=N2;
+GG2=G(setdiff(1:N,node2),setdiff(1:N,node2));
+node12=node1-(node2<node1);
+% reachability_matrix of GG2
+M = expm(full(GG2)) - eye(length(GG2)); M = (M>0);
+% N2 is the neighbors of node2 that are on the adjacency between node1 and node2
+for i=N2
+  j=i-(i>node2);
+  if M(node12,j)~=1, N02=setdiff(N02,i); N2=setdiff(N2,i); end
+  % 2.
+  if ~G(node2,i), N2=setdiff(N2,i); end
+end
+
+%fprintf('%d : N1=',node1); fprintf('%d',N1); fprintf('\n');
+%fprintf('%d : N2=',node2); fprintf('%d',N2); fprintf('\n');
+% 3.
+if length(N1)>length(N2), tmp=N1; N1=N2; N2=tmp; clear tmp, end
+% 4.
+C=N1;
+for test=1:2
+  if test==2, C=N2; end
+  % 5.
+  [I v1] = cond_indep_chisquare(node1,node2,C,data,'LRT',alpha,node_sizes);
+  if I, %fprintf('%d-%d separated (%2.5f) by C=',node1,node2,v1); fprintf('%d',C); fprintf('\n');
+    return,
+    %else
+    %fprintf('%d-%d not separated (%2.5f) by C=',node1,node2,v1); fprintf('%d',C); fprintf('\n');
+  end;
+
+
+  % 6.
+  step6=1;
+  while step6
+    step6=0;
+    if length(C)>=1
+      v=[];
+      for i=C
+	Ci = setdiff(C,i);
+	[I(i) v(i)] = cond_indep_chisquare(node1,node2,Ci,data,'LRT',alpha,node_sizes);
+      end
+      [vm ind] = min(v);
+
+      % 7.
+      if I(ind)
+	I = 1; return
+      else
+	if vm < v1
+	  v1 = vm;
+	  C = setdiff(C,ind);
+	  % goto step 6.
+	  step6 = 1;
+	end
+      end
+    end
+
+    % 8.
+    if test==2, I=0; return, end
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function I = try_to_separate_B(G,node1,node2,data,node_sizes,alpha,N1,N2)
+% I = try_to_separate_B(G,node1,node2,data,node_sizes,epsilon,N1,N2)
+%
+% G is the current partially directed graph.
+% data(i,m), node i in case m.
+% node_sizes is the vector of size of the attributs in data ( default max(data') )
+% N1 (optionnal) is the neighbors of node1 that are on an adjacency path between node1 and node2 (ditto for N2).
+% I is a boolean : I+1 <==> separated.
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+% 0.
+if node1==node2 | length(G)<2
+  disp('Error: Verify your arguments in try_to_separate_B.');I=0; return
+end
+if nargin < 4,
+  disp('Error : not enougth arguments'); I=0; return;
+end
+N=size(data,1);
+
+% 1.
+if nargin < 8
+  N1=find(G(node1,:)==1);
+  GG1=G(setdiff(1:N,node1),setdiff(1:N,node1));
+  node22=node2-(node2>node1);
+  M = expm(full(GG1)) - eye(length(GG1)); M = (M>0);
+  for i=N1
+    j=i-(i>node1);
+    if M(j,node22)~=1, N1=setdiff(N1,i); end
+  end
+  N2=find(G(node2,:)==1);
+  GG2=G(setdiff(1:N,node2),setdiff(1:N,node2));
+  node12=node1-(node2<node1);
+  M = expm(full(GG2)) - eye(length(GG2)); M = (M>0);
+  for i=N2
+    j=i-(i>node2);
+    if M(node12,j)~=1, N2=setdiff(N2,i); end
+  end
+end
+if nargin < 6, alpha=0.05; end
+if nargin < 5, node_sizes=max(data'); end
+M = expm(full(G)) - eye(length(G)); M = (M>0);
+
+% 2.
+N1b=[];
+for i=N1
+  NN1=find(G(i,:)==1);
+  for j=NN1
+    if M(i,j)~=1 & ~ismember(j,N1), N1b=union(N1b,j); end
+  end
+end
+
+% 3.
+N2b=[];
+for i=N2
+  NN2=find(G(i,:)==1);
+  for j=NN2
+    if M(i,j)~=1 & ~ismember(j,N2), N2b=union(N2b,j); end
+  end
+end
+
+% 4.
+if length(union(N1,N1b)) < length(union(N2,N2b))
+  C=union(N1,N1b);
+else
+  C=union(N2,N2b);
+end
+
+% 5.
+continu=1;
+while continu
+  l=length(C);
+  %fprintf('%d',continu);
+  [I v] = cond_indep_chisquare(node1,node2,C,data,'LRT',alpha,node_sizes);
+  if I==1; return, elseif l<2, I=0; return, end
+
+  % 6.
+  Cb=C;
+  for i=1:l
+    Ci=setdiff(C,C(i));
+    [I vi] = cond_indep_chisquare(node1,node2,Ci,data,'LRT',alpha,node_sizes);
+    e = (v+1)/3;    % e is a small value...
+	if I==1,return, elseif vi<v+e, Cb=setdiff(Cb,C(i)); end
+  end
+
+  % 7.
+  if length(Cb) < l, C=Cb; else continu==0; I=0; return; end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function I = try_to_separate_B_star(G,node1,node2,data,node_sizes,alpha,N1,N2)
+% I = try_to_separate_B_star(G,node1,node2,data,epsilon,node_sizess)
+%
+% G is the current partially directed graph.
+% I is a boolean.
+% N1 is the neighbors of node1 that are on an adjacency path between node1 and node2 (ditto for N2).
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+% 0.
+if node1==node2 | length(G)<2
+  disp('Error: Verify your arguments in try_to_separate_B_star.');I=0; return
+end
+if nargin < 4,
+  disp('Error : not enougth arguments');I=0; return;
+end
+N=size(data,1);
+
+% 1.
+if nargin < 8
+  N1=find(G(node1,:)==1);
+  GG1=G(setdiff(1:N,node1),setdiff(1:N,node1));
+  node22=node2-(node2>node1);
+  M = expm(full(GG1)) - eye(length(GG1)); M = (M>0);
+  for i=N1
+    j=i-(i>node1);
+    if M(j,node22)~=1, N1=setdiff(N1,i); end
+    % 2.
+    if ~G(node1,i), N1=setdiff(N1,i); end
+  end
+  N2=find(G(node2,:)==1);
+  GG2=G(setdiff(1:N,node2),setdiff(1:N,node2));
+  node12=node1-(node2<node1);
+  M = expm(full(GG2)) - eye(length(GG2)); M = (M>0);
+  for i=N2
+    j=i-(i>node2);
+    if M(node12,j)~=1, N2=setdiff(N2,i); end
+    % 2.
+    if ~G(node2,i), N2=setdiff(N2,i); end
+  end
+end
+if nargin < 6, alpha=0.05; end
+if nargin < 5, node_sizes=max(data'); end
+
+% 3.
+if length(N1)>length(N2), tmp=N1; N1=N2; N2=tmp; end
+
+% 4.
+C=N1;
+l=length(C);
+I=0;
+
+% 5.
+for test=1:2
+  continu=1;
+  %test
+  if test==2 & ~isempty(N2)
+    C=N2; l=length(C); IsInCi=zeros(1,l); IsInCi(l)=1;
+  else IsInCi=zeros(1,l);
+  end
+  s=ones(1,l);
+  % Pour tous les sous-ensemble Ci de C :
+  while continu & ~isempty(C)
+    Ci = setdiff(C.*IsInCi,0);
+    [I vi] = cond_indep_chisquare(node1,node2,Ci,data,'LRT',alpha,node_sizes);
+    if I, %fprintf('%d-%d separated (%2.5f) by C=',node1,node2,vi); fprintf('%d',Ci); fprintf('\n');
+      return,
+      %else
+      %fprintf('%d-%d not separated (%2.5f) by C=',node1,node2,vi); fprintf('%d',Ci); fprintf('\n');
+    end;
+    %    if I, return, end
+
+    if IsInCi==s, continu=0;
+    else
+      IsInCi(l)=IsInCi(l)+1;
+
+      notOK=1; i=l;
+      while notOK & i>1
+	if IsInCi(i)>s(i), IsInCi(i)=0; IsInCi(i-1)=IsInCi(i-1)+1; else notOK=0; end
+	i=i-1;
+      end
+    end
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function G1 = orient_edges(G,data,node_sizes,alpha)
+% G1 = orient_edges(G,data,node_sizes)
+%
+% G is the partially directed graph.
+% data(i,m), node i in case m.
+% node_sizes is the vector of size of the attributs in data ( default max(data') )
+%
+% see "Learning bayesian Networks from Data: A Efficient Approach Based on Information Theorie"
+%     Jie Cheng, David Bell and Weird Liu.
+
+% 0.
+if nargin < 4, alpha=0.05; end
+if nargin < 3, node_sizes=max(data'); end
+if nargin < 2, disp(' Require at least two arguments.'); return, end
+N=length(G);
+G1=G;
+
+% 1.
+[Lnode1 Lnode2]=find(triu(1-triu(G),1)); %[Lnode1 Lnode2]=ind2sub([N N],find(triu(1-triu(G),1)));
+for ii = 1:length(Lnode1),
+  node1=Lnode1(ii);
+  node2=Lnode2(ii);
+  %fprintf('%d %d\n',node1,node2);
+  N1 = find(G(node1,:)==1);
+  N2 = find(G(node2,:)==1);
+  if ~isempty(intersect(N1,N2))
+    %fprintf('V1='); fprintf('%d ',N1); fprintf('\n');
+    %fprintf('V2='); fprintf('%d ',N2); fprintf('\n');
+    GG1 = G(setdiff(1:N,node1),setdiff(1:N,node1));
+    node22 = node2-(node2>node1);
+    % reachability_matrix of GG1
+    M = expm(full(GG1)) - eye(length(GG1)); M = (M>0);
+    % N1 is the neighbors of node1 that are on the adjacency between node1 and node2
+    for i = N1
+      j = i-(i>node1);
+      if M(j,node22)~=1, N1=setdiff(N1,i);
+      end
+    end
+    GG2 = G(setdiff(1:N,node2),setdiff(1:N,node2));
+    node12 = node1-(node2<node1);
+    % reachability_matrix of GG2
+    M = expm(full(GG2)) - eye(length(GG2)); M = (M>0);
+    % N2 is the neighbors of node2 that are on the adjacency between node1 and node2
+    for i=N2
+      j = i-(i>node2);
+      if M(node12,j)~=1, N2=setdiff(N2,i); end
+    end
+    %fprintf('%d %d\n',node1,node2);
+    %fprintf('N1='); fprintf('%d ',N1); fprintf('\n');
+    %fprintf('N2='); fprintf('%d ',N2); fprintf('\n');
+
+    % 2.
+    M = expm(full(G)) - eye(length(G)); M = (M>0);
+    N1b=N1;
+    for i=N1
+      NN1 = find(G(i,:)==1);
+      for j=NN1
+	if M(i,j)~=1 & ~ismember(j,N1), N1b=union(N1b,j); end
+      end
+    end
+    %fprintf('N1''='); fprintf('%d ',N1b); fprintf('\n');
+
+    % 3.
+    N2b=N2;
+    for i=N2
+      NN2 = find(G(i,:)==1);
+      for j=NN2
+	if M(i,j)~=1 & ~ismember(j,N2), N2b=union(N2b,j); end
+      end
+    end
+    %fprintf('N2''='); fprintf('%d ',N2b); fprintf('\n');
+
+    % 4.
+    if length(N1b) < length(N2b)
+      C = N1b;
+    else
+      C = N2b;
+    end
+    %l=length(C);
+    %fprintf('C='); fprintf('%d ',C); fprintf('\n');
+
+    % 7.
+    step5=1;
+    while step5
+      step5=0;
+      %fprintf('.');
+      % 5.
+      l=length(C);
+      [I v] = cond_indep_chisquare(node1,node2,C,data,'LRT',alpha,node_sizes);
+      %fprintf('C='); fprintf('%d ',C);
+      %fprintf(': %d %2.5f\n',I,v);
+
+      step8=0;
+      if I==1 & v~=0 % v < epsilon
+	step8=1;
+      else
+	if  l==1
+	  G1(C,node1)=0; G1(C,node2)=0;
+	  fprintf('%d -> %d <- %d\n',node1,C,node2);
+	  step8=1;
+	end
+      end
+      %fprintf('%d\n',step8);
+
+      % 6.
+      if ~step8
+	Cb=C;
+	for i=1:l
+	  Ci=setdiff(C,C(i));
+	  [I vi] = cond_indep_chisquare(node1,node2,Ci,data,'LRT',alpha,node_sizes);
+	  % e = (v+1)/3;    % e is a small value...
+	  if I==1 % vi < v+e
+	    Cb=setdiff(Cb,C(i));
+	    if ismember(C(i),N1) & ismember(C(i),N2)
+	      G1(C(i),node1)=0; G1(C(i),node2)=0;
+	      fprintf('%d -> %d <- %d\n',node1,C(i),node2);
+	    end
+	    if I==1 % vi < epsilon
+	      step8=1;
+	    end
+	  end
+	end % for
+      end % if
+
+      % 7.
+      if ~step8
+	if length(Cb) < length(C), C=Cb; end
+	if length(C) > 0, step5==1; end
+      end
+    end % while step5
+    % step8 : passer � la paire de noeud suivant
+    %fprintf('\n');
+    %else
+    %fprintf(' No common neighbor\n');
+  end % if
+end % for
+
+% 11.
+step9=0;
+fprintf('Infering directions ');
+test = pdag_to_dag(G1);
+while ~isdag(test) %& step9<N
+  step9=step9+1;
+  %if ~isempty(test)
+    %fprintf('.');
+    % 9.
+    for a=1:N, for b=1:N, for c=1:N,
+	  if a~=b & b~=c & c~=a
+	    if G1(a,b)==1 & G1(b,a)==0
+	      %fprintf('%d -> %d ... \n',a,b);
+	      if G1(b,c)==1 & G1(c,b)==1
+		if G1(a,c)+G1(c,a)==0,
+		  G1(c,b)=0;
+		  fprintf('%d -> %d (9)\n',b,c);
+		end
+	      end
+	    end
+	  end
+    end, end, end
+
+    % 10.
+    for a=1:N-1, for b=a+1:N
+	if G1(a,b)==1 & G1(b,a)==1
+	  GGG1=xor(G1,G1'); % matrice des arcs orient�s de G1
+	  M = expm(full(GGG1)) - eye(length(GGG1)); M = (M>0);
+	  if M(a,b)==1,
+	    G1(b,a)=0;
+	    fprintf('%d -> %d (10)\n',a,b);
+	  end
+	end
+    end, end
+
+      test = pdag_to_dag(G1);
+      if isempty(test), G1=return_one_edge(G1); end
+  %else
+  %  G1, return,
+  %end
+end % while 11.
+G1 = pdag_to_dag(G1);
+fprintf('%d boucles\n',step9);
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function b = isdag(G)
+b = sum(sum(G.*G'));        % How many undirected arcs ? (x2)
+b=~b & ~isempty(G);
+if b
+  M = expm(full(G)) - eye(length(G)); M = (M>0);
+  b = b & find(sum(sum(eye(length(G)).*M))); % is there no cycle ?
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function G=return_one_edge(G)
+N=length(G); fam=[]; node2=[];
+permnode = randperm(5); i=0; %fprintf('rev\n');
+while isempty(fam) | isempty(node2) | i==N
+ i=i+1;
+ node = permnode(i); %node = ceil(rand(1)*N);
+ fam=find(G(node,:)==1);
+ par=find(G(:,node)==1);
+ fam = myunion(fam, par);
+ if ~isempty(fam)
+  node2 = fam(ceil(rand(1)*length(fam)));
+  par2=find(G(:,node)==1);
+  if ~isempty(intersect(par2, node)), node2=[]; end
+ end
+end
+if isempty(myintersect(node, par2)),
+ G(node, node2)=0;
+ G(node2, node)=1;
+ fprintf('%d -> %d (Rev)\n',node, node2);
+else
+ G(node, node2)=1;
+ G(node2, node)=0;
+ fprintf('%d -> %d (Rev)\n',node2, node);
+end