I have been trying to solve a routing problem, like the TSP
(traveling salesman problem) but with some twists. I have modeled the problem using linear-programming (CPlex library
) and a directed graph (with an Origin vertex) (Coin-Or::Lemon library
).
The linear program finds the solution, but my question lies in how to retrieve the path. I can iterate each vertex and edge of the graph to find out which the linear program is using, so I thought I'd just start on the Origin and use the chosen edges to get to next node until I reached the Origin again.
The problem was that the CPlex path may walk through any vertex more than once. So I decided to use a recursive algorithm. But I can't quite figure it out. Here's what I've tried:
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
This algorithm fails to find a path. If you please could point me in any direction I would be very grateful.
Edit
The answer provided helped me find the answer. Here's the code in C++
:
bool findPath2 ( Store_Instance &T, DiNode ¤t, 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;
}