Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
InducedSubgraph.h
Go to the documentation of this file.
1
32#pragma once
33
34#include <ogdf/basic/Graph.h>
36#include <ogdf/basic/List.h>
37#include <ogdf/basic/basic.h>
38#include <ogdf/basic/internal/config_autogen.h>
40
41#include <algorithm>
42#include <cstddef>
43#include <iterator>
44#include <type_traits>
45#include <utility>
46
47namespace ogdf {
48
49namespace internal {
50template<class T, class = void>
51struct is_iterator : std::false_type { };
52
53template<class T>
54struct is_iterator<T, std::void_t<typename std::iterator_traits<T>::iterator_category>>
55 : std::true_type { };
56
57template<typename Iterator>
58typename std::enable_if<!is_iterator<Iterator>::value, size_t>::type guess_dist(Iterator, Iterator) {
59 return 0;
60}
61
62template<typename Iterator>
63typename std::enable_if<is_iterator<Iterator>::value,
64 typename std::iterator_traits<Iterator>::difference_type>::type
65guess_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
75template<OGDF_NODE_ITER NI, bool notifyObservers, bool copyIDs>
76void 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
101template<OGDF_NODE_ITER NI, OGDF_EDGE_ITER EI, bool copyEmbedding, bool copyIDs, bool notifyObservers>
102std::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) {
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
215template<OGDF_NODE_ITER NI, OGDF_EDGE_FILTER EF, bool copyIDs, bool notifyObservers>
216std::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) {
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}
Includes declaration of graph class.
Decralation of GraphElement and GraphList classes.
Declaration of doubly linked lists and iterators.
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
adjEntry pred() const
Returns the predecessor in the adjacency list.
Definition Graph_d.h:222
adjEntry succ() const
Returns the successor in the adjacency list.
Definition Graph_d.h:219
bool isSource() const
Returns true iff this is the source adjacency entry of the corresponding edge.
Definition Graph_d.h:480
Class for the representation of edges.
Definition Graph_d.h:364
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition Graph_d.h:408
int index() const
Returns the index of the edge.
Definition Graph_d.h:396
AdjElement * m_adjSrc
Corresponding adjacency entry at source node.
Definition Graph_d.h:370
AdjElement * m_adjTgt
Corresponding adjacency entry at target node.
Definition Graph_d.h:371
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition Graph_d.h:411
node target() const
Returns the target node of the edge.
Definition Graph_d.h:402
node source() const
Returns the source node of the edge.
Definition Graph_d.h:399
internal::GraphEdgeRegistry m_regEdgeArrays
The registered edge arrays.
Definition Graph_d.h:878
internal::GraphAdjRegistry m_regAdjArrays
The registered adjEntry arrays.
Definition Graph_d.h:879
int m_edgeIdCount
The Index that will be assigned to the next created edge.
Definition Graph_d.h:875
int m_nodeIdCount
The Index that will be assigned to the next created node.
Definition Graph_d.h:874
virtual void postInsert(void *userData, int newNodes, int newEdges)
Callback notifying subclasses that an insert() call has finished.
Definition Graph_d.h:1891
virtual void nodeInserted(void *userData, node original, node copy)
Callback notifying subclasses that insert() copied a node.
Definition Graph_d.h:1873
void consistencyCheck() const
Asserts that this graph is consistent.
void insertNodes(const NI &nodesBegin, const NI &nodesEnd, NodeArray< node, true > &nodeMap, int &newNodes, void *cbData)
internal::GraphNodeRegistry m_regNodeArrays
The registered node arrays.
Definition Graph_d.h:877
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
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
virtual void edgeInserted(void *userData, edge original, edge copy)
Callback notifying subclasses that insert() copied an edge.
Definition Graph_d.h:1882
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.
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
Abstract Base class for graph observers.
Definition Graph_d.h:775
Class for the representation of nodes.
Definition Graph_d.h:241
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition Graph_d.h:272
int index() const
Returns the (unique) node index.
Definition Graph_d.h:275
const ListPure< GraphObserver * > & getObservers() const
Definition Observer.h:206
void keyAdded(Key key)
Records the addition of a new key and resizes all registered arrays if necessary.
void reserveSpace(int new_keys)
Resizes all arrays to make space of new_keys new keys.
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition Graph_d.h:717
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
Graph * graphOf() const
Returns a pointer to the associated graph.
Definition Graph_d.h:666
Decralation of graph iterators.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
std::enable_if<!is_iterator< Iterator >::value, size_t >::type guess_dist(Iterator, Iterator)
The namespace for all OGDF objects.
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
void copyEmbedding(const Graph &from, Graph &to, std::function< adjEntry(adjEntry)> adjMapFromTo)
HypergraphRegistry< HypernodeElement >::iterator end(const HypergraphRegistry< HypernodeElement > &self)
Definition GML.h:111