gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Planarity checking function instead of class (#62)
0 2 0
default
2 files changed with 27 insertions and 24 deletions:
↑ Collapse diff ↑
Show white space 96 line context
... ...
@@ -92,199 +92,182 @@
92 92
          }
93 93
        }
94 94
      }
95 95

	
96 96
      void backtrack(const Arc& arc) {
97 97
        Node source = _graph.source(arc);
98 98
        Node target = _graph.target(arc);
99 99

	
100 100
        if (_low_map[source] > _low_map[target]) {
101 101
          _low_map[source] = _low_map[target];
102 102
        }
103 103
      }
104 104

	
105 105
      const Graph& _graph;
106 106
      PredMap& _pred_map;
107 107
      TreeMap& _tree_map;
108 108
      OrderMap& _order_map;
109 109
      OrderList& _order_list;
110 110
      AncestorMap& _ancestor_map;
111 111
      LowMap& _low_map;
112 112
    };
113 113

	
114 114
    template <typename Graph, bool embedding = true>
115 115
    struct NodeDataNode {
116 116
      int prev, next;
117 117
      int visited;
118 118
      typename Graph::Arc first;
119 119
      bool inverted;
120 120
    };
121 121

	
122 122
    template <typename Graph>
123 123
    struct NodeDataNode<Graph, false> {
124 124
      int prev, next;
125 125
      int visited;
126 126
    };
127 127

	
128 128
    template <typename Graph>
129 129
    struct ChildListNode {
130 130
      typedef typename Graph::Node Node;
131 131
      Node first;
132 132
      Node prev, next;
133 133
    };
134 134

	
135 135
    template <typename Graph>
136 136
    struct ArcListNode {
137 137
      typename Graph::Arc prev, next;
138 138
    };
139 139

	
140
  }
141

	
142
  /// \ingroup planar
143
  ///
144
  /// \brief Planarity checking of an undirected simple graph
145
  ///
146
  /// This class implements the Boyer-Myrvold algorithm for planarity
147
  /// checking of an undirected graph. This class is a simplified
148
  /// version of the PlanarEmbedding algorithm class because neither
149
  /// the embedding nor the kuratowski subdivisons are not computed.
150 140
  template <typename Graph>
151 141
  class PlanarityChecking {
152 142
  private:
153 143

	
154 144
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
155 145

	
156 146
    const Graph& _graph;
157 147

	
158 148
  private:
159 149

	
160 150
    typedef typename Graph::template NodeMap<Arc> PredMap;
161 151

	
162 152
    typedef typename Graph::template EdgeMap<bool> TreeMap;
163 153

	
164 154
    typedef typename Graph::template NodeMap<int> OrderMap;
165 155
    typedef std::vector<Node> OrderList;
166 156

	
167 157
    typedef typename Graph::template NodeMap<int> LowMap;
168 158
    typedef typename Graph::template NodeMap<int> AncestorMap;
169 159

	
170 160
    typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
171 161
    typedef std::vector<NodeDataNode> NodeData;
172 162

	
173 163
    typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
174 164
    typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
175 165

	
176 166
    typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
177 167

	
178 168
    typedef typename Graph::template NodeMap<bool> EmbedArc;
179 169

	
180 170
  public:
181 171

	
182
    /// \brief Constructor
183
    ///
184
    /// \note The graph should be simple, i.e. parallel and loop arc
185
    /// free.
186 172
    PlanarityChecking(const Graph& graph) : _graph(graph) {}
187 173

	
188
    /// \brief Runs the algorithm.
189
    ///
190
    /// Runs the algorithm.
191
    /// \return %True when the graph is planar.
192 174
    bool run() {
193 175
      typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
194 176

	
195 177
      PredMap pred_map(_graph, INVALID);
196 178
      TreeMap tree_map(_graph, false);
197 179

	
198 180
      OrderMap order_map(_graph, -1);
199 181
      OrderList order_list;
200 182

	
201 183
      AncestorMap ancestor_map(_graph, -1);
202 184
      LowMap low_map(_graph, -1);
203 185

	
204 186
      Visitor visitor(_graph, pred_map, tree_map,
205 187
                      order_map, order_list, ancestor_map, low_map);
206 188
      DfsVisit<Graph, Visitor> visit(_graph, visitor);
207 189
      visit.run();
208 190

	
209 191
      ChildLists child_lists(_graph);
210 192
      createChildLists(tree_map, order_map, low_map, child_lists);
211 193

	
212 194
      NodeData node_data(2 * order_list.size());
213 195

	
214 196
      EmbedArc embed_arc(_graph, false);
215 197

	
216 198
      MergeRoots merge_roots(_graph);
217 199

	
218 200
      for (int i = order_list.size() - 1; i >= 0; --i) {
219 201

	
220 202
        Node node = order_list[i];
221 203

	
222 204
        Node source = node;
223 205
        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
224 206
          Node target = _graph.target(e);
225 207

	
226 208
          if (order_map[source] < order_map[target] && tree_map[e]) {
227 209
            initFace(target, node_data, order_map, order_list);
228 210
          }
229 211
        }
230 212

	
231 213
        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
232 214
          Node target = _graph.target(e);
233 215

	
234 216
          if (order_map[source] < order_map[target] && !tree_map[e]) {
235 217
            embed_arc[target] = true;
236 218
            walkUp(target, source, i, pred_map, low_map,
237 219
                   order_map, order_list, node_data, merge_roots);
238 220
          }
239 221
        }
240 222

	
241 223
        for (typename MergeRoots::Value::iterator it =
242
               merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
224
                 merge_roots[node].begin(); 
225
               it != merge_roots[node].end(); ++it) {
243 226
          int rn = *it;
244 227
          walkDown(rn, i, node_data, order_list, child_lists,
245 228
                   ancestor_map, low_map, embed_arc, merge_roots);
246 229
        }
247 230
        merge_roots[node].clear();
248 231

	
249 232
        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
250 233
          Node target = _graph.target(e);
251 234

	
252 235
          if (order_map[source] < order_map[target] && !tree_map[e]) {
253 236
            if (embed_arc[target]) {
254 237
              return false;
255 238
            }
256 239
          }
257 240
        }
258 241
      }
259 242

	
260 243
      return true;
261 244
    }
262 245

	
263 246
  private:
264 247

	
265 248
    void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
266 249
                          const LowMap& low_map, ChildLists& child_lists) {
267 250

	
268 251
      for (NodeIt n(_graph); n != INVALID; ++n) {
269 252
        Node source = n;
270 253

	
271 254
        std::vector<Node> targets;
272 255
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
273 256
          Node target = _graph.target(e);
274 257

	
275 258
          if (order_map[source] < order_map[target] && tree_map[e]) {
276 259
            targets.push_back(target);
277 260
          }
278 261
        }
279 262

	
280 263
        if (targets.size() == 0) {
281 264
          child_lists[source].first = INVALID;
282 265
        } else if (targets.size() == 1) {
283 266
          child_lists[source].first = targets[0];
284 267
          child_lists[targets[0]].prev = INVALID;
285 268
          child_lists[targets[0]].next = INVALID;
286 269
        } else {
287 270
          radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
288 271
          for (int i = 1; i < int(targets.size()); ++i) {
289 272
            child_lists[targets[i]].prev = targets[i - 1];
290 273
            child_lists[targets[i - 1]].next = targets[i];
... ...
@@ -404,174 +387,191 @@
404 387
              if (child_lists[child].next != INVALID) {
405 388
                child_lists[child_lists[child].next].prev =
406 389
                  child_lists[child].prev;
407 390
              }
408 391

	
409 392
              // Merging external faces
410 393
              {
411 394
                int en = cn;
412 395
                cn = cd ? node_data[cn].prev : node_data[cn].next;
413 396
                cd = node_data[cn].next == en;
414 397

	
415 398
              }
416 399

	
417 400
              if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
418 401
              if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
419 402

	
420 403
            }
421 404

	
422 405
            bool d = pn == node_data[n].prev;
423 406

	
424 407
            if (node_data[n].prev == node_data[n].next &&
425 408
                node_data[n].inverted) {
426 409
              d = !d;
427 410
            }
428 411

	
429 412
            // Embedding arc into external face
430 413
            if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
431 414
            if (d) node_data[n].prev = rn; else node_data[n].next = rn;
432 415
            pn = rn;
433 416

	
434 417
            embed_arc[order_list[n]] = false;
435 418
          }
436 419

	
437 420
          if (!merge_roots[node].empty()) {
438 421

	
439 422
            bool d = pn == node_data[n].prev;
440 423

	
441 424
            merge_stack.push_back(std::make_pair(n, d));
442 425

	
443 426
            int rn = merge_roots[node].front();
444 427

	
445 428
            int xn = node_data[rn].next;
446 429
            Node xnode = order_list[xn];
447 430

	
448 431
            int yn = node_data[rn].prev;
449 432
            Node ynode = order_list[yn];
450 433

	
451 434
            bool rd;
452
            if (!external(xnode, rorder, child_lists, ancestor_map, low_map)) {
435
              if (!external(xnode, rorder, child_lists, 
436
                            ancestor_map, low_map)) {
453 437
              rd = true;
454 438
            } else if (!external(ynode, rorder, child_lists,
455 439
                                 ancestor_map, low_map)) {
456 440
              rd = false;
457 441
            } else if (pertinent(xnode, embed_arc, merge_roots)) {
458 442
              rd = true;
459 443
            } else {
460 444
              rd = false;
461 445
            }
462 446

	
463 447
            merge_stack.push_back(std::make_pair(rn, rd));
464 448

	
465 449
            pn = rn;
466 450
            n = rd ? xn : yn;
467 451

	
468 452
          } else if (!external(node, rorder, child_lists,
469 453
                               ancestor_map, low_map)) {
470 454
            int nn = (node_data[n].next != pn ?
471 455
                      node_data[n].next : node_data[n].prev);
472 456

	
473 457
            bool nd = n == node_data[nn].prev;
474 458

	
475 459
            if (nd) node_data[nn].prev = pn;
476 460
            else node_data[nn].next = pn;
477 461

	
478 462
            if (n == node_data[pn].prev) node_data[pn].prev = nn;
479 463
            else node_data[pn].next = nn;
480 464

	
481 465
            node_data[nn].inverted =
482 466
              (node_data[nn].prev == node_data[nn].next && nd != rd);
483 467

	
484 468
            n = nn;
485 469
          }
486 470
          else break;
487 471

	
488 472
        }
489 473

	
490 474
        if (!merge_stack.empty() || n == rn) {
491 475
          break;
492 476
        }
493 477
      }
494 478
    }
495 479

	
496 480
    void initFace(const Node& node, NodeData& node_data,
497 481
                  const OrderMap& order_map, const OrderList& order_list) {
498 482
      int n = order_map[node];
499 483
      int rn = n + order_list.size();
500 484

	
501 485
      node_data[n].next = node_data[n].prev = rn;
502 486
      node_data[rn].next = node_data[rn].prev = n;
503 487

	
504 488
      node_data[n].visited = order_list.size();
505 489
      node_data[rn].visited = order_list.size();
506 490

	
507 491
    }
508 492

	
509 493
    bool external(const Node& node, int rorder,
510 494
                  ChildLists& child_lists, AncestorMap& ancestor_map,
511 495
                  LowMap& low_map) {
512 496
      Node child = child_lists[node].first;
513 497

	
514 498
      if (child != INVALID) {
515 499
        if (low_map[child] < rorder) return true;
516 500
      }
517 501

	
518 502
      if (ancestor_map[node] < rorder) return true;
519 503

	
520 504
      return false;
521 505
    }
522 506

	
523 507
    bool pertinent(const Node& node, const EmbedArc& embed_arc,
524 508
                   const MergeRoots& merge_roots) {
525 509
      return !merge_roots[node].empty() || embed_arc[node];
526 510
    }
527 511

	
528 512
  };
529 513

	
514
  }
515

	
516
  /// \ingroup planar
517
  ///
518
  /// \brief Planarity checking of an undirected simple graph
519
  ///
520
  /// This function implements the Boyer-Myrvold algorithm for
521
  /// planarity checking of an undirected graph. It is a simplified
522
  /// version of the PlanarEmbedding algorithm class because neither
523
  /// the embedding nor the kuratowski subdivisons are not computed.
524
  template <typename GR>
525
  bool checkPlanarity(const GR& graph) {
526
    _planarity_bits::PlanarityChecking<GR> pc(graph);
527
    return pc.run();
528
  }
529

	
530 530
  /// \ingroup planar
531 531
  ///
532 532
  /// \brief Planar embedding of an undirected simple graph
533 533
  ///
534 534
  /// This class implements the Boyer-Myrvold algorithm for planar
535 535
  /// embedding of an undirected graph. The planar embedding is an
536 536
  /// ordering of the outgoing edges of the nodes, which is a possible
537 537
  /// configuration to draw the graph in the plane. If there is not
538 538
  /// such ordering then the graph contains a \f$ K_5 \f$ (full graph
539 539
  /// with 5 nodes) or a \f$ K_{3,3} \f$ (complete bipartite graph on
540 540
  /// 3 ANode and 3 BNode) subdivision.
541 541
  ///
542 542
  /// The current implementation calculates either an embedding or a
543 543
  /// Kuratowski subdivision. The running time of the algorithm is 
544 544
  /// \f$ O(n) \f$.
545 545
  template <typename Graph>
546 546
  class PlanarEmbedding {
547 547
  private:
548 548

	
549 549
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
550 550

	
551 551
    const Graph& _graph;
552 552
    typename Graph::template ArcMap<Arc> _embedding;
553 553

	
554 554
    typename Graph::template EdgeMap<bool> _kuratowski;
555 555

	
556 556
  private:
557 557

	
558 558
    typedef typename Graph::template NodeMap<Arc> PredMap;
559 559

	
560 560
    typedef typename Graph::template EdgeMap<bool> TreeMap;
561 561

	
562 562
    typedef typename Graph::template NodeMap<int> OrderMap;
563 563
    typedef std::vector<Node> OrderList;
564 564

	
565 565
    typedef typename Graph::template NodeMap<int> LowMap;
566 566
    typedef typename Graph::template NodeMap<int> AncestorMap;
567 567

	
568 568
    typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
569 569
    typedef std::vector<NodeDataNode> NodeData;
570 570

	
571 571
    typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
572 572
    typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
573 573

	
574 574
    typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
575 575

	
576 576
    typedef typename Graph::template NodeMap<Arc> EmbedArc;
577 577

	
... ...
@@ -667,97 +667,97 @@
667 667
               merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
668 668
          int rn = *it;
669 669
          walkDown(rn, i, node_data, arc_lists, flip_map, order_list,
670 670
                   child_lists, ancestor_map, low_map, embed_arc, merge_roots);
671 671
        }
672 672
        merge_roots[node].clear();
673 673

	
674 674
        for (OutArcIt e(_graph, node); e != INVALID; ++e) {
675 675
          Node target = _graph.target(e);
676 676

	
677 677
          if (order_map[source] < order_map[target] && !tree_map[e]) {
678 678
            if (embed_arc[target] != INVALID) {
679 679
              if (kuratowski) {
680 680
                isolateKuratowski(e, node_data, arc_lists, flip_map,
681 681
                                  order_map, order_list, pred_map, child_lists,
682 682
                                  ancestor_map, low_map,
683 683
                                  embed_arc, merge_roots);
684 684
              }
685 685
              return false;
686 686
            }
687 687
          }
688 688
        }
689 689
      }
690 690

	
691 691
      for (int i = 0; i < int(order_list.size()); ++i) {
692 692

	
693 693
        mergeRemainingFaces(order_list[i], node_data, order_list, order_map,
694 694
                            child_lists, arc_lists);
695 695
        storeEmbedding(order_list[i], node_data, order_map, pred_map,
696 696
                       arc_lists, flip_map);
697 697
      }
698 698

	
699 699
      return true;
700 700
    }
701 701

	
702 702
    /// \brief Gives back the successor of an arc
703 703
    ///
704 704
    /// Gives back the successor of an arc. This function makes
705 705
    /// possible to query the cyclic order of the outgoing arcs from
706 706
    /// a node.
707 707
    Arc next(const Arc& arc) const {
708 708
      return _embedding[arc];
709 709
    }
710 710

	
711 711
    /// \brief Gives back the calculated embedding map
712 712
    ///
713 713
    /// The returned map contains the successor of each arc in the
714 714
    /// graph.
715
    const EmbeddingMap& embedding() const {
715
    const EmbeddingMap& embeddingMap() const {
716 716
      return _embedding;
717 717
    }
718 718

	
719 719
    /// \brief Gives back true if the undirected arc is in the
720 720
    /// kuratowski subdivision
721 721
    ///
722 722
    /// Gives back true if the undirected arc is in the kuratowski
723 723
    /// subdivision
724 724
    /// \note The \c run() had to be called with true value.
725 725
    bool kuratowski(const Edge& edge) {
726 726
      return _kuratowski[edge];
727 727
    }
728 728

	
729 729
  private:
730 730

	
731 731
    void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
732 732
                          const LowMap& low_map, ChildLists& child_lists) {
733 733

	
734 734
      for (NodeIt n(_graph); n != INVALID; ++n) {
735 735
        Node source = n;
736 736

	
737 737
        std::vector<Node> targets;
738 738
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
739 739
          Node target = _graph.target(e);
740 740

	
741 741
          if (order_map[source] < order_map[target] && tree_map[e]) {
742 742
            targets.push_back(target);
743 743
          }
744 744
        }
745 745

	
746 746
        if (targets.size() == 0) {
747 747
          child_lists[source].first = INVALID;
748 748
        } else if (targets.size() == 1) {
749 749
          child_lists[source].first = targets[0];
750 750
          child_lists[targets[0]].prev = INVALID;
751 751
          child_lists[targets[0]].next = INVALID;
752 752
        } else {
753 753
          radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
754 754
          for (int i = 1; i < int(targets.size()); ++i) {
755 755
            child_lists[targets[i]].prev = targets[i - 1];
756 756
            child_lists[targets[i - 1]].next = targets[i];
757 757
          }
758 758
          child_lists[targets.back()].next = INVALID;
759 759
          child_lists[targets.front()].prev = INVALID;
760 760
          child_lists[source].first = targets.front();
761 761
        }
762 762
      }
763 763
    }
Show white space 96 line context
... ...
@@ -194,66 +194,69 @@
194 194
      check(pd[m] != pd[n], "Two nodes with identical coordinates");
195 195
    }
196 196
  }
197 197

	
198 198
  for (Graph::EdgeIt e(graph); e != INVALID; ++e) {
199 199
    for (Graph::EdgeIt f(e); f != e; ++f) {
200 200
      Point<int> e1 = pd[graph.u(e)];
201 201
      Point<int> e2 = pd[graph.v(e)];
202 202
      Point<int> f1 = pd[graph.u(f)];
203 203
      Point<int> f2 = pd[graph.v(f)];
204 204

	
205 205
      if (graph.u(e) == graph.u(f)) {
206 206
        check(!collinear(e1, e2, f2), "Wrong drawing");
207 207
      } else if (graph.u(e) == graph.v(f)) {
208 208
        check(!collinear(e1, e2, f1), "Wrong drawing");
209 209
      } else if (graph.v(e) == graph.u(f)) {
210 210
        check(!collinear(e2, e1, f2), "Wrong drawing");
211 211
      } else if (graph.v(e) == graph.v(f)) {
212 212
        check(!collinear(e2, e1, f1), "Wrong drawing");
213 213
      } else {
214 214
        check(!intersect(e1, e2, f1, f2), "Wrong drawing");
215 215
      }
216 216
    }
217 217
  }
218 218
}
219 219

	
220 220
void checkColoring(const Graph& graph, PC& pc, int num) {
221 221
  for (NodeIt n(graph); n != INVALID; ++n) {
222 222
    check(pc.colorIndex(n) >= 0 && pc.colorIndex(n) < num,
223 223
          "Wrong coloring");
224 224
  }
225 225
  for (EdgeIt e(graph); e != INVALID; ++e) {
226 226
    check(pc.colorIndex(graph.u(e)) != pc.colorIndex(graph.v(e)),
227 227
          "Wrong coloring");
228 228
  }
229 229
}
230 230

	
231 231
int main() {
232 232

	
233 233
  for (int i = 0; i < lgfn; ++i) {
234 234
    std::istringstream lgfs(lgf[i]);
235 235

	
236 236
    SmartGraph graph;
237 237
    graphReader(graph, lgfs).run();
238 238

	
239 239
    check(simpleGraph(graph), "Test graphs must be simple");
240 240

	
241 241
    PE pe(graph);
242
    if (pe.run()) {
242
    bool planar = pe.run();
243
    check(checkPlanarity(graph) == planar, "Planarity checking failed");
244

	
245
    if (planar) {
243 246
      checkEmbedding(graph, pe);
244 247

	
245 248
      PlanarDrawing<Graph> pd(graph);
246
      pd.run(pe.embedding());
249
      pd.run(pe.embeddingMap());
247 250
      checkDrawing(graph, pd);
248 251

	
249 252
      PlanarColoring<Graph> pc(graph);
250
      pc.runFiveColoring(pe.embedding());
253
      pc.runFiveColoring(pe.embeddingMap());
251 254
      checkColoring(graph, pc, 5);
252 255

	
253 256
    } else {
254 257
      checkKuratowski(graph, pe);
255 258
    }
256 259
  }
257 260

	
258 261
  return 0;
259 262
}
0 comments (0 inline)