www.pudn.com > ConstrainedEM.zip > paintedPath.m


function [path,cutArcs] = paintedPath(E,paint,fromNode,toNode,silent) 
 
% Painted path algorithm, with graphics 
% 
% Enter with E = node-arc incidence matrix, 
%            paint = vector of colours 'r' 'g' 'w' 'b' (default all 'g') 
%            fromNode = origin (default 1) 
%            toNode   = destination (default 0) 
%            silent   = 1 to turn off graphics (default 0) 
% and the algorithm paints the network according to the direction 
% vector, then either finds a path from origin to destination, 
% or finds a cut separating origin from destination. 
% 
% If a path is found, it is returned as a list of arc indices, 
% with negative indices corresponding to arcs traversed in the reverse 
% direction, and the cut is set to empty. 
% 
% If a cut is found, the path is set to empty and the set of nodes on 
% the origin side of the cut is returned, along with the arcs crossing 
% the cut (negative for reverse arcs). 
% 
% If toNode is not a node of the network, both path and cut are returned 
% empty and cutArcs contains a tree spanning all nodes reachable from fromNode. 
% 
% 
% Note that this is not an efficient implementation: I have used the 
% node-arc incidence matrix to maintain similarity with lectures. 
 
% For use in course Mathematics 2A1. 
% 
% Copyright (c) March 1997, Alistair Mees, University of Western Australia.  
% 
% This program may be freely used for education but may not be 
% sold or used for commercial purposes without my express written 
% permission. 
% 
% email: Alistair.Mees@uwa.edu.au 
 
 
 
% Set up the output arguments: 
if nargout>=2 
  cutArcs = []; 
end 
path = []; 
 
 
% Set up the input arguments: 
if nargin<5 
  silent = 0; 
end 
if nargin<4 
  toNode = 0; 
end 
if nargin<3 
  fromNode = 1; 
end 
if nargin<2 
  paint = []; 
end 
 
% Make sure the input args make sense, and if necessary paint the network: 
[nNodes,nArcs,paint] = ppSanityCheck(E,paint,fromNode,toNode); 
 
if ~silent 
  % Display the network: 
  [arcHandles,nodeHandles,nodePosns] = showNetwork(E,paint); 
  set(nodeHandles,'facecolor',[0.4 0.4 0.4]); 
end 
 
 
% Painted path algorithm: 
labelled = fromNode; 
scanned = []; 
arcUsed = zeros(1,nNodes); 
 
while ~isempty(labelled)  &  ~any(toNode==labelled) 
 
  % Scan first labelled node: 
  n = labelled(1); 
   
  % Find arcs incident on node n: 
  outArcs = find(E(n,:)==1); 
  inArcs = find(E(n,:)==-1); 
  % Keep only those that satisfy the painting: 
  if ~isempty(outArcs) 
    outArcs = outArcs(find(paint(outArcs)=='g' | paint(outArcs)=='w')); 
  end 
  if ~isempty(inArcs) 
    inArcs  = inArcs(find(paint(inArcs)=='g' | paint(inArcs)=='b')); 
  end 
   
  % Look at nodes at other ends of arcs; if not labelled or scanned, label them: 
  for a = outArcs 
    destNode = find(E(:,a)==-1); 
	if ~any(ismember(destNode,labelled)) & ~any(ismember(destNode,scanned)) 
	  labelled = [labelled,destNode]; 
	  arcUsed(destNode) = a; 
	  if ~silent 
	    % Display arc as used: 
	    set(arcHandles(a),'linewidth',4); 
        % Display node as labelled: 
        set(nodeHandles(destNode),'facecolor','c');  
	  end 
	  if destNode==toNode 
	    break; 
	  end 
	end 
  end 
  for a = inArcs 
    srcNode = find(E(:,a)==1); 
	if ~any(ismember(srcNode,labelled)) & ~any(ismember(srcNode,scanned)) 
	  labelled = [labelled,srcNode]; 
	  arcUsed(srcNode) = -a;   % negative sign flags reverse arc 
	  if ~silent 
	    % Display arc as used: 
	    set(arcHandles(a),'linewidth',4); 
        % Display node as labelled: 
        set(nodeHandles(srcNode),'facecolor','c'); 
	  end 
	  if srcNode==toNode 
	    break; 
	  end 
	end 
  end 
   
  % Shift node n from labelled set to scanned set: 
  labelled(1) = []; 
  scanned = [scanned,n]; 
   
  if ~silent 
    % Paint node n as scanned: 
    set(nodeHandles(n),'facecolor','m'); 
    drawnow 
  end 
 
end 
 
% On exit either we have a path or a cut: 
if ~isempty(labelled)  &  any(toNode==labelled) 
 
  % Find the path by walking back from the toNode: 
  path = []; 
  n = toNode; 
  while n ~= fromNode 
    path = [arcUsed(n), path]; 
	if arcUsed(n)>0 
	  m = find( E(:,abs(arcUsed(n)))==1 ); 
	else 
	  m = find( E(:,abs(arcUsed(n)))==-1 ); 
	end 
	if isempty(m) 
	  error 'Can''t find the node I came here from!' 
	elseif m==0 
	  error 'Bad arc in reverse path' 
	elseif m==n 
	  error 'Program error: failed to find other end of path' 
	end 
	n = m; 
	   
  end 
 
  if ~silent 
    set(arcHandles,'linewidth',0.5); 
    set(arcHandles(abs(path)),'linewidth',4); 
    title 'Arcs emphasized form a path' 
  end 
 
elseif toNode<1  |  toNode>nNodes 
 
  % This case deals with e.g. setting nNodes to zero to get a spanning tree. 
  % We return empty path and cut, and set cutArcs to a spanning tree. 
  cut = []; 
  path = []; 
  % Just see which arcs we've used. 
  cutArcs = arcUsed(find(arcUsed~=0)); 
  if ~silent 
    title 'Arcs emphasized form a tree' 
  end 
   
else 
 
  % Return the set of labelled and/or scanned nodes: 
  cut = [scanned, labelled]; 
  if ~silent 
    % Identify the cut arcs and make them dotted and thick: 
    set(arcHandles,'linewidth',0.5); 
  end 
 
  % Now find the cut arcs: they are the ones that go from the source nodes 
  % of the cut (those in set "cut") to the others, so they are the columns 
  % of E for which there is a single +1 or -1 in the rows belonging to the 
  % source nodes. 
  if length(cut)>1 
    outArcs = find( sum(E(cut,:)) == 1  ); 
    inArcs  = find( sum(E(cut,:)) == -1 ); 
  else 
    outArcs = find( E(cut,:) ==  1 ); 
    inArcs  = find( E(cut,:) == -1 ); 
  end 
  cutArcs = [outArcs, -inArcs]; 
 
  if ~silent 
    set(arcHandles([outArcs inArcs]),'linewidth',4);  
    title 'Arcs emphasized cross the cut' 
  end 
   
end