使用Matlab Brute Force Search查找图表中的所有可能路径

时间:2015-03-03 05:22:08

标签: matlab graph brute-force search-path

我需要找到带图表的所有路径,并保存这些路径。我的起始节点是A,B或C,最后一个节点是G.我的图形最多有16个未加权的顶点。

我在下面制作了Matlab代码,但是 bifurcations 存在问题。另外,我不知道如何强加起始节点和最终节点。谁能帮我这个?

path       = cell(1,10) ;  % initialize
% one_graph  ={'AH','BO','CN','EG','EN','EO','HO','KN'} % (Graph example)
one_graph  ={'AH','BN','DH','DN','GN'} % (Graph example)

for p = 1:length(one_graph)

edge  = one_graph(p);
% In each graph there is only 1:1 conections
% detect node 1
existing_node1 = edge{1}(1) ;
Index_existing_node1 = strfind(allnodes, existing_node1) ;
[row1,col1] = find(ismember(allnodes, existing_node1));
 % detect node 2
existing_node2 = edge{1}(2) ;
Index_existing_node2 = strfind(allnodes, existing_node2);
[row2,col2] = find(ismember(allnodes, existing_node2));

path_nonz = path(~cellfun('isempty',path))   ;
t         = length(path_nonz)                ;
if t>0  % save the first 2 nodes in the path
ttt = strcmp(allnodes(row1), path{t});
ttt2 = strcmp(allnodes(row2), path{t});       
end;
if t==0
    path{t+1} = allnodes{row1}  ; 
    path{t+2} = allnodes{row2}  ;
elseif ttt == 1
    % disp('connect right')
    path{t+1} = allnodes{row2}  ;
elseif ttt2 == 1
    % disp('connect right')
    path{t+1} = allnodes{row1}  ;
else 
    disp('Not next vertex') 
end
end

例如,

one_graph  ={'AH','BN','DH','DN','GN'} % (Graph example)

我应该保存以下路径:

path1 = A HDN G

path2 = B N G

one_graph  ={'AH','BO','CN','EG','EN','EO','HO','KN'} % (Graph example)

我应该保存以下路径:

path1 = A HOE G

path2 = B OE G

path3 = C NE G

更新1:

来自邻接矩阵B(:,:,1)

B =

 0     0     0     0     0     0     0     1     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     1     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     1     0     0     0     0     0     1     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     1     0     0
 1     0     0     1     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     1     0     1     0     0     1     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0

我推导出适当的邻接列表:

Asparse = sparse(B(:,:,1));
Asparse =

 (8,1)        1
(14,2)        1
 (8,4)        1
(14,4)        1
(14,7)        1
 (1,8)        1
 (4,8)        1
 (2,14)       1
 (4,14)       1
 (7,14)       1

然后,我尝试使用Matlab Website

上的BFS算法
 [distances,times,pred] = bfs(Asparse,1);

但是,这并不能保存路径。它只保存每个当前节点的前一个节点(在pred中)以及从初始节点到每个节点的距离(在distances中)。任何想法,如何保存每条路径?

1 个答案:

答案 0 :(得分:1)

我必须编写一个自定义函数来执行此操作,因为1)大多数BFS / DFS函数在达到目标时停止,2)它们明确地忽略循环,这是到同一目标的多个路径所需的。

我相信这会得到你所需要的。我已对您的示例中的邻接矩阵稍作修改,以便从{2,7}{7,2}创建边缘,以便从2到{{1}有两条路径}。请注意,这是一个递归函数,因此,如果您获得大约500个节点,那么您将遇到问题,我们将不得不提出使用显式堆栈的版本。

14

如果你这样调用这个函数:

function paths = findpaths(Adj, nodes, currentPath, start, target)
   paths = {};
   nodes(start) = 0;
   currentPath = [currentPath start];
   childAdj = Adj(start,:) & nodes;
   childList = find(childAdj);
   childCount = numel(childList);
   if childCount == 0 || start == target
      if start == target
         paths = [paths; currentPath];
      end
      return;
   end
   for idx = 1:childCount
      currentNode = childList(idx);
      newNodes = nodes;
      newNodes(currentNode) = 0;
      newPaths = findpaths(Adj, newNodes, currentPath, currentNode, target);
      paths = [paths; newPaths];
   end
end

输出应为:

A =[
 0  0  0  0  0  0  0  1  0  0  0  0  0  0; 
 0  0  0  0  0  0  1  0  0  0  0  0  0  1; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  1  0  0  0  0  0  1; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  1  0  0  0  0  0  0  0  0  0  0  0  1; 
 1  0  0  1  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  0  0  0  0  0  0  0  0  0  0  0  0  0; 
 0  1  0  1  0  0  1  0  0  0  0  0  0  0];

unusedNodes=ones(1,size(A,1));
start=2;
target=14;
emptyPath=[];

allPaths = findpaths(A, unusedNodes, emptyPath, start, target)

当然,您需要为每个起始节点调用此方法。


实际上,您不必多次拨打此电话。我忘了告诉你还有一个提示。如果您的图表具有allPaths = { [1,1] = 2 7 14 [2,1] = 2 14 } 个节点,并且您引入了一个仅包含候选起始节点边缘的新节点n,则可以使用新节点作为开始调用该函数一次。

因此,如果我将节点n+1添加到上面的图中,边缘为:

15

并使用{15,1}, {15,2} %// I wouldn't bother with {1,15} and {2,15}, they're totally unnecessary 调用该函数,这是我得到的:

start = 15

您现在拥有一个调用的所有路径,但您需要从每个路径的头部删除新节点allPaths = { [1,1] = 15 1 8 4 14 [2,1] = 15 2 7 14 [3,1] = 15 2 14 }

相关问题