void Magnusson::backtrack(Node* start, TrackingAlgorithm::Path& p, TrackingAlgorithm::VisitorFunction nodeVisitor) { p.clear(); Node* current = start; while(current != &(graph_->getSourceNode())) { nodeVisitor(current); Arc* bestArc = nullptr; if(current == start) bestArc = selectorFunction_(current); else bestArc = current->getBestInArc(); assert(bestArc != nullptr); assert(bestArc->isEnabled()); if(bestArc->getType() != Arc::Dummy) bestArc->markUsed(); p.push_back(bestArc); current = bestArc->getSourceNode(); } nodeVisitor(current); std::reverse(p.begin(), p.end()); }
void Magnusson::cleanUpUsedSwapArcs(TrackingAlgorithm::Path &p, std::vector<Path>& paths) { std::vector<Arc*> usedSwapArcs; // if a swap arc was used, we can find the path that was affected by this and create the two paths after swapping bool foundSwapArc = true; while(foundSwapArc) { foundSwapArc = false; for(std::vector<Arc*>::reverse_iterator p_it = p.rbegin(); p_it != p.rend(); ++p_it) { // FIXME: sometimes points to free'd memory location? Arc* arc = *p_it; if(arc->getType() == Arc::Swap) { assert(arc->getUserData()); Arc* arcToRemove = std::static_pointer_cast<MagnussonSwapArcUserData>(arc->getUserData())->getCutArc(); Arc* replacementP = std::static_pointer_cast<MagnussonSwapArcUserData>(arc->getUserData())->getReplacementAArc(); Arc* replacementPath = std::static_pointer_cast<MagnussonSwapArcUserData>(arc->getUserData())->getReplacementBArc(); assert(arcToRemove != nullptr); assert(replacementP != nullptr); assert(replacementPath != nullptr); DEBUG_MSG("Trying to remove swap arc between " << arc->getSourceNode()->getUserData()->toString() << " and " << arc->getTargetNode()->getUserData()->toString()); for(Path& path : paths) { for(Node::ArcIt path_it = path.begin(); path_it != path.end(); ++path_it) { Arc* a = *path_it; if(a == arcToRemove) { // found candidate. store part of original path that will be used by new path Path temp(path_it+1, path.end()); for(Node::ArcIt temp_it = temp.begin(); temp_it != temp.end(); ++temp_it) { assert((*temp_it)->getType() != Arc::Swap); } // update original path by appending the replacement arc and the remainder of path P path.erase(path_it, path.end()); path.push_back(replacementPath); path.insert(path.end(), p_it.base(), p.end()); // update path p p.erase(p_it.base()-1, p.end()); p.push_back(replacementP); p.insert(p.end(), temp.begin(), temp.end()); if(usedArcsScoreZero_) { replacementPath->markUsed(); replacementP->markUsed(); // "unuse" the arc that was previously used arcToRemove->markUsed(false); } // remove all this swap arc usedSwapArcs.push_back(arc); #if DEBUG_LOG DEBUG_MSG("updated two paths. removed swap arc between " << arc->getSourceNode()->getUserData()->toString() << " and " << arc->getTargetNode()->getUserData()->toString()); graph_->print(); #endif foundSwapArc = true; break; } } if(foundSwapArc) break; } assert(foundSwapArc); break; } } } for(Arc* a: usedSwapArcs) { removeSwapArc(a); } #ifdef DEBUG_LOG DEBUG_MSG("Paths after removing swaps:"); printPath(p); for(Path& path : paths) printPath(path); for(Node::ArcIt p_it = p.begin(); p_it != p.end(); ++p_it) { assert((*p_it)->getType() != Arc::Swap); } #endif }