diff --git a/doc/astar_search.html b/doc/astar_search.html index 22b17d7d..e1828ff5 100644 --- a/doc/astar_search.html +++ b/doc/astar_search.html @@ -37,10 +37,28 @@ template <typename VertexListGraph, typename P, typename T, typename R> void astar_search_no_init + (const IncidenceGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params<P, T, R>& params); + +template <typename VertexListGraph, + typename AStarHeuristic, + typename P, typename T, typename R> +void +astar_search_tree (const VertexListGraph &g, typename graph_traits<VertexListGraph>::vertex_descriptor s, AStarHeuristic h, const bgl_named_params<P, T, R>& params); +template <typename VertexListGraph, + typename AStarHeuristic, + typename P, typename T, typename R> +void +astar_search_no_init_tree + (const IncidenceGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params<P, T, R>& params); + // Non-named parameter interface template <typename VertexListGraph, typename AStarHeuristic, typename AStarVisitor, typename PredecessorMap, @@ -60,7 +78,23 @@ astar_search CompareFunction compare, CombineFunction combine, CostInf inf, CostZero zero); -// Version that does not initialize property maps (used for implicit graphs) +template <typename VertexListGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, + typename CostMap, typename DistanceMap, + typename WeightMap, + typename CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero> +inline void +astar_search_tree + (const VertexListGraph &g, + typename graph_traits<VertexListGraph>::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero); + +// Versions that do not initialize property maps (used for implicit graphs) template <typename IncidenceGraph, typename AStarHeuristic, typename AStarVisitor, typename PredecessorMap, typename CostMap, typename DistanceMap, @@ -82,6 +116,22 @@ astar_search_no_init Note that the index_map and color parameters are swapped in astar_search_no_init() relative to astar_search(); the named parameter interfaces are not affected. + +template <typename IncidenceGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, + typename CostMap, typename DistanceMap, + typename WeightMap, + typename CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero> +inline void +astar_search_no_init_tree + (const IncidenceGraph &g, + typename graph_traits<IncidenceGraph>::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero);

@@ -125,7 +175,8 @@ useful for searching large state spaces -- in game-playing scenarios the entire graph. Implicit searches can be performed with this implementation of A* by creating special visitors that generate neighbors of newly-expanded vertices. Please note that -astar_search_no_init() must be used for implicit graphs; the basic +astar_search_no_init() or astar_search_no_init_tree() must be +used for implicit graphs; the basic astar_search() function requires a graph that models the Vertex List Graph concept. Both versions @@ -134,8 +185,9 @@ href="IncidenceGraph.html">Incidence Graph concept.

-This implementation of A* is based on an OPEN/CLOSED list formulation -of the algorithm. Vertices on the OPEN list have been ``discovered'' +For the non-tree versions of the algorithm, +this implementation of A* is based on an OPEN/CLOSED list formulation. +Vertices on the OPEN list have been ``discovered'' by the algorithm, but not ``expanded'' (we have not discovered their adjacent vertices). Vertices on the CLOSED list have been completely examined by our search (we have expanded them and added their children @@ -146,7 +198,11 @@ avoids ``cycles'' in the state space; the search will not become trapped by loops in the graph. The OPEN/CLOSED lists are implemented using BGL's vertex coloring mechanisms. Vertices in OPEN are colored gray, vertices in CLOSED are colored black, and undiscovered vertices -are colored white. +are colored white. For the versions of the algorithm whose names end in +_tree, all vertices are assumed to always be white, leading to +checking for repeated vertices being done using the distance map. If a dummy +value is used for the distance map and the graph contains cycles, the algorithm +will probably enter an infinite loop.

@@ -292,7 +348,8 @@ IN: weight_map(WeightMap w_map) IN: vertex_index_map(VertexIndexMap i_map)

This maps each vertex to an integer in the range [0, - num_vertices(g)). This is necessary for efficient updates of + num_vertices(g)). This is necessary in non-tree versions of the + algorithm for efficient updates of the heap data structure when an edge is relaxed. The type VertexIndexMap must be a model of Readable @@ -338,7 +395,10 @@ UTIL/OUT: distance_map(DistanceMap d_map) combine function object and the zero object for the identity element. Also the distance value type must have a StrictWeakOrdering - provided by the compare function object.
+ provided by the compare function object. A + constant_writable_property_map returning the infinity value can be + used for this parameter in tree versions of the algorithm when the graph does + not contain a directed cycle.
Default: shared_array_property_map with the same value type as the @@ -355,7 +415,10 @@ UTIL/OUT: rank_map(CostMap c_map) h) from the vertex to a goal. The type CostMap must be a model of Read/Write - Property Map. The vertex descriptor type of the graph + Property Map
in non-tree versions of the algorithm, and Writable Property + Map in tree versions of the algorithm. The vertex descriptor type + of the graph needs to be usable as the key type of the distance map. The value type of the distance map is the element type of a Monoid formed with the @@ -364,7 +427,8 @@ UTIL/OUT: rank_map(CostMap c_map) href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering provided by the compare function object. The value type for this map must be the same as the value type for the distance - map.
+ map. In tree versions of the algorithm, null_property_map can be + used for this parameter.
Default: shared_array_property_map with the same value type as the @@ -375,7 +439,8 @@ UTIL/OUT: rank_map(CostMap c_map) UTIL/OUT: color_map(ColorMap c_map)
- This is used during the execution of the algorithm to mark the + This is used during the execution of non-tree versions of the algorithm to + mark the vertices, indicating whether they are on the OPEN or CLOSED lists. The vertices start out white and become gray when they are inserted into the OPEN list. They then turn black when they are examined and diff --git a/doc/graph_concepts.html b/doc/graph_concepts.html index b18ce3bb..a7dd3060 100644 --- a/doc/graph_concepts.html +++ b/doc/graph_concepts.html @@ -396,7 +396,7 @@ disregard the directionality in the function names. The example below demonstrates using the out_edges(), source(), and target() with an undirected graph. The source code for this example and the following one can be found in examples/undirected.cpp. +href="../example/undirected_adjacency_list.cpp">example/undirected_adjacency_list.cpp.

diff --git a/doc/push_relabel_max_flow.html b/doc/push_relabel_max_flow.html
index 4fcab20a..cb96c83a 100644
--- a/doc/push_relabel_max_flow.html
+++ b/doc/push_relabel_max_flow.html
@@ -158,7 +158,7 @@ href="../example/max_flow.cpp">example/max_flow.cpp.
 #include <boost/config.hpp>
 #include <iostream>
 #include <string>
-#include <boost/graph/push_relabel_map_flow.hpp>
+#include <boost/graph/push_relabel_max_flow.hpp>
 #include <boost/graph/adjacency_list.hpp>
 #include <boost/graph/read_dimacs.hpp>
 
diff --git a/doc/read_graphml.html b/doc/read_graphml.html
index 42c542a1..21796d8e 100644
--- a/doc/read_graphml.html
+++ b/doc/read_graphml.html
@@ -20,7 +20,7 @@ http://www.boost.org/LICENSE_1_0.txt)
 Authors: Tiago de Paula Peixoto -->
 
 void read_graphml(std::istream& in, MutableGraph& graph,
-                  dynamic_properties& dp);
+                  dynamic_properties& dp, size_t graph_index = 0);
 

The read_graphml function interprets a graph described using the GraphML format and builds a BGL graph that captures that @@ -39,6 +39,10 @@ this object, using the GraphML attribute names as the property names, and with the appropriate C++ value type based on the GraphML attribute type definition. Graph properties are also set with the same dynamic_properties object, where the key type is the type of the graph itself.

+

If the file contains multiple graphs, the graph_index parameter controls +which graph will be loaded. It defaults to 0, meaning that the first graph +in the file will be loaded. If graph_index is greater than or equal to the +number of graphs in the file, an empty graph will be returned.

Requirements:
    @@ -156,7 +160,7 @@ graph. diff --git a/doc/read_graphml.rst b/doc/read_graphml.rst index c61156d8..1e8bd818 100644 --- a/doc/read_graphml.rst +++ b/doc/read_graphml.rst @@ -19,7 +19,7 @@ __ ../../../index.htm :: void read_graphml(std::istream& in, MutableGraph& graph, - dynamic_properties& dp); + dynamic_properties& dp, size_t graph_index = 0); The ``read_graphml`` function interprets a graph described using the @@ -42,6 +42,11 @@ and with the appropriate C++ value type based on the GraphML attribute type definition. Graph properties are also set with the same dynamic_properties_ object, where the key type is the type of the graph itself. +If the file contains multiple graphs, the ``graph_index`` parameter controls +which graph will be loaded. It defaults to ``0``, meaning that the first graph +in the file will be loaded. If ``graph_index`` is greater than or equal to the +number of graphs in the file, an empty graph will be returned. + Requirements: - The type of the graph must model the `Mutable Graph`_ concept. - The type of the iterator must model the `Multi-Pass Iterator`_ diff --git a/doc/small_world_generator.html b/doc/small_world_generator.html index 0b853502..5dfffae5 100644 --- a/doc/small_world_generator.html +++ b/doc/small_world_generator.html @@ -45,7 +45,7 @@ public: small_world_iterator(); small_world_iterator(RandomGenerator& gen, vertices_size_type n, - vertices_size_type k, double probability, + vertices_size_type k, double probability = 0., bool allow_self_loops = false); // Iterator operations reference operator*() const; @@ -82,7 +82,7 @@ Constructs a past-the-end iterator.
     small_world_iterator(RandomGenerator& gen, vertices_size_type n,
    -                     vertices_size_type k, double probability,
    +                     vertices_size_type k, double probability = 0.,
                          bool allow_self_loops = false);
     
    diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html index 90f2b754..3bf18523 100644 --- a/doc/table_of_contents.html +++ b/doc/table_of_contents.html @@ -172,7 +172,7 @@ href="./johnson_all_pairs_shortest.html">johnson_all_pairs_shortest_paths
  • floyd_warshall_all_pairs_shortest_paths
  • r_c_shortest_paths - resource-constrained shortest paths
  • -
  • astar_search
  • +
  • astar_search (A* search algorithm)
  • Minimum Spanning Tree Algorithms
      @@ -240,6 +240,7 @@
    1. Graph Structure Comparisons
      1. isomorphism +
      2. vf2_sub_graph_iso (VF2 subgraph isomorphism algorithm)
      3. mcgregor_common_subgraphs
      diff --git a/doc/vf2_sub_graph_iso.html b/doc/vf2_sub_graph_iso.html new file mode 100755 index 00000000..ae24e908 --- /dev/null +++ b/doc/vf2_sub_graph_iso.html @@ -0,0 +1,517 @@ + + + + + + Boost Graph Library: VF2 (Sub)Graph Isomorphism + + + +

      C++ Boost

      +

      + vf2_subgraph_iso +

      +
      +// All defaults interface
      +template <typename GraphSmall,
      +          typename GraphLarge,
      +          typename SubGraphIsoMapCallback>
      +bool vf2_subgraph_iso(const GraphSmall& graph_small,
      +                      const GraphLarge& graph_large, 
      +                      SubGraphIsoMapCallback user_callback)
      +
      +
      +// Named parameter version
      +template <typename GraphSmall,
      +          typename GraphLarge,
      +          typename VertexOrderSmall,
      +          typename SubGraphIsoMapCallback,
      +          typename Param,
      +          typename Tag,
      +          typename Rest>
      +bool vf2_subgraph_iso(const GraphSmall& graph_small,
      +                      const GraphLarge& graph_large,
      +                      SubGraphIsoMapCallback user_callback,
      +                      const VertexOrderSmall& vertex_order_small,
      +                      const bgl_named_params<Param, Tag, Rest>& params)
      +
      +
      +// Non-named parameter version
      +template <typename GraphSmall,
      +          typename GraphLarge,
      +          typename IndexMapSmall,
      +          typename IndexMapLarge,
      +          typename VertexOrderSmall,
      +          typename EdgeEquivalencePredicate,
      +          typename VertexEquivalencePredicate,
      +          typename SubGraphIsoMapCallback>
      +bool vf2_subgraph_iso(const GraphSmall& graph_small,
      +                      const GraphLarge& graph_large,
      +                      SubGraphIsoMapCallback user_callback,
      +                      IndexMapSmall index_map_small,
      +                      IndexMapLarge index_map_large, 
      +                      const VertexOrderSmall& vertex_order_small,
      +                      EdgeEquivalencePredicate edge_comp,
      +                      VertexEquivalencePredicate vertex_comp)
      +    
      +

      + An isomorphism between two graphs G1=(V1, E1) + and G2=(V2, E2) is a + bijective mapping M of the vertices of one graph to vertices of the other + graph that preserves the edge structure of the graphs. M is said to be a + graph-subgraph isomorphism if and only if M is an isomorphism between + G1 and a subgraph of G2. +

      + +

      + This function finds all graph-subgraph isomorphism mappings between + graphs graph_small and graph_large and outputs them to + user_callback. It continues until user_callback + returns true or the search space has been fully explored. vf2_subgraph_iso + returns true if a graph-subgraph isomorphism exists and false otherwise. + EdgeEquivalencePredicate and + VertexEquivalencePredicate predicates are used to test whether + edges and vertices are equivalent. To use property maps for equivalence, + see + + make_property_map_equivalent + function. By default + always_equivalent is used, which returns + true for any pair of vertices or edges. +

      +

      + The current implementation is based on the VF2 algorithm, + introduced by Cordella et al. An in-depth description of the algorithm is + given in [1] and [2] + and references therein. The original code by P. Foggia and collaborators can + be found at [3]. In brief, the process of + finding a mapping between the two graphs G1 and + G2 determines the isomorphism mapping M, + which associates vertices G1 with vertices of + G2 and vice versa. It can be described by means of a + state space representation which is created by the algorithm + while exploring the search graph in depth-first fashion. + Each state s of the matching process + can be associated with a partial mapping M(s). At each level, + the algorithm computes the set of the vertex pairs that are candidates to + be added to the current state s. If a pair of vertices + (v, w) is feasible, the mapping is extended and the associated + successor state s' is computed. + The whole procedure is then repeated for state s'. +

      + +

      Where Defined

      +

      + + boost/graph/vf2_sub_graph_iso.hpp
      + All functions are defined in the boost namespace. +

      + +

      Parameters

      + +

      IN: const GraphSmall& graph_small

      +
      +

      + The (first) smaller graph (fewer vertices) of the pair to be tested for + isomorphism. The type GraphSmall must be a + model of + Vertex List Graph, + Edge List Graph, + Bidirectional Graph and + Adjacency Matrix. + The edge descriptors graph_traits<GraphSmall>::edge_descriptor + must be + LessThan Comparable, cf. also the remark below. +

      +
      + +

      IN: const GraphLarge& graph_large

      +
      +

      + The (second) larger graph to be tested. + Type GraphLarge must be a model of + Vertex List Graph, + Edge List Graph, + Bidirectional Graph and + Adjacency Matrix. + The edge descriptors graph_traits<GraphLarge>::edge_descriptor + must be + LessThan Comparable, cf. also the remark below. +

      +
      + +

      OUT: SubGraphIsoMapCallback user_callback

      +
      +

      + A function object to be called when a graph-subgraph isomorphism has been discovered. The + operator() must have following form: +

      +
      +template <typename CorrespondenceMap1To2,
      +          typename CorrespondenceMap2To1>
      +bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const
      +      
      +

      + Both the CorrespondenceMap1To2 + and CorresondenceMap2To1 types are models + of Readable + Property Map and map equivalent vertices across the two + graphs given to vf2_subgraph_iso (or vf2_graph_iso). For + instance, if v is + from graph_small, w is from graph_large, + and the vertices can be considered equivalent, + then get(f, v) will be w and get(g, w) + will be v. If any vertex, say v in graph_small, + does not match a vertex in graph_large , + then get(f, v) will be graph_traits<GraphLarge>::null_vertex(). + Likewise for any unmatched vertices from graph_large, + get(g, w) will be graph_traits<GraphSmall>::null_vertex(). + + Returning false from the callback will abort the search immediately. Otherwise, + the entire search space will be explored. A "default" print callback + is provided as a utility function. +

      +
      + +

      IN: const VertexOrderSmall& vertex_order_small

      +
      +

      + The ordered vertices of the smaller (first) graph graph_small. + During the matching process the vertices are examined in the order given by + vertex_order_small. Type VertexOrderSmall must be a model + of ContainerConcept + with value type + graph_traits<GraphSmall>::vertex_descriptor. +
      + Default The vertices are ordered by multiplicity of + in/out degrees. +

      +
      + +

      Named Parameters

      + +

      IN: vertex_index1(IndexMapSmall index_map_small)

      +
      +

      + This maps each vertex to an integer in the range [0, num_vertices(graph_small)). + Type IndexMapSmall must be a model of + Readable Property Map. +
      + Default: get(vertex_index, graph_small) +

      +
      + +

      IN: vertex_index2(IndexMapLarge index_map_large)

      +
      +

      + This maps each vertex to an integer in the range [0, num_vertices(graph_large)). + Type IndexMapLarge must be a model of + Readable Property Map. +
      + Default: get(vertex_index, graph_large) +

      +
      + +

      IN: edges_equivalent(EdgeEquivalencePredicate edge_comp)

      +
      +

      + This function object is used to determine if edges between the two graphs + graph_small and graph_large are equivalent. + Type EdgeEquivalencePredicate must be a model of + Binary + Predicate and have argument types of + graph_traits<GraphSmall>::edge_descriptor and + graph_traits<GraphLarge>::edge_descriptor. + The edge descriptors must be + LessThan Comparable. A return value of true indicates that the edges are equivalent. +
      + Default: + always_equivalent +

      +
      + +

      IN: vertices_equivalent(VertexEquivalencePredicate vertex_comp)

      +
      +

      + This function object is used to determine if vertices between the two graphs + graph_small and graph_large are equivalent. + Type VertexEquivalencePredicate must be a model of + Binary Predicate + and have argument types of + graph_traits<GraphSmall>::vertex_descriptor and + graph_traits<GraphLarge>::vertex_descriptor. A return value of true + indicates that the vertices are equivalent. +
      + Default: + always_equivalent +

      +
      + +

      Related Functions

      +

      + Non-named parameter, named-parameter and all default parameter versions of + function +

      +

      vf2_graph_iso(...)

      +

      + for isomorphism testing take the same parameters as the corresponding + functions vf2_subgraph_iso for subgraph isomorphism testing. + The algorithm finds all isomorphism mappings between graphs + graph1 and graph2 and outputs them to + user_callback. It continues until user_callback + returns true or the search space has been fully explored. As before, + EdgeEquivalencePredicate and + VertexEquivalencePredicate predicates are used to test + whether edges and vertices are equivalent. By default + always_equivalent is used. +

      + +

      Utility Functions and Structs

      +

      + +template<typename Graph1, + typename Graph2> +struct vf2_print_callback + +

      +
      +

      + Callback function object that prints out the correspondences between vertices + of Graph1 and Graph2. The constructor takes + the two graphs G1 and G2. +

      +
      + +
      +template<typename Graph>
      +std::vector<typename graph_traits<Graph>::vertex_descriptor>
      +  vertex_order_by_mult(const Graph& graph) 
      +    
      +
      +

      + Returns a vector containing the vertices of a graph, sorted + by multiplicity of in/out degrees. +

      +
      + +
      +// Variant of verify_subgraph_iso with all default parameters
      +template<typename Graph1,
      +         typename Graph2,
      +         typename CorresponenceMap1To2>
      +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, 
      +                                    const CorresponenceMap1To2 f)
      +
      +
      +// Verifies a graph (sub)graph isomorphism map 
      +template<typename Graph1,
      +         typename Graph2,
      +         typename CorresponenceMap1To2,
      +         typename EdgeEquivalencePredicate,
      +         typename VertexEquivalencePredicate>
      +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, 
      +                                    const CorresponenceMap1To2 f,
      +                                    EdgeEquivalencePredicate edge_comp, 
      +                                    VertexEquivalencePredicate vertex_comp) 
      +    
      +
      +

      + This function can be used to verify a (sub)graph isomorphism + mapping f. The parameters are analogous to + function vf2_subgraph_iso (vf2_graph_iso). +

      +
      + + +

      Complexity

      +

      + Spatial and time complexity are given in [2]. The spatial + complexity of VF2 is of order O(V), where V is the (maximum) number + of vertices of the two graphs. Time complexity is O(V2) in the best case and + O(V!·V) in the worst case. +

      + +

      Examples

      + +

      Example 1

      +

      + In the example below, a small graph graph1 and a larger graph + graph2 are defined. Here small and large refers to the number of + vertices of the graphs. vf2_subgraph_iso computes all the + subgraph isomorphism mappings between the two graphs and outputs them + via callback. +

      +
      +typedef adjacency_list<setS, vecS, bidirectionalS> graph_type;
      +
      +// Build graph1
      +int num_vertices1 = 8; graph_type graph1(num_vertices1);
      +add_edge(0, 6, graph1); add_edge(0, 7, graph1);
      +add_edge(1, 5, graph1); add_edge(1, 7, graph1);
      +add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1);
      +add_edge(3, 4, graph1);
      +
      +// Build graph2
      +int num_vertices2 = 9; graph_type graph2(num_vertices2);
      +add_edge(0, 6, graph2); add_edge(0, 8, graph2);
      +add_edge(1, 5, graph2); add_edge(1, 7, graph2);
      +add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2);
      +add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2);
      +
      +// Create callback to print mappings
      +vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);
      +
      +
      +// Print out all subgraph isomorphism mappings between graph1 and graph2.
      +// Vertices and edges are assumed to be always equivalent.
      +vf2_subgraph_iso(graph1, graph2, callback);
      +    
      +

      + The complete example can be found under + examples/vf2_sub_graph_iso_example.cpp. +
      +

      + +

      Example 2

      +

      + In this example, the subgraph isomorphism mappings between multi-graphs are computed. The vertices + and edges of the multi-graphs are distinguished using property maps. +

      +
      +// Define edge and vertex properties
      +typedef property<edge_name_t, char> edge_property;
      +typedef property<vertex_name_t, char, property<vertex_index_t, int> > vertex_property;
      +
      +// Using a vecS graphs => the index maps are implicit.
      +typedef adjacency_list<vecS, vecS, bidirectionalS, vertex_property, edge_property> graph_type;
      +
      +// Create graph1
      +graph_type graph1;
      +// Add vertices... 
      +add_vertex(vertex_property('a'), graph1);
      +...
      +//... and edges 
      +add_edge(0, 1, edge_property('b'), graph1); 
      +add_edge(0, 1, edge_property('b'), graph1); 
      +...
      +
      +// Create graph2 
      +graph_type graph2;
      +add_vertex(vertex_property('a'), graph2);
      +...  
      +add_edge(0, 1, edge_property('a'), graph2); 
      +...
      +    
      + +

      + To distinguish vertices and edges with property maps, binary predicates are created using the + + make_property_map_equivalent function: +

      + +
      +// Create the vertex binary predicate
      +typedef property_map<graph_type, vertex_name_t>::type vertex_name_map_t;
      +typedef property_map_equivalent<vertex_name_map_t, vertex_name_map_t> vertex_comp_t;
      +vertex_comp_t vertex_comp =
      +  make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2));
      +
      +// Create the vertex binary predicate
      +typedef property_map<graph_type, edge_name_t>::type edge_name_map_t;
      +typedef property_map_equivalent<edge_name_map_t, edge_name_map_t> edge_comp_t;
      +edge_comp_t edge_comp =
      +  make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2));
      +    
      + +

      + Finally, a callback function object is created and the subgraph isomorphism mappings are + computed: +

      +
      +// Create callback
      +vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);
      +
      +
      +// Print out all subgraph isomorphism mappings between graph1 and graph2.
      +// Function vertex_order_by_mult is used to compute the order of 
      +// vertices of graph1. This is the order in which the vertices are examined
      +// during the matching process.
      +vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1),
      +                 edges_equivalent(edge_comp).vertices_equivalent(vertex_comp));
      +    
      + +

      + For the complete example, see + + examples/vf2_sub_graph_iso_multi_example.cpp. +
      +

      + +

      Notes

      +

      + If the EdgeList allows for parallel edges, e.g. vecS, the + algorithm does some bookkeeping of already identified edges. Matched edges + are temporarily stored using std::set as container, requiring that + edge_descriptor are + LessThan Comparable. In contrast, if instead you enforce the absence of + parallel edges, e.g. by using setS, the lookup function falls back + to edge() without performing any bookkeeping. +

      + +

      Bibliography

      + +
      +
      1
      +
      + L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. +
      An improved algorithm for matching large graphs. +
      In: 3rd IAPR-TC15 Workshop on Graph-based Representations in Pattern Recognition, pp. 149-159, Cuen, 2001. +

      +
      +
      2
      +
      + L. P. Cordella, P. Foggia, C. Sansone, and M. Vento. +
      A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs. +
      IEEE Trans. Pattern Anal. Mach. Intell., vol. 26, no. 10, pp. 1367-1372, 2004. +

      +
      +
      3
      +
      + + http://www.cs.sunysb.edu/~algorith/implement/vflib/implement.shtml +

      +
      +
      +
      +

      + Copyright © 2012, Flavio De Lorenzi + (fdlorenzi@gmail.com) +

      + + diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 5d4dc7f0..6d7d62f6 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -30,6 +30,7 @@ exe ospf-example : ospf-example.cpp ../build//boost_graph ; # exe cc-internet : cc-internet.cpp ../build//boost_graph ; exe implicit_graph : implicit_graph.cpp ; exe astar_maze : astar_maze.cpp ; +exe astar-cities : astar-cities.cpp ; exe stoer_wagner : stoer_wagner.cpp ; exe bfs-example : bfs-example.cpp ; exe bfs-example2 : bfs-example2.cpp ; @@ -43,3 +44,6 @@ exe strong_components : strong_components.cpp ../build//boost_graph ; exe strong-components : strong-components.cpp ; exe subgraph : subgraph.cpp ; exe subgraph_properties : subgraph_properties.cpp ; +exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; +exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; + diff --git a/example/astar-cities.cpp b/example/astar-cities.cpp index d5affd11..c594afa7 100644 --- a/example/astar-cities.cpp +++ b/example/astar-cities.cpp @@ -192,7 +192,7 @@ int main(int argc, char **argv) vector d(num_vertices(g)); try { // call astar named parameter interface - astar_search + astar_search_tree (g, start, distance_heuristic (locations, goal), diff --git a/example/undirected_adjacency_list.cpp b/example/undirected_adjacency_list.cpp index 97b14d99..49d31202 100644 --- a/example/undirected_adjacency_list.cpp +++ b/example/undirected_adjacency_list.cpp @@ -26,12 +26,12 @@ undirected_graph_demo1() add_edge(zero, two, undigraph); add_edge(one, two, undigraph); - std::cout << "out_edges(0): "; + std::cout << "out_edges(0):"; for (boost::tie(out, out_end) = out_edges(zero, undigraph); out != out_end; ++out) - std::cout << *out; - std::cout << std::endl << "in_edges(0): "; + std::cout << ' ' << *out; + std::cout << std::endl << "in_edges(0):"; for (boost::tie(in, in_end) = in_edges(zero, undigraph); in != in_end; ++in) - std::cout << *in; + std::cout << ' ' << *in; std::cout << std::endl; } @@ -91,6 +91,14 @@ undirected_graph_demo2() #endif std::cout << "weight[(u,v)] = " << get(weight, e1) << std::endl; std::cout << "weight[(v,u)] = " << get(weight, e2) << std::endl; + + std::cout << "the edges incident to v: "; + typename boost::graph_traits::out_edge_iterator e, e_end; + typename boost::graph_traits::vertex_descriptor + s = vertex(0, undigraph); + for (boost::tie(e, e_end) = out_edges(s, undigraph); e != e_end; ++e) + std::cout << "(" << source(*e, undigraph) + << "," << target(*e, undigraph) << ")" << std::endl; } @@ -103,7 +111,7 @@ main() typedef adjacency_list < vecS, vecS, directedS, no_property, Weight > DirectedGraph; undirected_graph_demo1 < UndirectedGraph > (); - undirected_graph_demo2 < UndirectedGraph > (); directed_graph_demo < DirectedGraph > (); + undirected_graph_demo2 < UndirectedGraph > (); return 0; } diff --git a/example/undirected_adjacency_list.expected b/example/undirected_adjacency_list.expected index 015a7afc..b02c6401 100644 --- a/example/undirected_adjacency_list.expected +++ b/example/undirected_adjacency_list.expected @@ -1,3 +1,5 @@ +out_edges(0): (0,1) (0,2) +in_edges(0): (1,0) (2,0) in a directed graph is (u,v) == (v,u) ? 0 weight[(u,v)] = 1.2 weight[(v,u)] = 2.4 diff --git a/example/vf2_sub_graph_iso_example.cpp b/example/vf2_sub_graph_iso_example.cpp new file mode 100755 index 00000000..8e17d2a7 --- /dev/null +++ b/example/vf2_sub_graph_iso_example.cpp @@ -0,0 +1,40 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +using namespace boost; + + +int main() { + + typedef adjacency_list graph_type; + + // Build graph1 + int num_vertices1 = 8; graph_type graph1(num_vertices1); + add_edge(0, 6, graph1); add_edge(0, 7, graph1); + add_edge(1, 5, graph1); add_edge(1, 7, graph1); + add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1); + add_edge(3, 4, graph1); + + // Build graph2 + int num_vertices2 = 9; graph_type graph2(num_vertices2); + add_edge(0, 6, graph2); add_edge(0, 8, graph2); + add_edge(1, 5, graph2); add_edge(1, 7, graph2); + add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2); + add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2); + + // Create callback to print mappings + vf2_print_callback callback(graph1, graph2); + + // Print out all subgraph isomorphism mappings between graph1 and graph2. + // Vertices and edges are assumed to be always equivalent. + vf2_subgraph_iso(graph1, graph2, callback); + + return 0; +} diff --git a/example/vf2_sub_graph_iso_multi_example.cpp b/example/vf2_sub_graph_iso_multi_example.cpp new file mode 100755 index 00000000..6f9e34a2 --- /dev/null +++ b/example/vf2_sub_graph_iso_multi_example.cpp @@ -0,0 +1,89 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +using namespace boost; + +int main() { + typedef property edge_property; + typedef property > vertex_property; + + // Using a vecS graphs => the index maps are implicit. + typedef adjacency_list graph_type; + + // Build graph1 + graph_type graph1; + + add_vertex(vertex_property('a'), graph1); + add_vertex(vertex_property('a'), graph1); + add_vertex(vertex_property('a'), graph1); + + add_edge(0, 1, edge_property('b'), graph1); + add_edge(0, 1, edge_property('b'), graph1); + add_edge(0, 1, edge_property('d'), graph1); + + add_edge(1, 2, edge_property('s'), graph1); + + add_edge(2, 2, edge_property('l'), graph1); + add_edge(2, 2, edge_property('l'), graph1); + + // Build graph2 + graph_type graph2; + + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + add_vertex(vertex_property('a'), graph2); + + add_edge(0, 1, edge_property('a'), graph2); + add_edge(0, 1, edge_property('a'), graph2); + add_edge(0, 1, edge_property('b'), graph2); + + add_edge(1, 2, edge_property('s'), graph2); + + add_edge(2, 3, edge_property('b'), graph2); + add_edge(2, 3, edge_property('d'), graph2); + add_edge(2, 3, edge_property('b'), graph2); + + add_edge(3, 4, edge_property('s'), graph2); + + add_edge(4, 4, edge_property('l'), graph2); + add_edge(4, 4, edge_property('l'), graph2); + + add_edge(4, 5, edge_property('c'), graph2); + add_edge(4, 5, edge_property('c'), graph2); + add_edge(4, 5, edge_property('c'), graph2); + + add_edge(5, 0, edge_property('s'), graph2); + + // create predicates + typedef property_map::type vertex_name_map_t; + typedef property_map_equivalent vertex_comp_t; + vertex_comp_t vertex_comp = + make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2)); + + typedef property_map::type edge_name_map_t; + typedef property_map_equivalent edge_comp_t; + edge_comp_t edge_comp = + make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2)); + + // Create callback + vf2_print_callback callback(graph1, graph2); + + // Print out all subgraph isomorphism mappings between graph1 and graph2. + // Function vertex_order_by_mult is used to compute the order of + // vertices of graph1. This is the order in which the vertices are examined + // during the matching process. + vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1), + edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)); + + return 0; +} diff --git a/include/boost/graph/adjacency_list.hpp b/include/boost/graph/adjacency_list.hpp index 21b7500d..6738fa22 100644 --- a/include/boost/graph/adjacency_list.hpp +++ b/include/boost/graph/adjacency_list.hpp @@ -188,6 +188,7 @@ namespace boost { } // namespace detail + template struct is_distributed_selector: mpl::false_ {}; //=========================================================================== diff --git a/include/boost/graph/astar_search.hpp b/include/boost/graph/astar_search.hpp index 38224a98..7d6da7c3 100644 --- a/include/boost/graph/astar_search.hpp +++ b/include/boost/graph/astar_search.hpp @@ -22,9 +22,12 @@ #include #include #include +#include #include +#include #include #include +#include #include namespace boost { @@ -159,8 +162,9 @@ namespace boost { template void tree_edge(Edge e, const Graph& g) { using boost::get; - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { m_vis.edge_relaxed(e, g); @@ -175,8 +179,9 @@ namespace boost { template void gray_target(Edge e, const Graph& g) { using boost::get; - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { put(m_cost, target(e, g), @@ -192,8 +197,9 @@ namespace boost { template void black_target(Edge e, const Graph& g) { using boost::get; - m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); + bool m_decreased = + relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); if(m_decreased) { m_vis.edge_relaxed(e, g); @@ -219,7 +225,6 @@ namespace boost { ColorMap m_color; BinaryFunction m_combine; BinaryPredicate m_compare; - bool m_decreased; C m_zero; }; @@ -263,6 +268,77 @@ namespace boost { breadth_first_visit(g, s, Q, bfs_vis, color); } + namespace graph_detail { + template + struct select1st { + typedef std::pair argument_type; + typedef A result_type; + A operator()(const std::pair& p) const {return p.first;} + }; + } + + template + inline void + astar_search_no_init_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf /*inf*/, CostZero zero) + { + typedef typename graph_traits::vertex_descriptor + Vertex; + typedef typename property_traits::value_type Distance; + typedef d_ary_heap_indirect< + std::pair, + 4, + null_property_map, std::size_t>, + function_property_map, std::pair >, + CompareFunction> + MutableQueue; + MutableQueue Q( + make_function_property_map >(graph_detail::select1st()), + null_property_map, std::size_t>(), + compare); + + vis.discover_vertex(s, g); + Q.push(std::make_pair(get(cost, s), s)); + while (!Q.empty()) { + Vertex v; + Distance v_rank; + boost::tie(v_rank, v) = Q.top(); + Q.pop(); + vis.examine_vertex(v, g); + BGL_FORALL_OUTEDGES_T(v, e, g, VertexListGraph) { + Vertex w = target(e, g); + vis.examine_edge(e, g); + Distance e_weight = get(weight, e); + if (compare(e_weight, zero)) + BOOST_THROW_EXCEPTION(negative_edge()); + bool decreased = + relax(e, g, weight, predecessor, distance, + combine, compare); + Distance w_d = combine(get(distance, v), e_weight); + if (decreased) { + vis.edge_relaxed(e, g); + Distance w_rank = combine(get(distance, w), h(w)); + put(cost, w, w_rank); + vis.discover_vertex(w, g); + Q.push(std::make_pair(w_rank, w)); + } else { + vis.edge_not_relaxed(e, g); + } + } + vis.finish_vertex(v, g); + } + } // Non-named parameter interface template + inline void + astar_search_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero) + { + + typename graph_traits::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(distance, *ui, inf); + put(cost, *ui, inf); + put(predecessor, *ui, *ui); + vis.initialize_vertex(*ui, g); + } + put(distance, s, zero); + put(cost, s, h(s)); + + astar_search_no_init_tree + (g, s, h, vis, predecessor, cost, distance, weight, + compare, combine, inf, zero); + + } + // Named parameter interfaces template + void + astar_search_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // Distance type is the value type of the distance map if there is one, + // otherwise the value type of the weight map. + typedef + typename detail::override_const_property_result< + arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type + weight_map_type; + typedef typename boost::property_traits::value_type W; + typedef + typename detail::map_maker::map_type + distance_map_type; + typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + + astar_search_tree + (g, s, h, + arg_pack[_visitor | make_astar_visitor(null_visitor())], + arg_pack[_predecessor_map | dummy_property_map()], + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::make_property_map_from_arg_pack_gen(W())(g, arg_pack), + detail::override_const_property(arg_pack, _weight_map, g, edge_weight), + arg_pack[_distance_compare | std::less()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, + arg_pack[_distance_zero | D()]); + } + template @@ -378,6 +528,37 @@ namespace boost { arg_pack[_distance_zero | D()]); } + template + void + astar_search_no_init_tree + (const VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + using namespace boost::graph::keywords; + typedef bgl_named_params params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + typedef + typename detail::override_const_property_result< + arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type + weight_map_type; + typedef typename boost::property_traits::value_type D; + const D inf = arg_pack[_distance_inf | (std::numeric_limits::max)()]; + astar_search_no_init_tree + (g, s, h, + arg_pack[_visitor | make_astar_visitor(null_visitor())], + arg_pack[_predecessor_map | dummy_property_map()], + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::make_property_map_from_arg_pack_gen(D())(g, arg_pack), + detail::override_const_property(arg_pack, _weight_map, g, edge_weight), + arg_pack[_distance_compare | std::less()], + arg_pack[_distance_combine | closed_plus(inf)], + inf, + arg_pack[_distance_zero | D()]); + } + } // namespace boost #endif // BOOST_GRAPH_ASTAR_SEARCH_HPP diff --git a/include/boost/graph/boykov_kolmogorov_max_flow.hpp b/include/boost/graph/boykov_kolmogorov_max_flow.hpp index 0834c631..1edc1323 100644 --- a/include/boost/graph/boykov_kolmogorov_max_flow.hpp +++ b/include/boost/graph/boykov_kolmogorov_max_flow.hpp @@ -442,11 +442,11 @@ class bk_max_flow { for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ edge_descriptor in_edge = get(m_rev_edge_map, *ei); vertex_descriptor other_node = source(in_edge, m_g); - if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){ + if(get_tree(other_node) == tColorTraits::black() && other_node != m_source){ if(get(m_res_cap_map, in_edge) > 0){ add_active_node(other_node); } - if(source(get_edge_to_parent(other_node), m_g) == current_node){ + if(has_parent(other_node) && source(get_edge_to_parent(other_node), m_g) == current_node){ //we are the parent of that node //it has to find a new parent, too set_no_parent(other_node); @@ -483,11 +483,11 @@ class bk_max_flow { for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ const edge_descriptor out_edge = *ei; const vertex_descriptor other_node = target(out_edge, m_g); - if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){ + if(get_tree(other_node) == tColorTraits::white() && other_node != m_sink){ if(get(m_res_cap_map, out_edge) > 0){ add_active_node(other_node); } - if(target(get_edge_to_parent(other_node), m_g) == current_node){ + if(has_parent(other_node) && target(get_edge_to_parent(other_node), m_g) == current_node){ //we were it's parent, so it has to find a new one, too set_no_parent(other_node); m_child_orphans.push(other_node); @@ -526,6 +526,9 @@ class bk_max_flow { inline void add_active_node(vertex_descriptor v){ BOOST_ASSERT(get_tree(v) != tColorTraits::gray()); if(get(m_in_active_list_map, v)){ + if (m_last_grow_vertex == v) { + m_last_grow_vertex = graph_traits::null_vertex(); + } return; } else{ put(m_in_active_list_map, v, true); diff --git a/include/boost/graph/compressed_sparse_row_graph.hpp b/include/boost/graph/compressed_sparse_row_graph.hpp index 42e2419a..33c26725 100644 --- a/include/boost/graph/compressed_sparse_row_graph.hpp +++ b/include/boost/graph/compressed_sparse_row_graph.hpp @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -1322,8 +1324,9 @@ struct csr_property_map_helper { typedef transform_value_property_map, all_const_type> const_type; }; +// disable_if isn't truly necessary but required to avoid ambiguity with specializations below template -struct property_map: +struct property_map >::type>: csr_property_map_helper< BOOST_CSR_GRAPH_TYPE, Tag, @@ -1370,35 +1373,35 @@ put(Tag tag, } template -struct property_map +struct property_map >::type> { typedef typed_identity_property_map type; typedef type const_type; }; template -struct property_map +struct property_map >::type> { typedef detail::csr_edge_index_map type; typedef type const_type; }; template -struct property_map +struct property_map >::type> { typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::vertex_map_type type; typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::const_vertex_map_type const_type; }; template -struct property_map +struct property_map >::type> { typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::edge_map_type type; typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::const_edge_map_type const_type; }; template -struct property_map +struct property_map >::type> { typedef boost::ref_property_map type; typedef boost::ref_property_map const_type; diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index fa398989..61959367 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -309,14 +309,16 @@ namespace boost { public: typedef Property property_type; inline stored_ra_edge_iter() { } - inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), - EdgeVec* edge_vec = 0) + inline explicit stored_ra_edge_iter(Vertex v) // Only used for comparisons + : stored_edge(v), m_i(0), m_vec(0){ } + inline stored_ra_edge_iter(Vertex v, Iter i, EdgeVec* edge_vec) : stored_edge(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ } - inline Property& get_property() { return (*m_vec)[m_i].get_property(); } + inline Property& get_property() { BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); } inline const Property& get_property() const { + BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); } - inline Iter get_iter() const { return m_vec->begin() + m_i; } + inline Iter get_iter() const { BOOST_ASSERT ((m_vec != 0)); return m_vec->begin() + m_i; } protected: std::size_t m_i; EdgeVec* m_vec; diff --git a/include/boost/graph/detail/d_ary_heap.hpp b/include/boost/graph/detail/d_ary_heap.hpp index 2d921926..cf930fc1 100644 --- a/include/boost/graph/detail/d_ary_heap.hpp +++ b/include/boost/graph/detail/d_ary_heap.hpp @@ -126,18 +126,21 @@ namespace boost { } Value& top() { + BOOST_ASSERT (!this->empty()); return data[0]; } const Value& top() const { + BOOST_ASSERT (!this->empty()); return data[0]; } void pop() { + BOOST_ASSERT (!this->empty()); put(index_in_heap, data[0], (size_type)(-1)); if (data.size() != 1) { data[0] = data.back(); - put(index_in_heap, data[0], 0); + put(index_in_heap, data[0], (size_type)(0)); data.pop_back(); preserve_heap_property_down(); verify_heap(); diff --git a/include/boost/graph/detail/is_distributed_selector.hpp b/include/boost/graph/detail/is_distributed_selector.hpp new file mode 100644 index 00000000..4319d9d8 --- /dev/null +++ b/include/boost/graph/detail/is_distributed_selector.hpp @@ -0,0 +1,26 @@ +// Copyright 2012 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Andrew Lumsdaine + +// Selector to determine whether a selector is distributedS (can only be true +// if has been included) so that we can +// disable various sequential-graph-only traits specializations for distributed +// graphs. + +#ifndef BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP +#define BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP + +#include + +namespace boost { + namespace detail { + template struct is_distributed_selector: boost::mpl::false_ {}; + } +} + +#endif // BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP diff --git a/include/boost/graph/detail/labeled_graph_traits.hpp b/include/boost/graph/detail/labeled_graph_traits.hpp index 6eb10609..a0c0973f 100644 --- a/include/boost/graph/detail/labeled_graph_traits.hpp +++ b/include/boost/graph/detail/labeled_graph_traits.hpp @@ -218,9 +218,9 @@ namespace graph_detail { #define LABELED_GRAPH_PARAMS typename G, typename L, typename S #define LABELED_GRAPH labeled_graph -// Specialize mutability traits for for the labeled graph. +// Specialize mutability traits for the labeled graph. // This specialization depends on the mutability of the underlying graph type. -// If the underlying graph is fully mutable, this this is also fully mutable. +// If the underlying graph is fully mutable, this is also fully mutable. // Otherwise, it's different. template struct graph_mutability_traits< LABELED_GRAPH > { diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index ca2a1ebd..c5ce6b6d 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -113,16 +113,17 @@ namespace boost { distance_weight_combine, distance_compare); if (was_edge_relaxed) { - vertex_queue.update(neighbor_vertex); visitor.edge_relaxed(current_edge, graph); + if (is_neighbor_undiscovered) { + visitor.discover_vertex(neighbor_vertex, graph); + vertex_queue.push(neighbor_vertex); + } else { + vertex_queue.update(neighbor_vertex); + } } else { visitor.edge_not_relaxed(current_edge, graph); } - if (is_neighbor_undiscovered) { - visitor.discover_vertex(neighbor_vertex, graph); - vertex_queue.push(neighbor_vertex); - } } // end out edge iteration visitor.finish_vertex(min_vertex, graph); diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp index 250d0b63..585308d1 100644 --- a/include/boost/graph/directed_graph.hpp +++ b/include/boost/graph/directed_graph.hpp @@ -9,6 +9,10 @@ #include #include +#include +#include +#include +#include namespace boost { @@ -27,8 +31,8 @@ struct directed_graph_tag { }; */ template < typename VertexProp = no_property, - typename EdgeProp= no_property, - typename GraphProp= no_property> + typename EdgeProp = no_property, + typename GraphProp = no_property> class directed_graph { public: @@ -39,15 +43,14 @@ public: typedef typename lookup_one_property::type vertex_bundled; typedef typename lookup_one_property::type edge_bundled; -private: - // Wrap the user-specified properties with an index. - typedef property vertex_property; - typedef property edge_property; - +public: + // Embed indices into the vertex type. + typedef property internal_vertex_property; + typedef property internal_edge_property; public: typedef adjacency_list< listS, listS, bidirectionalS, - vertex_property, edge_property, GraphProp, + internal_vertex_property, internal_edge_property, GraphProp, listS > graph_type; @@ -80,8 +83,8 @@ public: typedef typename graph_type::edge_parallel_category edge_parallel_category; typedef typename graph_type::traversal_category traversal_category; - typedef unsigned vertex_index_type; - typedef unsigned edge_index_type; + typedef std::size_t vertex_index_type; + typedef std::size_t edge_index_type; directed_graph(GraphProp const& p = GraphProp()) : m_graph(p), m_num_vertices(0), m_num_edges(0), m_max_vertex_index(0) @@ -137,6 +140,7 @@ public: vertices_size_type num_vertices() const { return m_num_vertices; } + private: // This helper function manages the attribution of vertex indices. vertex_descriptor make_index(vertex_descriptor v) { @@ -150,7 +154,7 @@ public: { return make_index(boost::add_vertex(m_graph)); } vertex_descriptor add_vertex(vertex_property_type const& p) - { return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); } + { return make_index(boost::add_vertex(internal_vertex_property(0u, p), m_graph)); } void clear_vertex(vertex_descriptor v) { @@ -186,7 +190,7 @@ public: std::pair add_edge(vertex_descriptor u, vertex_descriptor v, edge_property_type const& p) - { return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); } + { return make_index(boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); } void remove_edge(vertex_descriptor u, vertex_descriptor v) { @@ -516,37 +520,32 @@ remove_in_edge_if(typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) { return remove_in_edge_if(v, pred, g.impl()); } -// Helper code for working with property maps -namespace detail -{ - struct directed_graph_vertex_property_selector { - template - struct bind_ { - typedef typename DirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; +template +struct property_map: property_map {}; - struct directed_graph_edge_property_selector { - template - struct bind_ { - typedef typename DirectedGraph::graph_type Graph; - typedef property_map PropertyMap; - typedef typename PropertyMap::type type; - typedef typename PropertyMap::const_type const_type; - }; - }; -} +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; -template <> -struct vertex_property_selector -{ typedef detail::directed_graph_vertex_property_selector type; }; - -template <> -struct edge_property_selector -{ typedef detail::directed_graph_edge_property_selector type; }; +template +struct property_map { + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::const_type> + const_type; + typedef transform_value_property_map< + detail::remove_first_property, + typename property_map::type> + type; +}; // PropertyGraph concepts template @@ -559,6 +558,26 @@ inline typename property_map::const_type get(Property p, DIRECTED_GRAPH const& g) { return get(p, g.impl()); } +template +inline typename property_map::type +get(vertex_all_t, DIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::const_type +get(vertex_all_t, DIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(vertex_all, g.impl())); } + +template +inline typename property_map::type +get(edge_all_t, DIRECTED_GRAPH& g) +{ return typename property_map::type(detail::remove_first_property(), get(edge_all, g.impl())); } + +template +inline typename property_map::const_type +get(edge_all_t, DIRECTED_GRAPH const& g) +{ return typename property_map::const_type(detail::remove_first_property(), get(edge_all, g.impl())); } + template inline typename property_traits< typename property_map< @@ -568,10 +587,40 @@ inline typename property_traits< get(Property p, DIRECTED_GRAPH const& g, Key const& k) { return get(p, g.impl(), k); } +template +inline typename property_traits< + typename property_map< + typename DIRECTED_GRAPH::graph_type, vertex_all_t + >::const_type +>::value_type +get(vertex_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ return get(vertex_all, g.impl(), k).m_base; } + +template +inline typename property_traits< + typename property_map< + typename DIRECTED_GRAPH::graph_type, edge_all_t + >::const_type +>::value_type +get(edge_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ return get(edge_all, g.impl(), k).m_base; } + template inline void put(Property p, DIRECTED_GRAPH& g, Key const& k, Value const& v) { put(p, g.impl(), k, v); } +template +inline void put(vertex_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(vertex_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property(get(vertex_index, g.impl(), k), v)); +} + +template +inline void put(edge_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ put(edge_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property(get(edge_index, g.impl(), k), v)); +} + template typename graph_property::type& get_property(DIRECTED_GRAPH& g, Property p) diff --git a/include/boost/graph/graph_concepts.hpp b/include/boost/graph/graph_concepts.hpp index 8cb7cbb2..f03afeea 100644 --- a/include/boost/graph/graph_concepts.hpp +++ b/include/boost/graph/graph_concepts.hpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include @@ -55,12 +58,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_concept(Graph,(G)) { typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename graph_traits::directed_category directed_category; - typedef typename graph_traits::edge_parallel_category - edge_parallel_category; - - typedef typename graph_traits::traversal_category - traversal_category; + typedef typename graph_traits::edge_parallel_category edge_parallel_category; + typedef typename graph_traits::traversal_category traversal_category; BOOST_CONCEPT_USAGE(Graph) { @@ -75,11 +76,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); : Graph { typedef typename graph_traits::edge_descriptor edge_descriptor; - typedef typename graph_traits::out_edge_iterator - out_edge_iterator; + typedef typename graph_traits::out_edge_iterator out_edge_iterator; + typedef typename graph_traits::degree_size_type degree_size_type; + typedef typename graph_traits::traversal_category traversal_category; - typedef typename graph_traits::traversal_category - traversal_category; + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); BOOST_CONCEPT_USAGE(IncidenceGraph) { BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); @@ -123,6 +125,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + p = in_edges(v, g); n = in_degree(v, g); e = *p.first; @@ -153,6 +157,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + p = adjacent_vertices(v, g); v = *p.first; const_constraints(g); @@ -178,6 +184,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + #ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if // you want to use vector_as_graph, it is! I'm sure the graph @@ -227,6 +236,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + BOOST_STATIC_ASSERT((boost::mpl::not_ >::value)); + p = edges(g); e = *p.first; u = source(e, g); diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp index 625429e6..ceb0c2ac 100644 --- a/include/boost/graph/graph_traits.hpp +++ b/include/boost/graph/graph_traits.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,23 +29,47 @@ namespace boost { + namespace detail { +#define BOOST_GRAPH_MEMBER_OR_VOID(name) \ + BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \ + template struct BOOST_JOIN(get_member_, name) {typedef typename T::name type;}; \ + template struct BOOST_JOIN(get_opt_member_, name): \ + boost::mpl::eval_if_c< \ + BOOST_JOIN(has_, name)::value, \ + BOOST_JOIN(get_member_, name), \ + boost::mpl::identity > \ + {}; + BOOST_GRAPH_MEMBER_OR_VOID(adjacency_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(out_edge_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(in_edge_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(vertex_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(edge_iterator) + BOOST_GRAPH_MEMBER_OR_VOID(vertices_size_type) + BOOST_GRAPH_MEMBER_OR_VOID(edges_size_type) + BOOST_GRAPH_MEMBER_OR_VOID(degree_size_type) + } + template struct graph_traits { +#define BOOST_GRAPH_PULL_OPT_MEMBER(name) \ + typedef typename detail::BOOST_JOIN(get_opt_member_, name)::type name; + typedef typename G::vertex_descriptor vertex_descriptor; typedef typename G::edge_descriptor edge_descriptor; - typedef typename G::adjacency_iterator adjacency_iterator; - typedef typename G::out_edge_iterator out_edge_iterator; - typedef typename G::in_edge_iterator in_edge_iterator; - typedef typename G::vertex_iterator vertex_iterator; - typedef typename G::edge_iterator edge_iterator; + BOOST_GRAPH_PULL_OPT_MEMBER(adjacency_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(out_edge_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(in_edge_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(vertex_iterator) + BOOST_GRAPH_PULL_OPT_MEMBER(edge_iterator) typedef typename G::directed_category directed_category; typedef typename G::edge_parallel_category edge_parallel_category; typedef typename G::traversal_category traversal_category; - typedef typename G::vertices_size_type vertices_size_type; - typedef typename G::edges_size_type edges_size_type; - typedef typename G::degree_size_type degree_size_type; + BOOST_GRAPH_PULL_OPT_MEMBER(vertices_size_type) + BOOST_GRAPH_PULL_OPT_MEMBER(edges_size_type) + BOOST_GRAPH_PULL_OPT_MEMBER(degree_size_type) +#undef BOOST_GRAPH_PULL_OPT_MEMBER static inline vertex_descriptor null_vertex(); }; diff --git a/include/boost/graph/graphml.hpp b/include/boost/graph/graphml.hpp index 028cdc26..be73def3 100644 --- a/include/boost/graph/graphml.hpp +++ b/include/boost/graph/graphml.hpp @@ -204,14 +204,14 @@ template const char* mutate_graph_impl::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"}; void BOOST_GRAPH_DECL -read_graphml(std::istream& in, mutate_graph& g); +read_graphml(std::istream& in, mutate_graph& g, size_t desired_idx); template void -read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp) +read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp, size_t desired_idx = 0) { mutate_graph_impl mg(g,dp); - read_graphml(in, mg); + read_graphml(in, mg, desired_idx); } template diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp index f8a210ca..63355c94 100644 --- a/include/boost/graph/kamada_kawai_spring_layout.hpp +++ b/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -475,12 +475,12 @@ namespace boost { * from every vertex to every other vertex, which is computed in the * first stages of the algorithm. This value's type must be a model * of BasicMatrix with value type equal to the value type of the - * weight map. The default is a a vector of vectors. + * weight map. The default is a vector of vectors. * * \param spring_strength (UTIL/OUT) will be used to store the * strength of the spring between every pair of vertices. This * value's type must be a model of BasicMatrix with value type equal - * to the value type of the weight map. The default is a a vector of + * to the value type of the weight map. The default is a vector of * vectors. * * \param partial_derivatives (UTIL) will be used to store the diff --git a/include/boost/graph/labeled_graph.hpp b/include/boost/graph/labeled_graph.hpp index 67505d25..5b688b02 100644 --- a/include/boost/graph/labeled_graph.hpp +++ b/include/boost/graph/labeled_graph.hpp @@ -21,7 +21,7 @@ #include // This file implements a utility for creating mappings from arbitrary -// identifers to the vertices of a graph. +// identifiers to the vertices of a graph. namespace boost { @@ -104,7 +104,7 @@ namespace graph_detail { // Tag dispatch on random access containers (i.e., vectors). This function // basically requires a) that Container is vector