適合有向閉環圖的K-Shortest-Path


https://blog.csdn.net/cysisu/article/details/83411409

以上鍊接的代碼實現的是基於有向圖實現得到k條最短路徑的算法,k條最短路徑的算法是在上交大那篇論文中看到的思想,於是在網上找到了這個實現的代碼,但是在利用此代碼接入自己的地圖時規劃出來的路徑有些是不對的,根本不通的,原因就是我們自己的地圖是存在閉環的,而上述鏈接中的地圖是不存在閉環的。於是就對其進行了相應的修改:
K-Shortest-Path算法的思想:
https://www.cnblogs.com/qq952693358/p/7354070.html
改寫這個代碼的過程就是:將其寫成了一個類,在自己的架構中去調用。將他的代碼中的函數寫成類中的共有成員函數,在自己的架構中去調用接口傳參就可以了。



一.首先講一下如何對算法進行的修改
主要做了以下幾方面的修改:
(1)在規劃出一條最短路徑後會基於此最短路徑做迭代,迭代的過程中會將逐個將最短路徑中的邊設置爲無窮大,然後去更新地圖,此鏈接中給出的代碼是(修改前的代碼):

vector<vector<float> > K_Shortest_Path::cutEdge(const vector<vector<float> > &NW, vector<DijPath> kSPCost, unsigned int root)
{
   
   
    vector<vector<float>>NWCopy = NW;
    for (unsigned int i = 0; i < kSPCost.size(); i++)
    {
   
   
        //此for循環只是爲了尋找和root相同的點
        for (unsigned int j = 0; j < kSPCost[i].onePath.size(); j++)
        {
   
   
            if (kSPCost[i].onePath[j] == root)
            {
   
   
                unsigned int nextVertex = kSPCost[i].onePath[j + 1];
                //1.此處是做出修改的第一步
               if (j >= 1)           
                 {
   
                     
                unsigned int beforeVertex = kSPCost[i].onePath[j - 1];
                  NWCopy[root][beforeVertex] = INF;
               }
                NWCopy[root][nextVertex] = INF;  //設置爲不可連接
                break;
            }
        }
    }

    return NWCopy;
}

修改後的代碼:也就是屏蔽掉了if的判斷條件。

vector<vector<float> > K_Shortest_Path::cutEdge(const vector<vector<float> > &NW, vector<DijPath> kSPCost, unsigned int root)
{
   
   
    vector<vector<float>>NWCopy = NW;
    for (unsigned int i = 0; i < kSPCost.size(); i++)
    {
   
   
        //此for循環只是爲了尋找和root相同的點
        for (unsigned int j = 0; j < kSPCost[i].onePath.size(); j++)
        {
   
   
            if (kSPCost[i].onePath[j] == root)
            {
   
   
                unsigned int nextVertex = kSPCost[i].onePath[j + 1];
                //1.此處是做出修改的第一步
//                if (j >= 1)
//                {
   
   
//                    unsigned int beforeVertex = kSPCost[i].onePath[j - 1];
//                    NWCopy[root][beforeVertex] = INF;
//                }
                NWCopy[root][nextVertex] = INF;  //設置爲不可連接
                break;
            }
        }
    }

    return NWCopy;
}

(2)第二處做出的修改:在run()函數中,在基於第一條最短路徑迭代規劃接下來的最短路徑的時候,if的判斷條件進行了修改如下:

//前面的那個節點到終點的一條最短路徑
DijPath secondPath = dij.dijkstra(NWCopy, kSPCost[k - 1].onePath[i], dst);
 if (secondPath.cost > 100000 || secondPath.cost ==0 )//判斷兩點不可以到達
            {
   
   
                continue;
            }

之前是:

  DijPath secondPath = dij.dijkstra(NWCopy, kSPCost[k - 1].onePath[i], dst);
 if (secondPath.cost > 100000)//判斷兩點不可以到達
            {
   
   
                continue;
            }

cost變量之前是int類型的,在打印secondPath.cost這個值的時候發現有負無窮大的值也有0,所以將cost變量變成unsigned int 類型,這樣就不會出現負無窮大了,另外再將判斷條件加上一個==0,這樣就可以解決了。
以後再換別的地圖去用的時候,這個判斷條件可以根據secondPath.cost的只去修改。
二.其次講一下在這個將此鏈接中的代碼用在自己的框架中時遇到的問題:
(1)系統總是出現崩潰死掉的情況,原因是定義對象指針的時候沒有進行實例化;



vector<vector<unsigned int>> TaskManagerAGV::show_ksp(int startpoint, int endpoint)
{
   
   
//    qDebug()<<"entre the show_ksp";
    vector<vector<unsigned int>>pathlist,pathlistShow;

    QVector<QStringList> shortPathMatrix = getshortpathmatrix();
    pathlist = k_short_path->searchPath(startpoint, endpoint, shortPathMatrix, pathNodeMap, NodeHotValue);
    return pathlist;
}

k_short_path在類中的定義如下:

K_Shortest_Path *k_short_path;

只是做了如上定義,沒有進行實例化:

k_short_path = new K_Shortest_Path();

在類 K_Shortest_Path中的構造函數中加上此實例化的代碼,系統每次運行的時候就不會崩潰了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章