00001 00027 #ifndef MSMAZES_CORE_GRAPH_REMOVE_CROSS_EDGES_HPP 00028 #define MSMAZES_CORE_GRAPH_REMOVE_CROSS_EDGES_HPP 00029 00030 // std::vector 00031 #include <vector> 00032 // std::map 00033 #include <map> 00034 // std::pair and std::make_pair 00035 #include <utility> 00036 // boost::function_requires and basic concept check templates 00037 #include <boost/concept_check.hpp> 00038 // boost::queue 00039 #include <boost/pending/queue.hpp> 00040 // boost::property_map, boost::associative_property_map, 00041 // boost::make_iterator_property_map, boost::get, and boost::put 00042 #include <boost/property_map.hpp> 00043 // boost::ref 00044 #include <boost/ref.hpp> 00045 // boost::tie 00046 #include <boost/utility.hpp> 00047 // BOOST_PP_LESS 00048 #include <boost/preprocessor/comparison/less.hpp> 00049 // boost::remove_const 00050 #include <boost/type_traits/remove_const.hpp> 00051 // boost::remove_reference 00052 #include <boost/type_traits/remove_reference.hpp> 00053 // BGL concept check templates 00054 #include <boost/graph/graph_concepts.hpp> 00055 // boost::graph_traits 00056 #include <boost/graph/graph_traits.hpp> 00057 // boost::color_traits 00058 #include <boost/graph/properties.hpp> 00059 // boost::predecessor_recorder and boost::null_visitor 00060 #include <boost/graph/visitors.hpp> 00061 // boost::breadth_first_visit and boost::make_bfs_visitor 00062 #include <boost/graph/breadth_first_search.hpp> 00063 // boost::dfs_visitor, boost::depth_first_visit, and boost::make_dfs_visitor 00064 #include <boost/graph/depth_first_search.hpp> 00065 //#include <boost/graph/adjacency_list.hpp> must be included before this file. 00066 // msmazes::hasInEdges and msmazes::removeInEdges 00067 #include <msmazes/core/graph/in_edges.hpp> 00068 // Boost.Parameter keyword objects used by the Core Graph algorithms 00069 #include <msmazes/core/graph/keywords.hpp> 00070 00071 #if BOOST_PP_LESS(BOOST_PARAMETER_MAX_ARITY, 9) 00072 #error Set BOOST_PARAMETER_MAX_ARITY to 9 or higher, please. 00073 #endif 00074 00075 namespace msmazes { 00076 00100 class DefaultCrossEdgeRemovalIntruder 00101 { 00102 public: 00113 template < 00114 typename Graph 00115 > 00116 void 00117 pathEdgeTemporarilyRemoved( 00118 typename boost::graph_traits<Graph>::vertex_descriptor u 00119 , typename boost::graph_traits<Graph>::vertex_descriptor v 00120 , Graph& g 00121 ) 00122 { 00123 } 00124 00136 template < 00137 typename Graph 00138 > 00139 inline bool 00140 canRemoveCrossEdge( 00141 typename boost::graph_traits<Graph>::edge_descriptor e 00142 , Graph& g 00143 ) 00144 { 00145 return true; 00146 } 00147 00157 template < 00158 typename Graph 00159 > 00160 void 00161 pathEdgeReinstated( 00162 typename boost::graph_traits<Graph>::edge_descriptor e 00163 , Graph& g 00164 ) 00165 { 00166 } 00167 }; 00168 00169 namespace _removeCrossEdges { 00170 00171 /* 00172 * This event visitor class template helps the AltPathRanker class template 00173 * by ranking the vertices that the latter class has classified as cycles. 00174 */ 00179 template <typename VertexRankMap> 00180 class CycleRanker 00181 : public boost::base_visitor<CycleRanker<VertexRankMap> > 00182 { 00183 public: 00184 typedef boost::on_tree_edge 00185 event_filter; 00186 typedef typename boost::property_traits<VertexRankMap>::value_type 00187 Rank; 00188 00189 private: 00190 VertexRankMap _rank_map; 00191 00192 public: 00193 explicit CycleRanker(VertexRankMap rank_map) 00194 : _rank_map(rank_map) 00195 { 00196 } 00197 00198 CycleRanker(const CycleRanker& copy) 00199 : _rank_map(copy._rank_map) 00200 { 00201 } 00202 00203 ~CycleRanker() 00204 { 00205 } 00206 00207 template < 00208 typename Graph 00209 > 00210 void 00211 operator()( 00212 typename boost::graph_traits<Graph>::edge_descriptor e 00213 , Graph& g 00214 ) 00215 { 00216 boost::put( 00217 _rank_map 00218 , boost::target(e, g) 00219 , boost::get(_rank_map, boost::source(e, g)) 00220 ); 00221 } 00222 }; 00223 00224 /* 00225 * This event visitor class template carries out the actual removal of 00226 * cross-edges (with respect to the main path in the graph, not the 00227 * depth-first traversal that is passed an instance of this class). 00228 */ 00233 template < 00234 typename InputGraph 00235 , typename VertexIndexMap 00236 , typename VertexRankMap 00237 , typename CrossEdgeRemovalIntruder 00238 > 00239 class CrossEdgeRemover 00240 : public boost::base_visitor< 00241 CrossEdgeRemover< 00242 InputGraph 00243 , VertexIndexMap 00244 , VertexRankMap 00245 , CrossEdgeRemovalIntruder 00246 > 00247 > 00248 { 00249 public: 00250 typedef boost::on_discover_vertex 00251 event_filter; 00252 typedef typename boost::property_traits<VertexRankMap>::value_type 00253 Rank; 00254 00255 private: 00256 const Rank& _root_rank; 00257 00258 CrossEdgeRemovalIntruder& _intruder; 00259 InputGraph& _g; 00260 VertexIndexMap _index_map; 00261 VertexRankMap _rank_map; 00262 00263 public: 00264 CrossEdgeRemover( 00265 InputGraph& g 00266 , VertexIndexMap index_map 00267 , VertexRankMap rank_map 00268 , Rank& root_rank 00269 , CrossEdgeRemovalIntruder& intruder 00270 ) 00271 : _root_rank(root_rank) 00272 , _intruder(intruder) 00273 , _g(g) 00274 , _index_map(index_map) 00275 , _rank_map(rank_map) 00276 { 00277 } 00278 00279 CrossEdgeRemover(const CrossEdgeRemover& copy) 00280 : _root_rank(copy._root_rank) 00281 , _intruder(copy._intruder) 00282 , _g(copy._g) 00283 , _index_map(copy._index_map) 00284 , _rank_map(copy._rank_map) 00285 { 00286 } 00287 00288 ~CrossEdgeRemover() 00289 { 00290 } 00291 00292 template < 00293 typename Graph 00294 > 00295 void 00296 operator()( 00297 typename boost::graph_traits<Graph>::vertex_descriptor v 00298 , Graph& g 00299 ) 00300 { 00301 typename boost::graph_traits<InputGraph>::vertex_descriptor 00302 vertex = boost::vertex(boost::get(_index_map, v), _g); 00303 typename boost::graph_traits<InputGraph>::out_edge_iterator 00304 oi, oend; 00305 00306 boost::tie(oi, oend) = boost::out_edges(vertex, _g); 00307 00308 while (oi != oend) 00309 { 00310 if ( 00311 (_root_rank < boost::get(_rank_map, boost::target(*oi, _g))) 00312 && _intruder.canRemoveCrossEdge(*oi, _g) 00313 ) 00314 { 00315 /* 00316 * This vertex is connected to a vertex that is farther 00317 * down the main path than the source vertex of this 00318 * traversal (the vertex whose rank is root_rank). 00319 * Therefore, this edge is a cross edge. 00320 */ 00321 boost::remove_edge(oi, _g); 00322 boost::tie(oi, oend) = boost::out_edges(vertex, _g); 00323 } 00324 else 00325 { 00326 ++oi; 00327 } 00328 } 00329 } 00330 }; 00331 00332 /* 00333 * This event visitor class template ranks the vertices that are not part of 00334 * the main path so that the CrossEdgeRemover class template can identify 00335 * which edges to remove. 00336 */ 00341 template < 00342 typename VertexRankMap 00343 , typename VertexColorMap 00344 > 00345 class AltPathRanker 00346 : public boost::base_visitor<AltPathRanker<VertexRankMap,VertexColorMap> > 00347 { 00348 public: 00349 typedef boost::on_finish_vertex 00350 event_filter; 00351 typedef typename boost::property_traits<VertexColorMap>::value_type 00352 ColorValue; 00353 typedef boost::color_traits<ColorValue> 00354 Color; 00355 typedef typename boost::property_traits<VertexRankMap>::value_type 00356 Rank; 00357 typedef boost::dfs_visitor< 00358 std::pair<CycleRanker<VertexRankMap>,boost::null_visitor> 00359 > 00360 CycleVisitor; 00361 00362 private: 00363 static const Rank zero_rank = Rank(); 00364 00365 VertexRankMap _rank_map; 00366 VertexColorMap _color_map; 00367 CycleVisitor _cycle_visitor; 00368 00369 public: 00370 AltPathRanker(VertexRankMap rank_map, VertexColorMap color_map) 00371 : _rank_map(rank_map) 00372 , _color_map(color_map) 00373 , _cycle_visitor( 00374 boost::make_dfs_visitor( 00375 std::make_pair( 00376 CycleRanker<VertexRankMap>(rank_map) 00377 , boost::null_visitor() 00378 ) 00379 ) 00380 ) 00381 { 00382 } 00383 00384 AltPathRanker(const AltPathRanker& copy) 00385 : _rank_map(copy._rank_map) 00386 , _color_map(copy._color_map) 00387 , _cycle_visitor(copy._cycle_visitor) 00388 { 00389 } 00390 00391 ~AltPathRanker() 00392 { 00393 } 00394 00395 template <typename Graph> 00396 void 00397 operator()( 00398 typename boost::graph_traits<Graph>::vertex_descriptor v 00399 , Graph& g 00400 ) 00401 { 00402 typename boost::graph_traits<Graph>::adjacency_iterator vi, vend; 00403 bool has_cycles = false; 00404 Rank target_rank; 00405 00406 for (boost::tie(vi, vend) = boost::adjacent_vertices(v, g); 00407 vi != vend; 00408 ++vi) 00409 { 00410 target_rank = boost::get(_rank_map, *vi); 00411 00412 if (target_rank == zero_rank) 00413 { 00414 /* 00415 * The out-edge leads to a cycle. 00416 */ 00417 has_cycles = true; 00418 } 00419 else if ( 00420 (boost::get(_color_map, *vi) != Color::gray()) 00421 && (boost::get(_rank_map, v) < target_rank) 00422 ) 00423 { 00424 /* 00425 * This vertex is connected to a vertex with a higher rank 00426 * than zero (i.e. the first one so far) or a vertex farther 00427 * down the main path than the one with the current rank but 00428 * still is a predecessor to the source vertex of this 00429 * traversal. 00430 */ 00431 boost::put(_rank_map, v, target_rank); 00432 } 00433 } 00434 00435 if (boost::get(_rank_map, v) == zero_rank) 00436 { 00437 /* 00438 * Set the main depth-first traversal function to revisit this 00439 * vertex once it has a non-zero rank. 00440 */ 00441 boost::put(_color_map, v, Color::white()); 00442 } 00443 else if (has_cycles) 00444 { 00445 /* 00446 * Give the zero-ranked vertices in the cycle(s) the same rank 00447 * as that of this vertex. 00448 */ 00449 boost::depth_first_visit(g, v, _cycle_visitor, _color_map); 00450 } 00451 } 00452 }; 00453 00454 /* 00455 * The implementation. 00456 */ 00461 template < 00462 typename PathIterator 00463 , typename InputGraph 00464 , typename PredecessorMap 00465 , typename VertexIndexMap 00466 , typename VertexColorMap 00467 , typename VertexRankMap 00468 , typename Buffer 00469 , typename CrossEdgeRemovalIntruder 00470 > 00471 void 00472 impl( 00473 PathIterator path_begin 00474 , PathIterator path_end 00475 , InputGraph& g 00476 , PredecessorMap predecessor_map 00477 , VertexIndexMap index_map 00478 , VertexColorMap color_map 00479 , VertexRankMap rank_map 00480 , Buffer& Q 00481 , CrossEdgeRemovalIntruder& intruder 00482 ) 00483 { 00484 boost::function_requires< 00485 boost::BidirectionalIteratorConcept<PathIterator> 00486 >(); 00487 boost::function_requires< 00488 boost::VertexListGraphConcept<InputGraph> 00489 >(); 00490 boost::function_requires< 00491 boost::AdjacencyGraphConcept<InputGraph> 00492 >(); 00493 boost::function_requires< 00494 boost::EdgeMutableGraphConcept<InputGraph> 00495 >(); 00496 typedef boost::graph_traits<InputGraph> 00497 GraphTraits; 00498 boost::function_requires< 00499 boost::ConvertibleConcept< 00500 typename GraphTraits::directed_category 00501 , boost::directed_tag 00502 > 00503 >(); 00504 typedef typename GraphTraits::edge_descriptor 00505 Edge; 00506 typedef typename GraphTraits::vertex_descriptor 00507 Vertex; 00508 boost::function_requires< 00509 boost::ReadWritePropertyMapConcept<PredecessorMap,Vertex> 00510 >(); 00511 boost::function_requires< 00512 boost::ReadablePropertyMapConcept<VertexIndexMap,Vertex> 00513 >(); 00514 boost::function_requires< 00515 boost::ReadWritePropertyMapConcept<VertexColorMap,Vertex> 00516 >(); 00517 boost::function_requires< 00518 boost::ReadWritePropertyMapConcept<VertexRankMap,Vertex> 00519 >(); 00520 /* 00521 boost::function_requires< 00522 boost::BufferConcept<Buffer> 00523 >(); 00524 */ 00525 boost::function_requires< 00526 boost::ConvertibleConcept<typename Buffer::value_type,Vertex> 00527 >(); 00528 typedef typename GraphTraits::vertex_iterator 00529 VertexIterator; 00530 typedef typename boost::property_traits<VertexRankMap>::value_type 00531 Rank; 00532 typedef typename boost::property_traits<VertexColorMap>::value_type 00533 ColorValue; 00534 typedef boost::color_traits<ColorValue> 00535 Color; 00536 typedef boost::predecessor_recorder<PredecessorMap,boost::on_tree_edge> 00537 PredVisitor; 00538 typedef boost::bfs_visitor<std::pair<PredVisitor,boost::null_visitor> > 00539 BFSVisitor; 00540 typedef CrossEdgeRemover< 00541 InputGraph 00542 , VertexIndexMap 00543 , VertexRankMap 00544 , CrossEdgeRemovalIntruder 00545 > 00546 CERVisitor; 00547 typedef AltPathRanker<VertexRankMap,VertexColorMap> 00548 APRVisitor; 00549 typedef boost::dfs_visitor<std::pair<CERVisitor,APRVisitor> > 00550 DFSVisitor; 00551 00552 /* 00553 * The purpose of all the preparatory steps from here to the core 00554 * algorithm is to keep as many nontrivial complex paths (the ones that 00555 * don't contain the simple path or almost all of it unbroken) as 00556 * possible in the graph. 00557 * 00558 * Temporarily remove the main path from the graph so that the algorithm 00559 * does not mistake its edges for cross edges. 00560 */ 00561 PathIterator path_i = path_begin; 00562 PathIterator path_j = path_i; 00563 00564 while (++path_j != path_end) 00565 { 00566 boost::remove_edge(*path_i, *path_j, g); 00567 intruder.pathEdgeTemporarilyRemoved(*path_i, *path_j, g); 00568 path_i = path_j; 00569 } 00570 00571 /* 00572 * Remove all in-edges from the path target. Also remove all out-edges 00573 * from the path source. 00574 */ 00575 boost::clear_out_edges(*path_begin, g); 00576 removeInEdges(*path_i, g); 00577 00578 /* 00579 * Remove all in-edges from vertices between the farthest vertex down 00580 * the path with a non-zero in-degree (inclusive) and its most immediate 00581 * path predecessor with a non-zero out-degree (exclusive). 00582 */ 00583 path_j = path_i; 00584 boost::clear_out_edges(*(--path_j), g); 00585 00586 while ((path_j != path_begin) && !hasInEdges(*path_j, g)) 00587 { 00588 --path_j; 00589 } 00590 00591 while ((path_j != path_begin) && (boost::out_degree(*path_j, g) == 0)) 00592 { 00593 removeInEdges(*path_j, g); 00594 --path_j; 00595 } 00596 00597 boost::null_visitor 00598 vis_n; 00599 PredVisitor 00600 vis0(predecessor_map); 00601 BFSVisitor 00602 bfs_vis = boost::make_bfs_visitor(std::make_pair(vis0, vis_n)); 00603 00604 /* 00605 * Find the unweighted shortest paths using the path target as the 00606 * source. 00607 */ 00608 boost::breadth_first_visit(g, *path_i, Q, bfs_vis, color_map); 00609 00610 /* 00611 * Initialize all vertices in the graph to the "zero" rank and the 00612 * "unvisited" color. Do this here, not in a visitor class definition. 00613 */ 00614 const Rank zero_rank = Rank(); 00615 00616 VertexIterator v_i, v_end; 00617 00618 for (boost::tie(v_i, v_end) = boost::vertices(g); v_i != v_end; ++v_i) 00619 { 00620 boost::put(color_map, *v_i, Color::white()); 00621 boost::put(rank_map, *v_i, zero_rank); 00622 } 00623 00624 /* 00625 * Assign ranks to all vertices in the main path, with the source vertex 00626 * having the highest rank and the target vertex having the lowest rank 00627 * higher than the "zero" rank. 00628 */ 00629 Rank root_rank = zero_rank; 00630 00631 for (path_j = path_begin; path_j != path_end; ++path_j) 00632 { 00633 boost::put(rank_map, *path_j, ++root_rank); 00634 } 00635 00636 /* 00637 * In each "alternate path" resulting from the previous shortest-paths 00638 * call, assign all zero-ranked vertices the same rank as that path's 00639 * target. If at least two alternate paths share one or more vertices, 00640 * these vertices get the same rank as that of the highest ranking 00641 * target of the alternate paths. 00642 */ 00643 Vertex target_v; 00644 00645 path_j = path_i; 00646 00647 while (path_j != path_begin) 00648 { 00649 target_v = boost::get(predecessor_map, *(--path_j)); 00650 00651 if (target_v != *path_j) 00652 { 00653 /* 00654 * Only use the ranks of the alternate path targets that are 00655 * actually reachable from the main path target. 00656 */ 00657 for ( 00658 root_rank = boost::get(rank_map, *path_j); 00659 boost::get(rank_map, target_v) == zero_rank; 00660 target_v = boost::get(predecessor_map, target_v) 00661 ) 00662 { 00663 boost::put(color_map, target_v, Color::black()); 00664 boost::put(rank_map, target_v, root_rank); 00665 } 00666 } 00667 } 00668 00669 /* 00670 * Run the core algorithm on each vertex in the main path, starting with 00671 * the main path target. 00672 */ 00673 CERVisitor 00674 vis1(g, index_map, rank_map, root_rank, intruder); 00675 APRVisitor 00676 vis2(rank_map, color_map); 00677 DFSVisitor 00678 dfs_vis = boost::make_dfs_visitor(std::make_pair(vis1, vis2)); 00679 00680 path_j = path_i; 00681 00682 while (--path_j != path_begin) 00683 { 00684 if (boost::out_degree(*path_j, g) > 0) 00685 { 00686 root_rank = boost::get(rank_map, *path_j); 00687 00688 /* 00689 * Set the path vertices as terminating vertices for the 00690 * depth-first traversal. 00691 */ 00692 for (path_i = path_begin; path_i != path_end; ++path_i) 00693 { 00694 boost::put(color_map, *path_i, Color::black()); 00695 } 00696 00697 boost::depth_first_visit(g, *path_j, dfs_vis, color_map); 00698 00699 /* 00700 * Reset the color map after each visit. 00701 */ 00702 for ( 00703 boost::tie(v_i, v_end) = boost::vertices(g); 00704 v_i != v_end; 00705 ++v_i 00706 ) 00707 { 00708 boost::put(color_map, *v_i, Color::white()); 00709 } 00710 } 00711 } 00712 00713 /* 00714 * Put the main path back in the graph. 00715 */ 00716 Edge e; 00717 bool has_added_edge; 00718 00719 for (path_i = path_j; ++path_j != path_end; path_i = path_j) 00720 { 00721 boost::tie(e, has_added_edge) 00722 = boost::add_edge(*path_i, *path_j, g); 00723 00724 if (has_added_edge) 00725 { 00726 intruder.pathEdgeReinstated(e, g); 00727 } 00728 } 00729 00730 target_v = *path_i; 00731 00732 /* 00733 * Remove all edges that lead to dead ends (except for the destination). 00734 */ 00735 bool has_dead_ends = true; 00736 00737 while (has_dead_ends) 00738 { 00739 has_dead_ends = false; 00740 00741 for ( 00742 boost::tie(v_i, v_end) = boost::vertices(g); 00743 v_i != v_end; 00744 ++v_i 00745 ) 00746 { 00747 if ( 00748 (*v_i != target_v) 00749 && (boost::out_degree(*v_i, g) == 0) 00750 && hasInEdges(*v_i, g) 00751 ) 00752 { 00753 removeInEdges(*v_i, g); 00754 has_dead_ends = true; 00755 } 00756 } 00757 } 00758 } 00759 00764 struct parameters 00765 : boost::parameter::parameters< 00766 boost::parameter::required<keyword_tag::path_begin_arg> 00767 , boost::parameter::required<keyword_tag::path_end_arg> 00768 , boost::parameter::required<keyword_tag::input_graph_arg> 00769 , boost::parameter::optional<keyword_tag::util_predecessor_map_arg> 00770 , boost::parameter::optional<keyword_tag::util_index_map_arg> 00771 , boost::parameter::optional<keyword_tag::util_color_map_arg> 00772 , boost::parameter::optional<keyword_tag::util_rank_map_arg> 00773 , boost::parameter::optional<keyword_tag::util_buffer_arg> 00774 , boost::parameter::optional<keyword_tag::intruder_arg> 00775 > 00776 { 00777 }; 00778 } // namespace _removeCrossEdges 00779 00780 #ifdef MSMAZES_DOX 00781 01034 template < 01035 typename PathIterator 01036 , typename InputGraph 01037 , typename PredecessorMap 01038 , typename VertexIndexMap 01039 , typename VertexColorMap 01040 , typename VertexRankMap 01041 , typename Buffer 01042 , typename CrossEdgeRemovalIntruder 01043 > 01044 void 01045 removeCrossEdges( 01046 PathIterator path_begin 01047 , PathIterator path_end 01048 , InputGraph& g 01049 , PredecessorMap predecessor_map 01050 , VertexIndexMap index_map 01051 , VertexColorMap color_map 01052 , VertexRankMap rank_map 01053 , Buffer& Q 01054 , CrossEdgeRemovalIntruder& intruder 01055 ); 01056 01067 template <typename Params> 01068 void removeCrossEdges_with_named_params(Params& p) 01069 #else 01070 BOOST_PARAMETER_FUN( 01071 void 01072 , removeCrossEdges 01073 , 3 01074 , 9 01075 , _removeCrossEdges::parameters 01076 ) 01077 #endif /* MSMAZES_DOX */ 01078 { 01079 typedef typename boost::remove_const< 01080 typename boost::remove_reference< 01081 typename boost::parameter::binding< 01082 Params 01083 , keyword_tag::input_graph_arg 01084 >::type 01085 >::type 01086 >::type 01087 InputGraph; 01088 typedef typename boost::graph_traits<InputGraph>::vertex_descriptor 01089 Vertex; 01090 typedef std::map<Vertex,Vertex> 01091 VertexMap; 01092 typedef boost::associative_property_map<VertexMap> 01093 PredecessorMap; 01094 typedef typename boost::remove_const< 01095 typename boost::remove_reference< 01096 typename boost::parameter::binding< 01097 Params 01098 , keyword_tag::util_index_map_arg 01099 , typename boost::property_map< 01100 InputGraph 01101 , boost::vertex_index_t 01102 >::type 01103 >::type 01104 >::type 01105 >::type 01106 VertexIndexMap; 01107 typedef typename boost::property_traits<VertexIndexMap>::value_type 01108 Rank; 01109 01110 InputGraph& g 01111 = p[input_graph_arg]; 01112 VertexIndexMap index_map 01113 = p[util_index_map_arg | boost::get(boost::vertex_index_t(), g)]; 01114 VertexMap v_map; 01115 PredecessorMap pred_map(v_map); 01116 boost::queue<Vertex> Q; 01117 DefaultCrossEdgeRemovalIntruder intruder; 01118 01119 _removeCrossEdges::impl( 01120 p[path_begin_arg] 01121 , p[path_end_arg] 01122 , g 01123 , p[util_predecessor_map_arg | pred_map] 01124 , index_map 01125 , p[ 01126 util_color_map_arg 01127 | boost::make_iterator_property_map( 01128 std::vector<boost::default_color_type>( 01129 boost::num_vertices(g) 01130 ).begin() 01131 , index_map 01132 , boost::white_color 01133 ) 01134 ] 01135 , p[ 01136 util_rank_map_arg 01137 | boost::make_iterator_property_map( 01138 std::vector<Rank>(boost::num_vertices(g)).begin() 01139 , index_map 01140 , Rank() 01141 ) 01142 ] 01143 , p[util_buffer_arg | Q] 01144 , p[intruder_arg | intruder] 01145 ); 01146 } 01147 } // namespace msmazes 01148 01149 #endif /* MSMAZES_CORE_GRAPH_REMOVE_CROSS_EDGES_HPP */
Multi-State Mazes in C++ is hosted by . Use the Table of Contents for navigation.