| 567 | | |
| 568 | | return comp_term_sets(term_in1_count, term_in2_count, |
| 569 | | boost::mpl::int_<problem_selection>()) && |
| 570 | | comp_term_sets(term_out1_count, term_out2_count, |
| 571 | | boost::mpl::int_<problem_selection>()) && |
| 572 | | comp_term_sets(rest1_count, rest2_count, |
| 573 | | boost::mpl::int_<problem_selection>()); |
| | 576 | |
| | 577 | if (problem_selection != subgraph_mono) { |
| | 578 | return comp_term_sets(term_in1_count, term_in2_count, |
| | 579 | boost::mpl::int_<problem_selection>()) && |
| | 580 | comp_term_sets(term_out1_count, term_out2_count, |
| | 581 | boost::mpl::int_<problem_selection>()) && |
| | 582 | comp_term_sets(rest1_count, rest2_count, |
| | 583 | boost::mpl::int_<problem_selection>()); |
| | 584 | } else { // subgraph_iso and isomorphism |
| | 585 | return comp_term_sets(term_in1_count, term_in2_count, |
| | 586 | boost::mpl::int_<problem_selection>()) && |
| | 587 | comp_term_sets(term_out1_count, term_out2_count, |
| | 588 | boost::mpl::int_<problem_selection>()) && |
| | 589 | comp_term_sets(term_in1_count + term_out1_count + rest1_count, |
| | 590 | term_in2_count + term_out2_count + rest2_count, |
| | 591 | boost::mpl::int_<problem_selection>()); |
| | 592 | } |
| | 812 | // Enumerates all graph sub-graph mono-/iso-morphism mappings between graphs |
| | 813 | // graph_small and graph_large. Continues until user_callback returns true or the |
| | 814 | // search space has been fully explored. |
| | 815 | template <problem_selector problem_selection, |
| | 816 | typename GraphSmall, |
| | 817 | typename GraphLarge, |
| | 818 | typename IndexMapSmall, |
| | 819 | typename IndexMapLarge, |
| | 820 | typename VertexOrderSmall, |
| | 821 | typename EdgeEquivalencePredicate, |
| | 822 | typename VertexEquivalencePredicate, |
| | 823 | typename SubGraphIsoMapCallback> |
| | 824 | bool vf2_subgraph_morphism(const GraphSmall& graph_small, const GraphLarge& graph_large, |
| | 825 | SubGraphIsoMapCallback user_callback, |
| | 826 | IndexMapSmall index_map_small, IndexMapLarge index_map_large, |
| | 827 | const VertexOrderSmall& vertex_order_small, |
| | 828 | EdgeEquivalencePredicate edge_comp, |
| | 829 | VertexEquivalencePredicate vertex_comp) { |
| | 830 | |
| | 831 | // Graph requirements |
| | 832 | BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<GraphSmall> )); |
| | 833 | BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<GraphSmall> )); |
| | 834 | BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<GraphSmall> )); |
| | 835 | BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<GraphSmall> )); |
| | 836 | |
| | 837 | BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<GraphLarge> )); |
| | 838 | BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<GraphLarge> )); |
| | 839 | BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<GraphLarge> )); |
| | 840 | BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<GraphLarge> )); |
| | 841 | |
| | 842 | typedef typename graph_traits<GraphSmall>::vertex_descriptor vertex_small_type; |
| | 843 | typedef typename graph_traits<GraphLarge>::vertex_descriptor vertex_large_type; |
| | 844 | |
| | 845 | typedef typename graph_traits<GraphSmall>::vertices_size_type size_type_small; |
| | 846 | typedef typename graph_traits<GraphLarge>::vertices_size_type size_type_large; |
| | 847 | |
| | 848 | // Property map requirements |
| | 849 | BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMapSmall, vertex_small_type> )); |
| | 850 | typedef typename property_traits<IndexMapSmall>::value_type IndexMapSmallValue; |
| | 851 | BOOST_STATIC_ASSERT(( is_convertible<IndexMapSmallValue, size_type_small>::value )); |
| | 852 | |
| | 853 | BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMapLarge, vertex_large_type> )); |
| | 854 | typedef typename property_traits<IndexMapLarge>::value_type IndexMapLargeValue; |
| | 855 | BOOST_STATIC_ASSERT(( is_convertible<IndexMapLargeValue, size_type_large>::value )); |
| | 856 | |
| | 857 | // Edge & vertex requirements |
| | 858 | typedef typename graph_traits<GraphSmall>::edge_descriptor edge_small_type; |
| | 859 | typedef typename graph_traits<GraphLarge>::edge_descriptor edge_large_type; |
| | 860 | |
| | 861 | BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept<EdgeEquivalencePredicate, |
| | 862 | edge_small_type, edge_large_type> )); |
| | 863 | |
| | 864 | BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept<VertexEquivalencePredicate, |
| | 865 | vertex_small_type, vertex_large_type> )); |
| | 866 | |
| | 867 | // Vertex order requirements |
| | 868 | BOOST_CONCEPT_ASSERT(( ContainerConcept<VertexOrderSmall> )); |
| | 869 | typedef typename VertexOrderSmall::value_type order_value_type; |
| | 870 | BOOST_STATIC_ASSERT(( is_same<vertex_small_type, order_value_type>::value )); |
| | 871 | BOOST_ASSERT( num_vertices(graph_small) == vertex_order_small.size() ); |
| | 872 | |
| | 873 | if (num_vertices(graph_small) > num_vertices(graph_large)) |
| | 874 | return false; |
| | 875 | |
| | 876 | typename graph_traits<GraphSmall>::edges_size_type num_edges_small = num_edges(graph_small); |
| | 877 | typename graph_traits<GraphLarge>::edges_size_type num_edges_large = num_edges(graph_large); |
| | 878 | |
| | 879 | // Double the number of edges for undirected graphs: each edge counts as |
| | 880 | // in-edge and out-edge |
| | 881 | if (is_undirected(graph_small)) num_edges_small *= 2; |
| | 882 | if (is_undirected(graph_large)) num_edges_large *= 2; |
| | 883 | if (num_edges_small > num_edges_large) |
| | 884 | return false; |
| | 885 | |
| | 886 | if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0)) |
| | 887 | return true; |
| | 888 | |
| | 889 | detail::state<GraphSmall, GraphLarge, IndexMapSmall, IndexMapLarge, |
| | 890 | EdgeEquivalencePredicate, VertexEquivalencePredicate, |
| | 891 | SubGraphIsoMapCallback, problem_selection> |
| | 892 | s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp); |
| | 893 | |
| | 894 | return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s); |
| | 895 | } |
| | 896 | |
| | 912 | |
| | 913 | // Enumerates all graph sub-graph monomorphism mappings between graphs |
| | 914 | // graph_small and graph_large. Continues until user_callback returns true or the |
| | 915 | // search space has been fully explored. |
| | 916 | template <typename GraphSmall, |
| | 917 | typename GraphLarge, |
| | 918 | typename IndexMapSmall, |
| | 919 | typename IndexMapLarge, |
| | 920 | typename VertexOrderSmall, |
| | 921 | typename EdgeEquivalencePredicate, |
| | 922 | typename VertexEquivalencePredicate, |
| | 923 | typename SubGraphIsoMapCallback> |
| | 924 | bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large, |
| | 925 | SubGraphIsoMapCallback user_callback, |
| | 926 | IndexMapSmall index_map_small, IndexMapLarge index_map_large, |
| | 927 | const VertexOrderSmall& vertex_order_small, |
| | 928 | EdgeEquivalencePredicate edge_comp, |
| | 929 | VertexEquivalencePredicate vertex_comp) { |
| | 930 | return detail::vf2_subgraph_morphism<detail::subgraph_mono> |
| | 931 | (graph_small, graph_large, |
| | 932 | user_callback, |
| | 933 | index_map_small, index_map_large, |
| | 934 | vertex_order_small, |
| | 935 | edge_comp, |
| | 936 | vertex_comp); |
| | 937 | } |
| | 938 | |
| | 939 | |
| | 940 | // All default interface for vf2_subgraph_iso |
| | 941 | template <typename GraphSmall, |
| | 942 | typename GraphLarge, |
| | 943 | typename SubGraphIsoMapCallback> |
| | 944 | bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large, |
| | 945 | SubGraphIsoMapCallback user_callback) { |
| | 946 | return vf2_subgraph_mono(graph_small, graph_large, user_callback, |
| | 947 | get(vertex_index, graph_small), get(vertex_index, graph_large), |
| | 948 | vertex_order_by_mult(graph_small), |
| | 949 | always_equivalent(), always_equivalent()); |
| | 950 | } |
| | 951 | |
| | 952 | |
| | 953 | // Named parameter interface of vf2_subgraph_iso |
| | 954 | template <typename GraphSmall, |
| | 955 | typename GraphLarge, |
| | 956 | typename VertexOrderSmall, |
| | 957 | typename SubGraphIsoMapCallback, |
| | 958 | typename Param, |
| | 959 | typename Tag, |
| | 960 | typename Rest> |
| | 961 | bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large, |
| | 962 | SubGraphIsoMapCallback user_callback, |
| | 963 | const VertexOrderSmall& vertex_order_small, |
| | 964 | const bgl_named_params<Param, Tag, Rest>& params) { |
| | 965 | return vf2_subgraph_mono(graph_small, graph_large, user_callback, |
| | 966 | choose_const_pmap(get_param(params, vertex_index1), |
| | 967 | graph_small, vertex_index), |
| | 968 | choose_const_pmap(get_param(params, vertex_index2), |
| | 969 | graph_large, vertex_index), |
| | 970 | vertex_order_small, |
| | 971 | choose_param(get_param(params, edges_equivalent_t()), |
| | 972 | always_equivalent()), |
| | 973 | choose_param(get_param(params, vertices_equivalent_t()), |
| | 974 | always_equivalent()) |
| | 975 | ); |
| | 976 | } |
| 826 | | |
| 827 | | // Graph requirements |
| 828 | | BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<GraphSmall> )); |
| 829 | | BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<GraphSmall> )); |
| 830 | | BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<GraphSmall> )); |
| 831 | | BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<GraphSmall> )); |
| 832 | | |
| 833 | | BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<GraphLarge> )); |
| 834 | | BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<GraphLarge> )); |
| 835 | | BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<GraphLarge> )); |
| 836 | | BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<GraphLarge> )); |
| 837 | | |
| 838 | | typedef typename graph_traits<GraphSmall>::vertex_descriptor vertex_small_type; |
| 839 | | typedef typename graph_traits<GraphLarge>::vertex_descriptor vertex_large_type; |
| 840 | | |
| 841 | | typedef typename graph_traits<GraphSmall>::vertices_size_type size_type_small; |
| 842 | | typedef typename graph_traits<GraphLarge>::vertices_size_type size_type_large; |
| 843 | | |
| 844 | | // Property map requirements |
| 845 | | BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMapSmall, vertex_small_type> )); |
| 846 | | typedef typename property_traits<IndexMapSmall>::value_type IndexMapSmallValue; |
| 847 | | BOOST_STATIC_ASSERT(( is_convertible<IndexMapSmallValue, size_type_small>::value )); |
| 848 | | |
| 849 | | BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMapLarge, vertex_large_type> )); |
| 850 | | typedef typename property_traits<IndexMapLarge>::value_type IndexMapLargeValue; |
| 851 | | BOOST_STATIC_ASSERT(( is_convertible<IndexMapLargeValue, size_type_large>::value )); |
| 852 | | |
| 853 | | // Edge & vertex requirements |
| 854 | | typedef typename graph_traits<GraphSmall>::edge_descriptor edge_small_type; |
| 855 | | typedef typename graph_traits<GraphLarge>::edge_descriptor edge_large_type; |
| 856 | | |
| 857 | | BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept<EdgeEquivalencePredicate, |
| 858 | | edge_small_type, edge_large_type> )); |
| 859 | | |
| 860 | | BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept<VertexEquivalencePredicate, |
| 861 | | vertex_small_type, vertex_large_type> )); |
| 862 | | |
| 863 | | // Vertex order requirements |
| 864 | | BOOST_CONCEPT_ASSERT(( ContainerConcept<VertexOrderSmall> )); |
| 865 | | typedef typename VertexOrderSmall::value_type order_value_type; |
| 866 | | BOOST_STATIC_ASSERT(( is_same<vertex_small_type, order_value_type>::value )); |
| 867 | | BOOST_ASSERT( num_vertices(graph_small) == vertex_order_small.size() ); |
| 868 | | |
| 869 | | if (num_vertices(graph_small) > num_vertices(graph_large)) |
| 870 | | return false; |
| 871 | | |
| 872 | | typename graph_traits<GraphSmall>::edges_size_type num_edges_small = num_edges(graph_small); |
| 873 | | typename graph_traits<GraphLarge>::edges_size_type num_edges_large = num_edges(graph_large); |
| 874 | | |
| 875 | | // Double the number of edges for undirected graphs: each edge counts as |
| 876 | | // in-edge and out-edge |
| 877 | | if (is_undirected(graph_small)) num_edges_small *= 2; |
| 878 | | if (is_undirected(graph_large)) num_edges_large *= 2; |
| 879 | | if (num_edges_small > num_edges_large) |
| 880 | | return false; |
| 881 | | |
| 882 | | if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0)) |
| 883 | | return true; |
| 884 | | |
| 885 | | detail::state<GraphSmall, GraphLarge, IndexMapSmall, IndexMapLarge, |
| 886 | | EdgeEquivalencePredicate, VertexEquivalencePredicate, |
| 887 | | SubGraphIsoMapCallback, detail::subgraph_iso> |
| 888 | | s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp); |
| 889 | | |
| 890 | | return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s); |
| | 996 | return detail::vf2_subgraph_morphism<detail::subgraph_iso> |
| | 997 | (graph_small, graph_large, |
| | 998 | user_callback, |
| | 999 | index_map_small, index_map_large, |
| | 1000 | vertex_order_small, |
| | 1001 | edge_comp, |
| | 1002 | vertex_comp); |