1 /** \file
2  * \brief Declaration of class PlanRepExpansion representing a
3  *        planarized representation of the expansion of a graph.
4  *
5  * \author Carsten Gutwenger
6  *
7  * \par License:
8  * This file is part of the Open Graph Drawing Framework (OGDF).
9  *
10  * \par
11  * Copyright (C)<br>
12  * See README.md in the OGDF root directory for details.
13  *
14  * \par
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * Version 2 or 3 as published by the Free Software Foundation;
18  * see the file LICENSE.txt included in the packaging of this file
19  * for details.
20  *
21  * \par
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * \par
28  * You should have received a copy of the GNU General Public
29  * License along with this program; if not, see
30  * http://www.gnu.org/copyleft/gpl.html
31  */
32 
33 #pragma once
34 
35 #include <ogdf/basic/Graph.h>
36 #include <ogdf/basic/tuples.h>
37 #include <ogdf/basic/SList.h>
38 
39 #include <ogdf/basic/CombinatorialEmbedding.h>
40 #include <ogdf/basic/FaceSet.h>
41 #include <ogdf/basic/NodeSet.h>
42 
43 
44 namespace ogdf {
45 
46 /**
47  * \brief Planarized representations (of a connected component) of a graph.
48  *
49  * @ingroup plan-rep
50  *
51  * Maintains types of edges (generalization, association) and nodes,
52  * and the connected components of the graph.
53  */
54 class OGDF_EXPORT PlanRepExpansion : public Graph
55 {
56 public:
57 	struct Crossing {
CrossingCrossing58 		Crossing() { m_adj = nullptr; }
CrossingCrossing59 		explicit Crossing(adjEntry adj) { m_adj = adj; }
60 
61 		adjEntry m_adj;
62 		SList<adjEntry> m_partitionLeft;
63 		SList<adjEntry> m_partitionRight;
64 
65 		friend std::ostream &operator<<(std::ostream &os, const Crossing &c) {
66 			os << "(" << c.m_adj << ")";
67 			return os;
68 		}
69 	};
70 
71 
72 	/**
73 	 * \brief Representation of a node split in a planarized expansion.
74 	 *
75 	 * Stores in particular the insertion path of the node split (just like the
76 	 * chain of an original edge).
77 	 */
78 	class NodeSplit
79 	{
80 	public:
81 		/**
82 		 * \brief Creates an empty node split.
83 		 */
NodeSplit()84 		NodeSplit() { }
85 
86 		/**
87 		 * \brief Creates a node split and sets its iterator in the list of all node splits.
88 		 */
NodeSplit(ListIterator<NodeSplit> it)89 		explicit NodeSplit(ListIterator<NodeSplit> it) : m_nsIterator(it) { }
90 
91 		/**
92 		 * \brief Returns the first node on the node split's insertion path.
93 		 */
source()94 		node source() const { return m_path.front()->source(); }
95 
96 		/**
97 		 * \brief Returns the last node on the node split's insertion path.
98 		 */
target()99 		node target() const { return m_path.back ()->target(); }
100 
101 		List<edge> m_path; //!< The insertion path of the node split.
102 		ListIterator<NodeSplit> m_nsIterator; //!< This node split's iterator in the list of all node splits.
103 	};
104 
105 	//! Pointer to a node split.
106 	using nodeSplit = PlanRepExpansion::NodeSplit*;
107 
108 
109 	/**
110 	 * \brief Creates a planarized expansion of graph \p G.
111 	 *
112 	 * All nodes are allowed to be split.
113 	 */
114 	PlanRepExpansion(const Graph& G);
115 
116 	/**
117 	 * \brief Creates a planarized expansion of graph \p G with given splittable nodes.
118 	 *
119 	 * Only the node in \p splittableNodes are allowed to be split.
120 	 * @param G is the original graph of this planarized expansion.
121 	 * @param splittableNodes contains all the nodes in \p G that are splittable.
122 	 */
123 	PlanRepExpansion(const Graph& G, const List<node> &splittableNodes);
124 
~PlanRepExpansion()125 	~PlanRepExpansion() {}
126 
127 
128 	/**
129 	 * @name Acess methods
130 	 */
131 	//@{
132 
133 	//! Returns a reference to the original graph.
original()134 	const Graph &original() const { return *m_pGraph; }
135 
136 	//! Returns the original node of \p v, or 0 if \p v is a dummy.
original(node v)137 	node original(node v) const { return m_vOrig[v]; }
138 
139 	//! Returns the list of copy nodes of \p vOrig.
expansion(node vOrig)140 	const List<node> &expansion(node vOrig) const { return m_vCopy[vOrig]; }
141 
142 	//! Returns the first copy node of \p vOrig.
copy(node vOrig)143 	node copy(node vOrig) const { return m_vCopy[vOrig].front(); }
144 
145 	//! Returns the original edge of \p e, or 0 if \p e has none (e.g., \p e belongs to a node split).
originalEdge(edge e)146 	edge originalEdge(edge e) const { return m_eOrig[e]; }
147 
148 	//! Returns the insertion path of edge \p eOrig.
chain(edge eOrig)149 	const List<edge> &chain(edge eOrig) const { return m_eCopy[eOrig]; }
150 
151 	//! Returns the first edge in \p eOrig's insertion path.
copy(edge eOrig)152 	edge copy(edge eOrig) const { return m_eCopy[eOrig].front(); }
153 
154 	//! Returns true iff \p v is splittable.
splittable(node v)155 	bool splittable(node v) const { return m_splittable[v]; }
156 
157 	//! Returns true iff \p vOrig is splittable.
splittableOrig(node vOrig)158 	bool splittableOrig(node vOrig) const { return m_splittableOrig[vOrig]; }
159 
160 	//! Returns the node split associated with \p e, or 0 if none (e.g., \p e belongs to an original edge).
nodeSplitOf(edge e)161 	NodeSplit *nodeSplitOf(edge e) const { return m_eNodeSplit[e]; }
162 
163 	//! Returns the number of node splits.
numberOfNodeSplits()164 	int numberOfNodeSplits() const { return m_nodeSplits.size(); }
165 	int numberOfSplittedNodes() const;
166 
167 	//! Returns the list of node splits.
nodeSplits()168 	List<NodeSplit> &nodeSplits() { return m_nodeSplits; }
169 
170 	/**
171 	 * \brief Sets the original edge and corresponding node split of \p e and returns the corresponding insertion path.
172 	 *
173 	 * @param e is an edge in the planarized expansion.
174 	 * @param eOrig is assigned the original edge of \p e (or 0 if none).
175 	 * @param ns is assigned the node split corresponding to \p e (or 0 if none).
176 	 * @return a reference to the insertion path containing \p e; this is either the insertion
177 	 *         path of \p eOrig (if this is not 0), or of \p ns.
178 	 */
179 	List<edge> &setOrigs(edge e, edge &eOrig, nodeSplit &ns);
180 
position(edge e)181 	ListConstIterator<edge> position(edge e) const { return m_eIterator[e]; }
182 
183 	bool isPseudoCrossing(node v) const;
184 
185 	//! Computes the number of crossings.
186 	int computeNumberOfCrossings() const;
187 
188 	//@}
189 	/**
190 	 * @name Processing connected components
191 	 */
192 	//@{
193 
194 
195 	 /**
196 	 * \brief Returns the number of connected components in the original graph.
197 	 */
numberOfCCs()198 	int numberOfCCs() const {
199 		return m_nodesInCC.size();
200 	}
201 
202 	/**
203 	 * \brief Returns the index of the current connected component (-1 if not yet initialized).
204 	 */
currentCC()205 	int currentCC() const {
206 		return m_currentCC;
207 	}
208 
209 	/**
210 	 * \brief Returns the list of (original) nodes in connected component \p i.
211 	 *
212 	 * Note that connected components are numbered 0,1,...
213 	 */
nodesInCC(int i)214 	const List<node> &nodesInCC(int i) const {
215 		return m_nodesInCC[i];
216 	}
217 
218 	/**
219 	 * \brief Returns the list of (original) nodes in the current connected component.
220 	 */
nodesInCC()221 	const List<node> &nodesInCC() const {
222 		return m_nodesInCC[m_currentCC];
223 	}
224 
225 	/**
226 	 * \brief Initializes the planarized representation for connected component \p i.
227 	 *
228 	 * This initialization is always required. After performing this initialization,
229 	 * the planarized representation represents a copy of the <i>i</i>-th connected
230 	 * component of the original graph, where connected components are numbered
231 	 * 0,1,2,...
232 	 */
233 	void initCC(int i);
234 
235 
236 	//@}
237 	/**
238 	 * @name Update operations
239 	 */
240 	//@{
241 
242 	edge split(edge e) override;
243 
244 	void unsplit(edge eIn, edge eOut) override;
245 
246 	//! Removes edge \p e from the planarized expansion.
247 	virtual void delEdge(edge e) override;
248 
249 	//! Embeds the planarized expansion; returns true iff it is planar.
250 	bool embed();
251 
252 	void insertEdgePath(
253 		edge eOrig,
254 		nodeSplit ns,
255 		node vStart,
256 		node vEnd,
257 		List<Crossing> &eip,
258 		edge eSrc,
259 		edge eTgt);
260 
261 	/**
262 	 * \brief Inserts an edge or a node split according to insertion path \p crossedEdges.
263 	 *
264 	 * If \p eOrig is not 0, a new insertion path for \p eOrig is inserted; otherwise,
265 	 * a new insertion path for node split \p ns is inserted.
266 	 * @param eOrig is an original edge in the graph (or 0).
267 	 * @param ns is a node split in the planarized expansion.
268 	 * @param E is an embedding of the planarized expansion.
269 	 * @param crossedEdges defines the insertion path.
270 	 * \pre Not both \p eOrig and \p ns may be 0.
271 	 * \see GraphCopy::insertEdgePathEmbedded() for a specification of \p crossedEdges.
272 	 */
273 	void insertEdgePathEmbedded(
274 		edge eOrig,
275 		nodeSplit ns,
276 		CombinatorialEmbedding &E,
277 		const List<Tuple2<adjEntry,adjEntry> > &crossedEdges);
278 
279 	/**
280 	 * \brief Removes the insertion path of \p eOrig or \p ns.
281 	 *
282 	 * @param E is an embedding of the planarized expansion.
283 	 * @param eOrig is an original edge in the graph (or 0).
284 	 * @param ns is a node split in the planarized expansion.
285 	 * @param newFaces is assigned the set of new faces resulting from joining faces when removing edges.
286 	 * @param mergedNodes is assigned the set of nodes in the planarized expansion that resulted
287 	 *        from merging (splittable) nodes.
288 	 * @param oldSrc is assigned the source node of the removed insertion path.
289 	 * @param oldTgt is assigned the target node of the removed insertion path.
290 	 * \pre Not both \p eOrig and \p ns may be 0.
291 	 */
292 	void removeEdgePathEmbedded(
293 		CombinatorialEmbedding &E,
294 		edge eOrig,
295 		nodeSplit ns,
296 		FaceSet<false> &newFaces,
297 		NodeSet<false> &mergedNodes,
298 		node &oldSrc,
299 		node &oldTgt);
300 
301 	/**
302 	 * \brief Removes the insertion path of \p eOrig or \p ns.
303 	 *
304 	 * @param eOrig is an original edge in the graph (or 0).
305 	 * @param ns is a node split in the planarized expansion.
306 	 * @param oldSrc is assigned the source node of the removed insertion path.
307 	 * @param oldTgt is assigned the target node of the removed insertion path.
308 	 * \pre Not both \p eOrig and \p ns may be 0.
309 	 */
310 	void removeEdgePath(
311 		edge eOrig,
312 		nodeSplit ns,
313 		node &oldSrc,
314 		node &oldTgt);
315 
316 	/**
317 	 * \brief Removes an (unneccessary) node split consisting of a single edge.
318 	 *
319 	 * Nodes splits consisting of a single edge are superfluous and canbe removed
320 	 * by contracting the respective edge.
321 	 * @param ns is the node split to be removed.
322 	 * @param E is an embedding of the planarized expansion.
323 	 */
324 	void contractSplit(nodeSplit ns, CombinatorialEmbedding &E);
325 
326 	/**
327 	 * \brief Removes an (unneccessary) node split consisting of a single edge.
328 	 *
329 	 * Nodes splits consisting of a single edge are superfluous and canbe removed
330 	 * by contracting the respective edge.
331 	 * @param ns is the node split to be removed.
332 	 */
333 	void contractSplit(nodeSplit ns);
334 
335 	/**
336 	 * \brief Unsplits a superfluous expansion node of degree 2.
337 	 * @param u is a node in the planarized expansion which has degree 2 and is part of the
338 	 *        expansion of an original node.
339 	 * @param eContract is the edge incident to \p u which is part of a node split; this edge
340 	 *        gets contracted.
341 	 * @param eExpand is the edge incident to \p u which belongs to the insertion path
342 	 *        that gets enlarged.
343 	 * @param E is an embedding of the planarized expansion.
344 	 */
345 	edge unsplitExpandNode(
346 		node u,
347 		edge eContract,
348 		edge eExpand,
349 		CombinatorialEmbedding &E);
350 
351 	/**
352 	 * \brief Unsplits a superfluous expansion node of degree 2.
353 	 * @param u is a node in the planarized expansion which has degree 2 and is part of the
354 	 *        expansion of an original node.
355 	 * @param eContract is the edge incident to \p u which is part of a node split; this edge
356 	 *        gets contracted.
357 	 * @param eExpand is the edge incident to \p u which belongs to the insertion path
358 	 *        that gets enlarged.
359 	 */
360 	edge unsplitExpandNode(
361 		node u,
362 		edge eContract,
363 		edge eExpand);
364 
365 	/**
366 	 * \brief Splits edge \p e and introduces a new node split starting at \p v.
367 	 *
368 	 * @param v is a node in the planarized expansion; the expansion of \p v's original
369 	 *        node is enlarged.
370 	 * @param e is the edge to be split; the insertion path of \p e's original edge
371 	 *        must start or end at \p v.
372 	 * @param E is an embedding of the planarized expansion.
373 	 * @return the newly created edge; the node resulting from splitting \p e is the
374 	 *         target node of this edge.
375 	 */
376 	edge enlargeSplit(node v, edge e, CombinatorialEmbedding &E);
377 
378 	/**
379 	 * \brief Splits edge \p e and introduces a new node split starting at \p v.
380 	 *
381 	 * @param v is a node in the planarized expansion; the expansion of \p v's original
382 	 *        node is enlarged.
383 	 * @param e is the edge to be split; the insertion path of \p e's original edge
384 	 *        must start or end at \p v.
385 	 * @return the newly created edge; the node resulting from splitting \p e is the
386 	 *         target node of this edge.
387 	 */
388 	edge enlargeSplit(node v, edge e);
389 
390 	/**
391 	 * \brief Introduces a new node split by splitting an exisiting node split.
392 	 *
393 	 * @param e is the edge to be split; the node split corresponding to \p e is split
394 	 *        into two node splits.
395 	 * @param E is an embedding of the planarized expansion.
396 	 * @return the newly created edge;  the node resulting from splitting \p e is the
397 	 *         target node of this edge.
398 	 */
399 	edge splitNodeSplit(edge e, CombinatorialEmbedding &E);
400 
401 	/**
402 	 * \brief Introduces a new node split by splitting an exisiting node split.
403 	 *
404 	 * @param e is the edge to be split; the node split corresponding to \p e is split
405 	 *        into two node splits.
406 	 * @return the newly created edge;  the node resulting from splitting \p e is the
407 	 *         target node of this edge.
408 	 */
409 	edge splitNodeSplit(edge e);
410 
411 	/**
412 	 * \brief Removes a self-loop \p e = (\a u,\a u).
413 	 *
414 	 * \a u must be a dummy node; hence, \a u has degree 2 node after removing
415 	 * \p e, and \a u is unsplit afterwards.
416 	 * @param e must be a self loop in the planarized expansion.
417 	 * @param E is an embedding of the planarized expansion.
418 	 */
419 	void removeSelfLoop(edge e, CombinatorialEmbedding &E);
420 
421 	void removeSelfLoop(edge e);
422 
423 	/**
424 	 * \brief Converts a dummy node \p u to a copy of an original node \p vOrig.
425 	 *
426 	 * This method is used if two copy nodes \a x and \a y of the same original node \p vOrig
427 	 * can be connected by converting a dummy node \p u into a copy node of \p vOrig, since an
428 	 * insertion path starting (or ending) at \a x crosses an insertion path starting (or
429 	 * ending) at \a y.
430 	 * @param u is a dummy node in the planarized expansion.
431 	 * @param vOrig is an original node.
432 	 * @param ns is a node split that can be reused for connecting \a x with \p u.
433 	 */
434 	PlanRepExpansion::nodeSplit convertDummy(
435 		node u,
436 		node vOrig,
437 		PlanRepExpansion::nodeSplit ns);
438 
439 	edge separateDummy(
440 		adjEntry adj_1,
441 		adjEntry adj_2,
442 		node vStraight,
443 		bool isSrc);
444 
445 	void resolvePseudoCrossing(node v);
446 
447 	//@}
448 	/**
449 	 * @name Miscelleaneous
450 	 */
451 	//@{
452 
453 #ifdef OGDF_DEBUG
454 	void consistencyCheck() const;
455 #endif
456 
457 	//@}
458 
459 private:
460 	void doInit(const Graph &G, const List<node> &splittableNodes);
461 	void prepareNodeSplit(
462 		const SList<adjEntry> &partitionLeft,
463 		adjEntry &adjLeft,
464 		adjEntry &adjRight);
465 
466 	const Graph *m_pGraph;                      //!< The original graph.
467 	NodeArray<node> m_vOrig;                    //!< The corresponding node in the original graph.
468 	EdgeArray<edge> m_eOrig;                    //!< The corresponding edge in the original graph.
469 	EdgeArray<ListIterator<edge> > m_eIterator; //!< The position of copy edge in the list.
470 	EdgeArray<List<edge> > m_eCopy;             //!< The corresponding list of edges in the graph copy.
471 	NodeArray<ListIterator<node> > m_vIterator; //!< The position of copy node in the list.
472 	NodeArray<List<node> > m_vCopy;             //!< The corresponding list of nodes in the graph copy.
473 
474 	NodeArray<bool> m_splittable;
475 	NodeArray<bool> m_splittableOrig;
476 	EdgeArray<NodeSplit *> m_eNodeSplit;
477 	List<NodeSplit> m_nodeSplits;
478 
479 	int m_currentCC; //!< The index of the current component.
480 	int m_numCC;     //!< The number of components in the original graph.
481 
482 	Array<List<node> >  m_nodesInCC; //!< The list of original nodes in each component.
483 	EdgeArray<edge>     m_eAuxCopy; // auxiliary
484 };
485 
486 }
487