NetPath VirtualLinkRouter::searchPathDejkstra(VirtualLink * virtualLink, Network * network, SearchPathAlgorithm algorithm) { if ( virtualLink->getFirst() == virtualLink->getSecond() ) return NetPath(); // local variables std::set<ElementWeight, WeightCompare> elementsToParse; std::map<Element * , Link*> incomingEdge; std::map<Element * , std::vector<Link *> > elementLinks; // initializing parameters Links::iterator it = network->getLinks().begin(); Links::iterator itEnd = network->getLinks().end(); std::vector<Link *> * vecLinks = NULL; for ( ; it != itEnd; ++it ) { if ((*it)->getFirst() != virtualLink->getFirst()) elementsToParse.insert(ElementWeight((*it)->getFirst(), LONG_MAX)); // LONG_MAX equals to inf if ((*it)->getSecond() != virtualLink->getFirst()) elementsToParse.insert(ElementWeight((*it)->getSecond(), LONG_MAX)); vecLinks = &elementLinks[(*it)->getFirst()]; if (vecLinks->capacity() < NLinks) vecLinks->reserve(NLinks); vecLinks->push_back(*it); vecLinks = &elementLinks[(*it)->getSecond()]; if (vecLinks->capacity() < NLinks) vecLinks->reserve(NLinks); vecLinks->push_back(*it); } elementsToParse.insert(ElementWeight(virtualLink->getFirst(), 0)); elementsToParse.insert(ElementWeight(virtualLink->getSecond(), LONG_MAX)); Element * currentElement = virtualLink->getFirst(); Link edge("dijkstra edge", 0); ElementWeight temp(NULL, -LONG_MAX); std::set<ElementWeight, WeightCompare>::iterator tempIter; long curWeight = 0; // algorithm itself while ( currentElement != NULL && currentElement != virtualLink->getSecond() ) { temp.element = currentElement; tempIter = elementsToParse.find(temp); assert(tempIter != elementsToParse.end()); curWeight = tempIter->weight; // std::cerr << "currentElement = " << currentElement << ", tempIter->element = " << tempIter->element << ", weight = " << tempIter->weight << '\n'; elementsToParse.erase(tempIter); // going through all neighbors of current element, // parsing their weight and choosing the element with the // lowest weight if ( elementLinks.find(currentElement) == elementLinks.end() ) { return NetPath(); // No links assosiated with element } std::vector<Link *>& curLinks = elementLinks[currentElement]; unsigned int sz = curLinks.size(); for(unsigned int index = 0; index < sz; ++ index) { Link * cur = curLinks[index]; Element * other = cur->getFirst() == currentElement ? cur->getSecond() : cur->getFirst(); temp.element = other; temp.weight = LONG_MAX; tempIter = elementsToParse.find(temp); if ( tempIter != elementsToParse.end() ) { edge.setCapacity(cur->getCapacity()); edge.bindElements(currentElement, other); // weight of reaching the next element from current element long weight = getEdgeWeigth(edge, network, algorithm) + curWeight; if ( weight < tempIter->weight ) { // have to erase and reinsert because weight is a part of the key temp.element = other; temp.weight = weight; elementsToParse.erase(tempIter); elementsToParse.insert(temp); incomingEdge[other] = cur; } } temp.weight = -LONG_MAX; } if (elementsToParse.begin()->weight != LONG_MAX) currentElement = elementsToParse.begin()->element; else return NetPath(); // if an infinite weight is the minimum, it is a fail } if ( currentElement != virtualLink->getSecond() ) return NetPath(); // no way from one element to another // retrieving the way NetPath answer; Element * other = currentElement; // for parsing results with just one edge while ( incomingEdge[currentElement]->getFirst() != virtualLink->getFirst() && incomingEdge[currentElement]->getSecond() != virtualLink->getFirst() ) { answer.push_back(incomingEdge[currentElement]); other = incomingEdge[currentElement]->getFirst() == currentElement ? incomingEdge[currentElement]->getSecond() : incomingEdge[currentElement]->getFirst(); answer.push_back(static_cast<NetworkingElement *>(other)); currentElement = other; } answer.push_back(incomingEdge[other]); // this step may be skiped, but doing for sure std::reverse(answer.begin(), answer.end()); return answer; }
NetPath DijkstraRouter::search() { if ( !validateInput() ) { printf("[RD]Wrong input\n"); return NetPath(); } if ( link->getFirst() == link->getSecond() ) return NetPath(); std::set<ElementWeight, WeightCompare> elementsToParse; std::map<Element * , Link *> incomingEdge; std::map<Element * , std::vector<Link *> > elementLinks; Links & links = network->getLinks(); for ( Links::iterator i = links.begin(); i != links.end(); i++ ) { Link * l = *i; if ( l->getFirst() != link->getFirst() ) elementsToParse.insert(ElementWeight(l->getFirst(), LONG_MAX)); if ( l->getSecond() != link->getFirst() ) elementsToParse.insert(ElementWeight(l->getSecond(), LONG_MAX)); elementLinks[l->getFirst()].push_back(l); elementLinks[l->getSecond()].push_back(l); } elementsToParse.insert(ElementWeight(link->getFirst(), 0)); elementsToParse.insert(ElementWeight(link->getSecond(), LONG_MAX)); Element * currentElement = link->getFirst(); Link edge("dijkstraedge", 0); ElementWeight temp(0, -LONG_MAX); std::set<ElementWeight, WeightCompare>::iterator tempIter; long curWeight = 0; while ( currentElement != 0 && currentElement != link->getSecond() ) { temp.element = currentElement; tempIter = elementsToParse.find(temp); assert(tempIter != elementsToParse.end()); curWeight = tempIter->weight; elementsToParse.erase(tempIter); if ( elementLinks.find(currentElement) == elementLinks.end() ) return NetPath(); std::vector<Link *>& curLinks = elementLinks[currentElement]; unsigned int size = curLinks.size(); for(unsigned int index = 0; index < size; index++) { Link * cur = curLinks[index]; Element * other = cur->getFirst() == currentElement ? cur->getSecond() : cur->getFirst(); temp.element = other; temp.weight = LONG_MAX; tempIter = elementsToParse.find(temp); if ( tempIter != elementsToParse.end() ) { edge.setCapacity(cur->getCapacity()); edge.bindElements(currentElement, other); long weight = getEdgeWeight(&edge) + curWeight; if ( weight < tempIter->weight ) { temp.element = other; temp.weight = weight; elementsToParse.erase(tempIter); elementsToParse.insert(temp); incomingEdge[other] = cur; } } temp.weight = -LONG_MAX; } if (elementsToParse.begin()->weight != LONG_MAX) currentElement = elementsToParse.begin()->element; else return NetPath(); } if ( currentElement != link->getSecond() ) return NetPath(); Element * other = currentElement; NetPath result; while ( incomingEdge[currentElement]->getFirst() != link->getFirst() && incomingEdge[currentElement]->getSecond() != link->getFirst() ) { result.push_back(incomingEdge[currentElement]); other = incomingEdge[currentElement]->getFirst() == currentElement ? incomingEdge[currentElement]->getSecond() : incomingEdge[currentElement]->getFirst(); result.push_back((NetworkingElement *)other); currentElement = other; } result.push_back(incomingEdge[other]); std::reverse(result.begin(), result.end()); return result; }