270 m_originalGraph = &G;
271 m_originalTerminals = &terminals;
273 m_upperBound = MAX_WEIGHT;
275 m_mapping.init(m_graph);
276 m_terminals.reset(
new NodeSet<>(m_graph));
277 int nodeCount = m_originalGraph->numberOfNodes();
282 for (
node v : m_originalGraph->nodes) {
287 for (
edge e : m_originalGraph->edges) {
290 newEdge(source, target, e);
293 for (
node v : *m_originalTerminals) {
304 node v = e->source();
305 node w = e->target();
327 T result = MAX_WEIGHT;
332 OGDF_ASSERT(m_mapping[e]->graphOf() == m_originalGraph);
333 result = m_originalGraph->weight(m_mapping[e]);
341 for (
edge e : m_graph.edges) {
343 OGDF_ASSERT(m_mapping[e]->graphOf() == m_originalGraph);
360 edge result = m_mapping[e];
370 edge result = m_graph.newEdge(source, target);
371 m_mapping[result] = e;
372 setEdgeLookup(source, target, result);
381 setEdgeLookup(v, e->
target(), e);
382 m_graph.moveSource(e, v);
389 setEdgeLookup(e->
source(), v, e);
390 m_graph.moveTarget(e, v);
395 return m_terminals->isMember(v);
401 m_terminals->insert(v);
403 m_terminals->remove(v);
409 m_chosenEdges.clear();
411 m_recursionDepth = 0;
413 T result = bnbInternal(0,
tmp);
415 for (
edge e : m_chosenEdges) {
424 edge result =
nullptr;
439 for (
adjEntry adj =
t->firstAdj(); adj; adj = adj->succ()) {
440 edge e = adj->theEdge();
451 if (isTerminal(adj->twinNode()) && weightOf(e) <
minTermWeight) {
485 if (result !=
nullptr) {
500 T result = MAX_WEIGHT;
503#ifdef OGDF_MINSTEINERTREE_SHORE_LOGGING
508 if (m_terminals->size() < 2) {
510 if (
prevCost != m_upperBound || m_chosenEdges.empty()) {
520#ifdef OGDF_MINSTEINERTREE_SHORE_LOGGING
521 for (
int i = 0; i < m_recursionDepth; i++) {
524 std::cout <<
"branching on edge: " <<
branchingEdge << std::endl;
550 while (m_graph.searchEdge(targetNode,
nodeToRemove) !=
nullptr) {
557 while (m_graph.searchEdge(
nodeToRemove, targetNode) !=
nullptr) {
571 edge e = adj->theEdge();
577 edge f = lookupEdge(targetNode, adj->twinNode());
580 if (weightOf(
f) < weightOf(e)) {
598 moveTarget(e, targetNode);
603 moveSource(e, targetNode);
617 setTerminal(targetNode,
true);
619#ifdef OGDF_MINSTEINERTREE_SHORE_LOGGING
620 for (
int i = 0; i < m_recursionDepth; i++) {
623 std::cout <<
"inclusion branch" << std::endl;
641 edge e = lookupEdge(v, targetNode);
653 while (!delEdges.
empty()) {
663#ifdef OGDF_MINSTEINERTREE_SHORE_LOGGING
664 for (
int i = 0; i < m_recursionDepth; i++) {
667 std::cout <<
"exclusion branch" << std::endl;
692 m_graph.allNodes(nodes);
694 for (
node v : nodes) {
699 m_graph.allEdges(edges);
700 for (
edge e : edges) {
703 std::stringstream filename;
704 filename <<
"bnb_internal_" << m_recursionDepth <<
".svg";
Declaration and implementation of EdgeArray class.
Extends the GraphCopy concept to weighted graphs.
Declaration of doubly linked lists and iterators.
Declaration of ogdf::MinSteinerTreeModule.
Declaration and implementation of NodeArray class.
Declaration and implementation of ogdf::NodeSet.
Class for adjacency list elements.
The parameterized class Array2D implements dynamic two-dimensional arrays.
Dynamic arrays indexed with edges.
Class for the representation of edges.
node opposite(node v) const
Returns the adjacent node different from v.
node target() const
Returns the target node of the edge.
node source() const
Returns the source node of the edge.
Data type for general directed graphs (adjacency list representation).
Doubly linked lists (maintaining the length of the list).
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
E popFrontRet()
Removes the first element from the list and returns it.
Encapsulates a pointer to a list element.
bool empty() const
Returns true iff the list is empty.
Serves as an interface for various methods to compute or approximate minimum Steiner trees on undirec...
Implementation of Shore, Foulds and Gibbons exact branch and bound algorithm for solving Steiner tree...
void moveSource(edge e, node v)
Moves the source of the edge to the specified node.
bool validateMapping() const
Used to validate the current mapping of edges to orignal edges Used solely for debugging.
T solve(List< edge > &chosenEdges)
Solves the current STP instance.
const EdgeWeightedGraph< T > * m_originalGraph
bool isTerminal(const node v) const
Returns whether this node is a terminal or a Steiner node.
void setEdgeLookup(const node u, const node v, const edge e)
Sets the edge incident to both node u and v.
edge lookupEdge(const node u, const node v) const
Retrieves the edge incident to both node u and v.
virtual ~MinSteinerTreeShore()
void setTerminal(const node v, bool makeTerminal)
Updates the status of the given node to either terminal or Steiner node.
edge deleteEdge(edge e)
Removes the specified edge from the graph.
virtual T computeSteinerTree(const EdgeWeightedGraph< T > &G, const List< node > &terminals, const NodeArray< bool > &isTerminal, EdgeWeightedGraphCopy< T > *&finalSteinerTree) override
Builds a minimum Steiner tree given a weighted graph and a list of terminals.
T bnbInternal(T prevCost, List< edge > ¤tEdges)
Calculates the optimal Steinter tree recursivly.
List< edge > m_chosenEdges
const List< node > * m_originalTerminals
void moveTarget(edge e, node v)
Moves the target of the edge to the specified node.
edge newEdge(node source, node target, const edge originalEdge)
Creates a new edge.
std::unique_ptr< NodeSet<> > m_terminals
edge determineBranchingEdge(T prevCost) const
Decides which edge to branch on.
void printSVG()
Prints the current recursion status as a SVG image of the current reduced STP.
T weightOf(edge e) const
Returns the cost of the specified edge.
EdgeArray< edge > m_mapping
Dynamic arrays indexed with nodes.
Class for the representation of nodes.
int degree() const
Returns the degree of the node (indegree + outdegree).
int index() const
Returns the (unique) node index.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.