56 #include <forward_list>
62 #include <unordered_map>
68 class MinSteinerTreeModule;
71 namespace steiner_tree {
164 delete reducedSolution;
181 const node tC = nCopy[t];
183 ccIsTerminal[tC] =
true;
188 T cost = mst.
call(ccGraph, ccTerminals, ccIsTerminal, ccSolution);
195 if (ccSolution->
copy(nCopy[v]) !=
nullptr) {
200 if (ccSolution->
copy(eCopy[e]) !=
nullptr) {
243 EdgeWeightedGraphCopy<T>& correspondingOriginalSolution);
256 bool changed =
false;
271 bool triviallyChanged =
false;
272 changed |=
repeat([
this, &triviallyChanged, k]() {
273 bool innerChanged =
false;
306 return changed | triviallyChanged;
404 bool NTDkTest(
const int maxTestedDegree = 5,
const int k = 3);
502 static bool repeat(std::function<
bool()> f) {
503 bool changed =
false;
519 template<
typename TWhat,
typename TWhatArray>
520 void addNew(TWhat x,
const std::vector<node>& replacedNodes,
521 const std::vector<edge>& replacedEdges,
bool deleteReplacedElements,
522 TWhatArray& whatSonsListIndex);
526 const std::vector<edge>& replacedEdges,
bool deleteReplacedElements) {
532 const std::vector<edge>& replacedEdges,
bool deleteReplacedElements) {
556 finalSteinerTree =
nullptr;
565 delete finalSteinerTree;
566 return treeCostUpperBound;
580 const NodeArray<
List<std::pair<node, T>>>& closestTerminals);
592 T maxDistance,
int expandedEdges)
const;
600 const NodeArray<
List<std::pair<node, T>>>& closestTerminals)
const;
608 NodeArray<
List<std::pair<node, T>>>& closestTerminals)
const;
617 template<
typename LAMBDA>
632 : m_origGraph(wg), m_origTerminals(terminals), m_origIsTerminal(isTerminal), m_eps(1e-6) {
652 const node vC = nCopy[v];
675 template<
typename TWhat,
typename TWhatArray>
677 const std::vector<edge>& replacedEdges,
bool deleteReplacedElements,
678 TWhatArray& whatSonsListIndex) {
679 std::vector<int> sonsIndexList;
680 for (
node replacedNode : replacedNodes) {
681 sonsIndexList.push_back(m_nodeSonsListIndex[replacedNode]);
683 for (
edge replacedEdge : replacedEdges) {
684 sonsIndexList.push_back(m_edgeSonsListIndex[replacedEdge]);
687 m_sonsList.emplace_back(sonsIndexList);
688 whatSonsListIndex[x] = (int)m_sonsList.size() - 1;
690 if (deleteReplacedElements) {
691 for (
edge e : replacedEdges) {
692 m_copyGraph.delEdge(e);
694 for (
node v : replacedNodes) {
695 m_copyGraph.delNode(v);
704 isInSolution[listIndex] =
true;
708 for (
int son : m_sonsList[listIndex]) {
709 addToSolution(son, isInSolution);
719 Array<bool, int> isInSolution(-(m_origGraph.numberOfNodes() + m_origGraph.numberOfEdges()), -1,
723 for (
node v : reducedGraphSolution.
nodes) {
724 addToSolution(m_nodeSonsListIndex[reducedGraphSolution.
original(v)], isInSolution);
726 for (
edge e : reducedGraphSolution.
edges) {
727 addToSolution(m_edgeSonsListIndex[reducedGraphSolution.
original(e)], isInSolution);
732 for (
node v : m_origGraph.nodes) {
733 if (isInSolution[-(nextIndex++)]) {
734 correspondingOriginalSolution.
newNode(v);
737 for (
edge e : m_origGraph.edges) {
738 if (isInSolution[-(nextIndex++)]) {
739 correspondingOriginalSolution.
newEdge(e, m_origGraph.
weight(e));
748 const NodeArray<
List<std::pair<node, T>>>& closestTerminals) {
756 std::forward_list<NewEdgeData> newEdges;
762 const edge e2 = adj2->theEdge();
763 const node adjacentNode2 = adj2->twinNode();
765 T edgeWeight = m_copyGraph.
weight(e1) + m_copyGraph.
weight(e2);
767 const edge f = m_copyGraph.searchEdge(adjacentNode1, adjacentNode2);
768 if (f && m_copyGraph.
weight(f) <= edgeWeight) {
772 T bottleneckDistance = computeBottleneckDistance(adjacentNode1, adjacentNode2, tprime,
773 tprimeHPD, closestTerminals);
774 if (m_eps.
greater(edgeWeight, bottleneckDistance)) {
778 newEdges.emplace_front(NewEdgeData {e1, e2, f, edgeWeight});
782 for (
const auto& newEdge : newEdges) {
785 if (newEdge.already) {
787 m_copyGraph.
setWeight(newEdge.already, newEdge.weight);
788 newEdgeInGraph = newEdge.already;
790 newEdgeInGraph = m_copyGraph.
newEdge(newEdge.e1->opposite(v), newEdge.e2->opposite(v),
793 addNewEdge(newEdgeInGraph, {v}, {newEdge.e1, newEdge.e2},
false);
796 m_copyGraph.delNode(v);
801 m_copyTerminals.
clear();
802 for (
node v : m_copyGraph.nodes) {
803 if (m_copyIsTerminal[v]) {
813 const NodeArray<
List<std::pair<node, T>>>& closestTerminals)
const {
814 T bottleneckDistance = std::numeric_limits<T>::max();
816 for (
auto& xCloseTerminalDistancePair : closestTerminals[x]) {
817 for (
auto& yCloseTerminalDistancePair : closestTerminals[y]) {
818 T possibleBottleneckDistance =
819 xCloseTerminalDistancePair.second + yCloseTerminalDistancePair.second;
821 node xTprimeCopy = tprime.
copy(xCloseTerminalDistancePair.first);
822 node yTprimeCopy = tprime.
copy(yCloseTerminalDistancePair.first);
823 possibleBottleneckDistance +=
830 return bottleneckDistance;
836 auto deleteAll = [
this]() {
837 if (m_copyGraph.numberOfNodes() > 1) {
838 const node w = m_copyTerminals.front();
840 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
843 m_copyGraph.delNode(v);
850 if (m_copyTerminals.
size() == 1) {
856 for (
node v : m_copyGraph.nodes) {
862 if (eraseQueue.
empty()) {
866 for (; !eraseQueue.
empty(); eraseQueue.
pop()) {
873 if (m_copyIsTerminal[v]) {
875 edge e = v->firstAdj()->theEdge();
876 if (!m_copyIsTerminal[w]) {
877 m_copyIsTerminal[w] =
true;
880 m_copyTerminals.
del(m_copyTerminals.search(v));
881 m_costAlreadyInserted += m_copyGraph.
weight(e);
882 int cur = m_nodeSonsListIndex[w];
884 m_sonsList.emplace_back(
885 std::vector<int> {cur, m_nodeSonsListIndex[v], m_edgeSonsListIndex[e]});
886 m_nodeSonsListIndex[w] = (int)m_sonsList.size() - 1;
888 m_sonsList[cur].push_back(m_nodeSonsListIndex[v]);
889 m_sonsList[cur].push_back(m_edgeSonsListIndex[e]);
896 m_copyGraph.delNode(v);
897 if (m_copyTerminals.
size() == 1) {
907 bool changed =
false;
909 for (
node v : m_copyGraph.nodes) {
911 nextAdj = adj->succ();
913 edge e = adj->theEdge();
914 node adjNode = adj->twinNode();
916 if (nextAdj == adj->twin()) {
917 nextAdj = nextAdj->
succ();
919 m_copyGraph.delEdge(e);
922 if (minCostEdge[adjNode] ==
nullptr
923 || m_copyGraph.
weight(minCostEdge[adjNode]) > m_copyGraph.
weight(e)) {
924 if (minCostEdge[adjNode] !=
nullptr) {
925 m_copyGraph.delEdge(minCostEdge[adjNode]);
928 minCostEdge[adjNode] = e;
930 m_copyGraph.delEdge(e);
937 minCostEdge[adj->
twinNode()] =
nullptr;
945 for (
node v1 : m_copyGraph.nodes) {
948 shortestPath[v1][v2] = shortestPath[v2][v1] =
949 min(shortestPath[v1][v2], m_copyGraph.
weight(adj->
theEdge()));
953 for (
node pivot : m_copyGraph.nodes) {
954 for (
node v1 : m_copyGraph.nodes) {
955 for (
node v2 : m_copyGraph.nodes) {
956 if (shortestPath[v1][pivot] == std::numeric_limits<T>::max()
957 || shortestPath[pivot][v2] == std::numeric_limits<T>::max()) {
962 shortestPath[v1][pivot] + shortestPath[pivot][v2]);
971 shortestPath.init(m_copyGraph);
972 for (
node v : m_copyGraph.nodes) {
973 shortestPath[v].init(m_copyGraph, std::numeric_limits<T>::max());
976 floydWarshall(shortestPath);
982 bool changed =
false;
984 computeShortestPathMatrix(shortestPath);
986 for (
node v : m_copyGraph.nodes) {
988 nextAdj = adj->succ();
990 edge e = adj->theEdge();
991 node adjNode = adj->twinNode();
992 if (adjNode != v && shortestPath[v][adjNode] < m_copyGraph.
weight(e)) {
993 m_copyGraph.delEdge(e);
1001 template<
typename T>
1004 bool changed =
false;
1005 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
1008 if (m_copyIsTerminal[v] || v->degree() != 2) {
1013 edge eLeft = v->firstAdj()->theEdge();
1014 edge eRight = v->lastAdj()->theEdge();
1018 if (vLeft != vRight) {
1019 T weight = m_copyGraph.
weight(eLeft) + m_copyGraph.
weight(eRight);
1020 edge newEdge = m_copyGraph.
newEdge(vLeft, vRight, weight);
1021 addNewEdge(newEdge, {v}, {eLeft, eRight},
true);
1024 m_copyGraph.delNode(v);
1030 template<
typename T>
1035 int componentWithTerminals = -1;
1036 for (
node v : m_copyTerminals) {
1037 if (componentWithTerminals != -1 && hisConnectedComponent[v] != componentWithTerminals) {
1038 std::cerr <<
"terminals in different connected components!\n";
1041 componentWithTerminals = hisConnectedComponent[v];
1044 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
1046 if (hisConnectedComponent[v] != componentWithTerminals) {
1047 m_copyGraph.delNode(v);
1054 template<
typename T>
1058 bool changed =
false;
1068 for (
edge e = m_copyGraph.firstEdge(), nextE; e; e = nextE) {
1072 m_copyGraph.delEdge(e);
1080 template<
typename T>
1082 NodeArray<T>& distance, T maxDistance,
int expandedEdges)
const {
1086 distance[source] = 0;
1087 queue.
push(source, distance[source]);
1089 while (!queue.
empty()) {
1093 reachedNodes.
pushBack(currentNode);
1097 if (expandedEdges <= 0) {
1103 T possibleDistance = distance[currentNode] + m_copyGraph.
weight(e);
1105 if (m_eps.
geq(possibleDistance, maxDistance) || m_copyIsTerminal[adjacentNode]) {
1109 if (possibleDistance < distance[adjacentNode]) {
1110 distance[adjacentNode] = possibleDistance;
1111 if (queue.
contains(adjacentNode)) {
1112 queue.
decrease(adjacentNode, possibleDistance);
1114 queue.
push(adjacentNode, distance[adjacentNode]);
1121 template<
typename T>
1124 bool changed =
false;
1125 NodeArray<T> xDistance(m_copyGraph, std::numeric_limits<T>::max()),
1126 yDistance(m_copyGraph, std::numeric_limits<T>::max());
1128 for (
edge e = m_copyGraph.firstEdge(), nextE; e; e = nextE) {
1132 findClosestNonTerminals(e->source(), xReachedNodes, xDistance, m_copyGraph.
weight(e), 200);
1133 findClosestNonTerminals(e->target(), yReachedNodes, yDistance, m_copyGraph.
weight(e), 200);
1135 for (
node commonNode : xReachedNodes) {
1136 if (yDistance[commonNode] == std::numeric_limits<T>::max()) {
1139 if (m_eps.
less(xDistance[commonNode] + yDistance[commonNode], m_copyGraph.
weight(e))) {
1140 m_copyGraph.delEdge(e);
1146 for (
node reachedNode : xReachedNodes) {
1147 xDistance[reachedNode] = std::numeric_limits<T>::max();
1149 for (
node reachedNode : yReachedNodes) {
1150 yDistance[reachedNode] = std::numeric_limits<T>::max();
1156 template<
typename T>
1158 NodeArray<
List<std::pair<node, T>>>& closestTerminals)
const {
1161 closestTerminals.init(m_copyGraph);
1162 NodePairQueue queue;
1163 std::unordered_map<
NodePair,
typename NodePairQueue::Handle,
1168 for (
node v : m_copyTerminals) {
1169 closestTerminals[v].pushBack(std::make_pair(v, 0));
1170 qpos[
NodePair(v, v)] = queue.push(
NodePair(v, v), closestTerminals[v].front().second);
1173 auto getCurrentDist = [&closestTerminals](
const node currentNode,
const node sourceTerminal) {
1174 for (std::pair<node, T> currentPair : closestTerminals[currentNode]) {
1175 if (currentPair.first == sourceTerminal) {
1176 return currentPair.second;
1179 return static_cast<T
>(-1);
1182 auto setNewDist = [&closestTerminals, k](
const node currentNode,
const node sourceTerminal,
1187 for (
ListIterator<std::pair<node, T>> it = currentList.begin(); it.valid(); ++it) {
1188 if ((*it).first == sourceTerminal) {
1189 currentList.
del(it);
1194 if (currentList.
size() == k) {
1199 if (currentList.empty() || (*currentList.begin()).second >= newDist) {
1200 currentList.
pushFront(std::make_pair(sourceTerminal, newDist));
1205 while (it.
succ() != closestTerminals[currentNode].end() && (*it.
succ()).second < newDist) {
1208 closestTerminals[currentNode].insertAfter(std::make_pair(sourceTerminal, newDist), it);
1211 while (!queue.empty()) {
1212 NodePair minDistPair = queue.topElement();
1217 T currentDist = getCurrentDist(currentNode, sourceTerminal);
1218 if (currentDist == -1) {
1226 if (m_copyIsTerminal[adjacentNode]) {
1230 T possibleNewDistance = currentDist + m_copyGraph.
weight(e);
1233 T currentDistToAdjacentNode = getCurrentDist(adjacentNode, sourceTerminal);
1234 if (currentDistToAdjacentNode
1236 if (possibleNewDistance < currentDistToAdjacentNode) {
1237 queue.decrease(qpos[
NodePair(adjacentNode, sourceTerminal)], possibleNewDistance);
1238 setNewDist(adjacentNode, sourceTerminal, possibleNewDistance);
1241 if (closestTerminals[adjacentNode].size() < k
1242 || closestTerminals[adjacentNode].back().second > possibleNewDistance) {
1243 qpos[
NodePair(adjacentNode, sourceTerminal)] =
1244 queue.push(
NodePair(adjacentNode, sourceTerminal), possibleNewDistance);
1245 setNewDist(adjacentNode, sourceTerminal, possibleNewDistance);
1252 template<
typename T>
1256 bool changed =
false;
1263 computeClosestKTerminals(k, closestTerminals);
1267 for (
edge e = m_copyGraph.firstEdge(), nextE; e; e = nextE) {
1270 T bottleneckDistance = computeBottleneckDistance(e->source(), e->target(), tprime,
1271 tprimeHPD, closestTerminals);
1273 if (m_eps.
greater(m_copyGraph.
weight(e), bottleneckDistance)) {
1274 m_copyGraph.delEdge(e);
1282 template<
typename T>
1285 if (m_copyTerminals.
size() <= 2) {
1289 bool changed =
false;
1298 computeClosestKTerminals(k, closestTerminals);
1302 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
1305 if (m_copyIsTerminal[v]) {
1308 if (v->degree() <= 2 || v->degree() > maxTestedDegree) {
1314 for (
adjEntry adj : v->adjEntries) {
1319 bool deleteNode =
true;
1320 for (neighborSubset.
begin(3, v->degree()); neighborSubset.
valid() && deleteNode;
1321 neighborSubset.
next()) {
1323 std::unordered_map<node, node> initNodeToAuxGraph;
1324 std::unordered_map<node, node> auxGraphToInitNode;
1326 T sumToSelectedAdjacentNodes = 0;
1328 for (
int i = 0; i < neighborSubset.
size(); ++i) {
1329 const adjEntry adj = neighborSubset[i];
1331 sumToSelectedAdjacentNodes += m_copyGraph.
weight(adj->
theEdge());
1333 OGDF_ASSERT(initNodeToAuxGraph.find(adjacentNode) == initNodeToAuxGraph.end());
1336 initNodeToAuxGraph[adjacentNode] = newAuxGraphNode;
1337 auxGraphToInitNode[newAuxGraphNode] = adjacentNode;
1341 for (
node auxGraphNode1 : auxGraph.
nodes) {
1342 for (
node auxGraphNode2 = auxGraphNode1->
succ(); auxGraphNode2;
1343 auxGraphNode2 = auxGraphNode2->
succ()) {
1344 edge e = auxGraph.
newEdge(auxGraphNode1, auxGraphNode2);
1345 weight[e] = computeBottleneckDistance(auxGraphToInitNode[auxGraphNode1],
1346 auxGraphToInitNode[auxGraphNode2], tprime, tprimeHPD, closestTerminals);
1354 if (sumToSelectedAdjacentNodes < mstCost) {
1360 deleteSteinerDegreeTwoNode(v, tprime, tprimeHPD, closestTerminals);
1368 template<
typename T>
1371 isSuccessorOfMinCostEdge[currentNode] =
true;
1380 if (voronoiRegions.
predecessor(adjacentNode) == currentNode) {
1381 markSuccessors(adjacentNode, voronoiRegions, isSuccessorOfMinCostEdge);
1386 template<
typename T>
1397 if (first ==
nullptr
1404 if (second ==
nullptr || m_eps.
less(m_copyGraph.
weight(e), m_copyGraph.
weight(second))) {
1412 template<
typename T>
1414 if (edgesToBeAddedInSolution.empty()) {
1417 for (
edge e : edgesToBeAddedInSolution) {
1418 node x = e->source(), y = e->target();
1419 m_sonsList.emplace_back(std::vector<int> {
1420 m_nodeSonsListIndex[x], m_nodeSonsListIndex[y], m_edgeSonsListIndex[e]});
1421 m_costAlreadyInserted += m_copyGraph.
weight(e);
1422 node newNode = m_copyGraph.contract(e);
1423 m_nodeSonsListIndex[newNode] = (int)m_sonsList.size() - 1;
1424 m_copyIsTerminal[newNode] =
true;
1427 recomputeTerminalsList();
1431 template<
typename T>
1443 for (
node terminal : m_copyTerminals) {
1444 if (terminal->degree() >= 2) {
1445 findTwoMinimumCostEdges(terminal, minCostIncidentEdge1[terminal],
1446 minCostIncidentEdge2[terminal]);
1452 for (
node terminal : m_copyTerminals) {
1453 if (terminal->degree() >= 2) {
1454 node closestNode = minCostIncidentEdge1[terminal]->opposite(terminal);
1456 if (voronoiRegions.
seed(closestNode) == terminal) {
1457 markSuccessors(closestNode, voronoiRegions, isSuccessorOfMinCostEdge);
1463 NodeArray<T> distanceToClosestTerminal(m_copyGraph, std::numeric_limits<T>::max());
1464 for (
edge e : m_copyGraph.edges) {
1466 node seedX = voronoiRegions.
seed(x), seedY = voronoiRegions.
seed(y);
1467 if (seedX != seedY) {
1469 T distanceThroughE =
1472 if (isSuccessorOfMinCostEdge[x]) {
1475 if (isSuccessorOfMinCostEdge[y]) {
1484 for (
node terminal : m_copyTerminals) {
1485 if (terminal->degree() >= 2) {
1486 const edge e = minCostIncidentEdge1[terminal];
1487 const node closestAdjacentNode = e->
opposite(terminal);
1488 T distance {voronoiRegions.
seed(closestAdjacentNode) == terminal
1489 ? distanceToClosestTerminal[terminal]
1490 : m_copyGraph.
weight(e) + voronoiRegions.
distance(closestAdjacentNode)};
1492 if (m_eps.
geq(m_copyGraph.
weight(minCostIncidentEdge2[terminal]), distance)
1493 && !willBeAddedInSolution[e]) {
1494 edgesToBeAddedInSolution.
pushBack(e);
1495 willBeAddedInSolution[e] =
true;
1500 return addEdgesToSolution(edgesToBeAddedInSolution);
1503 template<
typename T>
1514 for (
edge e : m_copyGraph.edges) {
1515 auto updateMinCostLeavingRegionsFor = [&](
node seed) {
1516 if (minCostLeavingRegionEdge1[seed] ==
nullptr
1517 || m_copyGraph.
weight(minCostLeavingRegionEdge1[seed]) > m_copyGraph.
weight(e)) {
1518 minCostLeavingRegionEdge2[seed] = minCostLeavingRegionEdge1[seed];
1519 minCostLeavingRegionEdge1[seed] = e;
1520 }
else if (minCostLeavingRegionEdge2[seed] ==
nullptr
1521 || m_copyGraph.
weight(minCostLeavingRegionEdge2[seed]) > m_copyGraph.
weight(e)) {
1522 minCostLeavingRegionEdge2[seed] = e;
1526 const node seedX = voronoiRegions.
seed(x), seedY = voronoiRegions.
seed(y);
1527 if (seedX != seedY) {
1529 updateMinCostLeavingRegionsFor(seedX);
1530 updateMinCostLeavingRegionsFor(seedY);
1536 for (
node terminal : m_copyTerminals) {
1537 if (minCostLeavingRegionEdge2[terminal] ==
nullptr) {
1542 const edge e1 = minCostLeavingRegionEdge1[terminal];
1544 if (m_eps.
geq(m_copyGraph.
weight(minCostLeavingRegionEdge2[terminal]),
1546 && !willBeAddedInSolution[e1]) {
1547 edgesToBeAddedInSolution.
pushBack(e1);
1548 willBeAddedInSolution[e1] =
true;
1552 return addEdgesToSolution(edgesToBeAddedInSolution);
1555 template<
typename T>
1563 terminalRadius.
init(m_copyGraph, std::numeric_limits<T>::max());
1564 for (
node v : m_copyGraph.nodes) {
1565 node seedV = voronoiRegions.
seed(v);
1566 T distanceToSeedV = voronoiRegions.
distance(v);
1572 if (voronoiRegions.
seed(adjacentNode) != seedV) {
1579 template<
typename T>
1581 const T upperBound) {
1582 bool changed =
false;
1583 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
1585 if (m_eps.
greater(lowerBoundWithNode[v], upperBound)) {
1587 m_copyGraph.delNode(v);
1594 template<
typename T>
1597 if (m_copyTerminals.
size() <= 1) {
1603 NodeArray<T> lowerBoundWithNode(m_copyGraph, std::numeric_limits<T>::lowest());
1606 computeClosestKTerminals(3, closestTerminals);
1610 const T radiusSum = computeRadiusSum();
1611 for (
node v : m_copyGraph.nodes) {
1612 if (m_copyIsTerminal[v]) {
1616 if (closestTerminals[v].size() < 2) {
1617 lowerBoundWithNode[v] = std::numeric_limits<T>::max();
1621 std::pair<node, T> closestTerminalPair1 = *(closestTerminals[v].get(0)),
1622 closestTerminalPair2 = *(closestTerminals[v].get(1));
1623 T distanceToClosestTerminal1 = closestTerminalPair1.second,
1624 distanceToClosestTerminal2 = closestTerminalPair2.second;
1627 distanceToClosestTerminal1 + distanceToClosestTerminal2 + radiusSum);
1632 for (
edge e : m_copyGraph.edges) {
1635 T distanceToClosestTerminalX = (*closestTerminals[x].begin()).second;
1636 T distanceToClosestTerminalY = (*closestTerminals[y].begin()).second;
1639 m_copyGraph.
weight(e) + distanceToClosestTerminalX + distanceToClosestTerminalY
1645 Graph auxiliaryGraph;
1647 for (
node terminal : m_copyTerminals) {
1649 terminalInAuxiliaryGraph[terminal] = newAuxiliaryNode;
1653 for (
edge e : m_copyGraph.edges) {
1654 initialEdgeWeight[e] = m_copyGraph.
weight(e);
1656 Voronoi<T> voronoiRegions(m_copyGraph, initialEdgeWeight, m_copyTerminals);
1661 EdgeArray<T> edgeWeight(auxiliaryGraph, std::numeric_limits<T>::max());
1662 for (
edge e : m_copyGraph.edges) {
1664 node seedX = voronoiRegions.
seed(x), seedY = voronoiRegions.
seed(y);
1665 if (seedX == seedY) {
1669 auto pair =
NodePair(terminalInAuxiliaryGraph[seedX], terminalInAuxiliaryGraph[seedY]);
1670 if (edgeBetweenNodes.find(pair) == edgeBetweenNodes.end()) {
1671 edgeBetweenNodes[pair] = auxiliaryGraph.
newEdge(terminalInAuxiliaryGraph[seedX],
1672 terminalInAuxiliaryGraph[seedY]);
1674 edge auxiliaryEdge = edgeBetweenNodes[pair];
1680 T minimumSpanningTreeCost =
computeMinST(auxiliaryGraph, edgeWeight, isInTree);
1681 T longestEdgeCost = std::numeric_limits<T>::lowest();
1688 for (
node v : m_copyGraph.nodes) {
1689 if (m_copyIsTerminal[v] || closestTerminals[v].size() < 2) {
1693 std::pair<node, T> closestTerminalPair1 = *(closestTerminals[v].get(0)),
1694 closestTerminalPair2 = *(closestTerminals[v].get(1));
1695 T distanceToClosestTerminal1 = closestTerminalPair1.second,
1696 distanceToClosestTerminal2 = closestTerminalPair2.second;
1699 minimumSpanningTreeCost - longestEdgeCost + distanceToClosestTerminal1
1700 + distanceToClosestTerminal2);
1703 return deleteNodesAboveUpperBound(lowerBoundWithNode, upperBound)
1704 || deleteEdgesAboveUpperBound(lowerBoundWithEdge, upperBound);
1707 template<
typename T>
1710 bool changed =
false;
1711 if (m_copyTerminals.
size() > 1) {
1716 alg.
call(m_copyGraph, m_copyTerminals, lowerBoundNodes, lowerBoundEdges);
1718 changed |= deleteNodesAboveUpperBound(lowerBoundNodes, upperBound);
1719 changed |= deleteEdgesAboveUpperBound(lowerBoundEdges, upperBound);
1724 template<
typename T>
1726 const T upperBound) {
1727 bool changed =
false;
1728 for (
edge e = m_copyGraph.firstEdge(), nextE; e; e = nextE) {
1730 if (m_eps.
greater(lowerBoundWithEdge[e], upperBound)) {
1731 m_copyGraph.delEdge(e);
1738 template<
typename T>
1741 computeRadiusOfTerminals(terminalRadius);
1745 T largestRadius1 = std::numeric_limits<T>::lowest(),
1746 largestRadius2 = std::numeric_limits<T>::lowest();
1747 for (
node terminal : m_copyTerminals) {
1748 radiusSum += terminalRadius[terminal];
1750 if (terminalRadius[terminal] > largestRadius1) {
1751 largestRadius2 = largestRadius1;
1752 largestRadius1 = terminalRadius[terminal];
1754 if (terminalRadius[terminal] > largestRadius2) {
1755 largestRadius2 = terminalRadius[terminal];
1759 radiusSum -= largestRadius1 + largestRadius2;
1763 template<
typename T>
1768 bool changed =
false;
1769 if (maxDegreeTest <= 0) {
1770 maxDegreeTest = m_copyGraph.numberOfNodes();
1774 T upperBoundCost = computeMinSteinerTreeUpperBound(approximatedSteinerTree);
1777 for (
node v : approximatedSteinerTree->
nodes) {
1778 isInUpperBoundTree[approximatedSteinerTree->
original(v)] =
true;
1780 delete approximatedSteinerTree;
1789 computeClosestKTerminals(k, closestTerminals);
1794 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
1797 if (isInUpperBoundTree[v] || v->
degree() > maxDegreeTest) {
1806 dijkstra.
call(m_copyGraph, m_copyGraph.
edgeWeights(), v, predecessor, distance);
1809 node farthestTerminal =
nullptr;
1810 T distanceToFarthestTerminal(0);
1811 T distanceToClosestTerminal1 = std::numeric_limits<T>::max(),
1812 distanceToClosestTerminal2 = std::numeric_limits<T>::max();
1813 for (
node terminal : m_copyTerminals) {
1814 if (distanceToFarthestTerminal < distance[terminal]) {
1815 farthestTerminal = terminal;
1816 distanceToFarthestTerminal = distance[terminal];
1819 if (distanceToClosestTerminal1 > distance[terminal]) {
1820 distanceToClosestTerminal2 = distanceToClosestTerminal1;
1821 distanceToClosestTerminal1 = distance[terminal];
1823 if (distanceToClosestTerminal2 > distance[terminal]) {
1824 distanceToClosestTerminal2 = distance[terminal];
1829 if (predecessor[farthestTerminal] ==
nullptr
1830 || distanceToClosestTerminal2
1831 == std::numeric_limits<T>::max()
1832 || m_eps.
geq(distanceToFarthestTerminal + distanceToClosestTerminal1
1833 + distanceToClosestTerminal2,
1837 if (predecessor[farthestTerminal] !=
nullptr
1838 && distanceToClosestTerminal2 != std::numeric_limits<T>::max()
1839 && m_eps.
less(distanceToFarthestTerminal + distanceToClosestTerminal1,
1842 deleteSteinerDegreeTwoNode(v, tprime, tprimeHPD, closestTerminals);
1845 m_copyGraph.delNode(v);
1853 template<
typename T>
1854 template<
typename LAMBDA>
1860 distance.
init(m_copyGraph);
1862 dijkstra.
call(m_copyGraph, m_copyGraph.
edgeWeights(), v, predecessor, distance);
1864 for (
node terminal : m_copyTerminals) {
1865 if (predecessor[terminal] ==
nullptr) {
1869 if (optimalTerminal1 ==
nullptr
1870 || dist(optimalTerminal1, distance) > dist(terminal, distance)) {
1871 optimalTerminal2 = optimalTerminal1;
1872 optimalTerminal1 = terminal;
1874 if (optimalTerminal2 ==
nullptr
1875 || dist(optimalTerminal2, distance) > dist(terminal, distance)) {
1876 optimalTerminal2 = terminal;
1882 OGDF_ASSERT(optimalTerminal1 != optimalTerminal2);
1885 template<
typename T>
1888 if (m_copyTerminals.
size() <= 2) {
1894 const T upperBoundCost = computeMinSteinerTreeUpperBound(approximatedSteinerTree);
1897 for (
node v : approximatedSteinerTree->
nodes) {
1898 isInUpperBoundTree[approximatedSteinerTree->
original(v)] =
true;
1900 delete approximatedSteinerTree;
1903 NodeArray<T> minCostOfAdjacentEdge(m_copyGraph, std::numeric_limits<T>::max());
1904 for (
node terminal : m_copyTerminals) {
1905 for (
adjEntry adj : terminal->adjEntries) {
1908 cK += minCostOfAdjacentEdge[terminal];
1910 auto dist = [&minCostOfAdjacentEdge](
node terminal,
const NodeArray<T>& distance) {
1911 return distance[terminal] - minCostOfAdjacentEdge[terminal];
1915 std::set<edge> delEdges;
1918 for (
node v = m_copyGraph.firstNode(), nextV; v; v = nextV) {
1921 if (isInUpperBoundTree[v]) {
1926 node vOptimalTerminal1 =
nullptr, vOptimalTerminal2 =
nullptr;
1927 computeOptimalTerminals(v, dist, vOptimalTerminal1, vOptimalTerminal2, vDistance);
1930 if (m_eps.
geq(cK + dist(vOptimalTerminal1, vDistance) + dist(vOptimalTerminal2, vDistance),
1934 for (
adjEntry adj = v->firstAdj(), adjNext; adj; adj = adjNext) {
1935 adjNext = adj->succ();
1936 node w = adj->twinNode();
1937 if (m_copyIsTerminal[w]) {
1940 node wOptimalTerminal1 =
nullptr, wOptimalTerminal2 =
nullptr;
1941 computeOptimalTerminals(w, dist, wOptimalTerminal1, wOptimalTerminal2, wDistance);
1943 node vOptimalTerminal = vOptimalTerminal1;
1944 node wOptimalTerminal = wOptimalTerminal1;
1945 if (vOptimalTerminal == wOptimalTerminal) {
1948 if (m_eps.
leq(dist(vOptimalTerminal1, vDistance)
1949 + dist(wOptimalTerminal2, wDistance),
1950 dist(vOptimalTerminal2, vDistance)
1951 + dist(wOptimalTerminal1, wDistance))) {
1952 wOptimalTerminal = wOptimalTerminal2;
1954 vOptimalTerminal = vOptimalTerminal2;
1957 OGDF_ASSERT(vOptimalTerminal != wOptimalTerminal);
1958 if (m_eps.
geq(cK + dist(vOptimalTerminal, vDistance) + dist(wOptimalTerminal, wDistance)
1959 + m_copyGraph.
weight(adj->theEdge()),
1961 delEdges.insert(adj->theEdge());
1967 bool changed =
false;
1968 for (
edge e : delEdges) {
1969 m_copyGraph.delEdge(e);
1972 for (
node v : delNodes) {
1973 m_copyGraph.delNode(v);