root/branches/debug/core/src/shooting_star_search.hpp

Revision 144, 21.0 KB (checked in by anton, 3 years ago)

target edge added to found_goal exception

Line 
1//
2//=======================================================================
3// Copyright (c) 2004 Kristopher Beevers
4//               2007 Anton A. Patrushev, Orkney Inc.
5//
6// Distributed under the Boost Software License, Version 1.0. (See
7// accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9//=======================================================================
10//
11
12#ifndef BOOST_GRAPH_SHOOTING_STAR_SEARCH_HPP
13#define BOOST_GRAPH_SHOOTING_STAR_SEARCH_HPP
14
15#define MAX_RULE_LENGTH 5
16
17#include <functional>
18#include <boost/limits.hpp>
19#include <boost/graph/named_function_params.hpp>
20#include <boost/pending/mutable_queue.hpp>
21#include <boost/pending/relaxed_heap.hpp>
22#include <shooting_star_relax.hpp>
23#include <boost/pending/indirect_cmp.hpp>
24#include <boost/graph/exception.hpp>
25#include <boost/graph/breadth_first_search.hpp>
26
27#include <queue>
28#include "edge_visitors.hpp"
29
30#include <iostream>
31#include <fstream>
32
33template <class Edge>
34struct EdgeRankCompare
35{
36  bool operator()(const Edge& LHS, const Edge& RHS)
37  {
38    return (LHS.rank < RHS.rank);
39  }
40               
41};
42
43template <class Edge, class Container, class Cmp>
44class edge_queue : public std::priority_queue<Edge, Container, Cmp>
45{
46protected:
47  using std::priority_queue< Edge, Container, Cmp >::c;
48  using std::priority_queue< Edge, Container, Cmp >::comp;
49   
50public:
51  void sort()
52  {
53    sort_heap(c.begin(), c.end(), comp);
54  }   
55};
56
57namespace boost
58{
59 
60  template <class Heuristic, class Graph>
61  struct AStarHeuristicConcept
62  {
63    void constraints()
64    {
65      function_requires< CopyConstructibleConcept<Heuristic> >();
66      h(u);
67    }
68    Heuristic h;
69    typename graph_traits<Graph>::vertex_descriptor u;
70  };
71 
72   
73
74  template <class Graph, class CostType>
75  class astar_heuristic : public std::unary_function<
76    typename graph_traits<Graph>::vertex_descriptor, CostType>
77  {
78  public:
79    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
80    astar_heuristic() {}
81    CostType operator()(Vertex u) { return static_cast<CostType>(0); }
82  };
83 
84 
85  template <class Visitor, class Graph>
86  struct ShootingStarVisitorConcept {
87    void constraints()
88    {
89      function_requires< CopyConstructibleConcept<Visitor> >();
90      vis.initialize_vertex(u, g);
91      vis.discover_vertex(u, g);
92      vis.examine_vertex(u, g);
93      vis.examine_edge(e, g, e_max_id);
94      vis.black_target(e, pe, g, e_max_id);
95      vis.gray_target(e, pe, g, e_max_id);
96      vis.finish_vertex(u, g);
97     
98      vis.tree_edge(e, pe, g, e_max_id);
99
100      vis.initialize_edge(e, g);
101      vis.discover_edge(e, g);
102      vis.finish_edge(e, g);
103
104    }
105    Visitor vis;
106    Graph g;
107    typename graph_traits<Graph>::vertex_descriptor u;
108    typename graph_traits<Graph>::edge_descriptor e, pe;
109    int e_max_id;
110  };
111 
112 
113  // Main visitor function.
114  // It decides what to do with an edge of certain color
115 
116  template <class IncidenceGraph, class Buffer, class BFSVisitor,
117            class ColorMap, class EdgeColorMap/*, class HistoryMap*/>
118  void shooting_star_edges_visit (const IncidenceGraph& g,
119                            typename graph_traits<IncidenceGraph>::edge_descriptor s,
120                            Buffer& Q, BFSVisitor vis, ColorMap color, EdgeColorMap edge_color,
121                            int e_max_id)
122  {
123    function_requires< IncidenceGraphConcept<IncidenceGraph> >();
124    typedef graph_traits<IncidenceGraph> GTraits;
125    typedef typename GTraits::vertex_descriptor Vertex;
126    typedef typename GTraits::edge_descriptor Edge;
127    function_requires< ShootingStarVisitorConcept<BFSVisitor, IncidenceGraph> >();
128    function_requires< ReadWritePropertyMapConcept<EdgeColorMap, Edge> >();
129   
130    typedef typename property_traits<ColorMap>::value_type ColorValue;
131    typedef color_traits<ColorValue> Color;
132
133    typedef typename property_traits<EdgeColorMap>::value_type EdgeColorValue;
134    typedef color_traits<EdgeColorValue> EdgeColor;
135
136    typename GTraits::out_edge_iterator ei, ei_end;
137
138    std::fstream myfile;
139    myfile.open("/tmp/r_search.log", std::ios::out|std::ios::app);
140   
141    myfile<<"Graph size is "<<num_edges(g)<<" edges\n"<<std::flush;
142
143    // Paint source edge gray
144    put(edge_color, s, EdgeColor::gray());
145    myfile<<"edge "<<g[s].id<<" labeled as gray\n"<<std::flush;
146    vis.discover_edge(s, g);
147    myfile<<"edge "<<g[s].id<<" discovered\n"<<std::flush;
148   
149    // Enqueue the source edge
150    Q.push(s);
151    myfile<<"edge "<<g[s].id<<" inqueued\n"<<std::flush;
152   
153    // While the queue is not empty
154    while (! Q.empty())
155    {
156      // Get an edge from the top
157      Edge e = Q.top();  Q.pop();           
158      myfile<<" <<<<<<<<<<<<< examine edge "<<g[e].id<<" >>>>>>>>>>>>>>>>>>\n"<<std::flush;
159     
160      // Examine the edge
161      vis.examine_edge(e, g, e_max_id);
162     
163      // For all adjacent edges for the current one
164      for (tie(ei, ei_end) = out_edges(target(e, g), g); ei != ei_end; ++ei)
165      {
166        myfile<<" - checking adjacent edge "<<g[*ei].id<<"\n"<<std::flush;
167
168        // Get a color
169        EdgeColorValue e_color = get(edge_color, *ei);
170
171        // Discover the edge and paint it grey
172        // and enqueue it if it was white
173        if (e_color == EdgeColor::white())
174        {         
175          myfile<<"edge "<<g[*ei].id<<" is white\n"<<std::flush;
176          vis.tree_edge(*ei, e, g, e_max_id);
177          put(edge_color, *ei, EdgeColor::gray());   
178          vis.discover_edge(*ei, g);
179          Q.push(*ei);
180        }
181        // or execute appropriate function
182        // if it was grey or black
183        else
184        {                                     
185          vis.non_tree_edge(*ei, g);
186          if (e_color == EdgeColor::gray())
187          {         
188          myfile<<"edge "<<g[*ei].id<<" is grey\n"<<std::flush;
189            vis.gray_target(*ei, e, g, e_max_id);
190          }
191          else
192          {                                     
193          myfile<<"edge "<<g[*ei].id<<" is black\n"<<std::flush;
194            vis.black_target(*ei, e, g, e_max_id);
195          }
196        }
197       
198      } // end for
199
200      // Finally paint the parent edge black
201      put(edge_color, e, EdgeColor::black());       
202      vis.finish_edge(e, g);
203     
204    } // end while
205   
206    myfile.close();
207
208  }
209                                                                                                                                                                                             
210 
211  template <class Visitors = null_visitor>
212  class shooting_star_visitor : public bfs_visitor<Visitors>
213  {
214    public:
215      shooting_star_visitor() {}
216      shooting_star_visitor(Visitors vis)
217        : bfs_visitor<Visitors>(vis) {}
218 
219      template <class Edge, class Graph>
220      void edge_relaxed(Edge e, Graph& g)
221      {
222        invoke_visitors(this->m_vis, e, g, on_edge_relaxed());
223      }
224      template <class Edge, class Graph>
225      void edge_not_relaxed(Edge e, Graph& g)
226      {
227        invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed());     
228      }
229      template <class Edge, class Graph>
230      void initialize_edge(Edge e, Graph& g)
231      {
232        invoke_visitors(this->m_vis, e, g, on_initialize_edge());     
233      }
234   
235    private:
236      template <class Edge, class Graph>
237      void tree_edge(Edge e, Edge pe, Graph& g) {}
238      template <class Edge, class Graph>
239      void non_tree_edge(Edge e, Graph& g) {}
240  };
241
242  template <class Visitors>
243  shooting_star_visitor<Visitors>
244  make_shooting_star_visitor(Visitors vis)
245  {
246    return shooting_star_visitor<Visitors>(vis);
247  }
248 
249  typedef shooting_star_visitor<> default_shooting_star_visitor;
250 
251
252  namespace detail {
253
254    // Shooting* visitor
255    // based on BFS visitor concept from BGL   
256    template <class AStarHeuristic, class UniformCostVisitor,
257              class UpdatableQueue, class PredecessorMap,
258              class CostMap,
259              class DistanceMap, class WeightMap,
260              class EdgeMap,
261              class ColorMap, class EdgeColorMap,
262              class BinaryFunction,
263              class BinaryPredicate>
264    struct shooting_star_bfs_visitor
265    {
266     
267      typedef typename property_traits<CostMap>::value_type C;
268      typedef typename property_traits<ColorMap>::value_type ColorValue;
269      typedef color_traits<ColorValue> Color;
270
271      typedef typename property_traits<EdgeColorMap>::value_type EdgeColorValue;
272      typedef color_traits<ColorValue> EdgeColor;
273
274      typedef typename property_traits<DistanceMap>::value_type distance_type;
275     
276      shooting_star_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis,
277                        UpdatableQueue& Q, PredecessorMap& p,
278                        CostMap c, DistanceMap d, WeightMap w, EdgeMap em,
279                        ColorMap col, EdgeColorMap ecol, //HistoryMap his,
280                        BinaryFunction combine,
281                        BinaryPredicate compare, C zero)
282        : m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c),
283          m_distance(d), m_weight(w), m_edge(em), m_color(col),
284          m_ecolor(ecol), //m_history(his),
285          m_combine(combine), m_compare(compare), m_zero(zero)
286        {
287          std::fstream myfile;
288          myfile.open("/tmp/r_search.log", std::ios::out|std::ios::app);
289          myfile<<"Create shooting_star_bfs_visitor\n"<<std::flush;
290          myfile.close();
291        }
292
293      shooting_star_bfs_visitor(const shooting_star_bfs_visitor &v)
294        : m_h(v.m_h), m_vis(v.m_vis), m_Q(v.m_Q), m_predecessor(v.m_predecessor), m_cost(v.m_cost),
295          m_distance(v.m_distance), m_weight(v.m_weight), m_edge(v.m_edge), m_color(v.m_color),
296          m_ecolor(v.m_ecolor), //m_history(his),
297          m_combine(v.m_combine), m_compare(v.m_compare), m_zero(v.m_zero)
298      {
299        std::fstream myfile;
300        myfile.open("/tmp/r_search.log", std::ios::out|std::ios::app);
301        myfile<<"Copy shooting_star_bfs_visitor\n"<<std::flush;
302        myfile.close();
303      }
304         
305      ~shooting_star_bfs_visitor()
306      {
307        std::fstream myfile;
308        myfile.open("/tmp/r_search.log", std::ios::out|std::ios::app);
309        myfile<<"Delete shooting_star_bfs_visitor\n"<<std::flush;
310        myfile.close();
311      }
312     
313      template <class Vertex, class Graph>
314      void initialize_vertex(Vertex u, Graph& g)
315      {
316        m_vis.initialize_vertex(u, g);
317      }
318      template <class Edge, class Graph>
319      void initialize_edge(Edge e, Graph& g)
320      {
321        m_vis.initialize_edge(e, g);
322      }
323      template <class Vertex, class Graph>
324      void discover_vertex(Vertex u, Graph& g)
325      {
326        m_vis.discover_vertex(u, g);
327      }
328      template <class Edge, class Graph>
329      void discover_edge(Edge e, Graph& g)
330      {
331        m_vis.discover_vertex(e, g);
332      }
333      template <class Vertex, class Graph>
334      void examine_vertex(Vertex u, Graph& g)
335      {
336        m_vis.examine_vertex(u, g);
337      }
338      template <class Vertex, class Graph>
339      void finish_vertex(Vertex u, Graph& g)
340      {
341        m_vis.finish_vertex(u, g);
342      }
343      template <class Edge, class Graph>
344      void examine_edge(Edge e, Graph& g, int e_max_id)
345      {
346        if (m_compare(get(m_weight, e), m_zero))
347          throw negative_edge();
348        m_vis.examine_edge(e, g, e_max_id);
349      }
350      template <class Edge, class Graph>
351      void non_tree_edge(Edge, Graph&) {}
352     
353      template <class Edge, class Graph>
354      void finish_edge(Edge e, Graph& g)
355      {
356        m_vis.finish_edge(e, g);
357      }
358     
359     
360      template <class Edge, class Graph>
361      void tree_edge(Edge e, Edge pe, Graph& g, int e_max_id)
362      {
363        m_decreased = relax(e, pe, g, m_weight, m_edge, m_predecessor, m_distance,
364                            m_cost, m_combine, m_compare, e_max_id);
365   
366        if(m_decreased)
367        {
368          m_vis.edge_relaxed(e, g);
369         
370          put(m_cost, e,
371              m_combine(get(m_distance, e),
372                        m_h(e)));
373
374        }
375        else
376          m_vis.edge_not_relaxed(e, g);
377      }
378     
379     
380      template <class Edge, class Graph>
381      void gray_target(Edge e, Edge pe, Graph& g, int e_max_id)
382      {
383        m_decreased = relax(e, pe, g, m_weight, m_edge, m_predecessor, m_distance,
384                            m_cost, m_combine, m_compare, e_max_id);
385
386        if(m_decreased)
387        {
388          put(m_cost, e,
389              m_combine(get(m_distance, e),
390                        m_h(e)));
391                       
392          m_Q.update(e);
393                 
394          m_vis.edge_relaxed(e, g);
395        }
396        else
397          m_vis.edge_not_relaxed(e, g);
398      }
399     
400           
401      template <class Edge, class Graph>
402      void black_target(Edge e, Edge pe, Graph& g, int e_max_id)
403      {
404
405        m_decreased = relax(e, pe, g, m_weight, m_edge, m_predecessor, m_distance,
406                            m_cost, m_combine, m_compare, e_max_id);
407
408        if(m_decreased)
409        {
410          m_vis.edge_relaxed(e, g);
411          put(m_cost, e, m_combine(get(m_distance, e), m_h(e)));
412         
413          m_Q.push(e);
414          put(m_ecolor, e, EdgeColor::gray());
415          m_vis.black_target(e, g);
416        }
417        else
418          m_vis.edge_not_relaxed(e, g);
419      } 
420
421      AStarHeuristic m_h;
422      UniformCostVisitor m_vis;
423      UpdatableQueue& m_Q;
424      PredecessorMap& m_predecessor;
425      CostMap m_cost;
426      EdgeMap m_edge;
427      DistanceMap m_distance;
428      WeightMap m_weight;
429      ColorMap m_color;
430      EdgeColorMap m_ecolor;
431      BinaryFunction m_combine;
432      BinaryPredicate m_compare;
433      bool m_decreased;
434      C m_zero;     
435    };
436   
437  } // namespace detail
438
439  template <typename VertexAndEdgeListGraph, typename AStarHeuristic,
440            typename ShootingStarVisitor, typename PredecessorMap,
441            typename CostMap,
442            typename DistanceMap,
443            typename WeightMap,
444            typename EdgeMap,
445            typename ColorMap, typename EdgeColorMap,
446            typename IndexMap,
447            typename CompareFunction, typename CombineFunction,
448            typename CostInf, typename CostZero>
449  inline void
450  shooting_star_search_no_init
451    (VertexAndEdgeListGraph &g,
452     typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor s,
453     AStarHeuristic h, ShootingStarVisitor vis,
454     PredecessorMap &predecessor, CostMap cost,
455     DistanceMap distance, WeightMap weight, EdgeMap edge_map,
456     ColorMap color, EdgeColorMap edge_color,
457     IndexMap index_map, CompareFunction compare, CombineFunction combine,
458     CostInf inf, CostZero zero, int e_max_id)
459  {
460    typedef indirect_cmp<CostMap, CompareFunction> IndirectCmp;
461    IndirectCmp icmp(cost, compare);
462 
463    typedef typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor
464      Edge;
465   
466    // Queue to store the list of edges to examine.
467    // I really hate this queue for what it does with the memory sometimes.
468    //
469    //And by the way...
470    //
471    //This place is for rent :)
472    //
473    typedef mutable_queue<Edge, std::vector<Edge>, IndirectCmp, IndexMap>
474      MutableQueue;
475    MutableQueue Q(num_edges(g), icmp, index_map);
476
477    detail::shooting_star_bfs_visitor<AStarHeuristic, ShootingStarVisitor,
478        MutableQueue, PredecessorMap, CostMap, DistanceMap,
479        WeightMap, EdgeMap, ColorMap, EdgeColorMap, /*HistoryMap,*/ CombineFunction, CompareFunction>
480      bfs_vis(h, vis, Q, predecessor, cost, distance, weight,
481              edge_map, color, edge_color, combine, compare, zero);
482 
483    shooting_star_edges_visit(g, s, Q, bfs_vis, color, edge_color, e_max_id);
484  }
485 
486  // Non-named parameter interface
487  template <typename VertexAndEdgeListGraph, typename AStarHeuristic,
488            typename ShootingStarVisitor, typename PredecessorMap,
489            typename CostMap, typename DistanceMap,
490            typename WeightMap, typename EdgeMap,
491            typename IndexMap,
492            typename ColorMap, typename EdgeColorMap,
493            //typename HistoryMap,
494            typename CompareFunction, typename CombineFunction,
495            typename CostInf, typename CostZero>
496  inline void
497  shooting_star_search
498    (VertexAndEdgeListGraph &g,
499     typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor s,
500     AStarHeuristic h, ShootingStarVisitor vis,
501     PredecessorMap &predecessor, CostMap cost,
502     DistanceMap distance, WeightMap weight,
503     EdgeMap edge_map, IndexMap index_map, ColorMap color, EdgeColorMap edge_color,
504     CompareFunction compare, CombineFunction combine,
505     CostInf inf, CostZero zero, int e_max_id)
506  {
507   
508    typedef typename property_traits<ColorMap>::value_type ColorValue;
509    typedef color_traits<ColorValue> Color;
510   
511    typedef typename property_traits<EdgeColorMap>::value_type EdgeColorValue;
512    typedef color_traits<EdgeColorValue> EdgeColor;
513
514    typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator ui, ui_end;
515    typename graph_traits<VertexAndEdgeListGraph>::edge_iterator ei, ei_end;
516
517    for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
518    {
519      vis.initialize_vertex(*ui, g);
520    }
521
522    for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
523    {
524      put(distance, *ei, inf);
525      put(edge_color, *ei, EdgeColor::white());
526      predecessor[g[*ei].id] = *ei;
527      put(cost, *ei, inf);
528    }
529
530    put(distance, s, zero);
531
532    put(cost, s, h(s));
533
534    shooting_star_search_no_init
535      (g, s, h, vis, predecessor, cost, distance, weight, edge_map,
536       color, edge_color, index_map, compare, combine, inf, zero, e_max_id);
537   
538  }
539 
540  namespace detail
541  {
542    template <class VertexAndEdgeListGraph, class AStarHeuristic,
543              class CostMap, class DistanceMap, class WeightMap, class EdgeMap,
544              class IndexMap,
545              class PredecessorMap,
546              class ColorMap, class EdgeColorMap,
547              class Params>
548    inline void
549    shooting_star_dispatch2
550      (VertexAndEdgeListGraph& g,
551       typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor s,
552       AStarHeuristic h, CostMap cost, DistanceMap distance,
553       WeightMap weight, EdgeMap edge_map, IndexMap index_map,
554       PredecessorMap& predecessor, ColorMap color,
555       EdgeColorMap edge_color, const Params& params,
556       int e_max_id)
557    {
558      dummy_property_map p_map;
559      typedef typename property_traits<CostMap>::value_type C;
560      shooting_star_search
561        (g, s, h,
562         choose_param(get_param(params, graph_visitor),
563                      make_shooting_star_visitor(null_visitor())),
564         predecessor,
565         cost, distance, weight, edge_map, index_map, color, edge_color, //history,
566         choose_param(get_param(params, distance_compare_t()),
567                      std::less<C>()),
568         choose_param(get_param(params, distance_combine_t()),
569                      closed_plus<C>()),
570         choose_param(get_param(params, distance_inf_t()),
571                      std::numeric_limits<C>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()),
572         choose_param(get_param(params, distance_zero_t()),
573                      C()),
574         e_max_id
575        );
576    }
577 
578    template <class VertexAndEdgeListGraph, class AStarHeuristic,
579              class CostMap, class DistanceMap, class WeightMap,
580              class EdgeMap, class IndexMap,
581              class PredecessorMap,
582              class ColorMap, class EdgeColorMap,
583              class Params>
584    inline void
585    shooting_star_dispatch1
586      (VertexAndEdgeListGraph& g,
587       typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor s,
588       AStarHeuristic h, CostMap cost, DistanceMap distance,
589       WeightMap weight, EdgeMap edge_map, IndexMap index_map, PredecessorMap& predecessor,
590       ColorMap color, EdgeColorMap edge_color, const Params& params,
591       int e_max_id)
592    {
593      typedef typename property_traits<WeightMap>::value_type D;
594      typename std::vector<D>::size_type
595        n = is_default_param(distance) ? num_vertices(g) : 1;
596      std::vector<D> distance_map(n);
597      n = is_default_param(cost) ? num_vertices(g) : 1;
598      std::vector<D> cost_map(n);
599
600      std::vector<default_color_type> color_map(num_vertices(g));
601      default_color_type c = white_color;
602     
603      detail::shooting_star_dispatch2
604        (g, s, h,
605         choose_param(cost, make_iterator_property_map
606                      (cost_map.begin(), index_map,
607                       cost_map[0])),
608         choose_param(distance, make_iterator_property_map
609                      (distance_map.begin(), index_map,
610                       distance_map[0])),
611         weight, edge_map, index_map,
612         predecessor,
613         choose_param(color, make_iterator_property_map
614                      (color_map.begin(), index_map, c)),
615         edge_color,
616         params,
617         e_max_id);
618    }
619  } // namespace detail
620 
621  // Named parameter interface
622  template <typename VertexAndEdgeListGraph,
623            typename AStarHeuristic,
624            typename P, typename T, typename R,
625            typename IndexMap,
626            typename DistanceMap,
627            typename CostMap,
628            typename PredecessorMap>
629  void
630  shooting_star_search
631    (VertexAndEdgeListGraph &g,
632     typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor s,
633     AStarHeuristic h, const bgl_named_params<P, T, R>& params,
634     IndexMap edge_index,
635     DistanceMap distance,
636     CostMap cost,
637     PredecessorMap &pre_map,
638     int e_max_id)
639  {
640    typedef typename graph_traits<VertexAndEdgeListGraph>::edge_descriptor tEdge;
641
642    detail::shooting_star_dispatch1
643      (g, s, h,
644       cost,
645       distance,
646       choose_const_pmap(get_param(params, edge_weight), g, edge_weight), //weight
647       choose_const_pmap(get_param(params, edge_weight2), g, edge_weight2), //adjacent edges cost
648       edge_index,
649       pre_map, //predecessors
650       get_param(params, vertex_color), //vertex color (deprecated)
651       get_param(params, edge_color), //edge color
652       params,
653       e_max_id
654       );   
655  }
656 
657} // namespace boost
658
659#endif // BOOST_GRAPH_SHOOTING_STAR_SEARCH_HPP
Note: See TracBrowser for help on using the browser.