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) {
148  edgeInserted(cbData, eG, e);
149  for (GraphObserver* obs : getObservers()) {
150  obs->edgeAdded(e);
151  }
152  }
153  }
154  }
155 
156  if (!copyEmbedding) {
157 #ifdef OGDF_HEAVY_DEBUG
159 #endif
160  postInsert(cbData, newNodes, newEdges);
161  return {newNodes, newEdges};
162  }
163 
164  for (auto it = nodesBegin; it != nodesEnd; ++it) {
165  node vG = *it;
166  node v = nodeMap[vG];
167  for (adjEntry adjG : vG->adjEntries) {
168  edge eG = adjG->theEdge();
169  edge e = edgeMap[eG];
170  if (e == nullptr) {
171  continue;
172  }
173  adjEntry adj = adjG->isSource() ? e->adjSource() : e->adjTarget();
174  // edgeMap[eG] might be an old entry that was already inserted into the list
175  // so check whether adj is already in the list, indicated by having succ or pred,
176  // or being the only entry in the list
177  if (adj->succ() != nullptr || adj->pred() != nullptr || v->adjEntries.head() == adj) {
178  continue;
179  }
180  v->adjEntries.pushBack(adj);
181  }
182  }
183 
184  // notify observers of added edges after adjEntries are initialized
185  if (notifyObservers) {
186  m_regEdgeArrays.reserveSpace(newEdges);
187  m_regAdjArrays.reserveSpace(newEdges); // registry adds factor 2 in calculateArraySize
188 
189  for (auto it = edgesBegin; it != edgesEnd; ++it) {
190  edge eG = *it;
191  edge e = edgeMap[eG];
192  if (nodeMap[eG->source()] == nullptr || nodeMap[eG->target()] == nullptr) {
193  continue;
194  }
195  OGDF_ASSERT(e != nullptr);
198  edgeInserted(cbData, eG, e);
199  for (GraphObserver* obs : getObservers()) {
200  obs->edgeAdded(e);
201  }
202  }
203  }
204 
205 #ifdef OGDF_HEAVY_DEBUG
207 #endif
208 
209  postInsert(cbData, newNodes, newEdges);
210  return {newNodes, newEdges};
211 }
212 
213 template<OGDF_NODE_ITER NI, OGDF_EDGE_FILTER EF, bool copyIDs, bool notifyObservers>
214 std::pair<int, int> Graph::insert(const NI& nodesBegin, const NI& nodesEnd, const EF& edgeFilter,
215  NodeArray<node>& nodeMap, EdgeArray<edge>& edgeMap) {
216  OGDF_ASSERT(nodeMap.valid());
217  OGDF_ASSERT(edgeMap.valid());
218  OGDF_ASSERT(nodeMap.graphOf() == edgeMap.graphOf());
219  int newNodes = 0, newEdges = 0;
220  void* cbData =
221  preInsert(true, copyIDs, notifyObservers, true, nodeMap, edgeMap, &newNodes, &newEdges);
222  if (nodesBegin == nodesEnd) {
223  postInsert(cbData, newNodes, newEdges);
224  return {newNodes, newEdges};
225  }
226  insertNodes<NI, notifyObservers, copyIDs>(nodesBegin, nodesEnd, nodeMap, newNodes, cbData);
227 
228  for (auto it = nodesBegin; it != nodesEnd; ++it) {
229  node vG = *it;
230  node v = nodeMap[vG];
231  for (adjEntry adjG : vG->adjEntries) {
232  edge eG = adjG->theEdge();
233  if (!edgeFilter(eG)) {
234  continue;
235  }
236  // edgeMap[eG] is *not* overwritten if it is != nullptr
237  edge e = edgeMap[eG];
238  if (e == nullptr) {
239  // add the first adjEntry of the edge
240  node twin = nodeMap[adjG->twinNode()];
241  if (twin == nullptr) {
242  // we can be sure that the other adjEntry wasn't selected and
243  // we thus cannot add this (selected) edge
244  continue;
245  }
246  if (copyIDs) {
247  m_edgeIdCount = max(m_edgeIdCount, eG->index() + 1);
248  }
249  if (adjG->isSource()) {
250  e = edgeMap[eG] = pureNewEdge(v, twin, copyIDs ? eG->index() : m_edgeIdCount++);
251  v->adjEntries.pushBack(e->m_adjSrc);
252  } else {
253  e = edgeMap[eG] = pureNewEdge(twin, v, copyIDs ? eG->index() : m_edgeIdCount++);
254  v->adjEntries.pushBack(e->m_adjTgt);
255  }
256  newEdges++;
257  } else {
258  // complete the edge with its second adjEntry
259  adjEntry adj = adjG->isSource() ? e->adjSource() : e->adjTarget();
260  // edgeMap[eG] might be an old entry that was already inserted into the list
261  // so check whether adj is already in the list, indicated by having succ or pred,
262  // or being the only entry in the list
263  if (adj->succ() == nullptr && adj->pred() == nullptr && v->adjEntries.head() != adj) {
264  v->adjEntries.pushBack(adj);
265  // at this point, other edges might still be incomplete, so we cannot call observers
266  }
267  }
268  }
269  }
270 
271  // notify observers of added edges after all adjEntries are initialized
272  if (notifyObservers) {
273  m_regEdgeArrays.reserveSpace(newEdges);
274  m_regAdjArrays.reserveSpace(newEdges); // registry adds factor 2 in calculateArraySize
275 
276  for (auto it = nodesBegin; it != nodesEnd; ++it) {
277  node vG = *it;
278  for (adjEntry adjG : vG->adjEntries) {
279  if (!adjG->isSource()) {
280  continue;
281  }
282  edge eG = adjG->theEdge();
283  edge e = edgeMap[eG];
284  // we will call Observers for *all* edgeMap entries
285  if (e == nullptr) {
286  continue;
287  }
290  edgeInserted(cbData, eG, e);
291  for (GraphObserver* obs : getObservers()) {
292  obs->edgeAdded(e);
293  }
294  }
295  }
296  }
297 
298 #ifdef OGDF_HEAVY_DEBUG
300 #endif
301 
302  postInsert(cbData, newNodes, newEdges);
303  return {newNodes, newEdges};
304 }
305 
306 }
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:1971
ogdf::AdjElement::pred
adjEntry pred() const
Returns the predecessor in the adjacency list.
Definition: Graph_d.h:221
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:2002
ogdf::internal::GraphRegisteredArray::graphOf
Graph * graphOf() const
Returns a pointer to the associated graph.
Definition: Graph_d.h:665
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:274
ogdf::Graph::m_regEdgeArrays
internal::GraphEdgeRegistry m_regEdgeArrays
The registered edge arrays.
Definition: Graph_d.h:881
ogdf::EdgeElement::index
int index() const
Returns the index of the edge.
Definition: Graph_d.h:395
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:1903
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:1885
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:142
ogdf::AdjElement::isSource
bool isSource() const
Returns true iff this is the source adjacency entry of the corresponding edge.
Definition: Graph_d.h:479
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:160
ogdf::EdgeElement::m_adjTgt
AdjElement * m_adjTgt
Corresponding adjacency entry at target node.
Definition: Graph_d.h:370
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:878
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:218
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::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:398
ogdf::GraphObserver
Abstract Base class for graph observers.
Definition: Graph_d.h:777
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
ogdf::RegistryBase::keyAdded
void keyAdded(Key key)
Records the addition of a new key and resizes all registered arrays if necessary.
Definition: RegisteredArray.h:171
ogdf::EdgeElement::adjSource
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition: Graph_d.h:407
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:1873
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:175
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:877
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:410
ogdf::EdgeElement::m_adjSrc
AdjElement * m_adjSrc
Corresponding adjacency entry at source node.
Definition: Graph_d.h:369
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:880
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
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:1894
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
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:240
ogdf::Graph::m_regAdjArrays
internal::GraphAdjRegistry m_regAdjArrays
The registered adjEntry arrays.
Definition: Graph_d.h:882
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::RegistryBase::reserveSpace
void reserveSpace(int new_keys)
Resizes all arrays to make space of new_keys new keys.
Definition: RegisteredArray.h:206