44namespace steiner_tree {
93 const edge e = adj->theEdge();
114 for (
int id = 1;
id <= gamma.size(); ++id) {
141 for (
node t : gamma.terminals(
id)) {
149 std::unique_ptr<ArrayBuffer<std::pair<node, int>>>
basis(
157#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
158 std::cout <<
"Computing min-cost flow for blowup component " <<
id <<
" of "
159 << gamma.size() << std::endl;
160 std::cout <<
" * terminals of component are " << gamma.terminals(
id) << std::endl;
163 std::cout <<
" * supply node " << v <<
" with supply " <<
supply[v] << std::endl;
166 std::cout <<
" * demand node " << v <<
" with demand " << -
supply[v] << std::endl;
170 std::cout <<
" * edge " << e <<
" with cost " <<
blowupGraph.getCost(e)
171 <<
" and flow bounds [" <<
lB[e] <<
", " <<
blowupGraph.getCapacity(e)
189 basis->push(std::make_pair(e->target(), flow[e]));
190 weight -= flow[e] * cost[e];
194#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
195 std::cout <<
"Basis weight is " << weight << std::endl
196 <<
"Checking if " << gamma.cost(
id) <<
"(component cost) * "
197 <<
blowupGraph.getLCM() <<
"(lcm) <= " << weight <<
"(basis weight)"
203#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
204 std::cout <<
"Using basis because it is feasible." << std::endl;
221 for (
int id = 1;
id <= gamma.size(); ++id) {
222 if (gamma.cost(
id) > cost) {
223 cost = gamma.cost(
id);
237 const edge rootEdge) {
241 while (!
stack.empty()) {
251 const node w = adj->theEdge()->target();
262#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
263 std::cout <<
"Remove basis from blowup graph" << std::endl;
269 for (
auto p :
basis) {
270 const node v = p.first;
271 const int count = p.second;
274#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
275 std::cout <<
" * node " << v <<
" with count " <<
count <<
" (of " <<
origCap <<
")"
280#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
281 std::cout <<
" -> deferred because fractional" << std::endl;
287#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
288 std::cout <<
" -> done" << std::endl;
293#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
295 std::cout <<
"Deferred core edges:" << std::endl;
299 const node v = p.item();
300 const int count = -p.priority();
302#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
303 std::cout <<
" * node " << v <<
" with count " <<
count <<
" of " <<
origCap << std::endl;
319 const std::minstd_rand&
rng,
double eps = 1e-8)
334#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
335 std::cout <<
"Start solving based on LP solution" << std::endl;
342#ifdef OGDF_STEINER_TREE_GOEMANS_APPROXIMATION_LOGGING
344 <<
" terminals" << std::endl;
351 std::unique_ptr<ArrayBuffer<std::pair<node, int>>>
maxBasis;
Definition of the ogdf::steiner_tree::goemans::BlowupComponents class template.
Definition of ogdf::steiner_tree::goemans::CoreEdgeRandomSpanningTree class template.
Declaration and implementation of Goldberg-Tarjan max-flow algorithm with global relabeling and gap r...
Definition of ogdf::MinCostFlowReinelt class template.
Class for adjacency list elements.
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
void push(edge e)
Puts a new element in the buffer.
int capacity() const
Returns the current capacity of the datastructure. Note that this value is rather irrelevant if the a...
Dynamic arrays indexed with edges.
Class for the representation of edges.
node target() const
Returns the target node of the edge.
node source() const
Returns the source node of the edge.
Doubly linked lists (maintaining the length of the list).
Computes a max flow via Preflow-Push (global relabeling and gap relabeling heuristic).
static bool checkComputedFlow(const Graph &G, const EdgeArray< int > &lowerBound, const EdgeArray< int > &upperBound, const EdgeArray< TCost > &cost, const NodeArray< int > &supply, const EdgeArray< int > &flow, TCost &value)
checks if a computed flow is a feasible solution to the given problem instance.
Computes a min-cost flow using a network simplex method.
virtual bool call(const Graph &G, const EdgeArray< int > &lowerBound, const EdgeArray< int > &upperBound, const EdgeArray< TCost > &cost, const NodeArray< int > &supply, EdgeArray< int > &flow, NodeArray< TCost > &dual) override
Computes a min-cost flow in the directed graph G using a network simplex method.
Dynamic arrays indexed with nodes.
Class for the representation of nodes.
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Augments any data elements of type X with keys of type Priority. This class is also its own Comparer.
The actual 1.39-approximation algorithm by Goemans et al. with a set of terminalized nodes as result.
int findCheapestComponentAndRemainingBasis(std::unique_ptr< ArrayBuffer< std::pair< node, int > > > &maxBasis, const BlowupGraph< T > &blowupGraph, const BlowupComponents< T > &gamma)
For the end of the algorithm: find cheapest component and choose all remaining core edges as basis.
void removeFractionalBasisAndCleanup(ArrayBuffer< std::pair< node, int > > &basis, BlowupGraph< T > &blowupGraph, BlowupComponents< T > &gamma)
Remove a given basis and cleanup, the basis may be given fractionally.
const EdgeWeightedGraph< T > & m_G
const FullComponentWithExtraStore< T, double > & m_fullCompStore
all enumerated full components, with solution
int gammoidGetRank(const BlowupGraph< T > &blowupGraph) const
Computes the rank of the gammoid (given by the blowup graph)
Approximation(const EdgeWeightedGraph< T > &G, const List< node > &terminals, const NodeArray< bool > &isTerminal, const FullComponentWithExtraStore< T, double > &fullCompStore, const std::minstd_rand &rng, double eps=1e-8)
Initialize everything.
const List< node > & m_terminals
const NodeArray< bool > & m_isTerminal
void addComponent(NodeArray< bool > &isNewTerminal, const BlowupGraph< T > &blowupGraph, const edge rootEdge)
Add a component of the blowup graph to the final solution (by changing nonterminals to terminals)
const double m_eps
epsilon for double operations
int findComponentAndMaxBasis(std::unique_ptr< ArrayBuffer< std::pair< node, int > > > &maxBasis, BlowupGraph< T > &blowupGraph, const BlowupComponents< T > &gamma)
Finds the best component and its maximum-weight basis in the given blowup graph with given core and w...
void solve(NodeArray< bool > &isNewTerminal)
Perform the actual approximation algorithm on the LP solution.
Obtain and provides information about components in a given blowup graph.
A special-purpose blowup graph for gammoid computation: directed, with special source and target,...
Computes a random set of core edges.
bool isLoopFree(const Graph &G)
Returns true iff G contains no self-loop.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.
Add edges into a blowup graph and delete them on destruction.
edge add(node v, node w, T cost, int capacity)
Add a temporary edge to the blowup graph.
TemporaryEdges(BlowupGraph< T > &blowupGraph)
Construct object for a specific blowupGraph.
~TemporaryEdges()
Remove the edges again.
BlowupGraph< T > & m_blowupGraph