Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
SpannerKortsarzPeleg.h
Go to the documentation of this file.
1
33#pragma once
34
36#include <ogdf/basic/Graph.h>
41#include <ogdf/basic/List.h>
42#include <ogdf/basic/basic.h>
46
47#include <algorithm>
48#include <cstdint>
49#include <string>
50
51namespace ogdf {
52
83template<typename TWeight>
84class SpannerKortsarzPeleg : public SpannerModule<TWeight> {
88
89public:
91 virtual bool preconditionsOk(const GraphAttributes& GA, double stretch,
92 std::string& error) override {
93 if (GA.directed()) {
94 error = "The graph must be undirected";
95 return false;
96 }
97 if (stretch != 2.0) {
98 error = "The stretch must be 2.0";
99 return false;
100 }
101 if (!isSimple(GA.constGraph())) {
102 error = "The graph is not simple";
103 return false;
104 }
106 error = "The graph must be unweighted";
107 return false;
108 }
109 return true;
110 }
111
112private:
113 virtual void init(const GraphAttributes& GA, double stretch, GraphCopySimple& spanner,
114 EdgeArray<bool>& inSpanner) override {
115 SpannerModule<TWeight>::init(GA, stretch, spanner, inSpanner);
116 m_G.clear();
117 m_G.init(GA.constGraph());
118 }
119
120 virtual typename SpannerModule<TWeight>::ReturnType execute() override {
121 while (true) {
122 node maxNode = nullptr;
123 double maxDensity = 0.0;
124 NodeSet maxDenseSubset(m_GA->constGraph());
125 List<edge> maxE_U; // holds the edges of the maximum dense subgraph
126
127 for (node v : m_G.nodes) {
128 // Create neighbor graph
129 GraphCopySimple neighborGraph;
130 // Note: v is not part of the neighbor graph.
131 neighborGraph.setOriginalGraph(m_G);
132 for (adjEntry adj : v->adjEntries) {
133 neighborGraph.newNode(adj->twinNode());
134 }
135 for (edge e : m_G.edges) {
136 if (neighborGraph.copy(e->target()) != nullptr
137 && neighborGraph.copy(e->source()) != nullptr) {
138 neighborGraph.newEdge(e);
139 }
140 }
141
142 // Calculate dense subgraph and find all edges E_U of this subgraph
143 NodeSet denseSubset(m_G);
144 int64_t timelimit = -1;
145 if (isTimelimitEnabled()) {
146 timelimit = max(static_cast<int64_t>(0), getTimeLeft());
147 }
148 bool success = maximumDensitySubgraph(
149 neighborGraph, denseSubset,
150 [&](node n) {
151 OGDF_ASSERT(neighborGraph.original(n) != nullptr);
152 return neighborGraph.original(n);
153 },
154 timelimit);
155 if (!success) {
157 }
158
159 List<edge> E_U;
160 for (edge e : m_G.edges) {
161 if (denseSubset.isMember(e->source()) && denseSubset.isMember(e->target())) {
162 E_U.pushBack(e);
163 }
164 }
165
166 // Did we found a new maximum dense subgraph?
167 double density = denseSubset.size() == 0
168 ? 0.0
169 : static_cast<double>(E_U.size()) / denseSubset.size();
170 if (m_eps.greater(density, maxDensity)) {
171 maxDensity = density;
172 maxNode = v;
173 maxDenseSubset = denseSubset;
174 maxE_U = E_U;
175 }
176 }
177
178 if (m_eps.less(maxDensity, 1.0)) {
179 break;
180 }
181
182 OGDF_ASSERT(maxNode != nullptr);
183
184 // add edges to spanner
185 for (node u : maxDenseSubset.nodes()) {
186 edge e = m_G.searchEdge(maxNode, u); // e is part of m_G
187 addToSpanner(e);
188
189 // remove from m_G
190 m_G.delEdge(e);
191 }
192
193 // Remove R(H^u, maxDenseSubset) from m_G
194 // Improvement: H^c (see paper) is actually not needed. Since
195 // R(H^u, maxDenseSubset) is the intersection of E_U and the current spanner
196 // edges, but E_U only consists of current spanner edges (Note that the loop
197 // above only contains edges not in E_U since maxNode is not part of the
198 // neighbor graph), the intersection is not needed. One can directly delete
199 // all edges in E_U.
200 for (edge e : maxE_U) {
201 m_G.delEdge(e);
202 }
203 }
204
205 // Add uncovered edges to spanner
206 for (edge e : m_G.edges) {
207 addToSpanner(e);
208 }
209
211 }
212
216 inline void addToSpanner(edge e) {
218 (*m_inSpanner)[m_G.original(e)] = true;
219 }
220
221 using SpannerModule<TWeight>::assertTimeLeft;
223 using SpannerModule<TWeight>::getTimeLeft;
224 using SpannerModule<TWeight>::m_GA;
225 using SpannerModule<TWeight>::m_spanner;
226 using SpannerModule<TWeight>::m_inSpanner;
227};
228
229}
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Includes declaration of graph class.
Declaration of class GraphAttributes which extends a Graph by additional attributes.
Declaration of graph copy classes.
Decralation of GraphElement and GraphList classes.
Declaration and implementation of NodeSet, EdgeSet, and AdjEntrySet classes.
Declaration of doubly linked lists and iterators.
Declares maximum density subgraph algorithms.
Basic module for spanner algorithms.
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
Class for the representation of edges.
Definition Graph_d.h:364
std::enable_if< std::is_integral< T >::value, bool >::type less(const T &x, const T &y) const
Compare if x is LESS than y for integral types.
Definition EpsilonTest.h:55
std::enable_if< std::is_integral< T >::value, bool >::type greater(const T &x, const T &y) const
Compare if x is GREATER than y for integral types.
Stores additional attributes of a graph (like layout information).
bool directed() const
Returns if the graph is directed.
const Graph & constGraph() const
Returns a reference to the associated graph.
static const long edgeDoubleWeight
Corresponds to edge attribute doubleWeight(edge).
bool has(long attr) const
Returns true iff all attributes in attr are available.
static const long edgeIntWeight
Corresponds to edge attribute intWeight(edge).
node newNode(node vOrig)
Creates a new node in the graph copy with original node vOrig.
Definition GraphCopy.h:191
void init(const Graph &G)
Re-initializes the copy using G, creating copies for all nodes and edges in G.
Definition GraphCopy.h:72
const Graph & original() const
Returns a reference to the original graph.
Definition GraphCopy.h:104
Copies of graphs with mapping between nodes and edges.
Definition GraphCopy.h:260
edge newEdge(edge eOrig)
Creates a new edge in the graph copy with original edge eOrig.
Definition GraphCopy.h:320
void setOriginalGraph(const Graph *G) override
Re-initializes the copy using G (which might be null), but does not create any nodes or edges.
void delEdge(edge e) override
Removes edge e.
void clear() override
Removes all nodes and edges from this copy but does not break the link with the original graph.
edge copy(edge e) const override
Returns the edge in the graph copy corresponding to e.
Definition GraphCopy.h:294
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition Graph_d.h:929
edge searchEdge(node v, node w, bool directed=false) const
Searches and returns an edge connecting nodes v and w in time O( min(deg(v ), deg(w ))).
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition Graph_d.h:932
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
int size() const
Returns the number of elements in the list.
Definition List.h:1488
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1547
ReturnType
The return type of a module.
Definition Module.h:52
Class for the representation of nodes.
Definition Graph_d.h:241
Node sets.
Definition GraphSets.h:54
const list_type & nodes()
Returns a reference to the list of nodes contained in this set.
Definition GraphSets.h:64
int size() const
Returns the number of elements in this set.
bool isMember(element_type v) const
Returns true iff element v is contained in this set.
Approximation multiplicative 2-spanner calculation.
virtual bool preconditionsOk(const GraphAttributes &GA, double stretch, std::string &error) override
void addToSpanner(edge e)
Adds e from m_G to the spanner and sets inSpanner.
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner) override
Initializes members and create an empty spanner.
GraphCopySimple m_G
The copy of GA.constGraph() to work on. Edges will be removed in each iteration.
virtual SpannerModule< TWeight >::ReturnType execute() override
Executes the core algorithm.
Interface for spanner algorithms.
void assertTimeLeft()
Assert, that time is left.
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner)
Initializes members and create an empty spanner.
const GraphAttributes * m_GA
EdgeArray< bool > * m_inSpanner
GraphCopySimple * m_spanner
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition Graph_d.h:717
bool maximumDensitySubgraph(Graph &G, NodeSet &subgraphNodes, std::function< node(node)> resultNodeMap=[](node v) { return v;}, int64_t timelimit=-1)
Calculates the maximum density subgraph of G.
bool isSimple(const Graph &G)
Returns true iff G contains neither self-loops nor parallel edges.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.
Declaration of simple graph algorithms.
A simple exception used to exit from the execution, if the timelimit is reached.