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