通过一组连接的节点/流程图查找所有非重复路径

时间:2011-09-02 10:52:08

标签: algorithm statistics graph-algorithm data-analysis

我试图通过给定的流程图来理解是否可以以任何合理的方式建立一组非重复路径。

以下是我所拥有的流程图的一些基本事实:

  • 他们有一个或多个起点
  • 他们有一个或多个终点
  • 所有起点都有一个从它们引出的连接器
  • 所有步骤至少有一个或多个入站连接器以及一个或多个出站连接器 连接器
  • 如果每个必须有多个以下 命名为:
    • 启动终结者
    • 终结者
    • 从步骤
    • 引出的连接

我可以访问我能想象的所有数据(查找所有起点,获取所有连接,连接名称等)。

我基本上希望在从开始点到结束点的过程中找到尽可能多的唯一路径,在这些过程中,您不会反复循环。所以你可以多次完成相同的步骤,但是你不能在任何给定的路线中多次重复完整的电路。

这似乎是人们会写论文的类型,并且证明了为什么它可以或不可以完成,我只是不知道我需要谷歌的神奇话语;-) Sudo代码或类似的将是理想的(并且令人惊讶)但如果有人能指出我正确的方向,我很乐意自己阅读。

任何搜索条款的建议都非常欢迎并且非常欣赏

注意我会感兴趣的解决方案会提出许多额外的“愚蠢”可能性,之后必须由人进行审核 - 看看它产生了什么仍然很有趣。

澄清事情的一个例子:

        G<--2-E<--1-F-2--|
        |     |     ^    |
        |     1     |    |
        |     |     2    |
        \/   \/     |   \/
start--->A--->B---->C-1->D---end

一些路线:

  • 开始,A,B,C:1,d,端
  • 开始,A,B,C:2,F:1,E:1,B,C:1,d,端
  • 开始,A,B,C:2,F:1,E:2,G,A,B,C:1,d,端
  • 开始,A,B,C:2,F:2,d,端

很好,但更有趣的是:

  • 开始,A,B,C:2,F:1,E:2,G,A,B,C:2,F 1,B,C:2,F:2,d,端

我点击C三次,每次选择选项二,都没有重复。

额外点:我认为我可以将一些具有多个出站连接器的节点标记为在任何给定的进程执行中保持一致。如果有一个“写代码”进程,它有一个带有两个出站连接器“c#”和“java”的决策点“语言”,我可以说在这个进程的任何给定执行中它将始终是c#或java - 在执行过程中永远不会改变。而不是可能会发生变化的事情,比如“有没有错误?”在第一次通过时可能有一个是,然后在第二次通过(在一些修复错误步骤之后;-)可能有结果否。

您是否知道与此类额外分析/处理/定义相关的任何术语或技术?

编辑:我在JS中添加了一个示例解决方案作为基于@Ishtar答案的答案。

3 个答案:

答案 0 :(得分:2)

深度优先搜索怎么样?这将遍历所有可能的路径。唯一困难的部分是忽略可能再次导致相同周期的路径。如果你在一个节点,你检查你是否曾经在那里(一个周期),并确保相同的顺序不在路径中。

例如

start,A,B,C:2,F:1,E:1,B,C:2,F:1,E:1,B

从这里开始,我们只能转到C.回顾(最后4个节点),我们找到周期C:2,F:1,E:1,B。循环已经存在,所以我们不能去节点c。由于我们不能去其他地方,这个分支没有给出正确的路径。

伪代码:

allpaths(path,node)
  cycle = path.substring(path.lastIndex(node)) + node
  if path.contains(cycle)
    return
  path = path + node
  if node.isEndNode
    print path
    return
  for child in node.children
    allpaths(path, child)

答案 1 :(得分:1)

这是相关的吗? finding all the elementary circuits of a directed graph。即使它不是您使用的算法,它也可能有助于使用适当的定义和名称。

答案 2 :(得分:0)

@Ishtars解决方案网页中的一个完整示例,该图是问题中的一个...它似乎工作,没有经过广泛测试。它比我期望的解决方案简单得多; - )

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">

        function connection(name, endPoint) {
            this.name = name;
            this.endPoint = endPoint;
        }

        function node(name) {
            this.name = name;
            this.connections = [];

            this.addConnection = function (conn) {
                this.connections[this.connections.length] = conn;
            }
        }


        function printPath(path) {
            document.getElementById('output').innerHTML = 
              document.getElementById('output').innerHTML
              + path + '<br />';
        }

        function allPaths(path, node) {
            if (node.name == "end") {
                printPath(path + ',' + node.name);
                return;
            }
            cycle = path.substring(path.lastIndexOf(node.name)) + ',' + node.name;
            if (cycle.length > 1 && path.indexOf(cycle) > 0) {
                return;
            }
            for (var i = 0; i < node.connections.length; i++) {
               allPaths(path + ',' + node.name + ":" + 
                   node.connections[i].name
                   ,node.connections[i].endPoint);
            }
       }

        var start = new node("start");
        var a = new node("A");
        var b = new node("B");
        var c = new node("C");
        var d = new node("D");
        var e = new node("E");
        var f = new node("F");
        var g = new node("G");
        var end = new node("end");

        start.addConnection(new connection("1", a));
        a.addConnection(new connection("1", b));
        b.addConnection(new connection("1", c));
        c.addConnection(new connection("1", d));
        c.addConnection(new connection("2", f));
        d.addConnection(new connection("1", end));
        f.addConnection(new connection("1", e));
        f.addConnection(new connection("2", d));
        e.addConnection(new connection("1", b));
        e.addConnection(new connection("2", g));
        g.addConnection(new connection("1", a));

    </script>
</head>
<body onload="javascript:allPaths('start', a)";>
    <div id="output"></div>
</body>
</html>

这是输出(以防任何人发现错误; - ):

start,A:1,B:1,C:1,D:1,end
start,A:1,B:1,C:2,F:1,E:1,B:1,C:1,D:1,end
start,A:1,B:1,C:2,F:1,E:1,B:1,C:2,F:1,E:2,G:1,A:1,B:1,C:1,D:1,end
start,A:1,B:1,C:2,F:1,E:1,B:1,C:2,F:1,E:2,G:1,A:1,B:1,C:2,F:2,D:1,end
start,A:1,B:1,C:2,F:1,E:1,B:1,C:2,F:2,D:1,end
start,A:1,B:1,C:2,F:1,E:2,G:1,A:1,B:1,C:1,D:1,end
start,A:1,B:1,C:2,F:1,E:2,G:1,A:1,B:1,C:2,F:1,E:1,B:1,C:1,D:1,end
start,A:1,B:1,C:2,F:1,E:2,G:1,A:1,B:1,C:2,F:1,E:1,B:1,C:2,F:2,D:1,end
start,A:1,B:1,C:2,F:1,E:2,G:1,A:1,B:1,C:2,F:2,D:1,end
start,A:1,B:1,C:2,F:2,D:1,end

猜猜我在写这篇文章的时候并不知道jsFiddle,这里面是上面代码的小提琴:

http://jsfiddle.net/6bWMp/1/