... | ... |
@@ -425,397 +425,404 @@ |
425 | 425 |
|
426 | 426 |
int rn = merge_roots[node].front(); |
427 | 427 |
|
428 | 428 |
int xn = node_data[rn].next; |
429 | 429 |
Node xnode = order_list[xn]; |
430 | 430 |
|
431 | 431 |
int yn = node_data[rn].prev; |
432 | 432 |
Node ynode = order_list[yn]; |
433 | 433 |
|
434 | 434 |
bool rd; |
435 | 435 |
if (!external(xnode, rorder, child_lists, |
436 | 436 |
ancestor_map, low_map)) { |
437 | 437 |
rd = true; |
438 | 438 |
} else if (!external(ynode, rorder, child_lists, |
439 | 439 |
ancestor_map, low_map)) { |
440 | 440 |
rd = false; |
441 | 441 |
} else if (pertinent(xnode, embed_arc, merge_roots)) { |
442 | 442 |
rd = true; |
443 | 443 |
} else { |
444 | 444 |
rd = false; |
445 | 445 |
} |
446 | 446 |
|
447 | 447 |
merge_stack.push_back(std::make_pair(rn, rd)); |
448 | 448 |
|
449 | 449 |
pn = rn; |
450 | 450 |
n = rd ? xn : yn; |
451 | 451 |
|
452 | 452 |
} else if (!external(node, rorder, child_lists, |
453 | 453 |
ancestor_map, low_map)) { |
454 | 454 |
int nn = (node_data[n].next != pn ? |
455 | 455 |
node_data[n].next : node_data[n].prev); |
456 | 456 |
|
457 | 457 |
bool nd = n == node_data[nn].prev; |
458 | 458 |
|
459 | 459 |
if (nd) node_data[nn].prev = pn; |
460 | 460 |
else node_data[nn].next = pn; |
461 | 461 |
|
462 | 462 |
if (n == node_data[pn].prev) node_data[pn].prev = nn; |
463 | 463 |
else node_data[pn].next = nn; |
464 | 464 |
|
465 | 465 |
node_data[nn].inverted = |
466 | 466 |
(node_data[nn].prev == node_data[nn].next && nd != rd); |
467 | 467 |
|
468 | 468 |
n = nn; |
469 | 469 |
} |
470 | 470 |
else break; |
471 | 471 |
|
472 | 472 |
} |
473 | 473 |
|
474 | 474 |
if (!merge_stack.empty() || n == rn) { |
475 | 475 |
break; |
476 | 476 |
} |
477 | 477 |
} |
478 | 478 |
} |
479 | 479 |
|
480 | 480 |
void initFace(const Node& node, NodeData& node_data, |
481 | 481 |
const OrderMap& order_map, const OrderList& order_list) { |
482 | 482 |
int n = order_map[node]; |
483 | 483 |
int rn = n + order_list.size(); |
484 | 484 |
|
485 | 485 |
node_data[n].next = node_data[n].prev = rn; |
486 | 486 |
node_data[rn].next = node_data[rn].prev = n; |
487 | 487 |
|
488 | 488 |
node_data[n].visited = order_list.size(); |
489 | 489 |
node_data[rn].visited = order_list.size(); |
490 | 490 |
|
491 | 491 |
} |
492 | 492 |
|
493 | 493 |
bool external(const Node& node, int rorder, |
494 | 494 |
ChildLists& child_lists, AncestorMap& ancestor_map, |
495 | 495 |
LowMap& low_map) { |
496 | 496 |
Node child = child_lists[node].first; |
497 | 497 |
|
498 | 498 |
if (child != INVALID) { |
499 | 499 |
if (low_map[child] < rorder) return true; |
500 | 500 |
} |
501 | 501 |
|
502 | 502 |
if (ancestor_map[node] < rorder) return true; |
503 | 503 |
|
504 | 504 |
return false; |
505 | 505 |
} |
506 | 506 |
|
507 | 507 |
bool pertinent(const Node& node, const EmbedArc& embed_arc, |
508 | 508 |
const MergeRoots& merge_roots) { |
509 | 509 |
return !merge_roots[node].empty() || embed_arc[node]; |
510 | 510 |
} |
511 | 511 |
|
512 | 512 |
}; |
513 | 513 |
|
514 | 514 |
} |
515 | 515 |
|
516 | 516 |
/// \ingroup planar |
517 | 517 |
/// |
518 | 518 |
/// \brief Planarity checking of an undirected simple graph |
519 | 519 |
/// |
520 | 520 |
/// This function implements the Boyer-Myrvold algorithm for |
521 |
/// planarity checking of an undirected graph. It is a simplified |
|
521 |
/// planarity checking of an undirected simple graph. It is a simplified |
|
522 | 522 |
/// version of the PlanarEmbedding algorithm class because neither |
523 |
/// the embedding nor the |
|
523 |
/// the embedding nor the Kuratowski subdivisons are computed. |
|
524 | 524 |
template <typename GR> |
525 | 525 |
bool checkPlanarity(const GR& graph) { |
526 | 526 |
_planarity_bits::PlanarityChecking<GR> pc(graph); |
527 | 527 |
return pc.run(); |
528 | 528 |
} |
529 | 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 |
/// embedding of an undirected graph. The planar embedding is an |
|
535 |
/// embedding of an undirected simple 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 |
/// such ordering then the graph contains a \f$ K_5 \f$ (full graph |
|
539 |
/// with 5 nodes) or a \f$ K_{3,3} \f$ (complete bipartite graph on |
|
540 |
/// |
|
538 |
/// such ordering then the graph contains a K<sub>5</sub> (full graph |
|
539 |
/// with 5 nodes) or a K<sub>3,3</sub> (complete bipartite graph on |
|
540 |
/// 3 Red and 3 Blue nodes) subdivision. |
|
541 | 541 |
/// |
542 | 542 |
/// The current implementation calculates either an embedding or a |
543 |
/// Kuratowski subdivision. The running time of the algorithm is |
|
544 |
/// \f$ O(n) \f$. |
|
543 |
/// Kuratowski subdivision. The running time of the algorithm is O(n). |
|
544 |
/// |
|
545 |
/// \see PlanarDrawing, checkPlanarity() |
|
545 | 546 |
template <typename Graph> |
546 | 547 |
class PlanarEmbedding { |
547 | 548 |
private: |
548 | 549 |
|
549 | 550 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
550 | 551 |
|
551 | 552 |
const Graph& _graph; |
552 | 553 |
typename Graph::template ArcMap<Arc> _embedding; |
553 | 554 |
|
554 | 555 |
typename Graph::template EdgeMap<bool> _kuratowski; |
555 | 556 |
|
556 | 557 |
private: |
557 | 558 |
|
558 | 559 |
typedef typename Graph::template NodeMap<Arc> PredMap; |
559 | 560 |
|
560 | 561 |
typedef typename Graph::template EdgeMap<bool> TreeMap; |
561 | 562 |
|
562 | 563 |
typedef typename Graph::template NodeMap<int> OrderMap; |
563 | 564 |
typedef std::vector<Node> OrderList; |
564 | 565 |
|
565 | 566 |
typedef typename Graph::template NodeMap<int> LowMap; |
566 | 567 |
typedef typename Graph::template NodeMap<int> AncestorMap; |
567 | 568 |
|
568 | 569 |
typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode; |
569 | 570 |
typedef std::vector<NodeDataNode> NodeData; |
570 | 571 |
|
571 | 572 |
typedef _planarity_bits::ChildListNode<Graph> ChildListNode; |
572 | 573 |
typedef typename Graph::template NodeMap<ChildListNode> ChildLists; |
573 | 574 |
|
574 | 575 |
typedef typename Graph::template NodeMap<std::list<int> > MergeRoots; |
575 | 576 |
|
576 | 577 |
typedef typename Graph::template NodeMap<Arc> EmbedArc; |
577 | 578 |
|
578 | 579 |
typedef _planarity_bits::ArcListNode<Graph> ArcListNode; |
579 | 580 |
typedef typename Graph::template ArcMap<ArcListNode> ArcLists; |
580 | 581 |
|
581 | 582 |
typedef typename Graph::template NodeMap<bool> FlipMap; |
582 | 583 |
|
583 | 584 |
typedef typename Graph::template NodeMap<int> TypeMap; |
584 | 585 |
|
585 | 586 |
enum IsolatorNodeType { |
586 | 587 |
HIGHX = 6, LOWX = 7, |
587 | 588 |
HIGHY = 8, LOWY = 9, |
588 | 589 |
ROOT = 10, PERTINENT = 11, |
589 | 590 |
INTERNAL = 12 |
590 | 591 |
}; |
591 | 592 |
|
592 | 593 |
public: |
593 | 594 |
|
594 |
/// \brief The map for |
|
595 |
/// \brief The map type for storing the embedding |
|
596 |
/// |
|
597 |
/// The map type for storing the embedding. |
|
598 |
/// \see embeddingMap() |
|
595 | 599 |
typedef typename Graph::template ArcMap<Arc> EmbeddingMap; |
596 | 600 |
|
597 | 601 |
/// \brief Constructor |
598 | 602 |
/// |
599 |
/// \note The graph should be simple, i.e. parallel and loop arc |
|
600 |
/// free. |
|
603 |
/// Constructor. |
|
604 |
/// \pre The graph must be simple, i.e. it should not |
|
605 |
/// contain parallel or loop arcs. |
|
601 | 606 |
PlanarEmbedding(const Graph& graph) |
602 | 607 |
: _graph(graph), _embedding(_graph), _kuratowski(graph, false) {} |
603 | 608 |
|
604 |
/// \brief |
|
609 |
/// \brief Run the algorithm. |
|
605 | 610 |
/// |
606 |
/// Runs the algorithm. |
|
607 |
/// \param kuratowski If the parameter is false, then the |
|
611 |
/// This function runs the algorithm. |
|
612 |
/// \param kuratowski If this parameter is set to \c false, then the |
|
608 | 613 |
/// algorithm does not compute a Kuratowski subdivision. |
609 |
///\return |
|
614 |
/// \return \c true if the graph is planar. |
|
610 | 615 |
bool run(bool kuratowski = true) { |
611 | 616 |
typedef _planarity_bits::PlanarityVisitor<Graph> Visitor; |
612 | 617 |
|
613 | 618 |
PredMap pred_map(_graph, INVALID); |
614 | 619 |
TreeMap tree_map(_graph, false); |
615 | 620 |
|
616 | 621 |
OrderMap order_map(_graph, -1); |
617 | 622 |
OrderList order_list; |
618 | 623 |
|
619 | 624 |
AncestorMap ancestor_map(_graph, -1); |
620 | 625 |
LowMap low_map(_graph, -1); |
621 | 626 |
|
622 | 627 |
Visitor visitor(_graph, pred_map, tree_map, |
623 | 628 |
order_map, order_list, ancestor_map, low_map); |
624 | 629 |
DfsVisit<Graph, Visitor> visit(_graph, visitor); |
625 | 630 |
visit.run(); |
626 | 631 |
|
627 | 632 |
ChildLists child_lists(_graph); |
628 | 633 |
createChildLists(tree_map, order_map, low_map, child_lists); |
629 | 634 |
|
630 | 635 |
NodeData node_data(2 * order_list.size()); |
631 | 636 |
|
632 | 637 |
EmbedArc embed_arc(_graph, INVALID); |
633 | 638 |
|
634 | 639 |
MergeRoots merge_roots(_graph); |
635 | 640 |
|
636 | 641 |
ArcLists arc_lists(_graph); |
637 | 642 |
|
638 | 643 |
FlipMap flip_map(_graph, false); |
639 | 644 |
|
640 | 645 |
for (int i = order_list.size() - 1; i >= 0; --i) { |
641 | 646 |
|
642 | 647 |
Node node = order_list[i]; |
643 | 648 |
|
644 | 649 |
node_data[i].first = INVALID; |
645 | 650 |
|
646 | 651 |
Node source = node; |
647 | 652 |
for (OutArcIt e(_graph, node); e != INVALID; ++e) { |
648 | 653 |
Node target = _graph.target(e); |
649 | 654 |
|
650 | 655 |
if (order_map[source] < order_map[target] && tree_map[e]) { |
651 | 656 |
initFace(target, arc_lists, node_data, |
652 | 657 |
pred_map, order_map, order_list); |
653 | 658 |
} |
654 | 659 |
} |
655 | 660 |
|
656 | 661 |
for (OutArcIt e(_graph, node); e != INVALID; ++e) { |
657 | 662 |
Node target = _graph.target(e); |
658 | 663 |
|
659 | 664 |
if (order_map[source] < order_map[target] && !tree_map[e]) { |
660 | 665 |
embed_arc[target] = e; |
661 | 666 |
walkUp(target, source, i, pred_map, low_map, |
662 | 667 |
order_map, order_list, node_data, merge_roots); |
663 | 668 |
} |
664 | 669 |
} |
665 | 670 |
|
666 | 671 |
for (typename MergeRoots::Value::iterator it = |
667 | 672 |
merge_roots[node].begin(); it != merge_roots[node].end(); ++it) { |
668 | 673 |
int rn = *it; |
669 | 674 |
walkDown(rn, i, node_data, arc_lists, flip_map, order_list, |
670 | 675 |
child_lists, ancestor_map, low_map, embed_arc, merge_roots); |
671 | 676 |
} |
672 | 677 |
merge_roots[node].clear(); |
673 | 678 |
|
674 | 679 |
for (OutArcIt e(_graph, node); e != INVALID; ++e) { |
675 | 680 |
Node target = _graph.target(e); |
676 | 681 |
|
677 | 682 |
if (order_map[source] < order_map[target] && !tree_map[e]) { |
678 | 683 |
if (embed_arc[target] != INVALID) { |
679 | 684 |
if (kuratowski) { |
680 | 685 |
isolateKuratowski(e, node_data, arc_lists, flip_map, |
681 | 686 |
order_map, order_list, pred_map, child_lists, |
682 | 687 |
ancestor_map, low_map, |
683 | 688 |
embed_arc, merge_roots); |
684 | 689 |
} |
685 | 690 |
return false; |
686 | 691 |
} |
687 | 692 |
} |
688 | 693 |
} |
689 | 694 |
} |
690 | 695 |
|
691 | 696 |
for (int i = 0; i < int(order_list.size()); ++i) { |
692 | 697 |
|
693 | 698 |
mergeRemainingFaces(order_list[i], node_data, order_list, order_map, |
694 | 699 |
child_lists, arc_lists); |
695 | 700 |
storeEmbedding(order_list[i], node_data, order_map, pred_map, |
696 | 701 |
arc_lists, flip_map); |
697 | 702 |
} |
698 | 703 |
|
699 | 704 |
return true; |
700 | 705 |
} |
701 | 706 |
|
702 |
/// \brief |
|
707 |
/// \brief Give back the successor of an arc |
|
703 | 708 |
/// |
704 |
/// |
|
709 |
/// This function gives back the successor of an arc. It makes |
|
705 | 710 |
/// possible to query the cyclic order of the outgoing arcs from |
706 | 711 |
/// a node. |
707 | 712 |
Arc next(const Arc& arc) const { |
708 | 713 |
return _embedding[arc]; |
709 | 714 |
} |
710 | 715 |
|
711 |
/// \brief |
|
716 |
/// \brief Give back the calculated embedding map |
|
712 | 717 |
/// |
713 |
/// The returned map contains the successor of each arc in the |
|
714 |
/// graph. |
|
718 |
/// This function gives back the calculated embedding map, which |
|
719 |
/// contains the successor of each arc in the cyclic order of the |
|
720 |
/// outgoing arcs of its source node. |
|
715 | 721 |
const EmbeddingMap& embeddingMap() const { |
716 | 722 |
return _embedding; |
717 | 723 |
} |
718 | 724 |
|
719 |
/// \brief Gives back true if the undirected arc is in the |
|
720 |
/// kuratowski subdivision |
|
725 |
/// \brief Give back \c true if the given edge is in the Kuratowski |
|
726 |
/// subdivision |
|
721 | 727 |
/// |
722 |
/// Gives back true if the undirected arc is in the kuratowski |
|
723 |
/// subdivision |
|
724 |
/// \note The \c run() had to be called with true value. |
|
725 |
bool kuratowski(const Edge& edge) { |
|
728 |
/// This function gives back \c true if the given edge is in the found |
|
729 |
/// Kuratowski subdivision. |
|
730 |
/// \pre The \c run() function must be called with \c true parameter |
|
731 |
/// before using this function. |
|
732 |
bool kuratowski(const Edge& edge) const { |
|
726 | 733 |
return _kuratowski[edge]; |
727 | 734 |
} |
728 | 735 |
|
729 | 736 |
private: |
730 | 737 |
|
731 | 738 |
void createChildLists(const TreeMap& tree_map, const OrderMap& order_map, |
732 | 739 |
const LowMap& low_map, ChildLists& child_lists) { |
733 | 740 |
|
734 | 741 |
for (NodeIt n(_graph); n != INVALID; ++n) { |
735 | 742 |
Node source = n; |
736 | 743 |
|
737 | 744 |
std::vector<Node> targets; |
738 | 745 |
for (OutArcIt e(_graph, n); e != INVALID; ++e) { |
739 | 746 |
Node target = _graph.target(e); |
740 | 747 |
|
741 | 748 |
if (order_map[source] < order_map[target] && tree_map[e]) { |
742 | 749 |
targets.push_back(target); |
743 | 750 |
} |
744 | 751 |
} |
745 | 752 |
|
746 | 753 |
if (targets.size() == 0) { |
747 | 754 |
child_lists[source].first = INVALID; |
748 | 755 |
} else if (targets.size() == 1) { |
749 | 756 |
child_lists[source].first = targets[0]; |
750 | 757 |
child_lists[targets[0]].prev = INVALID; |
751 | 758 |
child_lists[targets[0]].next = INVALID; |
752 | 759 |
} else { |
753 | 760 |
radixSort(targets.begin(), targets.end(), mapToFunctor(low_map)); |
754 | 761 |
for (int i = 1; i < int(targets.size()); ++i) { |
755 | 762 |
child_lists[targets[i]].prev = targets[i - 1]; |
756 | 763 |
child_lists[targets[i - 1]].next = targets[i]; |
757 | 764 |
} |
758 | 765 |
child_lists[targets.back()].next = INVALID; |
759 | 766 |
child_lists[targets.front()].prev = INVALID; |
760 | 767 |
child_lists[source].first = targets.front(); |
761 | 768 |
} |
762 | 769 |
} |
763 | 770 |
} |
764 | 771 |
|
765 | 772 |
void walkUp(const Node& node, Node root, int rorder, |
766 | 773 |
const PredMap& pred_map, const LowMap& low_map, |
767 | 774 |
const OrderMap& order_map, const OrderList& order_list, |
768 | 775 |
NodeData& node_data, MergeRoots& merge_roots) { |
769 | 776 |
|
770 | 777 |
int na, nb; |
771 | 778 |
bool da, db; |
772 | 779 |
|
773 | 780 |
na = nb = order_map[node]; |
774 | 781 |
da = true; db = false; |
775 | 782 |
|
776 | 783 |
while (true) { |
777 | 784 |
|
778 | 785 |
if (node_data[na].visited == rorder) break; |
779 | 786 |
if (node_data[nb].visited == rorder) break; |
780 | 787 |
|
781 | 788 |
node_data[na].visited = rorder; |
782 | 789 |
node_data[nb].visited = rorder; |
783 | 790 |
|
784 | 791 |
int rn = -1; |
785 | 792 |
|
786 | 793 |
if (na >= int(order_list.size())) { |
787 | 794 |
rn = na; |
788 | 795 |
} else if (nb >= int(order_list.size())) { |
789 | 796 |
rn = nb; |
790 | 797 |
} |
791 | 798 |
|
792 | 799 |
if (rn == -1) { |
793 | 800 |
int nn; |
794 | 801 |
|
795 | 802 |
nn = da ? node_data[na].prev : node_data[na].next; |
796 | 803 |
da = node_data[nn].prev != na; |
797 | 804 |
na = nn; |
798 | 805 |
|
799 | 806 |
nn = db ? node_data[nb].prev : node_data[nb].next; |
800 | 807 |
db = node_data[nn].prev != nb; |
801 | 808 |
nb = nn; |
802 | 809 |
|
803 | 810 |
} else { |
804 | 811 |
|
805 | 812 |
Node rep = order_list[rn - order_list.size()]; |
806 | 813 |
Node parent = _graph.source(pred_map[rep]); |
807 | 814 |
|
808 | 815 |
if (low_map[rep] < rorder) { |
809 | 816 |
merge_roots[parent].push_back(rn); |
810 | 817 |
} else { |
811 | 818 |
merge_roots[parent].push_front(rn); |
812 | 819 |
} |
813 | 820 |
|
814 | 821 |
if (parent != root) { |
815 | 822 |
na = nb = order_map[parent]; |
816 | 823 |
da = true; db = false; |
817 | 824 |
} else { |
818 | 825 |
break; |
819 | 826 |
} |
820 | 827 |
} |
821 | 828 |
} |
... | ... |
@@ -1966,215 +1973,218 @@ |
1966 | 1973 |
for (typename Graph::OutArcIt e(graph, s); e != INVALID; ++e) { |
1967 | 1974 |
visited.set(graph.target(e), true); |
1968 | 1975 |
} |
1969 | 1976 |
|
1970 | 1977 |
typename Graph::Arc oppe = INVALID; |
1971 | 1978 |
|
1972 | 1979 |
e = embedding[graph.oppositeArc(mine)]; |
1973 | 1980 |
e = embedding[graph.oppositeArc(e)]; |
1974 | 1981 |
while (graph.target(e) != s) { |
1975 | 1982 |
if (visited[graph.source(e)]) { |
1976 | 1983 |
oppe = e; |
1977 | 1984 |
break; |
1978 | 1985 |
} |
1979 | 1986 |
e = embedding[graph.oppositeArc(e)]; |
1980 | 1987 |
} |
1981 | 1988 |
visited.setAll(false); |
1982 | 1989 |
|
1983 | 1990 |
if (oppe == INVALID) { |
1984 | 1991 |
|
1985 | 1992 |
e = embedding[graph.oppositeArc(mine)]; |
1986 | 1993 |
typename Graph::Arc pn = mine, p = e; |
1987 | 1994 |
|
1988 | 1995 |
e = embedding[graph.oppositeArc(e)]; |
1989 | 1996 |
while (graph.target(e) != s) { |
1990 | 1997 |
typename Graph::Arc n = |
1991 | 1998 |
graph.direct(graph.addEdge(s, graph.source(e)), true); |
1992 | 1999 |
|
1993 | 2000 |
embedding[n] = pn; |
1994 | 2001 |
embedding[graph.oppositeArc(n)] = e; |
1995 | 2002 |
embedding[graph.oppositeArc(p)] = graph.oppositeArc(n); |
1996 | 2003 |
|
1997 | 2004 |
pn = n; |
1998 | 2005 |
|
1999 | 2006 |
p = e; |
2000 | 2007 |
e = embedding[graph.oppositeArc(e)]; |
2001 | 2008 |
} |
2002 | 2009 |
|
2003 | 2010 |
embedding[graph.oppositeArc(e)] = pn; |
2004 | 2011 |
|
2005 | 2012 |
} else { |
2006 | 2013 |
|
2007 | 2014 |
mine = embedding[graph.oppositeArc(mine)]; |
2008 | 2015 |
s = graph.source(mine); |
2009 | 2016 |
oppe = embedding[graph.oppositeArc(oppe)]; |
2010 | 2017 |
typename Graph::Node t = graph.source(oppe); |
2011 | 2018 |
|
2012 | 2019 |
typename Graph::Arc ce = graph.direct(graph.addEdge(s, t), true); |
2013 | 2020 |
embedding[ce] = mine; |
2014 | 2021 |
embedding[graph.oppositeArc(ce)] = oppe; |
2015 | 2022 |
|
2016 | 2023 |
typename Graph::Arc pn = ce, p = oppe; |
2017 | 2024 |
e = embedding[graph.oppositeArc(oppe)]; |
2018 | 2025 |
while (graph.target(e) != s) { |
2019 | 2026 |
typename Graph::Arc n = |
2020 | 2027 |
graph.direct(graph.addEdge(s, graph.source(e)), true); |
2021 | 2028 |
|
2022 | 2029 |
embedding[n] = pn; |
2023 | 2030 |
embedding[graph.oppositeArc(n)] = e; |
2024 | 2031 |
embedding[graph.oppositeArc(p)] = graph.oppositeArc(n); |
2025 | 2032 |
|
2026 | 2033 |
pn = n; |
2027 | 2034 |
|
2028 | 2035 |
p = e; |
2029 | 2036 |
e = embedding[graph.oppositeArc(e)]; |
2030 | 2037 |
|
2031 | 2038 |
} |
2032 | 2039 |
embedding[graph.oppositeArc(e)] = pn; |
2033 | 2040 |
|
2034 | 2041 |
pn = graph.oppositeArc(ce), p = mine; |
2035 | 2042 |
e = embedding[graph.oppositeArc(mine)]; |
2036 | 2043 |
while (graph.target(e) != t) { |
2037 | 2044 |
typename Graph::Arc n = |
2038 | 2045 |
graph.direct(graph.addEdge(t, graph.source(e)), true); |
2039 | 2046 |
|
2040 | 2047 |
embedding[n] = pn; |
2041 | 2048 |
embedding[graph.oppositeArc(n)] = e; |
2042 | 2049 |
embedding[graph.oppositeArc(p)] = graph.oppositeArc(n); |
2043 | 2050 |
|
2044 | 2051 |
pn = n; |
2045 | 2052 |
|
2046 | 2053 |
p = e; |
2047 | 2054 |
e = embedding[graph.oppositeArc(e)]; |
2048 | 2055 |
|
2049 | 2056 |
} |
2050 | 2057 |
embedding[graph.oppositeArc(e)] = pn; |
2051 | 2058 |
} |
2052 | 2059 |
} |
2053 | 2060 |
} |
2054 | 2061 |
|
2055 | 2062 |
} |
2056 | 2063 |
|
2057 | 2064 |
/// \ingroup planar |
2058 | 2065 |
/// |
2059 | 2066 |
/// \brief Schnyder's planar drawing algorithm |
2060 | 2067 |
/// |
2061 | 2068 |
/// The planar drawing algorithm calculates positions for the nodes |
2062 |
/// in the plane which coordinates satisfy that if the arcs are |
|
2063 |
/// represented with straight lines then they will not intersect |
|
2069 |
/// in the plane. These coordinates satisfy that if the edges are |
|
2070 |
/// represented with straight lines, then they will not intersect |
|
2064 | 2071 |
/// each other. |
2065 | 2072 |
/// |
2066 |
/// Scnyder's algorithm embeds the graph on \c (n-2,n-2) size grid, |
|
2067 |
/// i.e. each node will be located in the \c [0,n-2]x[0,n-2] square. |
|
2073 |
/// Scnyder's algorithm embeds the graph on an \c (n-2)x(n-2) size grid, |
|
2074 |
/// i.e. each node will be located in the \c [0..n-2]x[0..n-2] square. |
|
2068 | 2075 |
/// The time complexity of the algorithm is O(n). |
2076 |
/// |
|
2077 |
/// \see PlanarEmbedding |
|
2069 | 2078 |
template <typename Graph> |
2070 | 2079 |
class PlanarDrawing { |
2071 | 2080 |
public: |
2072 | 2081 |
|
2073 | 2082 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
2074 | 2083 |
|
2075 |
/// \brief The point type for |
|
2084 |
/// \brief The point type for storing coordinates |
|
2076 | 2085 |
typedef dim2::Point<int> Point; |
2077 |
/// \brief The map type for |
|
2086 |
/// \brief The map type for storing the coordinates of the nodes |
|
2078 | 2087 |
typedef typename Graph::template NodeMap<Point> PointMap; |
2079 | 2088 |
|
2080 | 2089 |
|
2081 | 2090 |
/// \brief Constructor |
2082 | 2091 |
/// |
2083 | 2092 |
/// Constructor |
2084 |
/// \pre The graph |
|
2093 |
/// \pre The graph must be simple, i.e. it should not |
|
2094 |
/// contain parallel or loop arcs. |
|
2085 | 2095 |
PlanarDrawing(const Graph& graph) |
2086 | 2096 |
: _graph(graph), _point_map(graph) {} |
2087 | 2097 |
|
2088 | 2098 |
private: |
2089 | 2099 |
|
2090 | 2100 |
template <typename AuxGraph, typename AuxEmbeddingMap> |
2091 | 2101 |
void drawing(const AuxGraph& graph, |
2092 | 2102 |
const AuxEmbeddingMap& next, |
2093 | 2103 |
PointMap& point_map) { |
2094 | 2104 |
TEMPLATE_GRAPH_TYPEDEFS(AuxGraph); |
2095 | 2105 |
|
2096 | 2106 |
typename AuxGraph::template ArcMap<Arc> prev(graph); |
2097 | 2107 |
|
2098 | 2108 |
for (NodeIt n(graph); n != INVALID; ++n) { |
2099 | 2109 |
Arc e = OutArcIt(graph, n); |
2100 | 2110 |
|
2101 | 2111 |
Arc p = e, l = e; |
2102 | 2112 |
|
2103 | 2113 |
e = next[e]; |
2104 | 2114 |
while (e != l) { |
2105 | 2115 |
prev[e] = p; |
2106 | 2116 |
p = e; |
2107 | 2117 |
e = next[e]; |
2108 | 2118 |
} |
2109 | 2119 |
prev[e] = p; |
2110 | 2120 |
} |
2111 | 2121 |
|
2112 | 2122 |
Node anode, bnode, cnode; |
2113 | 2123 |
|
2114 | 2124 |
{ |
2115 | 2125 |
Arc e = ArcIt(graph); |
2116 | 2126 |
anode = graph.source(e); |
2117 | 2127 |
bnode = graph.target(e); |
2118 | 2128 |
cnode = graph.target(next[graph.oppositeArc(e)]); |
2119 | 2129 |
} |
2120 | 2130 |
|
2121 | 2131 |
IterableBoolMap<AuxGraph, Node> proper(graph, false); |
2122 | 2132 |
typename AuxGraph::template NodeMap<int> conn(graph, -1); |
2123 | 2133 |
|
2124 | 2134 |
conn[anode] = conn[bnode] = -2; |
2125 | 2135 |
{ |
2126 | 2136 |
for (OutArcIt e(graph, anode); e != INVALID; ++e) { |
2127 | 2137 |
Node m = graph.target(e); |
2128 | 2138 |
if (conn[m] == -1) { |
2129 | 2139 |
conn[m] = 1; |
2130 | 2140 |
} |
2131 | 2141 |
} |
2132 | 2142 |
conn[cnode] = 2; |
2133 | 2143 |
|
2134 | 2144 |
for (OutArcIt e(graph, bnode); e != INVALID; ++e) { |
2135 | 2145 |
Node m = graph.target(e); |
2136 | 2146 |
if (conn[m] == -1) { |
2137 | 2147 |
conn[m] = 1; |
2138 | 2148 |
} else if (conn[m] != -2) { |
2139 | 2149 |
conn[m] += 1; |
2140 | 2150 |
Arc pe = graph.oppositeArc(e); |
2141 | 2151 |
if (conn[graph.target(next[pe])] == -2) { |
2142 | 2152 |
conn[m] -= 1; |
2143 | 2153 |
} |
2144 | 2154 |
if (conn[graph.target(prev[pe])] == -2) { |
2145 | 2155 |
conn[m] -= 1; |
2146 | 2156 |
} |
2147 | 2157 |
|
2148 | 2158 |
proper.set(m, conn[m] == 1); |
2149 | 2159 |
} |
2150 | 2160 |
} |
2151 | 2161 |
} |
2152 | 2162 |
|
2153 | 2163 |
|
2154 | 2164 |
typename AuxGraph::template ArcMap<int> angle(graph, -1); |
2155 | 2165 |
|
2156 | 2166 |
while (proper.trueNum() != 0) { |
2157 | 2167 |
Node n = typename IterableBoolMap<AuxGraph, Node>::TrueIt(proper); |
2158 | 2168 |
proper.set(n, false); |
2159 | 2169 |
conn[n] = -2; |
2160 | 2170 |
|
2161 | 2171 |
for (OutArcIt e(graph, n); e != INVALID; ++e) { |
2162 | 2172 |
Node m = graph.target(e); |
2163 | 2173 |
if (conn[m] == -1) { |
2164 | 2174 |
conn[m] = 1; |
2165 | 2175 |
} else if (conn[m] != -2) { |
2166 | 2176 |
conn[m] += 1; |
2167 | 2177 |
Arc pe = graph.oppositeArc(e); |
2168 | 2178 |
if (conn[graph.target(next[pe])] == -2) { |
2169 | 2179 |
conn[m] -= 1; |
2170 | 2180 |
} |
2171 | 2181 |
if (conn[graph.target(prev[pe])] == -2) { |
2172 | 2182 |
conn[m] -= 1; |
2173 | 2183 |
} |
2174 | 2184 |
|
2175 | 2185 |
proper.set(m, conn[m] == 1); |
2176 | 2186 |
} |
2177 | 2187 |
} |
2178 | 2188 |
|
2179 | 2189 |
{ |
2180 | 2190 |
Arc e = OutArcIt(graph, n); |
... | ... |
@@ -2273,465 +2283,473 @@ |
2273 | 2283 |
processed[m] = true; |
2274 | 2284 |
m = bpred[m]; |
2275 | 2285 |
} |
2276 | 2286 |
while (!st.empty()) { |
2277 | 2287 |
border.push_back(st.back()); |
2278 | 2288 |
st.pop_back(); |
2279 | 2289 |
} |
2280 | 2290 |
} |
2281 | 2291 |
} |
2282 | 2292 |
} |
2283 | 2293 |
|
2284 | 2294 |
{ |
2285 | 2295 |
typename AuxGraph::template NodeMap<bool> processed(graph, false); |
2286 | 2296 |
std::vector<Node> st; |
2287 | 2297 |
for (NodeIt n(graph); n != INVALID; ++n) { |
2288 | 2298 |
if (!processed[n] && n != anode && n != bnode) { |
2289 | 2299 |
st.push_back(n); |
2290 | 2300 |
processed[n] = true; |
2291 | 2301 |
Node m = cpred[n]; |
2292 | 2302 |
while (m != INVALID && !processed[m]) { |
2293 | 2303 |
st.push_back(m); |
2294 | 2304 |
processed[m] = true; |
2295 | 2305 |
m = cpred[m]; |
2296 | 2306 |
} |
2297 | 2307 |
while (!st.empty()) { |
2298 | 2308 |
corder.push_back(st.back()); |
2299 | 2309 |
st.pop_back(); |
2300 | 2310 |
} |
2301 | 2311 |
} |
2302 | 2312 |
} |
2303 | 2313 |
} |
2304 | 2314 |
|
2305 | 2315 |
typename AuxGraph::template NodeMap<int> atree(graph, 0); |
2306 | 2316 |
for (int i = aorder.size() - 1; i >= 0; --i) { |
2307 | 2317 |
Node n = aorder[i]; |
2308 | 2318 |
atree[n] = 1; |
2309 | 2319 |
for (OutArcIt e(graph, n); e != INVALID; ++e) { |
2310 | 2320 |
if (apred[graph.target(e)] == n) { |
2311 | 2321 |
atree[n] += atree[graph.target(e)]; |
2312 | 2322 |
} |
2313 | 2323 |
} |
2314 | 2324 |
} |
2315 | 2325 |
|
2316 | 2326 |
typename AuxGraph::template NodeMap<int> btree(graph, 0); |
2317 | 2327 |
for (int i = border.size() - 1; i >= 0; --i) { |
2318 | 2328 |
Node n = border[i]; |
2319 | 2329 |
btree[n] = 1; |
2320 | 2330 |
for (OutArcIt e(graph, n); e != INVALID; ++e) { |
2321 | 2331 |
if (bpred[graph.target(e)] == n) { |
2322 | 2332 |
btree[n] += btree[graph.target(e)]; |
2323 | 2333 |
} |
2324 | 2334 |
} |
2325 | 2335 |
} |
2326 | 2336 |
|
2327 | 2337 |
typename AuxGraph::template NodeMap<int> apath(graph, 0); |
2328 | 2338 |
apath[bnode] = apath[cnode] = 1; |
2329 | 2339 |
typename AuxGraph::template NodeMap<int> apath_btree(graph, 0); |
2330 | 2340 |
apath_btree[bnode] = btree[bnode]; |
2331 | 2341 |
for (int i = 1; i < int(aorder.size()); ++i) { |
2332 | 2342 |
Node n = aorder[i]; |
2333 | 2343 |
apath[n] = apath[apred[n]] + 1; |
2334 | 2344 |
apath_btree[n] = btree[n] + apath_btree[apred[n]]; |
2335 | 2345 |
} |
2336 | 2346 |
|
2337 | 2347 |
typename AuxGraph::template NodeMap<int> bpath_atree(graph, 0); |
2338 | 2348 |
bpath_atree[anode] = atree[anode]; |
2339 | 2349 |
for (int i = 1; i < int(border.size()); ++i) { |
2340 | 2350 |
Node n = border[i]; |
2341 | 2351 |
bpath_atree[n] = atree[n] + bpath_atree[bpred[n]]; |
2342 | 2352 |
} |
2343 | 2353 |
|
2344 | 2354 |
typename AuxGraph::template NodeMap<int> cpath(graph, 0); |
2345 | 2355 |
cpath[anode] = cpath[bnode] = 1; |
2346 | 2356 |
typename AuxGraph::template NodeMap<int> cpath_atree(graph, 0); |
2347 | 2357 |
cpath_atree[anode] = atree[anode]; |
2348 | 2358 |
typename AuxGraph::template NodeMap<int> cpath_btree(graph, 0); |
2349 | 2359 |
cpath_btree[bnode] = btree[bnode]; |
2350 | 2360 |
for (int i = 1; i < int(corder.size()); ++i) { |
2351 | 2361 |
Node n = corder[i]; |
2352 | 2362 |
cpath[n] = cpath[cpred[n]] + 1; |
2353 | 2363 |
cpath_atree[n] = atree[n] + cpath_atree[cpred[n]]; |
2354 | 2364 |
cpath_btree[n] = btree[n] + cpath_btree[cpred[n]]; |
2355 | 2365 |
} |
2356 | 2366 |
|
2357 | 2367 |
typename AuxGraph::template NodeMap<int> third(graph); |
2358 | 2368 |
for (NodeIt n(graph); n != INVALID; ++n) { |
2359 | 2369 |
point_map[n].x = |
2360 | 2370 |
bpath_atree[n] + cpath_atree[n] - atree[n] - cpath[n] + 1; |
2361 | 2371 |
point_map[n].y = |
2362 | 2372 |
cpath_btree[n] + apath_btree[n] - btree[n] - apath[n] + 1; |
2363 | 2373 |
} |
2364 | 2374 |
|
2365 | 2375 |
} |
2366 | 2376 |
|
2367 | 2377 |
public: |
2368 | 2378 |
|
2369 |
/// \brief |
|
2379 |
/// \brief Calculate the node positions |
|
2370 | 2380 |
/// |
2371 |
/// This function calculates the node positions. |
|
2372 |
/// \return %True if the graph is planar. |
|
2381 |
/// This function calculates the node positions on the plane. |
|
2382 |
/// \return \c true if the graph is planar. |
|
2373 | 2383 |
bool run() { |
2374 | 2384 |
PlanarEmbedding<Graph> pe(_graph); |
2375 | 2385 |
if (!pe.run()) return false; |
2376 | 2386 |
|
2377 | 2387 |
run(pe); |
2378 | 2388 |
return true; |
2379 | 2389 |
} |
2380 | 2390 |
|
2381 |
/// \brief |
|
2391 |
/// \brief Calculate the node positions according to a |
|
2382 | 2392 |
/// combinatorical embedding |
2383 | 2393 |
/// |
2384 |
/// This function calculates the node locations. The \c embedding |
|
2385 |
/// parameter should contain a valid combinatorical embedding, i.e. |
|
2386 |
/// |
|
2394 |
/// This function calculates the node positions on the plane. |
|
2395 |
/// The given \c embedding map should contain a valid combinatorical |
|
2396 |
/// embedding, i.e. a valid cyclic order of the arcs. |
|
2397 |
/// It can be computed using PlanarEmbedding. |
|
2387 | 2398 |
template <typename EmbeddingMap> |
2388 | 2399 |
void run(const EmbeddingMap& embedding) { |
2389 | 2400 |
typedef SmartEdgeSet<Graph> AuxGraph; |
2390 | 2401 |
|
2391 | 2402 |
if (3 * countNodes(_graph) - 6 == countEdges(_graph)) { |
2392 | 2403 |
drawing(_graph, embedding, _point_map); |
2393 | 2404 |
return; |
2394 | 2405 |
} |
2395 | 2406 |
|
2396 | 2407 |
AuxGraph aux_graph(_graph); |
2397 | 2408 |
typename AuxGraph::template ArcMap<typename AuxGraph::Arc> |
2398 | 2409 |
aux_embedding(aux_graph); |
2399 | 2410 |
|
2400 | 2411 |
{ |
2401 | 2412 |
|
2402 | 2413 |
typename Graph::template EdgeMap<typename AuxGraph::Edge> |
2403 | 2414 |
ref(_graph); |
2404 | 2415 |
|
2405 | 2416 |
for (EdgeIt e(_graph); e != INVALID; ++e) { |
2406 | 2417 |
ref[e] = aux_graph.addEdge(_graph.u(e), _graph.v(e)); |
2407 | 2418 |
} |
2408 | 2419 |
|
2409 | 2420 |
for (EdgeIt e(_graph); e != INVALID; ++e) { |
2410 | 2421 |
Arc ee = embedding[_graph.direct(e, true)]; |
2411 | 2422 |
aux_embedding[aux_graph.direct(ref[e], true)] = |
2412 | 2423 |
aux_graph.direct(ref[ee], _graph.direction(ee)); |
2413 | 2424 |
ee = embedding[_graph.direct(e, false)]; |
2414 | 2425 |
aux_embedding[aux_graph.direct(ref[e], false)] = |
2415 | 2426 |
aux_graph.direct(ref[ee], _graph.direction(ee)); |
2416 | 2427 |
} |
2417 | 2428 |
} |
2418 | 2429 |
_planarity_bits::makeConnected(aux_graph, aux_embedding); |
2419 | 2430 |
_planarity_bits::makeBiNodeConnected(aux_graph, aux_embedding); |
2420 | 2431 |
_planarity_bits::makeMaxPlanar(aux_graph, aux_embedding); |
2421 | 2432 |
drawing(aux_graph, aux_embedding, _point_map); |
2422 | 2433 |
} |
2423 | 2434 |
|
2424 | 2435 |
/// \brief The coordinate of the given node |
2425 | 2436 |
/// |
2426 |
/// |
|
2437 |
/// This function returns the coordinate of the given node. |
|
2427 | 2438 |
Point operator[](const Node& node) const { |
2428 | 2439 |
return _point_map[node]; |
2429 | 2440 |
} |
2430 | 2441 |
|
2431 |
/// \brief |
|
2442 |
/// \brief Return the grid embedding in a node map |
|
2432 | 2443 |
/// |
2433 |
/// |
|
2444 |
/// This function returns the grid embedding in a node map of |
|
2445 |
/// \c dim2::Point<int> coordinates. |
|
2434 | 2446 |
const PointMap& coords() const { |
2435 | 2447 |
return _point_map; |
2436 | 2448 |
} |
2437 | 2449 |
|
2438 | 2450 |
private: |
2439 | 2451 |
|
2440 | 2452 |
const Graph& _graph; |
2441 | 2453 |
PointMap _point_map; |
2442 | 2454 |
|
2443 | 2455 |
}; |
2444 | 2456 |
|
2445 | 2457 |
namespace _planarity_bits { |
2446 | 2458 |
|
2447 | 2459 |
template <typename ColorMap> |
2448 | 2460 |
class KempeFilter { |
2449 | 2461 |
public: |
2450 | 2462 |
typedef typename ColorMap::Key Key; |
2451 | 2463 |
typedef bool Value; |
2452 | 2464 |
|
2453 | 2465 |
KempeFilter(const ColorMap& color_map, |
2454 | 2466 |
const typename ColorMap::Value& first, |
2455 | 2467 |
const typename ColorMap::Value& second) |
2456 | 2468 |
: _color_map(color_map), _first(first), _second(second) {} |
2457 | 2469 |
|
2458 | 2470 |
Value operator[](const Key& key) const { |
2459 | 2471 |
return _color_map[key] == _first || _color_map[key] == _second; |
2460 | 2472 |
} |
2461 | 2473 |
|
2462 | 2474 |
private: |
2463 | 2475 |
const ColorMap& _color_map; |
2464 | 2476 |
typename ColorMap::Value _first, _second; |
2465 | 2477 |
}; |
2466 | 2478 |
} |
2467 | 2479 |
|
2468 | 2480 |
/// \ingroup planar |
2469 | 2481 |
/// |
2470 | 2482 |
/// \brief Coloring planar graphs |
2471 | 2483 |
/// |
2472 | 2484 |
/// The graph coloring problem is the coloring of the graph nodes |
2473 |
/// that there are not adjacent nodes with the same color. The |
|
2474 |
/// planar graphs can be always colored with four colors, it is |
|
2475 |
/// |
|
2485 |
/// so that there are no adjacent nodes with the same color. The |
|
2486 |
/// planar graphs can always be colored with four colors, which is |
|
2487 |
/// proved by Appel and Haken. Their proofs provide a quadratic |
|
2476 | 2488 |
/// time algorithm for four coloring, but it could not be used to |
2477 |
/// implement efficient algorithm. The five and six coloring can be |
|
2478 |
/// made in linear time, but in this class the five coloring has |
|
2489 |
/// implement an efficient algorithm. The five and six coloring can be |
|
2490 |
/// made in linear time, but in this class, the five coloring has |
|
2479 | 2491 |
/// quadratic worst case time complexity. The two coloring (if |
2480 | 2492 |
/// possible) is solvable with a graph search algorithm and it is |
2481 | 2493 |
/// implemented in \ref bipartitePartitions() function in LEMON. To |
2482 |
/// decide whether the planar graph is three colorable is |
|
2483 |
/// NP-complete. |
|
2494 |
/// decide whether a planar graph is three colorable is NP-complete. |
|
2484 | 2495 |
/// |
2485 | 2496 |
/// This class contains member functions for calculate colorings |
2486 | 2497 |
/// with five and six colors. The six coloring algorithm is a simple |
2487 | 2498 |
/// greedy coloring on the backward minimum outgoing order of nodes. |
2488 |
/// This order can be computed as in each phase the node with least |
|
2489 |
/// outgoing arcs to unprocessed nodes is chosen. This order |
|
2499 |
/// This order can be computed by selecting the node with least |
|
2500 |
/// outgoing arcs to unprocessed nodes in each phase. This order |
|
2490 | 2501 |
/// guarantees that when a node is chosen for coloring it has at |
2491 | 2502 |
/// most five already colored adjacents. The five coloring algorithm |
2492 | 2503 |
/// use the same method, but if the greedy approach fails to color |
2493 | 2504 |
/// with five colors, i.e. the node has five already different |
2494 | 2505 |
/// colored neighbours, it swaps the colors in one of the connected |
2495 | 2506 |
/// two colored sets with the Kempe recoloring method. |
2496 | 2507 |
template <typename Graph> |
2497 | 2508 |
class PlanarColoring { |
2498 | 2509 |
public: |
2499 | 2510 |
|
2500 | 2511 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
2501 | 2512 |
|
2502 |
/// \brief The map type for |
|
2513 |
/// \brief The map type for storing color indices |
|
2503 | 2514 |
typedef typename Graph::template NodeMap<int> IndexMap; |
2504 |
/// \brief The map type for |
|
2515 |
/// \brief The map type for storing colors |
|
2516 |
/// |
|
2517 |
/// The map type for storing colors. |
|
2518 |
/// \see Palette, Color |
|
2505 | 2519 |
typedef ComposeMap<Palette, IndexMap> ColorMap; |
2506 | 2520 |
|
2507 | 2521 |
/// \brief Constructor |
2508 | 2522 |
/// |
2509 |
/// Constructor |
|
2510 |
/// \pre The graph should be simple, i.e. loop and parallel arc free. |
|
2523 |
/// Constructor. |
|
2524 |
/// \pre The graph must be simple, i.e. it should not |
|
2525 |
/// contain parallel or loop arcs. |
|
2511 | 2526 |
PlanarColoring(const Graph& graph) |
2512 | 2527 |
: _graph(graph), _color_map(graph), _palette(0) { |
2513 | 2528 |
_palette.add(Color(1,0,0)); |
2514 | 2529 |
_palette.add(Color(0,1,0)); |
2515 | 2530 |
_palette.add(Color(0,0,1)); |
2516 | 2531 |
_palette.add(Color(1,1,0)); |
2517 | 2532 |
_palette.add(Color(1,0,1)); |
2518 | 2533 |
_palette.add(Color(0,1,1)); |
2519 | 2534 |
} |
2520 | 2535 |
|
2521 |
/// \brief |
|
2536 |
/// \brief Return the node map of color indices |
|
2522 | 2537 |
/// |
2523 |
/// Returns the \e NodeMap of color indexes. The values are in the |
|
2524 |
/// range \c [0..4] or \c [0..5] according to the coloring method. |
|
2538 |
/// This function returns the node map of color indices. The values are |
|
2539 |
/// in the range \c [0..4] or \c [0..5] according to the coloring method. |
|
2525 | 2540 |
IndexMap colorIndexMap() const { |
2526 | 2541 |
return _color_map; |
2527 | 2542 |
} |
2528 | 2543 |
|
2529 |
/// \brief |
|
2544 |
/// \brief Return the node map of colors |
|
2530 | 2545 |
/// |
2531 |
/// Returns the \e NodeMap of colors. The values are five or six |
|
2532 |
/// distinct \ref lemon::Color "colors". |
|
2546 |
/// This function returns the node map of colors. The values are among |
|
2547 |
/// five or six distinct \ref lemon::Color "colors". |
|
2533 | 2548 |
ColorMap colorMap() const { |
2534 | 2549 |
return composeMap(_palette, _color_map); |
2535 | 2550 |
} |
2536 | 2551 |
|
2537 |
/// \brief |
|
2552 |
/// \brief Return the color index of the node |
|
2538 | 2553 |
/// |
2539 |
/// Returns the color index of the node. The values are in the |
|
2540 |
/// range \c [0..4] or \c [0..5] according to the coloring method. |
|
2554 |
/// This function returns the color index of the given node. The value is |
|
2555 |
/// in the range \c [0..4] or \c [0..5] according to the coloring method. |
|
2541 | 2556 |
int colorIndex(const Node& node) const { |
2542 | 2557 |
return _color_map[node]; |
2543 | 2558 |
} |
2544 | 2559 |
|
2545 |
/// \brief |
|
2560 |
/// \brief Return the color of the node |
|
2546 | 2561 |
/// |
2547 |
/// Returns the color of the node. The values are five or six |
|
2548 |
/// distinct \ref lemon::Color "colors". |
|
2562 |
/// This function returns the color of the given node. The value is among |
|
2563 |
/// five or six distinct \ref lemon::Color "colors". |
|
2549 | 2564 |
Color color(const Node& node) const { |
2550 | 2565 |
return _palette[_color_map[node]]; |
2551 | 2566 |
} |
2552 | 2567 |
|
2553 | 2568 |
|
2554 |
/// \brief |
|
2569 |
/// \brief Calculate a coloring with at most six colors |
|
2555 | 2570 |
/// |
2556 | 2571 |
/// This function calculates a coloring with at most six colors. The time |
2557 | 2572 |
/// complexity of this variant is linear in the size of the graph. |
2558 |
/// \return %True when the algorithm could color the graph with six color. |
|
2559 |
/// If the algorithm fails, then the graph could not be planar. |
|
2560 |
/// \note This function can return true if the graph is not |
|
2561 |
/// planar but it can be colored with 6 colors. |
|
2573 |
/// \return \c true if the algorithm could color the graph with six colors. |
|
2574 |
/// If the algorithm fails, then the graph is not planar. |
|
2575 |
/// \note This function can return \c true if the graph is not |
|
2576 |
/// planar, but it can be colored with at most six colors. |
|
2562 | 2577 |
bool runSixColoring() { |
2563 | 2578 |
|
2564 | 2579 |
typename Graph::template NodeMap<int> heap_index(_graph, -1); |
2565 | 2580 |
BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index); |
2566 | 2581 |
|
2567 | 2582 |
for (NodeIt n(_graph); n != INVALID; ++n) { |
2568 | 2583 |
_color_map[n] = -2; |
2569 | 2584 |
heap.push(n, countOutArcs(_graph, n)); |
2570 | 2585 |
} |
2571 | 2586 |
|
2572 | 2587 |
std::vector<Node> order; |
2573 | 2588 |
|
2574 | 2589 |
while (!heap.empty()) { |
2575 | 2590 |
Node n = heap.top(); |
2576 | 2591 |
heap.pop(); |
2577 | 2592 |
_color_map[n] = -1; |
2578 | 2593 |
order.push_back(n); |
2579 | 2594 |
for (OutArcIt e(_graph, n); e != INVALID; ++e) { |
2580 | 2595 |
Node t = _graph.runningNode(e); |
2581 | 2596 |
if (_color_map[t] == -2) { |
2582 | 2597 |
heap.decrease(t, heap[t] - 1); |
2583 | 2598 |
} |
2584 | 2599 |
} |
2585 | 2600 |
} |
2586 | 2601 |
|
2587 | 2602 |
for (int i = order.size() - 1; i >= 0; --i) { |
2588 | 2603 |
std::vector<bool> forbidden(6, false); |
2589 | 2604 |
for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) { |
2590 | 2605 |
Node t = _graph.runningNode(e); |
2591 | 2606 |
if (_color_map[t] != -1) { |
2592 | 2607 |
forbidden[_color_map[t]] = true; |
2593 | 2608 |
} |
2594 | 2609 |
} |
2595 | 2610 |
for (int k = 0; k < 6; ++k) { |
2596 | 2611 |
if (!forbidden[k]) { |
2597 | 2612 |
_color_map[order[i]] = k; |
2598 | 2613 |
break; |
2599 | 2614 |
} |
2600 | 2615 |
} |
2601 | 2616 |
if (_color_map[order[i]] == -1) { |
2602 | 2617 |
return false; |
2603 | 2618 |
} |
2604 | 2619 |
} |
2605 | 2620 |
return true; |
2606 | 2621 |
} |
2607 | 2622 |
|
2608 | 2623 |
private: |
2609 | 2624 |
|
2610 | 2625 |
bool recolor(const Node& u, const Node& v) { |
2611 | 2626 |
int ucolor = _color_map[u]; |
2612 | 2627 |
int vcolor = _color_map[v]; |
2613 | 2628 |
typedef _planarity_bits::KempeFilter<IndexMap> KempeFilter; |
2614 | 2629 |
KempeFilter filter(_color_map, ucolor, vcolor); |
2615 | 2630 |
|
2616 | 2631 |
typedef FilterNodes<const Graph, const KempeFilter> KempeGraph; |
2617 | 2632 |
KempeGraph kempe_graph(_graph, filter); |
2618 | 2633 |
|
2619 | 2634 |
std::vector<Node> comp; |
2620 | 2635 |
Bfs<KempeGraph> bfs(kempe_graph); |
2621 | 2636 |
bfs.init(); |
2622 | 2637 |
bfs.addSource(u); |
2623 | 2638 |
while (!bfs.emptyQueue()) { |
2624 | 2639 |
Node n = bfs.nextNode(); |
2625 | 2640 |
if (n == v) return false; |
2626 | 2641 |
comp.push_back(n); |
2627 | 2642 |
bfs.processNextNode(); |
2628 | 2643 |
} |
2629 | 2644 |
|
2630 | 2645 |
int scolor = ucolor + vcolor; |
2631 | 2646 |
for (int i = 0; i < static_cast<int>(comp.size()); ++i) { |
2632 | 2647 |
_color_map[comp[i]] = scolor - _color_map[comp[i]]; |
2633 | 2648 |
} |
2634 | 2649 |
|
2635 | 2650 |
return true; |
2636 | 2651 |
} |
2637 | 2652 |
|
2638 | 2653 |
template <typename EmbeddingMap> |
2639 | 2654 |
void kempeRecoloring(const Node& node, const EmbeddingMap& embedding) { |
2640 | 2655 |
std::vector<Node> nodes; |
2641 | 2656 |
nodes.reserve(4); |
2642 | 2657 |
|
2643 | 2658 |
for (Arc e = OutArcIt(_graph, node); e != INVALID; e = embedding[e]) { |
2644 | 2659 |
Node t = _graph.target(e); |
2645 | 2660 |
if (_color_map[t] != -1) { |
2646 | 2661 |
nodes.push_back(t); |
2647 | 2662 |
if (nodes.size() == 4) break; |
2648 | 2663 |
} |
2649 | 2664 |
} |
2650 | 2665 |
|
2651 | 2666 |
int color = _color_map[nodes[0]]; |
2652 | 2667 |
if (recolor(nodes[0], nodes[2])) { |
2653 | 2668 |
_color_map[node] = color; |
2654 | 2669 |
} else { |
2655 | 2670 |
color = _color_map[nodes[1]]; |
2656 | 2671 |
recolor(nodes[1], nodes[3]); |
2657 | 2672 |
_color_map[node] = color; |
2658 | 2673 |
} |
2659 | 2674 |
} |
2660 | 2675 |
|
2661 | 2676 |
public: |
2662 | 2677 |
|
2663 |
/// \brief |
|
2678 |
/// \brief Calculate a coloring with at most five colors |
|
2664 | 2679 |
/// |
2665 | 2680 |
/// This function calculates a coloring with at most five |
2666 | 2681 |
/// colors. The worst case time complexity of this variant is |
2667 | 2682 |
/// quadratic in the size of the graph. |
2683 |
/// \param embedding This map should contain a valid combinatorical |
|
2684 |
/// embedding, i.e. a valid cyclic order of the arcs. |
|
2685 |
/// It can be computed using PlanarEmbedding. |
|
2668 | 2686 |
template <typename EmbeddingMap> |
2669 | 2687 |
void runFiveColoring(const EmbeddingMap& embedding) { |
2670 | 2688 |
|
2671 | 2689 |
typename Graph::template NodeMap<int> heap_index(_graph, -1); |
2672 | 2690 |
BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index); |
2673 | 2691 |
|
2674 | 2692 |
for (NodeIt n(_graph); n != INVALID; ++n) { |
2675 | 2693 |
_color_map[n] = -2; |
2676 | 2694 |
heap.push(n, countOutArcs(_graph, n)); |
2677 | 2695 |
} |
2678 | 2696 |
|
2679 | 2697 |
std::vector<Node> order; |
2680 | 2698 |
|
2681 | 2699 |
while (!heap.empty()) { |
2682 | 2700 |
Node n = heap.top(); |
2683 | 2701 |
heap.pop(); |
2684 | 2702 |
_color_map[n] = -1; |
2685 | 2703 |
order.push_back(n); |
2686 | 2704 |
for (OutArcIt e(_graph, n); e != INVALID; ++e) { |
2687 | 2705 |
Node t = _graph.runningNode(e); |
2688 | 2706 |
if (_color_map[t] == -2) { |
2689 | 2707 |
heap.decrease(t, heap[t] - 1); |
2690 | 2708 |
} |
2691 | 2709 |
} |
2692 | 2710 |
} |
2693 | 2711 |
|
2694 | 2712 |
for (int i = order.size() - 1; i >= 0; --i) { |
2695 | 2713 |
std::vector<bool> forbidden(5, false); |
2696 | 2714 |
for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) { |
2697 | 2715 |
Node t = _graph.runningNode(e); |
2698 | 2716 |
if (_color_map[t] != -1) { |
2699 | 2717 |
forbidden[_color_map[t]] = true; |
2700 | 2718 |
} |
2701 | 2719 |
} |
2702 | 2720 |
for (int k = 0; k < 5; ++k) { |
2703 | 2721 |
if (!forbidden[k]) { |
2704 | 2722 |
_color_map[order[i]] = k; |
2705 | 2723 |
break; |
2706 | 2724 |
} |
2707 | 2725 |
} |
2708 | 2726 |
if (_color_map[order[i]] == -1) { |
2709 | 2727 |
kempeRecoloring(order[i], embedding); |
2710 | 2728 |
} |
2711 | 2729 |
} |
2712 | 2730 |
} |
2713 | 2731 |
|
2714 |
/// \brief |
|
2732 |
/// \brief Calculate a coloring with at most five colors |
|
2715 | 2733 |
/// |
2716 | 2734 |
/// This function calculates a coloring with at most five |
2717 | 2735 |
/// colors. The worst case time complexity of this variant is |
2718 | 2736 |
/// quadratic in the size of the graph. |
2719 |
/// \return |
|
2737 |
/// \return \c true if the graph is planar. |
|
2720 | 2738 |
bool runFiveColoring() { |
2721 | 2739 |
PlanarEmbedding<Graph> pe(_graph); |
2722 | 2740 |
if (!pe.run()) return false; |
2723 | 2741 |
|
2724 | 2742 |
runFiveColoring(pe.embeddingMap()); |
2725 | 2743 |
return true; |
2726 | 2744 |
} |
2727 | 2745 |
|
2728 | 2746 |
private: |
2729 | 2747 |
|
2730 | 2748 |
const Graph& _graph; |
2731 | 2749 |
IndexMap _color_map; |
2732 | 2750 |
Palette _palette; |
2733 | 2751 |
}; |
2734 | 2752 |
|
2735 | 2753 |
} |
2736 | 2754 |
|
2737 | 2755 |
#endif |
0 comments (0 inline)