... | ... |
@@ -497,72 +497,73 @@ |
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; |
... | ... |
@@ -570,64 +571,68 @@ |
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 |
|
... | ... |
@@ -678,72 +683,74 @@ |
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]; |
... | ... |
@@ -2038,71 +2045,74 @@ |
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 |
} |
... | ... |
@@ -2345,241 +2355,246 @@ |
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 |
} |
... | ... |
@@ -2639,99 +2654,102 @@ |
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)