From 5ec43278169708a77586d347d734d72c370b3448 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Thu, 7 Sep 2023 19:25:47 +0200 Subject: [PATCH 01/10] Invariant contiguous range requirement removal Invariant contiguous range requirement removal - Vertex invariants for use in isomorphism algorithm must no longer have low upper bounds due to a hidden allocation linear in the maximum encountered vertex invariant. - Vertex invariants must no longer be convertible to `size_t`, but can be any comparable and hashable types - Build `unordered_map`-backed invariant multiplicity map efficiently from sorted vertex invariants --- doc/isomorphism.html | 5 +- include/boost/graph/isomorphism.hpp | 123 ++++++++++++++++++---------- 2 files changed, 84 insertions(+), 44 deletions(-) diff --git a/doc/isomorphism.html b/doc/isomorphism.html index 40a9867bf..524ce9c75 100644 --- a/doc/isomorphism.html +++ b/doc/isomorphism.html @@ -114,9 +114,8 @@

Named Parameters

href="http://www.boost.org/sgi/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction, with the argument type of vertex_invariant1 being Graph1's vertex descriptor type, the argument type of vertex_invariant2 being -Graph2's vertex descriptor type, and both functions having integral -result types. The values returned by these two functions must have a low upper -bound, as memory linear in the maximal invariant value is allocated. +Graph2's vertex descriptor type, and both functions sharing a +result type that is totally ordered and hashable, such as an integer.
Default: degree_vertex_invariant for both arguments
Python: Unsupported parameter. diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 060410f2c..c2d696c80 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -30,6 +30,22 @@ namespace boost namespace detail { + template < typename T > + struct HashableConcept { + BOOST_CONCEPT_USAGE(HashableConcept) + { + hash hasher; + typedef typename hash::result_type hash_result; + hash_result val = hasher(t); + boost::ignore_unused_variable_warning(val); + } + + T t; + }; + + template < typename Invariant > + struct InvariantConcept : LessThanComparable, EqualityComparable, HashableConcept {}; + template < typename Graph1, typename Graph2, typename IsoMapping, typename Invariant1, typename Invariant2, typename IndexMap1, typename IndexMap2 > @@ -39,8 +55,8 @@ namespace detail typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_t; typedef typename graph_traits< Graph1 >::edge_descriptor edge1_t; typedef typename graph_traits< Graph1 >::vertices_size_type size_type; - typedef typename Invariant1::result_type invar1_value; - typedef typename Invariant2::result_type invar2_value; + typedef typename Invariant1::result_type invariant_t; + typedef unordered_map< invariant_t, size_type > multiplicity_map; const Graph1& G1; const Graph2& G2; @@ -81,17 +97,17 @@ namespace detail friend struct compare_multiplicity; struct compare_multiplicity { - compare_multiplicity(Invariant1 invariant1, size_type* multiplicity) + compare_multiplicity(Invariant1 invariant1, const multiplicity_map& multiplicity) : invariant1(invariant1), multiplicity(multiplicity) { } bool operator()(const vertex1_t& x, const vertex1_t& y) const { - return multiplicity[invariant1(x)] - < multiplicity[invariant1(y)]; + return multiplicity.at(invariant1(x)) + < multiplicity.at(invariant1(y)); } Invariant1 invariant1; - size_type* multiplicity; + const multiplicity_map& multiplicity; }; struct record_dfs_order : default_dfs_visitor @@ -158,46 +174,65 @@ namespace detail ); } + // Generates map of invariant multiplicity from sorted invariants + multiplicity_map multiplicities(const std::vector< invariant_t >& invariants) { + // Assumes invariants are sorted + multiplicity_map invar_multiplicity; + + typedef typename std::vector< invariant_t >::const_iterator invar_iter; + typedef typename multiplicity_map::iterator invar_map_iter; + invar_iter it = invariants.begin(); + const invar_iter end = invariants.end(); + + if(it == end) { + return invar_multiplicity; + } + + invariant_t invar = *it; + invar_map_iter inserted = invar_multiplicity.emplace(invar, 1).first; + ++it; + for(; it != end; ++it) + { + if(*it == invar) + { + inserted->second += 1; + } + else + { + invar = *it; + inserted = invar_multiplicity.emplace(invar, 1).first; + } + } + + return invar_multiplicity; + } + bool test_isomorphism() { // reset isomapping BGL_FORALL_VERTICES_T(v, G1, Graph1) f[v] = graph_traits< Graph2 >::null_vertex(); - std::size_t max_invariant = 0; - { - std::vector< invar1_value > invar1_array; - invar1_array.reserve(num_vertices(G1)); - BGL_FORALL_VERTICES_T(v, G1, Graph1) - invar1_array.push_back(invariant1(v)); - sort(invar1_array); - - std::vector< invar2_value > invar2_array; - invar2_array.reserve(num_vertices(G2)); - BGL_FORALL_VERTICES_T(v, G2, Graph2) - invar2_array.push_back(invariant2(v)); - sort(invar2_array); - if (!equal(invar1_array, invar2_array)) - return false; - - // Empty graphs case is covered before test_isomorphism is - // called, so the invar?_arrays cannot be empty, so back() is - // safe. Also the two invariant arrays are equal: - max_invariant = invar1_array.back(); - assert(max_invariant != std::numeric_limits::max()); - max_invariant += 1; - } - + // Calculate all invariants of G1 and G2, sort and compare + std::vector< invariant_t > invar1_array; + invar1_array.reserve(num_vertices(G1)); + BGL_FORALL_VERTICES_T(v, G1, Graph1) + invar1_array.push_back(invariant1(v)); + sort(invar1_array); + + std::vector< invariant_t > invar2_array; + invar2_array.reserve(num_vertices(G2)); + BGL_FORALL_VERTICES_T(v, G2, Graph2) + invar2_array.push_back(invariant2(v)); + sort(invar2_array); + if (!equal(invar1_array, invar2_array)) + return false; + + // Sort vertices by the multiplicity of their invariants std::vector< vertex1_t > V_mult; BGL_FORALL_VERTICES_T(v, G1, Graph1) V_mult.push_back(v); - { - std::vector< size_type > multiplicity(max_invariant, 0); - BGL_FORALL_VERTICES_T(v, G1, Graph1) - ++multiplicity.at(invariant1(v)); - sort( - V_mult, compare_multiplicity(invariant1, &multiplicity[0])); - } + sort(V_mult, compare_multiplicity(invariant1, multiplicities(invar1_array))); std::vector< default_color_type > color_vec(num_vertices(G1)); safe_iterator_property_map< @@ -437,7 +472,7 @@ namespace detail } if(!unmatched_g1_vertices.empty()) { - typedef unordered_multimap< invar2_value, vertex2_t > g2_invariant_vertex_multimap; + typedef unordered_multimap< invariant_t, vertex2_t > g2_invariant_vertex_multimap; typedef typename g2_invariant_vertex_multimap::iterator multimap_iter; g2_invariant_vertex_multimap unmatched_invariants; BGL_FORALL_VERTICES_T(v, G2, Graph2) @@ -451,7 +486,7 @@ namespace detail const v1_iter end = unmatched_g1_vertices.end(); for(v1_iter iter = unmatched_g1_vertices.begin(); iter != end; ++iter) { - invar1_value unmatched_g1_vertex_invariant = invariant1(*iter); + invariant_t unmatched_g1_vertex_invariant = invariant1(*iter); multimap_iter matching_invariant = unmatched_invariants.find(unmatched_g1_vertex_invariant); BOOST_ASSERT(matching_invariant != unmatched_invariants.end()); f[*iter] = matching_invariant->second; @@ -546,11 +581,17 @@ bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f, typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_t; typedef typename graph_traits< Graph1 >::vertices_size_type size_type; + typedef typename Invariant1::result_type invariant1_t; + typedef typename Invariant2::result_type invariant2_t; + + BOOST_STATIC_ASSERT(is_same::value); + BOOST_CONCEPT_ASSERT((detail::InvariantConcept)); + // Vertex invariant requirement BOOST_CONCEPT_ASSERT( - (AdaptableUnaryFunctionConcept< Invariant1, size_type, vertex1_t >)); + (AdaptableUnaryFunctionConcept< Invariant1, invariant1_t, vertex1_t >)); BOOST_CONCEPT_ASSERT( - (AdaptableUnaryFunctionConcept< Invariant2, size_type, vertex2_t >)); + (AdaptableUnaryFunctionConcept< Invariant2, invariant2_t, vertex2_t >)); // Property map requirements BOOST_CONCEPT_ASSERT( From 0be4c876bde3ddf0d2dcea8907573cd054816ff9 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Tue, 19 Sep 2023 10:58:34 +0200 Subject: [PATCH 02/10] Avoid requiring invariant default-constructibility Avoid requiring invariant default-constructibility - Refactor concept checking with boost type_traits --- include/boost/graph/isomorphism.hpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index c2d696c80..c45abec0a 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -18,6 +18,9 @@ #include #include // for make_indirect_pmap #include +#include +#include +#include #ifndef BOOST_GRAPH_ITERATION_MACROS_HPP #define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file @@ -30,21 +33,17 @@ namespace boost namespace detail { - template < typename T > - struct HashableConcept { - BOOST_CONCEPT_USAGE(HashableConcept) - { - hash hasher; - typedef typename hash::result_type hash_result; - hash_result val = hasher(t); - boost::ignore_unused_variable_warning(val); - } + namespace concept + { + template < typename T > + using TestHashable = decltype(hash()(std::declval())); - T t; - }; + template < typename T > + struct Hashable: std::integral_constant> {}; - template < typename Invariant > - struct InvariantConcept : LessThanComparable, EqualityComparable, HashableConcept {}; + template < typename T > + struct Invariant: std::integral_constant::value && boost::has_less::value && boost::has_equal_to::value> {}; + } template < typename Graph1, typename Graph2, typename IsoMapping, typename Invariant1, typename Invariant2, typename IndexMap1, @@ -585,7 +584,7 @@ bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f, typedef typename Invariant2::result_type invariant2_t; BOOST_STATIC_ASSERT(is_same::value); - BOOST_CONCEPT_ASSERT((detail::InvariantConcept)); + BOOST_STATIC_ASSERT(detail::concept::Invariant::value); // Vertex invariant requirement BOOST_CONCEPT_ASSERT( From 8f3139bed4da6510e523b3f1c6f981a47d4b7d54 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Tue, 19 Sep 2023 11:00:02 +0200 Subject: [PATCH 03/10] Avoid reference member in multiplicity functor --- include/boost/graph/isomorphism.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index c45abec0a..43fc80ec9 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -97,16 +97,19 @@ namespace detail struct compare_multiplicity { compare_multiplicity(Invariant1 invariant1, const multiplicity_map& multiplicity) - : invariant1(invariant1), multiplicity(multiplicity) + : invariant1(invariant1), multiplicity(&multiplicity) { } bool operator()(const vertex1_t& x, const vertex1_t& y) const { - return multiplicity.at(invariant1(x)) - < multiplicity.at(invariant1(y)); + auto x_multiplicity_iter = multiplicity->find(invariant1(x)); + assert(x_multiplicity_iter != multiplicity->end()); + auto y_multiplicity_iter = multiplicity->find(invariant1(y)); + assert(y_multiplicity_iter != multiplicity->end()); + return *x_multiplicity_iter < *y_multiplicity_iter; } Invariant1 invariant1; - const multiplicity_map& multiplicity; + const multiplicity_map* multiplicity; }; struct record_dfs_order : default_dfs_visitor From db7b3736d6a0a69083cb0e716a0dfcaf08fa396a Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Tue, 19 Sep 2023 11:02:56 +0200 Subject: [PATCH 04/10] Refactor multiplicities() with iterators --- include/boost/graph/isomorphism.hpp | 57 +++++++++++++++-------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 43fc80ec9..ef88961ce 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -177,36 +177,37 @@ namespace detail } // Generates map of invariant multiplicity from sorted invariants - multiplicity_map multiplicities(const std::vector< invariant_t >& invariants) { - // Assumes invariants are sorted - multiplicity_map invar_multiplicity; + template + multiplicity_map multiplicities(ForwardIterator first, const ForwardIterator last) + { + assert(std::is_sorted(first, last)); + multiplicity_map invar_multiplicity; + + typedef typename std::vector< invariant_t >::const_iterator invar_iter; + typedef typename multiplicity_map::iterator invar_map_iter; + + if(first == last) + return invar_multiplicity; + + invar_iter it = std::move(first); - typedef typename std::vector< invariant_t >::const_iterator invar_iter; - typedef typename multiplicity_map::iterator invar_map_iter; - invar_iter it = invariants.begin(); - const invar_iter end = invariants.end(); + invariant_t invar = *it; + invar_map_iter inserted = invar_multiplicity.emplace(invar, 1).first; + ++it; + for(; it != last; ++it) + { + if(*it == invar) + { + inserted->second += 1; + } + else + { + invar = *it; + inserted = invar_multiplicity.emplace(invar, 1).first; + } + } - if(it == end) { return invar_multiplicity; - } - - invariant_t invar = *it; - invar_map_iter inserted = invar_multiplicity.emplace(invar, 1).first; - ++it; - for(; it != end; ++it) - { - if(*it == invar) - { - inserted->second += 1; - } - else - { - invar = *it; - inserted = invar_multiplicity.emplace(invar, 1).first; - } - } - - return invar_multiplicity; } bool test_isomorphism() @@ -234,7 +235,7 @@ namespace detail std::vector< vertex1_t > V_mult; BGL_FORALL_VERTICES_T(v, G1, Graph1) V_mult.push_back(v); - sort(V_mult, compare_multiplicity(invariant1, multiplicities(invar1_array))); + sort(V_mult, compare_multiplicity(invariant1, multiplicities(invar1_array.begin(), invar1_array.end()))); std::vector< default_color_type > color_vec(num_vertices(G1)); safe_iterator_property_map< From 2f5a3c2ccc28b2da4c0a7ddbe49239324c4635fc Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Tue, 19 Sep 2023 11:03:53 +0200 Subject: [PATCH 05/10] Clean up bracket style --- include/boost/graph/isomorphism.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index ef88961ce..fb3853664 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -474,13 +474,15 @@ namespace detail } } - if(!unmatched_g1_vertices.empty()) { + if(!unmatched_g1_vertices.empty()) + { typedef unordered_multimap< invariant_t, vertex2_t > g2_invariant_vertex_multimap; typedef typename g2_invariant_vertex_multimap::iterator multimap_iter; g2_invariant_vertex_multimap unmatched_invariants; BGL_FORALL_VERTICES_T(v, G2, Graph2) { - if(!in_S[v]) { + if(!in_S[v]) + { unmatched_invariants.emplace(invariant2(v), v); } } From 2c36c0f8199a10b8223f9d46262d595fee645569 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Tue, 19 Sep 2023 17:17:57 +0200 Subject: [PATCH 06/10] Replace is_detected_v w/ is_detected<...>::value --- include/boost/graph/isomorphism.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index fb3853664..9fd5c4d01 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -39,7 +39,7 @@ namespace detail using TestHashable = decltype(hash()(std::declval())); template < typename T > - struct Hashable: std::integral_constant> {}; + struct Hashable: std::integral_constant::value> {}; template < typename T > struct Invariant: std::integral_constant::value && boost::has_less::value && boost::has_equal_to::value> {}; From b9fbc47bbb2f7afaf39058da8726a0e7da33b243 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Wed, 20 Sep 2023 11:54:51 +0200 Subject: [PATCH 07/10] Remove C++20 reserved keyword namespace (concept) --- include/boost/graph/isomorphism.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 9fd5c4d01..e29fb7f2b 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -33,17 +33,14 @@ namespace boost namespace detail { - namespace concept - { - template < typename T > - using TestHashable = decltype(hash()(std::declval())); + template < typename T > + using TestHashable = decltype(hash()(std::declval())); - template < typename T > - struct Hashable: std::integral_constant::value> {}; + template < typename T > + struct Hashable: std::integral_constant::value> {}; - template < typename T > - struct Invariant: std::integral_constant::value && boost::has_less::value && boost::has_equal_to::value> {}; - } + template < typename T > + struct Invariant: std::integral_constant::value && boost::has_less::value && boost::has_equal_to::value> {}; template < typename Graph1, typename Graph2, typename IsoMapping, typename Invariant1, typename Invariant2, typename IndexMap1, @@ -590,7 +587,7 @@ bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f, typedef typename Invariant2::result_type invariant2_t; BOOST_STATIC_ASSERT(is_same::value); - BOOST_STATIC_ASSERT(detail::concept::Invariant::value); + BOOST_STATIC_ASSERT(detail::Invariant::value); // Vertex invariant requirement BOOST_CONCEPT_ASSERT( From 71cea99db348f173c6db80a026e83c92efdb9c26 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Thu, 21 Sep 2023 10:38:53 +0200 Subject: [PATCH 08/10] Remove Invariant concept checking --- include/boost/graph/isomorphism.hpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index e29fb7f2b..31da0a663 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -18,9 +18,6 @@ #include #include // for make_indirect_pmap #include -#include -#include -#include #ifndef BOOST_GRAPH_ITERATION_MACROS_HPP #define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file @@ -33,15 +30,6 @@ namespace boost namespace detail { - template < typename T > - using TestHashable = decltype(hash()(std::declval())); - - template < typename T > - struct Hashable: std::integral_constant::value> {}; - - template < typename T > - struct Invariant: std::integral_constant::value && boost::has_less::value && boost::has_equal_to::value> {}; - template < typename Graph1, typename Graph2, typename IsoMapping, typename Invariant1, typename Invariant2, typename IndexMap1, typename IndexMap2 > @@ -587,7 +575,6 @@ bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f, typedef typename Invariant2::result_type invariant2_t; BOOST_STATIC_ASSERT(is_same::value); - BOOST_STATIC_ASSERT(detail::Invariant::value); // Vertex invariant requirement BOOST_CONCEPT_ASSERT( From 2e7d74b1a0f93d73975b5488e96486766d11ac32 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Thu, 21 Sep 2023 10:39:22 +0200 Subject: [PATCH 09/10] Remove iterator rename in multiplicities --- include/boost/graph/isomorphism.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index 31da0a663..e4e7c13f2 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -165,29 +165,26 @@ namespace detail template multiplicity_map multiplicities(ForwardIterator first, const ForwardIterator last) { + typedef typename multiplicity_map::iterator invar_map_iter; + assert(std::is_sorted(first, last)); multiplicity_map invar_multiplicity; - typedef typename std::vector< invariant_t >::const_iterator invar_iter; - typedef typename multiplicity_map::iterator invar_map_iter; - if(first == last) return invar_multiplicity; - - invar_iter it = std::move(first); - invariant_t invar = *it; + invariant_t invar = *first; invar_map_iter inserted = invar_multiplicity.emplace(invar, 1).first; - ++it; - for(; it != last; ++it) + ++first; + for(; first != last; ++first) { - if(*it == invar) + if(*first == invar) { inserted->second += 1; } else { - invar = *it; + invar = *first; inserted = invar_multiplicity.emplace(invar, 1).first; } } From 044c7d65a54a6af5f3a59f60283f6028787ca758 Mon Sep 17 00:00:00 2001 From: Jan-Grimo Sobez Date: Fri, 12 Apr 2024 07:45:36 +0200 Subject: [PATCH 10/10] Use unordered_flat_map, parameterize invariant map --- include/boost/graph/isomorphism.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp index e4e7c13f2..5a7d31ddc 100644 --- a/include/boost/graph/isomorphism.hpp +++ b/include/boost/graph/isomorphism.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include // for make_indirect_pmap #include @@ -32,7 +33,7 @@ namespace detail template < typename Graph1, typename Graph2, typename IsoMapping, typename Invariant1, typename Invariant2, typename IndexMap1, - typename IndexMap2 > + typename IndexMap2, typename InvariantCountMap = boost::unordered_flat_map::vertices_size_type > > class isomorphism_algo { typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_t; @@ -40,7 +41,6 @@ namespace detail typedef typename graph_traits< Graph1 >::edge_descriptor edge1_t; typedef typename graph_traits< Graph1 >::vertices_size_type size_type; typedef typename Invariant1::result_type invariant_t; - typedef unordered_map< invariant_t, size_type > multiplicity_map; const Graph1& G1; const Graph2& G2; @@ -81,7 +81,7 @@ namespace detail friend struct compare_multiplicity; struct compare_multiplicity { - compare_multiplicity(Invariant1 invariant1, const multiplicity_map& multiplicity) + compare_multiplicity(Invariant1 invariant1, const InvariantCountMap& multiplicity) : invariant1(invariant1), multiplicity(&multiplicity) { } @@ -94,7 +94,7 @@ namespace detail return *x_multiplicity_iter < *y_multiplicity_iter; } Invariant1 invariant1; - const multiplicity_map* multiplicity; + const InvariantCountMap* multiplicity; }; struct record_dfs_order : default_dfs_visitor @@ -163,12 +163,12 @@ namespace detail // Generates map of invariant multiplicity from sorted invariants template - multiplicity_map multiplicities(ForwardIterator first, const ForwardIterator last) + InvariantCountMap multiplicities(ForwardIterator first, const ForwardIterator last) { - typedef typename multiplicity_map::iterator invar_map_iter; + typedef typename InvariantCountMap::iterator invar_map_iter; assert(std::is_sorted(first, last)); - multiplicity_map invar_multiplicity; + InvariantCountMap invar_multiplicity; if(first == last) return invar_multiplicity;