首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从线性规划解中检索顶点路径

从线性规划解中检索顶点路径
EN

Stack Overflow用户
提问于 2013-06-26 11:09:13
回答 1查看 403关注 0票数 1

我一直在尝试解决一个路由问题,就像TSP (旅行推销员问题),但有一些曲折。我已经使用线性规划(CPlex library)和有向图(具有原点顶点) (Coin-Or::Lemon library)对问题进行了建模。

线性程序找到了解决方案,但我的问题在于如何检索路径。我可以迭代图的每个顶点和边,以找出线性程序使用的是哪个,所以我认为我应该从Origin开始,并使用选择的边来到达下一个节点,直到我再次到达Origin。

问题是CPlex路径可能会多次遍历任何顶点。所以我决定使用递归算法。但我不太明白。这是我尝试过的:

代码语言:javascript
复制
FindPath ( node N, path P)
    AddedAnyPath <- false
    for each edge E out of N that hasn't been used yet
        T is the target of E
        add T to P

        if findPath ( E, P )
            AddedAnyPath = true
    end for each
    
    if AddedAnyPath 
        if all edges were used
            return true
        else
            return false
        end if
    endif
end

此算法找不到路径。如果您能给我指个方向,我将不胜感激。

编辑

提供的答案帮助我找到了答案。下面是C++中的代码

代码语言:javascript
复制
bool findPath2 ( Store_Instance &T, DiNode &current, list <DiNode> &path, ListDigraph::ArcMap<bool> &usedArcs, IloCplex &cplex, ListDigraph::ArcMap<IloNumVar> &x) {
DiNode currentNode = current;
bool success = false;
int positionToInsert = 1;
while (true) {
    //Find an unvisited edge E whose value is 1.
    Arc unvisitedArc = INVALID;
    for(Digraph::OutArcIt a(T.g, currentNode); a != INVALID; ++a) {
        if(cplex.getValue(x[a]) >= 1-EPS && !usedArcs[a]) {
            unvisitedArc = a;
            break;
        }
    }
    if (unvisitedArc != INVALID) {
        //Mark edge as visited
        usedArcs[unvisitedArc] = true;
        //Get the target T of the edge
        DiNode target = T.g.target(unvisitedArc);
        //Add Edge E to the path
        list<DiNode>::iterator iterator = path.begin();
        advance(iterator, positionToInsert);
        path.insert(iterator, target);
        //Increase the iterator
        positionToInsert++;
        //If all the edges whose value is 1 are visited, stop
        bool usedAllEdges = true;
        for (ArcIt a(T.g); a != INVALID; ++a){
            if (cplex.getValue(x[a]) > 1-EPS && usedArcs[a] == false) {
                usedAllEdges = false;
                break;
            }
        }
        if (usedAllEdges) {
            success = true;
            break;
        }
        //Else, Set N to be T and repeat
        else currentNode = target;
    } else {
        //No arcs were found. Find a node from the path that has unvisited Arc
        positionToInsert = 0;
        DiNode target = INVALID;
        for (list<DiNode>::const_iterator iterator = path.begin(), end = path.end(); iterator != end; ++iterator) {
            DiNode v = *iterator;
            for(Digraph::OutArcIt a(T.g, v); a != INVALID; ++a) {
                if(cplex.getValue(x[a]) >= 1-EPS && !usedArcs[a]) {
                    target = v;
                    break;
                }
            }
            positionToInsert ++;
            if (target != INVALID) break;
        }

        if (target != INVALID) {
            //cout << "found lost node" << endl;
            currentNode = target;
        } else {
            success = false;
            break;
        }
    }
}
return success;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-27 03:38:06

TSP (路径)的解决方案是一个有序的顶点列表,这些顶点在原点开始和结束,访问每个顶点。有两种可能的情况。

如果你允许一个顶点被访问两次,那么在你的变体中,你就是在允许“子游览”。(案例2)

您将拥有变量X_nt,它将是1。(连接节点n和节点t的边变量)。

如果您没有子路径:案例1,当您返回源节点时,您可以停止。

看起来您正在允许分游(多个周期,上面的情况2)。如果是这样,您必须访问属于TSP解决方案的所有边,其值为1。(修改代码以跟随每个节点的任意一条边到其终端节点,一次访问一条边)。

代码语言:javascript
复制
Let starting n = origin node
For node n:
  Find an unvisited edge E whose value is 1. 
  Mark edge as visited
  Get the target T of the edge
  Add Edge E to the path
  If all the edges whose value is 1 are visited, stop
  Else, Set N to be T and repeat

希望这能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17310890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档