使用每个节点恰好一次从源节点到结束节点的路由算法

时间:2015-11-13 23:04:00

标签: graph routes traveling-salesman floyd-warshall

我尝试创建一个路径,给定一个起始节点和终端节点,它将传递到图中的每个节点,并最大限度地降低这样做的成本。

图表是无向的,并且每个节点都直接相互连接。每条边的重量都是正的。我认为因为每个节点都相互连接,所以有很多"循环"在我的图表中,但我不想生成一个带有循环的路线。

因此,对于具有N个节点的图,我有(N * N-1)个有向边。具有节点A,B,C,D的图形将具有边缘:

  • A到B / B到A
  • A到C / C到A
  • A到D / D到A
  • B至C / C至B
  • C至D / D至C
  • B到D / D到B

当我从维基百科实施Floyd Warshall算法时,我只得到一个包含2个节点的数组。本文中的一个函数为您提供从节点U到节点V的最短路径,并且该函数仅返回[U,V](包含U和V的数组)

我必须误解Floyd Warshall究竟要解决的问题。我将附上我的代码,以显示我是如何在javascript中实现它的。

    function colorsToEdgeMatrix(colors){
        var dist = [];
        for(var i = 0; i < colors.length;i++){
        dist[i] = [];
        var c1 = colors[i];
        for(var j = 0; j < colors.length;j++){
           if(i == j){continue;}
        var c2 = colors[j];
        dist[i][j] = colorDistance(c1,c2);
        }
    }
    return dist;
}
    function colorsToNextMatrix(colors){
        var next = [];
        for(var i = 0; i < colors.length;i++){
            next[i] = [];
            for(var j = 0; j < colors.length;j++){
                if(i == j){continue;}
                next[i][j] = j;
            }
        }
        return next;
    }
    //lab colors
    function FloydWarshallWithPathReconstruction (colors){
       var next = [];
       var dist = colorsToEdgeMatrix(colors);
       var next = colorsToNextMatrix(colors);
       var N = colors.length;
        for(var k = 0; k < N; k++){ // standard Floyd-Warshall implementation
            for(var i = 0; i < N; i++){
                for(var j = 0; j < N; j++){
                    if(dist[i][k] + dist[k][j] < dist[i][j]){
                       dist[i][j] = dist[i][k] + dist[k][j]
                       next[i][j] = next[i][k]
                    }
                }
            }
       }
       return next;
    }

    function Path(next,u, v) {
       var path = [];
       if(next[u][v] == null){
           return []
       }
       path = [u]
       while(u != v){
           u = next[u][v]
           path.push(u)
       }
       return path;
    }


    var lab = randomLABArray(100); //make an array of LAB color space colors. a LAB element has an array structure [L,a,b]
    lab = sortLuminosityLAB(lab); //sorts the LAB colors from light to dark
    var next = FloydWarshallWithPathReconstruction(lab); //gets all paths using floyd warshall
    var path = Path(next, 0, lab.length-1); //gets the path calculated from lightest to darkest
    console.log( path );

此算法是否不一定会返回通过每个节点的路径?我猜它的作用是为每个开始和结束节点吐出最佳路径,并且不保证任何路径都通过每个节点...

我使用最近邻算法得到了不错的结果,并且在10个元素之后不可能使用Brute Force。我希望Floyd Warshall会给出更好的结果

嗯......所以这实际上可能是汉密尔顿路径问题,并不像我想的那么简单......

1 个答案:

答案 0 :(得分:0)

这可以简化为旅行商问题,如下所示。选择一个大数M,它大于图表中所有权重的总和。将此数字添加到图形中所有边的权重,但连接起始节点和结束节点的边缘除外。该边缘的成本应设为零。解决由此产生的旅行商问题。很容易看出TSP的最佳解决方案将包括连接起始节点和结束节点的边缘。将该边缘从最佳解决方案中移开并将权重调整回其原始值 - 您已找到解决问题的最佳方案。

相反,常规TSP可以更简单的方式减少您的问题。随机选择一个节点并复制它。让其中一个新复制的节点成为起始节点,另一个节点作为终端节点。解决此实例的最佳路径问题。然后 - 将这两个节点重新合并到原始节点中,原始节点将两端拼接在一起形成一个电路,这很容易被看作是最佳的。这证实了你的直觉,即问题至少与汉密尔顿电路问题一样困难。