Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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