Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:29

0001 //=======================================================================
0002 // Copyright 2009 Trustees of Indiana University.
0003 // Authors: Michael Hansen, Andrew Lumsdaine
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //=======================================================================
0009 
0010 #ifndef BOOST_GRAPH_GRID_GRAPH_HPP
0011 #define BOOST_GRAPH_GRID_GRAPH_HPP
0012 
0013 #include <cmath>
0014 #include <functional>
0015 #include <numeric>
0016 
0017 #include <boost/array.hpp>
0018 #include <boost/limits.hpp>
0019 #include <boost/graph/graph_traits.hpp>
0020 #include <boost/graph/properties.hpp>
0021 #include <boost/iterator/counting_iterator.hpp>
0022 #include <boost/iterator/transform_iterator.hpp>
0023 #include <boost/property_map/property_map.hpp>
0024 
0025 #define BOOST_GRID_GRAPH_TEMPLATE_PARAMS \
0026     std::size_t DimensionsT, typename VertexIndexT, typename EdgeIndexT
0027 
0028 #define BOOST_GRID_GRAPH_TYPE \
0029     grid_graph< DimensionsT, VertexIndexT, EdgeIndexT >
0030 
0031 #define BOOST_GRID_GRAPH_TRAITS_T typename graph_traits< BOOST_GRID_GRAPH_TYPE >
0032 
0033 namespace boost
0034 {
0035 
0036 // Class prototype for grid_graph
0037 template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS > class grid_graph;
0038 
0039 //===================
0040 // Index Property Map
0041 //===================
0042 
0043 template < typename Graph, typename Descriptor, typename Index >
0044 struct grid_graph_index_map
0045 {
0046 public:
0047     typedef Index value_type;
0048     typedef Index reference_type;
0049     typedef reference_type reference;
0050     typedef Descriptor key_type;
0051     typedef readable_property_map_tag category;
0052 
0053     grid_graph_index_map() {}
0054 
0055     grid_graph_index_map(const Graph& graph) : m_graph(&graph) {}
0056 
0057     value_type operator[](key_type key) const
0058     {
0059         return (m_graph->index_of(key));
0060     }
0061 
0062     friend inline Index get(
0063         const grid_graph_index_map< Graph, Descriptor, Index >& index_map,
0064         const typename grid_graph_index_map< Graph, Descriptor,
0065             Index >::key_type& key)
0066     {
0067         return (index_map[key]);
0068     }
0069 
0070 protected:
0071     const Graph* m_graph;
0072 };
0073 
0074 template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS >
0075 struct property_map< BOOST_GRID_GRAPH_TYPE, vertex_index_t >
0076 {
0077     typedef grid_graph_index_map< BOOST_GRID_GRAPH_TYPE,
0078         BOOST_GRID_GRAPH_TRAITS_T::vertex_descriptor,
0079         BOOST_GRID_GRAPH_TRAITS_T::vertices_size_type >
0080         type;
0081     typedef type const_type;
0082 };
0083 
0084 template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS >
0085 struct property_map< BOOST_GRID_GRAPH_TYPE, edge_index_t >
0086 {
0087     typedef grid_graph_index_map< BOOST_GRID_GRAPH_TYPE,
0088         BOOST_GRID_GRAPH_TRAITS_T::edge_descriptor,
0089         BOOST_GRID_GRAPH_TRAITS_T::edges_size_type >
0090         type;
0091     typedef type const_type;
0092 };
0093 
0094 //==========================
0095 // Reverse Edge Property Map
0096 //==========================
0097 
0098 template < typename Descriptor > struct grid_graph_reverse_edge_map
0099 {
0100 public:
0101     typedef Descriptor value_type;
0102     typedef Descriptor reference_type;
0103     typedef reference_type reference;
0104     typedef Descriptor key_type;
0105     typedef readable_property_map_tag category;
0106 
0107     grid_graph_reverse_edge_map() {}
0108 
0109     value_type operator[](const key_type& key) const
0110     {
0111         return (value_type(key.second, key.first));
0112     }
0113 
0114     friend inline Descriptor get(
0115         const grid_graph_reverse_edge_map< Descriptor >& rev_map,
0116         const typename grid_graph_reverse_edge_map< Descriptor >::key_type& key)
0117     {
0118         return (rev_map[key]);
0119     }
0120 };
0121 
0122 template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS >
0123 struct property_map< BOOST_GRID_GRAPH_TYPE, edge_reverse_t >
0124 {
0125     typedef grid_graph_reverse_edge_map<
0126         BOOST_GRID_GRAPH_TRAITS_T::edge_descriptor >
0127         type;
0128     typedef type const_type;
0129 };
0130 
0131 //=================
0132 // Function Objects
0133 //=================
0134 
0135 namespace detail
0136 {
0137 
0138     // vertex_at
0139     template < typename Graph > struct grid_graph_vertex_at
0140     {
0141 
0142         typedef typename graph_traits< Graph >::vertex_descriptor result_type;
0143 
0144         grid_graph_vertex_at() : m_graph(0) {}
0145 
0146         grid_graph_vertex_at(const Graph* graph) : m_graph(graph) {}
0147 
0148         result_type operator()(
0149             typename graph_traits< Graph >::vertices_size_type vertex_index)
0150             const
0151         {
0152             return (vertex(vertex_index, *m_graph));
0153         }
0154 
0155     private:
0156         const Graph* m_graph;
0157     };
0158 
0159     // out_edge_at
0160     template < typename Graph > struct grid_graph_out_edge_at
0161     {
0162 
0163     private:
0164         typedef
0165             typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
0166 
0167     public:
0168         typedef typename graph_traits< Graph >::edge_descriptor result_type;
0169 
0170         grid_graph_out_edge_at() : m_vertex(), m_graph(0) {}
0171 
0172         grid_graph_out_edge_at(
0173             vertex_descriptor source_vertex, const Graph* graph)
0174         : m_vertex(source_vertex), m_graph(graph)
0175         {
0176         }
0177 
0178         result_type operator()(
0179             typename graph_traits< Graph >::degree_size_type out_edge_index)
0180             const
0181         {
0182             return (out_edge_at(m_vertex, out_edge_index, *m_graph));
0183         }
0184 
0185     private:
0186         vertex_descriptor m_vertex;
0187         const Graph* m_graph;
0188     };
0189 
0190     // in_edge_at
0191     template < typename Graph > struct grid_graph_in_edge_at
0192     {
0193 
0194     private:
0195         typedef
0196             typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
0197 
0198     public:
0199         typedef typename graph_traits< Graph >::edge_descriptor result_type;
0200 
0201         grid_graph_in_edge_at() : m_vertex(), m_graph(0) {}
0202 
0203         grid_graph_in_edge_at(
0204             vertex_descriptor target_vertex, const Graph* graph)
0205         : m_vertex(target_vertex), m_graph(graph)
0206         {
0207         }
0208 
0209         result_type operator()(
0210             typename graph_traits< Graph >::degree_size_type in_edge_index)
0211             const
0212         {
0213             return (in_edge_at(m_vertex, in_edge_index, *m_graph));
0214         }
0215 
0216     private:
0217         vertex_descriptor m_vertex;
0218         const Graph* m_graph;
0219     };
0220 
0221     // edge_at
0222     template < typename Graph > struct grid_graph_edge_at
0223     {
0224 
0225         typedef typename graph_traits< Graph >::edge_descriptor result_type;
0226 
0227         grid_graph_edge_at() : m_graph(0) {}
0228 
0229         grid_graph_edge_at(const Graph* graph) : m_graph(graph) {}
0230 
0231         result_type operator()(
0232             typename graph_traits< Graph >::edges_size_type edge_index) const
0233         {
0234             return (edge_at(edge_index, *m_graph));
0235         }
0236 
0237     private:
0238         const Graph* m_graph;
0239     };
0240 
0241     // adjacent_vertex_at
0242     template < typename Graph > struct grid_graph_adjacent_vertex_at
0243     {
0244 
0245     public:
0246         typedef typename graph_traits< Graph >::vertex_descriptor result_type;
0247 
0248         grid_graph_adjacent_vertex_at(
0249             result_type source_vertex, const Graph* graph)
0250         : m_vertex(source_vertex), m_graph(graph)
0251         {
0252         }
0253 
0254         result_type operator()(
0255             typename graph_traits< Graph >::degree_size_type adjacent_index)
0256             const
0257         {
0258             return (target(
0259                 out_edge_at(m_vertex, adjacent_index, *m_graph), *m_graph));
0260         }
0261 
0262     private:
0263         result_type m_vertex;
0264         const Graph* m_graph;
0265     };
0266 
0267 } // namespace detail
0268 
0269 //===========
0270 // Grid Graph
0271 //===========
0272 
0273 template < std::size_t Dimensions, typename VertexIndex = std::size_t,
0274     typename EdgeIndex = VertexIndex >
0275 class grid_graph
0276 {
0277 
0278 private:
0279     typedef boost::array< bool, Dimensions > WrapDimensionArray;
0280     grid_graph() {};
0281 
0282 public:
0283     typedef grid_graph< Dimensions, VertexIndex, EdgeIndex > type;
0284 
0285     // sizes
0286     typedef VertexIndex vertices_size_type;
0287     typedef EdgeIndex edges_size_type;
0288     typedef EdgeIndex degree_size_type;
0289 
0290     // descriptors
0291     typedef boost::array< VertexIndex, Dimensions > vertex_descriptor;
0292     typedef std::pair< vertex_descriptor, vertex_descriptor > edge_descriptor;
0293 
0294     // vertex_iterator
0295     typedef counting_iterator< vertices_size_type > vertex_index_iterator;
0296     typedef detail::grid_graph_vertex_at< type > vertex_function;
0297     typedef transform_iterator< vertex_function, vertex_index_iterator >
0298         vertex_iterator;
0299 
0300     // edge_iterator
0301     typedef counting_iterator< edges_size_type > edge_index_iterator;
0302     typedef detail::grid_graph_edge_at< type > edge_function;
0303     typedef transform_iterator< edge_function, edge_index_iterator >
0304         edge_iterator;
0305 
0306     // out_edge_iterator
0307     typedef counting_iterator< degree_size_type > degree_iterator;
0308     typedef detail::grid_graph_out_edge_at< type > out_edge_function;
0309     typedef transform_iterator< out_edge_function, degree_iterator >
0310         out_edge_iterator;
0311 
0312     // in_edge_iterator
0313     typedef detail::grid_graph_in_edge_at< type > in_edge_function;
0314     typedef transform_iterator< in_edge_function, degree_iterator >
0315         in_edge_iterator;
0316 
0317     // adjacency_iterator
0318     typedef detail::grid_graph_adjacent_vertex_at< type >
0319         adjacent_vertex_function;
0320     typedef transform_iterator< adjacent_vertex_function, degree_iterator >
0321         adjacency_iterator;
0322 
0323     // categories
0324     typedef directed_tag directed_category;
0325     typedef disallow_parallel_edge_tag edge_parallel_category;
0326     struct traversal_category : virtual public incidence_graph_tag,
0327                                 virtual public adjacency_graph_tag,
0328                                 virtual public vertex_list_graph_tag,
0329                                 virtual public edge_list_graph_tag,
0330                                 virtual public bidirectional_graph_tag,
0331                                 virtual public adjacency_matrix_tag
0332     {
0333     };
0334 
0335     static inline vertex_descriptor null_vertex()
0336     {
0337         vertex_descriptor maxed_out_vertex;
0338         std::fill(maxed_out_vertex.begin(), maxed_out_vertex.end(),
0339             (std::numeric_limits< vertices_size_type >::max)());
0340 
0341         return (maxed_out_vertex);
0342     }
0343 
0344     // Constructor that defaults to no wrapping for all dimensions.
0345     grid_graph(vertex_descriptor dimension_lengths)
0346     : m_dimension_lengths(dimension_lengths)
0347     {
0348 
0349         std::fill(m_wrap_dimension.begin(), m_wrap_dimension.end(), false);
0350 
0351         precalculate();
0352     }
0353 
0354     // Constructor that allows for wrapping to be specified for all
0355     // dimensions at once.
0356     grid_graph(vertex_descriptor dimension_lengths, bool wrap_all_dimensions)
0357     : m_dimension_lengths(dimension_lengths)
0358     {
0359 
0360         std::fill(m_wrap_dimension.begin(), m_wrap_dimension.end(),
0361             wrap_all_dimensions);
0362 
0363         precalculate();
0364     }
0365 
0366     // Constructor that allows for individual dimension wrapping to be
0367     // specified.
0368     grid_graph(
0369         vertex_descriptor dimension_lengths, WrapDimensionArray wrap_dimension)
0370     : m_dimension_lengths(dimension_lengths), m_wrap_dimension(wrap_dimension)
0371     {
0372 
0373         precalculate();
0374     }
0375 
0376     // Returns the number of dimensions in the graph
0377     inline std::size_t dimensions() const { return (Dimensions); }
0378 
0379     // Returns the length of dimension [dimension_index]
0380     inline vertices_size_type length(std::size_t dimension) const
0381     {
0382         return (m_dimension_lengths[dimension]);
0383     }
0384 
0385     // Returns a value indicating if dimension [dimension_index] wraps
0386     inline bool wrapped(std::size_t dimension) const
0387     {
0388         return (m_wrap_dimension[dimension]);
0389     }
0390 
0391     // Gets the vertex that is [distance] units ahead of [vertex] in
0392     // dimension [dimension_index].
0393     vertex_descriptor next(vertex_descriptor vertex,
0394         std::size_t dimension_index, vertices_size_type distance = 1) const
0395     {
0396 
0397         vertices_size_type new_position = vertex[dimension_index] + distance;
0398 
0399         if (wrapped(dimension_index))
0400         {
0401             new_position %= length(dimension_index);
0402         }
0403         else
0404         {
0405             // Stop at the end of this dimension if necessary.
0406             new_position = (std::min)(
0407                 new_position, vertices_size_type(length(dimension_index) - 1));
0408         }
0409 
0410         vertex[dimension_index] = new_position;
0411 
0412         return (vertex);
0413     }
0414 
0415     // Gets the vertex that is [distance] units behind [vertex] in
0416     // dimension [dimension_index].
0417     vertex_descriptor previous(vertex_descriptor vertex,
0418         std::size_t dimension_index, vertices_size_type distance = 1) const
0419     {
0420 
0421         // We're assuming that vertices_size_type is unsigned, so we
0422         // need to be careful about the math.
0423         vertex[dimension_index] = (distance > vertex[dimension_index])
0424             ? (wrapped(dimension_index) ? (length(dimension_index)
0425                    - (distance % length(dimension_index)))
0426                                         : 0)
0427             : vertex[dimension_index] - distance;
0428 
0429         return (vertex);
0430     }
0431 
0432 protected:
0433     // Returns the number of vertices in the graph
0434     inline vertices_size_type num_vertices() const { return (m_num_vertices); }
0435 
0436     // Returns the number of edges in the graph
0437     inline edges_size_type num_edges() const { return (m_num_edges); }
0438 
0439     // Returns the number of edges in dimension [dimension_index]
0440     inline edges_size_type num_edges(std::size_t dimension_index) const
0441     {
0442         return (m_edge_count[dimension_index]);
0443     }
0444 
0445     // Returns the index of [vertex] (See also vertex_at)
0446     vertices_size_type index_of(vertex_descriptor vertex) const
0447     {
0448 
0449         vertices_size_type vertex_index = 0;
0450         vertices_size_type index_multiplier = 1;
0451 
0452         for (std::size_t dimension_index = 0; dimension_index < Dimensions;
0453              ++dimension_index)
0454         {
0455 
0456             vertex_index += (vertex[dimension_index] * index_multiplier);
0457             index_multiplier *= length(dimension_index);
0458         }
0459 
0460         return (vertex_index);
0461     }
0462 
0463     // Returns the vertex whose index is [vertex_index] (See also
0464     // index_of(vertex_descriptor))
0465     vertex_descriptor vertex_at(vertices_size_type vertex_index) const
0466     {
0467 
0468         boost::array< vertices_size_type, Dimensions > vertex;
0469         vertices_size_type index_divider = 1;
0470 
0471         for (std::size_t dimension_index = 0; dimension_index < Dimensions;
0472              ++dimension_index)
0473         {
0474 
0475             vertex[dimension_index]
0476                 = (vertex_index / index_divider) % length(dimension_index);
0477 
0478             index_divider *= length(dimension_index);
0479         }
0480 
0481         return (vertex);
0482     }
0483 
0484     // Returns the edge whose index is [edge_index] (See also
0485     // index_of(edge_descriptor)).  NOTE: The index mapping is
0486     // dependent upon dimension wrapping.
0487     edge_descriptor edge_at(edges_size_type edge_index) const
0488     {
0489 
0490         // Edge indices are sorted into bins by dimension
0491         std::size_t dimension_index = 0;
0492         edges_size_type dimension_edges = num_edges(0);
0493 
0494         while (edge_index >= dimension_edges)
0495         {
0496             edge_index -= dimension_edges;
0497             ++dimension_index;
0498             dimension_edges = num_edges(dimension_index);
0499         }
0500 
0501         vertex_descriptor vertex_source, vertex_target;
0502         bool is_forward
0503             = ((edge_index / (num_edges(dimension_index) / 2)) == 0);
0504 
0505         if (wrapped(dimension_index))
0506         {
0507             vertex_source = vertex_at(edge_index % num_vertices());
0508             vertex_target = is_forward
0509                 ? next(vertex_source, dimension_index)
0510                 : previous(vertex_source, dimension_index);
0511         }
0512         else
0513         {
0514 
0515             // Dimensions can wrap arbitrarily, so an index needs to be
0516             // computed in a more complex manner.  This is done by
0517             // grouping the edges for each dimension together into "bins"
0518             // and considering [edge_index] as an offset into the bin.
0519             // Each bin consists of two parts: the "forward" looking edges
0520             // and the "backward" looking edges for the dimension.
0521 
0522             edges_size_type vertex_offset
0523                 = edge_index % num_edges(dimension_index);
0524 
0525             // Consider vertex_offset an index into the graph's vertex
0526             // space but with the dimension [dimension_index] reduced in
0527             // size by one.
0528             vertices_size_type index_divider = 1;
0529 
0530             for (std::size_t dimension_index_iter = 0;
0531                  dimension_index_iter < Dimensions; ++dimension_index_iter)
0532             {
0533 
0534                 std::size_t dimension_length
0535                     = (dimension_index_iter == dimension_index)
0536                     ? length(dimension_index_iter) - 1
0537                     : length(dimension_index_iter);
0538 
0539                 vertex_source[dimension_index_iter]
0540                     = (vertex_offset / index_divider) % dimension_length;
0541 
0542                 index_divider *= dimension_length;
0543             }
0544 
0545             if (is_forward)
0546             {
0547                 vertex_target = next(vertex_source, dimension_index);
0548             }
0549             else
0550             {
0551                 // Shift forward one more unit in the dimension for backward
0552                 // edges since the algorithm above will leave us one behind.
0553                 vertex_target = vertex_source;
0554                 ++vertex_source[dimension_index];
0555             }
0556 
0557         } // if (wrapped(dimension_index))
0558 
0559         return (std::make_pair(vertex_source, vertex_target));
0560     }
0561 
0562     // Returns the index for [edge] (See also edge_at)
0563     edges_size_type index_of(edge_descriptor edge) const
0564     {
0565         vertex_descriptor source_vertex = source(edge, *this);
0566         vertex_descriptor target_vertex = target(edge, *this);
0567 
0568         BOOST_ASSERT(source_vertex != target_vertex);
0569 
0570         // Determine the dimension where the source and target vertices
0571         // differ (should only be one if this is a valid edge).
0572         std::size_t different_dimension_index = 0;
0573 
0574         while (source_vertex[different_dimension_index]
0575             == target_vertex[different_dimension_index])
0576         {
0577 
0578             ++different_dimension_index;
0579         }
0580 
0581         edges_size_type edge_index = 0;
0582 
0583         // Offset the edge index into the appropriate "bin" (see edge_at
0584         // for a more in-depth description).
0585         for (std::size_t dimension_index = 0;
0586              dimension_index < different_dimension_index; ++dimension_index)
0587         {
0588 
0589             edge_index += num_edges(dimension_index);
0590         }
0591 
0592         // Get the position of both vertices in the differing dimension.
0593         vertices_size_type source_position
0594             = source_vertex[different_dimension_index];
0595         vertices_size_type target_position
0596             = target_vertex[different_dimension_index];
0597 
0598         // Determine if edge is forward or backward
0599         bool is_forward = true;
0600 
0601         if (wrapped(different_dimension_index))
0602         {
0603 
0604             // If the dimension is wrapped, an edge is going backward if
0605             // either A: its target precedes the source in the differing
0606             // dimension and the vertices are adjacent or B: its source
0607             // precedes the target and they're not adjacent.
0608             if (((target_position < source_position)
0609                     && ((source_position - target_position) == 1))
0610                 || ((source_position < target_position)
0611                     && ((target_position - source_position) > 1)))
0612             {
0613 
0614                 is_forward = false;
0615             }
0616         }
0617         else if (target_position < source_position)
0618         {
0619             is_forward = false;
0620         }
0621 
0622         // "Backward" edges are in the second half of the bin.
0623         if (!is_forward)
0624         {
0625             edge_index += (num_edges(different_dimension_index) / 2);
0626         }
0627 
0628         // Finally, apply the vertex offset
0629         if (wrapped(different_dimension_index))
0630         {
0631             edge_index += index_of(source_vertex);
0632         }
0633         else
0634         {
0635             vertices_size_type index_multiplier = 1;
0636 
0637             if (!is_forward)
0638             {
0639                 --source_vertex[different_dimension_index];
0640             }
0641 
0642             for (std::size_t dimension_index = 0; dimension_index < Dimensions;
0643                  ++dimension_index)
0644             {
0645 
0646                 edge_index
0647                     += (source_vertex[dimension_index] * index_multiplier);
0648                 index_multiplier
0649                     *= (dimension_index == different_dimension_index)
0650                     ? length(dimension_index) - 1
0651                     : length(dimension_index);
0652             }
0653         }
0654 
0655         return (edge_index);
0656     }
0657 
0658     // Returns the number of out-edges for [vertex]
0659     degree_size_type out_degree(vertex_descriptor vertex) const
0660     {
0661 
0662         degree_size_type out_edge_count = 0;
0663 
0664         for (std::size_t dimension_index = 0; dimension_index < Dimensions;
0665              ++dimension_index)
0666         {
0667 
0668             // If the vertex is on the edge of this dimension, then its
0669             // number of out edges is dependent upon whether the dimension
0670             // wraps or not.
0671             if ((vertex[dimension_index] == 0)
0672                 || (vertex[dimension_index] == (length(dimension_index) - 1)))
0673             {
0674                 out_edge_count += (wrapped(dimension_index) ? 2 : 1);
0675             }
0676             else
0677             {
0678                 // Next and previous edges, regardless or wrapping
0679                 out_edge_count += 2;
0680             }
0681         }
0682 
0683         return (out_edge_count);
0684     }
0685 
0686     // Returns an out-edge for [vertex] by index. Indices are in the
0687     // range [0, out_degree(vertex)).
0688     edge_descriptor out_edge_at(
0689         vertex_descriptor vertex, degree_size_type out_edge_index) const
0690     {
0691 
0692         edges_size_type edges_left = out_edge_index + 1;
0693         std::size_t dimension_index = 0;
0694         bool is_forward = false;
0695 
0696         // Walks the out edges of [vertex] and accommodates for dimension
0697         // wrapping.
0698         while (edges_left > 0)
0699         {
0700 
0701             if (!wrapped(dimension_index))
0702             {
0703                 if (!is_forward && (vertex[dimension_index] == 0))
0704                 {
0705                     is_forward = true;
0706                     continue;
0707                 }
0708                 else if (is_forward
0709                     && (vertex[dimension_index]
0710                         == (length(dimension_index) - 1)))
0711                 {
0712                     is_forward = false;
0713                     ++dimension_index;
0714                     continue;
0715                 }
0716             }
0717 
0718             --edges_left;
0719 
0720             if (edges_left > 0)
0721             {
0722                 is_forward = !is_forward;
0723 
0724                 if (!is_forward)
0725                 {
0726                     ++dimension_index;
0727                 }
0728             }
0729         }
0730 
0731         return (std::make_pair(vertex,
0732             is_forward ? next(vertex, dimension_index)
0733                        : previous(vertex, dimension_index)));
0734     }
0735 
0736     // Returns the number of in-edges for [vertex]
0737     inline degree_size_type in_degree(vertex_descriptor vertex) const
0738     {
0739         return (out_degree(vertex));
0740     }
0741 
0742     // Returns an in-edge for [vertex] by index. Indices are in the
0743     // range [0, in_degree(vertex)).
0744     edge_descriptor in_edge_at(
0745         vertex_descriptor vertex, edges_size_type in_edge_index) const
0746     {
0747 
0748         edge_descriptor out_edge = out_edge_at(vertex, in_edge_index);
0749         return (
0750             std::make_pair(target(out_edge, *this), source(out_edge, *this)));
0751     }
0752 
0753     // Pre-computes the number of vertices and edges
0754     void precalculate()
0755     {
0756         m_num_vertices = std::accumulate(m_dimension_lengths.begin(),
0757             m_dimension_lengths.end(), vertices_size_type(1),
0758             std::multiplies< vertices_size_type >());
0759 
0760         // Calculate number of edges in each dimension
0761         m_num_edges = 0;
0762 
0763         for (std::size_t dimension_index = 0; dimension_index < Dimensions;
0764              ++dimension_index)
0765         {
0766 
0767             if (wrapped(dimension_index))
0768             {
0769                 m_edge_count[dimension_index] = num_vertices() * 2;
0770             }
0771             else
0772             {
0773                 m_edge_count[dimension_index]
0774                     = (num_vertices()
0775                           - (num_vertices() / length(dimension_index)))
0776                     * 2;
0777             }
0778 
0779             m_num_edges += num_edges(dimension_index);
0780         }
0781     }
0782 
0783     const vertex_descriptor m_dimension_lengths;
0784     WrapDimensionArray m_wrap_dimension;
0785     vertices_size_type m_num_vertices;
0786 
0787     boost::array< edges_size_type, Dimensions > m_edge_count;
0788     edges_size_type m_num_edges;
0789 
0790 public:
0791     //================
0792     // VertexListGraph
0793     //================
0794 
0795     friend inline std::pair< typename type::vertex_iterator,
0796         typename type::vertex_iterator >
0797     vertices(const type& graph)
0798     {
0799         typedef typename type::vertex_iterator vertex_iterator;
0800         typedef typename type::vertex_function vertex_function;
0801         typedef typename type::vertex_index_iterator vertex_index_iterator;
0802 
0803         return (std::make_pair(
0804             vertex_iterator(vertex_index_iterator(0), vertex_function(&graph)),
0805             vertex_iterator(vertex_index_iterator(graph.num_vertices()),
0806                 vertex_function(&graph))));
0807     }
0808 
0809     friend inline typename type::vertices_size_type num_vertices(
0810         const type& graph)
0811     {
0812         return (graph.num_vertices());
0813     }
0814 
0815     friend inline typename type::vertex_descriptor vertex(
0816         typename type::vertices_size_type vertex_index, const type& graph)
0817     {
0818 
0819         return (graph.vertex_at(vertex_index));
0820     }
0821 
0822     //===============
0823     // IncidenceGraph
0824     //===============
0825 
0826     friend inline std::pair< typename type::out_edge_iterator,
0827         typename type::out_edge_iterator >
0828     out_edges(typename type::vertex_descriptor vertex, const type& graph)
0829     {
0830         typedef typename type::degree_iterator degree_iterator;
0831         typedef typename type::out_edge_function out_edge_function;
0832         typedef typename type::out_edge_iterator out_edge_iterator;
0833 
0834         return (std::make_pair(out_edge_iterator(degree_iterator(0),
0835                                    out_edge_function(vertex, &graph)),
0836             out_edge_iterator(degree_iterator(graph.out_degree(vertex)),
0837                 out_edge_function(vertex, &graph))));
0838     }
0839 
0840     friend inline typename type::degree_size_type out_degree(
0841         typename type::vertex_descriptor vertex, const type& graph)
0842     {
0843         return (graph.out_degree(vertex));
0844     }
0845 
0846     friend inline typename type::edge_descriptor out_edge_at(
0847         typename type::vertex_descriptor vertex,
0848         typename type::degree_size_type out_edge_index, const type& graph)
0849     {
0850         return (graph.out_edge_at(vertex, out_edge_index));
0851     }
0852 
0853     //===============
0854     // AdjacencyGraph
0855     //===============
0856 
0857     friend typename std::pair< typename type::adjacency_iterator,
0858         typename type::adjacency_iterator >
0859     adjacent_vertices(
0860         typename type::vertex_descriptor vertex, const type& graph)
0861     {
0862         typedef typename type::degree_iterator degree_iterator;
0863         typedef
0864             typename type::adjacent_vertex_function adjacent_vertex_function;
0865         typedef typename type::adjacency_iterator adjacency_iterator;
0866 
0867         return (std::make_pair(adjacency_iterator(degree_iterator(0),
0868                                    adjacent_vertex_function(vertex, &graph)),
0869             adjacency_iterator(degree_iterator(graph.out_degree(vertex)),
0870                 adjacent_vertex_function(vertex, &graph))));
0871     }
0872 
0873     //==============
0874     // EdgeListGraph
0875     //==============
0876 
0877     friend inline typename type::edges_size_type num_edges(const type& graph)
0878     {
0879         return (graph.num_edges());
0880     }
0881 
0882     friend inline typename type::edge_descriptor edge_at(
0883         typename type::edges_size_type edge_index, const type& graph)
0884     {
0885         return (graph.edge_at(edge_index));
0886     }
0887 
0888     friend inline std::pair< typename type::edge_iterator,
0889         typename type::edge_iterator >
0890     edges(const type& graph)
0891     {
0892         typedef typename type::edge_index_iterator edge_index_iterator;
0893         typedef typename type::edge_function edge_function;
0894         typedef typename type::edge_iterator edge_iterator;
0895 
0896         return (std::make_pair(
0897             edge_iterator(edge_index_iterator(0), edge_function(&graph)),
0898             edge_iterator(edge_index_iterator(graph.num_edges()),
0899                 edge_function(&graph))));
0900     }
0901 
0902     //===================
0903     // BiDirectionalGraph
0904     //===================
0905 
0906     friend inline std::pair< typename type::in_edge_iterator,
0907         typename type::in_edge_iterator >
0908     in_edges(typename type::vertex_descriptor vertex, const type& graph)
0909     {
0910         typedef typename type::in_edge_function in_edge_function;
0911         typedef typename type::degree_iterator degree_iterator;
0912         typedef typename type::in_edge_iterator in_edge_iterator;
0913 
0914         return (std::make_pair(in_edge_iterator(degree_iterator(0),
0915                                    in_edge_function(vertex, &graph)),
0916             in_edge_iterator(degree_iterator(graph.in_degree(vertex)),
0917                 in_edge_function(vertex, &graph))));
0918     }
0919 
0920     friend inline typename type::degree_size_type in_degree(
0921         typename type::vertex_descriptor vertex, const type& graph)
0922     {
0923         return (graph.in_degree(vertex));
0924     }
0925 
0926     friend inline typename type::degree_size_type degree(
0927         typename type::vertex_descriptor vertex, const type& graph)
0928     {
0929         return (graph.out_degree(vertex) * 2);
0930     }
0931 
0932     friend inline typename type::edge_descriptor in_edge_at(
0933         typename type::vertex_descriptor vertex,
0934         typename type::degree_size_type in_edge_index, const type& graph)
0935     {
0936         return (graph.in_edge_at(vertex, in_edge_index));
0937     }
0938 
0939     //==================
0940     // Adjacency Matrix
0941     //==================
0942 
0943     friend std::pair< typename type::edge_descriptor, bool > edge(
0944         typename type::vertex_descriptor source_vertex,
0945         typename type::vertex_descriptor destination_vertex, const type& graph)
0946     {
0947 
0948         std::pair< typename type::edge_descriptor, bool > edge_exists
0949             = std::make_pair(
0950                 std::make_pair(source_vertex, destination_vertex), false);
0951 
0952         for (std::size_t dimension_index = 0; dimension_index < Dimensions;
0953              ++dimension_index)
0954         {
0955 
0956             typename type::vertices_size_type dim_difference = 0;
0957             typename type::vertices_size_type source_dim
0958                 = source_vertex[dimension_index],
0959                 dest_dim = destination_vertex[dimension_index];
0960 
0961             dim_difference = (source_dim > dest_dim) ? (source_dim - dest_dim)
0962                                                      : (dest_dim - source_dim);
0963 
0964             if (dim_difference > 0)
0965             {
0966 
0967                 // If we've already found a valid edge, this would mean that
0968                 // the vertices are really diagonal across dimensions and
0969                 // therefore not connected.
0970                 if (edge_exists.second)
0971                 {
0972                     edge_exists.second = false;
0973                     break;
0974                 }
0975 
0976                 // If the difference is one, the vertices are right next to
0977                 // each other and the edge is valid.  The edge is still
0978                 // valid, though, if the dimension wraps and the vertices
0979                 // are on opposite ends.
0980                 if ((dim_difference == 1)
0981                     || (graph.wrapped(dimension_index)
0982                         && (((source_dim == 0)
0983                                 && (dest_dim
0984                                     == (graph.length(dimension_index) - 1)))
0985                             || ((dest_dim == 0)
0986                                 && (source_dim
0987                                     == (graph.length(dimension_index) - 1))))))
0988                 {
0989 
0990                     edge_exists.second = true;
0991                     // Stay in the loop to check for diagonal vertices.
0992                 }
0993                 else
0994                 {
0995 
0996                     // Stop checking - the vertices are too far apart.
0997                     edge_exists.second = false;
0998                     break;
0999                 }
1000             }
1001 
1002         } // for dimension_index
1003 
1004         return (edge_exists);
1005     }
1006 
1007     //=============================
1008     // Index Property Map Functions
1009     //=============================
1010 
1011     friend inline typename type::vertices_size_type get(vertex_index_t,
1012         const type& graph, typename type::vertex_descriptor vertex)
1013     {
1014         return (graph.index_of(vertex));
1015     }
1016 
1017     friend inline typename type::edges_size_type get(
1018         edge_index_t, const type& graph, typename type::edge_descriptor edge)
1019     {
1020         return (graph.index_of(edge));
1021     }
1022 
1023     friend inline grid_graph_index_map< type, typename type::vertex_descriptor,
1024         typename type::vertices_size_type >
1025     get(vertex_index_t, const type& graph)
1026     {
1027         return (grid_graph_index_map< type, typename type::vertex_descriptor,
1028             typename type::vertices_size_type >(graph));
1029     }
1030 
1031     friend inline grid_graph_index_map< type, typename type::edge_descriptor,
1032         typename type::edges_size_type >
1033     get(edge_index_t, const type& graph)
1034     {
1035         return (grid_graph_index_map< type, typename type::edge_descriptor,
1036             typename type::edges_size_type >(graph));
1037     }
1038 
1039     friend inline grid_graph_reverse_edge_map< typename type::edge_descriptor >
1040     get(edge_reverse_t, const type& graph)
1041     {
1042         return (
1043             grid_graph_reverse_edge_map< typename type::edge_descriptor >());
1044     }
1045 
1046     template < typename Graph, typename Descriptor, typename Index >
1047     friend struct grid_graph_index_map;
1048 
1049     template < typename Descriptor > friend struct grid_graph_reverse_edge_map;
1050 
1051 }; // grid_graph
1052 
1053 } // namespace boost
1054 
1055 #undef BOOST_GRID_GRAPH_TYPE
1056 #undef BOOST_GRID_GRAPH_TEMPLATE_PARAMS
1057 #undef BOOST_GRID_GRAPH_TRAITS_T
1058 
1059 #endif // BOOST_GRAPH_GRID_GRAPH_HPP