Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

SpannerKortsarzPeleg.h
Go to the documentation of this file.
1 
33 #pragma once
34 
35 #include <ogdf/basic/EpsilonTest.h>
36 #include <ogdf/basic/Graph.h>
38 #include <ogdf/basic/GraphCopy.h>
39 #include <ogdf/basic/GraphList.h>
40 #include <ogdf/basic/GraphSets.h>
41 #include <ogdf/basic/List.h>
42 #include <ogdf/basic/basic.h>
46 
47 #include <algorithm>
48 #include <cstdint>
49 #include <string>
50 
51 namespace ogdf {
52 
83 template<typename TWeight>
84 class SpannerKortsarzPeleg : public SpannerModule<TWeight> {
88 
89 public:
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 
112 private:
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<true> 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<true> 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 
227 };
228 
229 }
ogdf::GraphAttributes::edgeIntWeight
static const long edgeIntWeight
Corresponds to edge attribute intWeight(edge).
Definition: GraphAttributes.h:125
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::GraphAttributes
Stores additional attributes of a graph (like layout information).
Definition: GraphAttributes.h:72
GraphAttributes.h
Declaration of class GraphAttributes which extends a Graph by additional attributes.
ogdf::SpannerModule::isTimelimitEnabled
bool isTimelimitEnabled()
Definition: SpannerModule.h:167
ogdf::GraphCopySimple::delEdge
void delEdge(edge e) override
Removes edge e.
ogdf::SpannerKortsarzPeleg::preconditionsOk
virtual bool preconditionsOk(const GraphAttributes &GA, double stretch, std::string &error) override
Definition: SpannerKortsarzPeleg.h:91
ogdf::SpannerModule::TimeoutException
Definition: SpannerModule.h:189
EpsilonTest.h
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Graph.h
Includes declaration of graph class.
ogdf::EpsilonTest
Definition: EpsilonTest.h:39
ogdf::GraphCopySimple::copy
edge copy(edge e) const override
Returns the edge in the graph copy corresponding to e.
Definition: GraphCopy.h:295
ogdf::SpannerModule::m_spanner
GraphCopySimple * m_spanner
Definition: SpannerModule.h:136
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::SpannerKortsarzPeleg::addToSpanner
void addToSpanner(edge e)
Adds e from m_G to the spanner and sets inSpanner.
Definition: SpannerKortsarzPeleg.h:216
ogdf::SpannerModule::init
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner)
Initializes members and create an empty spanner.
Definition: SpannerModule.h:142
MaximumDensitySubgraph.h
Declares maximum density subgraph algorithms.
ogdf::NodeSet::nodes
const RS::list_type & nodes()
Returns a reference to the list of nodes contained in this set.
Definition: GraphSets.h:70
ogdf::SpannerKortsarzPeleg::init
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner) override
Initializes members and create an empty spanner.
Definition: SpannerKortsarzPeleg.h:113
ogdf::NodeSet< true >
ogdf::GraphCopySimple
Copies of graphs with mapping between nodes and edges.
Definition: GraphCopy.h:261
ogdf::RegisteredSet::size
int size() const
Returns the number of elements in this set.
Definition: RegisteredSet.h:153
ogdf::GraphCopySimple::setOriginalGraph
void setOriginalGraph(const Graph *G) override
Re-initializes the copy using G (which might be null), but does not create any nodes or edges.
ogdf::GraphAttributes::directed
bool directed() const
Returns if the graph is directed.
Definition: GraphAttributes.h:232
ogdf::GraphAttributes::constGraph
const Graph & constGraph() const
Returns a reference to the associated graph.
Definition: GraphAttributes.h:223
GraphSets.h
Declaration and implementation of NodeSet, EdgeSet, and AdjEntrySet classes.
SpannerModule.h
Basic module for spanner algorithms.
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::EpsilonTest::less
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
ogdf::maximumDensitySubgraph
bool maximumDensitySubgraph(Graph &G, NodeSet< true > &subgraphNodes, std::function< node(node)> resultNodeMap=[](node v) { return v;}, int64_t timelimit=-1)
Calculates the maximum density subgraph of G.
ogdf::GraphCopyBase::init
void init(const Graph &G)
Re-initializes the copy using G, creating copies for all nodes and edges in G.
Definition: GraphCopy.h:73
ogdf::Graph::nodes
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition: Graph_d.h:932
ogdf::SpannerModule::getTimeLeft
int64_t getTimeLeft()
Definition: SpannerModule.h:172
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:271
ogdf::SpannerKortsarzPeleg::m_G
GraphCopySimple m_G
The copy of GA.constGraph() to work on. Edges will be removed in each iteration.
Definition: SpannerKortsarzPeleg.h:86
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
ogdf::GraphCopyBase::newNode
node newNode(node vOrig)
Creates a new node in the graph copy with original node vOrig.
Definition: GraphCopy.h:192
GraphCopy.h
Declaration of graph copy classes.
ogdf::List< edge >
ogdf::RegisteredSet::isMember
bool isMember(element_type v) const
Returns true iff element v is contained in this set.
Definition: RegisteredSet.h:138
ogdf::SpannerModule
Interface for spanner algorithms.
Definition: SpannerModule.h:63
ogdf::EpsilonTest::greater
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.
Definition: EpsilonTest.h:159
ogdf::SpannerKortsarzPeleg::execute
virtual SpannerModule< TWeight >::ReturnType execute() override
Executes the core algorithm.
Definition: SpannerKortsarzPeleg.h:120
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
ogdf::GraphCopySimple::clear
void clear() override
Removes all nodes and edges from this copy but does not break the link with the original graph.
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:935
basic.h
Basic declarations, included by all source files.
ogdf::SpannerKortsarzPeleg::m_eps
EpsilonTest m_eps
Definition: SpannerKortsarzPeleg.h:87
ogdf::SpannerModule::m_GA
const GraphAttributes * m_GA
Definition: SpannerModule.h:134
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
ogdf::Graph::searchEdge
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 ))).
List.h
Declaration of doubly linked lists and iterators.
ogdf::List::size
int size() const
Returns the number of elements in the list.
Definition: List.h:1488
ogdf::GraphAttributes::edgeDoubleWeight
static const long edgeDoubleWeight
Corresponds to edge attribute doubleWeight(edge).
Definition: GraphAttributes.h:128
ogdf::SpannerKortsarzPeleg
Approximation multiplicative 2-spanner calculation.
Definition: SpannerKortsarzPeleg.h:84
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::Module::ReturnType
ReturnType
The return type of a module.
Definition: Module.h:52
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::GraphCopySimple::newEdge
edge newEdge(edge eOrig)
Creates a new edge in the graph copy with original edge eOrig.
Definition: GraphCopy.h:321
ogdf::isSimple
bool isSimple(const Graph &G)
Returns true iff G contains neither self-loops nor parallel edges.
Definition: simple_graph_alg.h:402
simple_graph_alg.h
Declaration of simple graph algorithms.
ogdf::GraphAttributes::has
bool has(long attr) const
Returns true iff all attributes in attr are available.
Definition: GraphAttributes.h:200
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1547
ogdf::GraphCopyBase::original
const Graph & original() const
Returns a reference to the original graph.
Definition: GraphCopy.h:105
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716