Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

InducedSubgraph.h
Go to the documentation of this file.
1 
32 #pragma once
33 
34 #include <ogdf/basic/Graph.h>
35 #include <ogdf/basic/GraphList.h>
36 #include <ogdf/basic/List.h>
37 #include <ogdf/basic/basic.h>
40 
41 #include <algorithm>
42 #include <cstddef>
43 #include <iterator>
44 #include <type_traits>
45 #include <utility>
46 
47 namespace ogdf {
48 
49 namespace internal {
50 template<class T, class = void>
51 struct is_iterator : std::false_type { };
52 
53 template<class T>
54 struct is_iterator<T, std::void_t<typename std::iterator_traits<T>::iterator_category>>
55  : std::true_type { };
56 
57 template<typename Iterator>
58 typename std::enable_if<!is_iterator<Iterator>::value, size_t>::type guess_dist(Iterator, Iterator) {
59  return 0;
60 }
61 
62 template<typename Iterator>
63 typename std::enable_if<is_iterator<Iterator>::value,
64  typename std::iterator_traits<Iterator>::difference_type>::type
65 guess_dist([[maybe_unused]] Iterator begin, [[maybe_unused]] Iterator end) {
66  if constexpr (std::is_same<typename std::iterator_traits<Iterator>::iterator_category,
67  std::random_access_iterator_tag>::value) {
68  return end - begin;
69  } else {
70  return 0;
71  }
72 }
73 }
74 
75 template<OGDF_NODE_ITER NI, bool notifyObservers, bool copyIDs>
76 void Graph::insertNodes(const NI& nodesBegin, const NI& nodesEnd, NodeArray<node, true>& nodeMap,
77  int& newNodes, void* cbData) {
78  int guessedNodes = internal::guess_dist(nodesBegin, nodesEnd);
79  if (guessedNodes > 0 && notifyObservers) {
80  m_regNodeArrays.reserveSpace(guessedNodes);
81  }
82 
83  for (auto it = nodesBegin; it != nodesEnd; ++it) {
84  node vG = *it;
85  if (copyIDs) {
86  m_nodeIdCount = max(m_nodeIdCount, vG->index() + 1);
87  }
88  // nodeMap[vG] is overwritten if it is != nullptr
89  node v = nodeMap[vG] = pureNewNode(copyIDs ? vG->index() : m_nodeIdCount++);
90  newNodes++;
91  if (notifyObservers) {
93  nodeInserted(cbData, vG, v);
94  for (GraphObserver* obs : getObservers()) {
95  obs->nodeAdded(v);
96  }
97  }
98  }
99 }
100 
101 template<OGDF_NODE_ITER NI, OGDF_EDGE_ITER EI, bool copyEmbedding, bool copyIDs, bool notifyObservers>
102 std::pair<int, int> Graph::insert(const NI& nodesBegin, const NI& nodesEnd, const EI& edgesBegin,
103  const EI& edgesEnd, NodeArray<node>& nodeMap, EdgeArray<edge>& edgeMap) {
104  OGDF_ASSERT(nodeMap.valid());
105  OGDF_ASSERT(edgeMap.valid());
106  OGDF_ASSERT(nodeMap.graphOf() == edgeMap.graphOf());
107  int newNodes = 0, newEdges = 0;
108  void* cbData = preInsert(copyEmbedding, copyIDs, notifyObservers, false, nodeMap, edgeMap,
109  &newNodes, &newEdges);
110  if (nodesBegin == nodesEnd) {
111  postInsert(cbData, newNodes, newEdges);
112  return {newNodes, newEdges};
113  }
114  insertNodes<NI, notifyObservers, copyIDs>(nodesBegin, nodesEnd, nodeMap, newNodes, cbData);
115 
116  if (edgesBegin == edgesEnd) {
117  postInsert(cbData, newNodes, newEdges);
118  return {newNodes, newEdges};
119  }
120 
121  if (!copyEmbedding && notifyObservers) {
122  int guessedEdges = internal::guess_dist(edgesBegin, edgesEnd);
123  if (guessedEdges > 0) {
124  m_regEdgeArrays.reserveSpace(guessedEdges);
125  m_regAdjArrays.reserveSpace(guessedEdges); // registry adds factor 2 in calculateArraySize
126  }
127  }
128 
129  for (auto it = edgesBegin; it != edgesEnd; ++it) {
130  edge eG = *it;
131  node src = nodeMap[eG->source()];
132  node tgt = nodeMap[eG->target()];
133  if (src == nullptr || tgt == nullptr) {
134  continue;
135  }
136  if (copyIDs) {
137  m_edgeIdCount = max(m_edgeIdCount, eG->index() + 1);
138  }
139  // edgeMap[eG] is overwritten, even if it is != nullptr
140  edge e = edgeMap[eG] = pureNewEdge(src, tgt, copyIDs ? eG->index() : m_edgeIdCount++);
141  newEdges++;
142  if (!copyEmbedding) {
143  src->adjEntries.pushBack(e->m_adjSrc);
144  tgt->adjEntries.pushBack(e->m_adjTgt);
145  if (notifyObservers) {
149  edgeInserted(cbData, eG, e);
150  for (GraphObserver* obs : getObservers()) {
151  obs->edgeAdded(e);
152  }
153  }
154  }
155  }
156 
157  if (!copyEmbedding) {
158 #ifdef OGDF_HEAVY_DEBUG
160 #endif
161  postInsert(cbData, newNodes, newEdges);
162  return {newNodes, newEdges};
163  }
164 
165  for (auto it = nodesBegin; it != nodesEnd; ++it) {
166  node vG = *it;
167  node v = nodeMap[vG];
168  for (adjEntry adjG : vG->adjEntries) {
169  edge eG = adjG->theEdge();
170  edge e = edgeMap[eG];
171  if (e == nullptr) {
172  continue;
173  }
174  adjEntry adj = adjG->isSource() ? e->adjSource() : e->adjTarget();
175  // edgeMap[eG] might be an old entry that was already inserted into the list
176  // so check whether adj is already in the list, indicated by having succ or pred,
177  // or being the only entry in the list
178  if (adj->succ() != nullptr || adj->pred() != nullptr || v->adjEntries.head() == adj) {
179  continue;
180  }
181  v->adjEntries.pushBack(adj);
182  }
183  }
184 
185  // notify observers of added edges after adjEntries are initialized
186  if (notifyObservers) {
187  m_regEdgeArrays.reserveSpace(newEdges);
188  m_regAdjArrays.reserveSpace(newEdges); // registry adds factor 2 in calculateArraySize
189 
190  for (auto it = edgesBegin; it != edgesEnd; ++it) {
191  edge eG = *it;
192  edge e = edgeMap[eG];
193  if (nodeMap[eG->source()] == nullptr || nodeMap[eG->target()] == nullptr) {
194  continue;
195  }
196  OGDF_ASSERT(e != nullptr);
200  edgeInserted(cbData, eG, e);
201  for (GraphObserver* obs : getObservers()) {
202  obs->edgeAdded(e);
203  }
204  }
205  }
206 
207 #ifdef OGDF_HEAVY_DEBUG
209 #endif
210 
211  postInsert(cbData, newNodes, newEdges);
212  return {newNodes, newEdges};
213 }
214 
215 template<OGDF_NODE_ITER NI, OGDF_EDGE_FILTER EF, bool copyIDs, bool notifyObservers>
216 std::pair<int, int> Graph::insert(const NI& nodesBegin, const NI& nodesEnd, const EF& edgeFilter,
217  NodeArray<node>& nodeMap, EdgeArray<edge>& edgeMap) {
218  OGDF_ASSERT(nodeMap.valid());
219  OGDF_ASSERT(edgeMap.valid());
220  OGDF_ASSERT(nodeMap.graphOf() == edgeMap.graphOf());
221  int newNodes = 0, newEdges = 0;
222  void* cbData =
223  preInsert(true, copyIDs, notifyObservers, true, nodeMap, edgeMap, &newNodes, &newEdges);
224  if (nodesBegin == nodesEnd) {
225  postInsert(cbData, newNodes, newEdges);
226  return {newNodes, newEdges};
227  }
228  insertNodes<NI, notifyObservers, copyIDs>(nodesBegin, nodesEnd, nodeMap, newNodes, cbData);
229 
230  for (auto it = nodesBegin; it != nodesEnd; ++it) {
231  node vG = *it;
232  node v = nodeMap[vG];
233  for (adjEntry adjG : vG->adjEntries) {
234  edge eG = adjG->theEdge();
235  if (!edgeFilter(eG)) {
236  continue;
237  }
238  // edgeMap[eG] is *not* overwritten if it is != nullptr
239  edge e = edgeMap[eG];
240  if (e == nullptr) {
241  // add the first adjEntry of the edge
242  node twin = nodeMap[adjG->twinNode()];
243  if (twin == nullptr) {
244  // we can be sure that the other adjEntry wasn't selected and
245  // we thus cannot add this (selected) edge
246  continue;
247  }
248  if (copyIDs) {
249  m_edgeIdCount = max(m_edgeIdCount, eG->index() + 1);
250  }
251  if (adjG->isSource()) {
252  e = edgeMap[eG] = pureNewEdge(v, twin, copyIDs ? eG->index() : m_edgeIdCount++);
253  v->adjEntries.pushBack(e->m_adjSrc);
254  } else {
255  e = edgeMap[eG] = pureNewEdge(twin, v, copyIDs ? eG->index() : m_edgeIdCount++);
256  v->adjEntries.pushBack(e->m_adjTgt);
257  }
258  newEdges++;
259  } else {
260  // complete the edge with its second adjEntry
261  adjEntry adj = adjG->isSource() ? e->adjSource() : e->adjTarget();
262  // edgeMap[eG] might be an old entry that was already inserted into the list
263  // so check whether adj is already in the list, indicated by having succ or pred,
264  // or being the only entry in the list
265  if (adj->succ() == nullptr && adj->pred() == nullptr && v->adjEntries.head() != adj) {
266  v->adjEntries.pushBack(adj);
267  // at this point, other edges might still be incomplete, so we cannot call observers
268  }
269  }
270  }
271  }
272 
273  // notify observers of added edges after all adjEntries are initialized
274  if (notifyObservers) {
275  m_regEdgeArrays.reserveSpace(newEdges);
276  m_regAdjArrays.reserveSpace(newEdges); // registry adds factor 2 in calculateArraySize
277 
278  for (auto it = nodesBegin; it != nodesEnd; ++it) {
279  node vG = *it;
280  for (adjEntry adjG : vG->adjEntries) {
281  if (!adjG->isSource()) {
282  continue;
283  }
284  edge eG = adjG->theEdge();
285  edge e = edgeMap[eG];
286  // we will call Observers for *all* edgeMap entries
287  if (e == nullptr) {
288  continue;
289  }
293  edgeInserted(cbData, eG, e);
294  for (GraphObserver* obs : getObservers()) {
295  obs->edgeAdded(e);
296  }
297  }
298  }
299  }
300 
301 #ifdef OGDF_HEAVY_DEBUG
303 #endif
304 
305  postInsert(cbData, newNodes, newEdges);
306  return {newNodes, newEdges};
307 }
308 
309 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
Graph.h
Includes declaration of graph class.
ogdf::Graph::pureNewNode
node pureNewNode(int index)
Creates a new node object with id index and adds it to the list of nodes.
Definition: Graph_d.h:1959
ogdf::AdjElement::pred
adjEntry pred() const
Returns the predecessor in the adjacency list.
Definition: Graph_d.h:222
ogdf::Graph::pureNewEdge
edge pureNewEdge(node src, node tgt, int index)
Creates a new edge object with id index and corresponding AdjElements and adds it to the list of edge...
Definition: Graph_d.h:1990
ogdf::internal::GraphRegisteredArray::graphOf
Graph * graphOf() const
Returns a pointer to the associated graph.
Definition: Graph_d.h:666
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::begin
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
ogdf::NodeElement::index
int index() const
Returns the (unique) node index.
Definition: Graph_d.h:275
ogdf::Graph::m_regEdgeArrays
internal::GraphEdgeRegistry m_regEdgeArrays
The registered edge arrays.
Definition: Graph_d.h:878
ogdf::EdgeElement::index
int index() const
Returns the index of the edge.
Definition: Graph_d.h:396
ogdf::Graph::insertNodes
void insertNodes(const NI &nodesBegin, const NI &nodesEnd, NodeArray< node, true > &nodeMap, int &newNodes, void *cbData)
Definition: InducedSubgraph.h:76
ogdf::Graph::postInsert
virtual void postInsert(void *userData, int newNodes, int newEdges)
Callback notifying subclasses that an insert() call has finished.
Definition: Graph_d.h:1891
ogdf::internal::is_iterator
Definition: InducedSubgraph.h:51
ogdf::Graph::nodeInserted
virtual void nodeInserted(void *userData, node original, node copy)
Callback notifying subclasses that insert() copied a node.
Definition: Graph_d.h:1873
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:143
ogdf::AdjElement::isSource
bool isSource() const
Returns true iff this is the source adjacency entry of the corresponding edge.
Definition: Graph_d.h:480
ogdf::internal::guess_dist
std::enable_if<!is_iterator< Iterator >::value, size_t >::type guess_dist(Iterator, Iterator)
Definition: InducedSubgraph.h:58
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:161
ogdf::EdgeElement::m_adjTgt
AdjElement * m_adjTgt
Corresponding adjacency entry at target node.
Definition: Graph_d.h:371
ogdf::Observable< GraphObserver, Graph >::getObservers
const ListPure< GraphObserver * > & getObservers() const
Definition: Observer.h:206
ogdf::Graph::m_edgeIdCount
int m_edgeIdCount
The Index that will be assigned to the next created edge.
Definition: Graph_d.h:875
backward::Color::type
type
Definition: backward.hpp:1716
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::AdjElement::succ
adjEntry succ() const
Returns the successor in the adjacency list.
Definition: Graph_d.h:219
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:272
ogdf::Graph::consistencyCheck
void consistencyCheck() const
Asserts that this graph is consistent.
config_autogen.h
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:399
ogdf::GraphObserver
Abstract Base class for graph observers.
Definition: Graph_d.h:775
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:659
ogdf::RegistryBase::keyAdded
void keyAdded(Key key)
Records the addition of a new key and resizes all registered arrays if necessary.
Definition: RegisteredArray.h:203
ogdf::EdgeElement::adjSource
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition: Graph_d.h:408
ogdf::Graph::preInsert
virtual void * preInsert(bool copyEmbedding, bool copyIDs, bool notifyObservers, bool edgeFilter, NodeArray< node > &nodeMap, EdgeArray< edge > &edgeMap, int *newNodes, int *newEdges)
Callback notifying subclasses that some graph is about to be insert() -ed.
Definition: Graph_d.h:1861
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:176
graph_iterators.h
Decralation of graph iterators.
ogdf::Graph::m_nodeIdCount
int m_nodeIdCount
The Index that will be assigned to the next created node.
Definition: Graph_d.h:874
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:411
ogdf::EdgeElement::m_adjSrc
AdjElement * m_adjSrc
Corresponding adjacency entry at source node.
Definition: Graph_d.h:370
ogdf::Graph::insert
std::pair< int, int > insert(const NI &nodesBegin, const NI &nodesEnd, const EI &edgesBegin, const EI &edgesEnd, NodeArray< node > &nodeMap, EdgeArray< edge > &edgeMap)
Inserts a copy of a given subgraph into this graph.
Definition: InducedSubgraph.h:102
basic.h
Basic declarations, included by all source files.
std
Definition: GML.h:111
ogdf::end
HypergraphRegistry< HypernodeElement >::iterator end(const HypergraphRegistry< HypernodeElement > &self)
ogdf::Graph::m_regNodeArrays
internal::GraphNodeRegistry m_regNodeArrays
The registered node arrays.
Definition: Graph_d.h:877
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:364
List.h
Declaration of doubly linked lists and iterators.
ogdf::Graph::edgeInserted
virtual void edgeInserted(void *userData, edge original, edge copy)
Callback notifying subclasses that insert() copied an edge.
Definition: Graph_d.h:1882
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:402
ogdf::copyEmbedding
void copyEmbedding(const Graph &from, Graph &to, std::function< adjEntry(adjEntry)> adjMapFromTo)
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:241
ogdf::Graph::m_regAdjArrays
internal::GraphAdjRegistry m_regAdjArrays
The registered adjEntry arrays.
Definition: Graph_d.h:879
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:717
ogdf::RegistryBase::reserveSpace
void reserveSpace(int new_keys)
Resizes all arrays to make space of new_keys new keys.
Definition: RegisteredArray.h:249