Ticket #8166: vf2_subgraph_mono.patch

File vf2_subgraph_mono.patch, 20.6 KB (added by Jakob Lykke Andersen <jlandersen@…>, 10 years ago)
  • boost/graph/vf2_sub_graph_iso.hpp

     
    372372    };
    373373
    374374
    375     enum problem_selector { subgraph_iso, isomorphism };
     375    enum problem_selector {subgraph_mono, subgraph_iso, isomorphism };
    376376   
    377377    // The actual state associated with both graphs
    378378    template<typename Graph1,
     
    405405      base_state<Graph1, Graph2, IndexMap1, IndexMap2> state1_;
    406406      base_state<Graph2, Graph1, IndexMap2, IndexMap1> state2_;
    407407
    408       // Two helper functions used in Feasibility and Valid functions to test
     408      // Three helper functions used in Feasibility and Valid functions to test
    409409      // terminal set counts when testing for:
     410          // - graph sub-graph monomorphism, or
     411      inline bool comp_term_sets(graph1_size_type a,
     412                                 graph2_size_type b,
     413                                 boost::mpl::int_<subgraph_mono>) const {
     414        return a <= b;
     415      }
     416         
    410417      // - graph sub-graph isomorphism, or
    411418      inline bool comp_term_sets(graph1_size_type a,
    412419                                 graph2_size_type b,
     
    519526          BGL_FORALL_INEDGES_T(w_new, e2, graph2_, Graph2) {
    520527            vertex2_type w = source(e2, graph2_);
    521528            if (state2_.in_core(w) || (w == w_new)) {
    522               vertex1_type v = v_new;
    523               if (w != w_new)
    524                 v = state2_.core(w);
     529              if (problem_selection != subgraph_mono) {
     530                vertex1_type v = v_new;
     531                if (w != w_new)
     532                  v = state2_.core(w);
    525533             
    526               if (!edge1_exists(v, v_new,
    527                                 edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
    528                                 graph1_))
    529                 return false;
    530              
     534                if (!edge1_exists(v, v_new,
     535                                  edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
     536                                  graph1_))
     537                  return false;
     538              }
    531539            } else {
    532540              if (0 < state2_.in_depth(w))
    533541                ++term_in2_count;
     
    545553          BGL_FORALL_OUTEDGES_T(w_new, e2, graph2_, Graph2) {
    546554            vertex2_type w = target(e2, graph2_);
    547555            if (state2_.in_core(w) || (w == w_new)) {
    548               vertex1_type v = v_new;
    549               if (w != w_new)
    550                 v = state2_.core(w);
     556              if (problem_selection != subgraph_mono) {
     557                vertex1_type v = v_new;
     558                if (w != w_new)
     559                  v = state2_.core(w);
    551560             
    552               if (!edge1_exists(v_new, v,
    553                                 edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
    554                                 graph1_))
    555                 return false;
    556              
     561                if (!edge1_exists(v_new, v,
     562                                  edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
     563                                  graph1_))
     564                  return false;
     565              }
    557566            } else {
    558567              if (0 < state2_.in_depth(w))
    559568                ++term_in2_count;
     
    564573            }
    565574          }
    566575        }
    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        }
    574593      }
    575594     
    576595      // Returns true if vertex v in graph1 is a possible candidate to
     
    790809
    791810    }
    792811
     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       
    793897  } // namespace detail
    794898
    795899
     
    805909    return vertex_order;
    806910  }
    807911
     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  }
    808977 
     978 
    809979  // Enumerates all graph sub-graph isomorphism mappings between graphs
    810980  // graph_small and graph_large. Continues until user_callback returns true or the
    811981  // search space has been fully explored.
     
    823993                        const VertexOrderSmall& vertex_order_small,
    824994                        EdgeEquivalencePredicate edge_comp,
    825995                        VertexEquivalencePredicate vertex_comp) {
    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);
    8911003  }
    8921004
    8931005
  • libs/graph/doc/vf2_sub_graph_iso.html

     
    8787      graph that preserves the edge structure of the graphs. <em>M</em> is said to be a
    8888      graph-subgraph isomorphism if and only if <em>M</em> is an isomorphism between
    8989      <em>G<sub>1</sub></em> and a subgraph of <em>G<sub>2</sub></em>.
     90      An induced subgraph of a graph <em>G = (V, E)<em> is a normal subgraph
     91      <em>G' = (V', E')</em> with the extra condition that all edges of <em>G</em>
     92      which have both endpoints in <em>V'</em> are in <em>E'</em>.
    9093    </p>
    9194   
    9295    <p>
    93       This function finds all graph-subgraph isomorphism mappings between
     96      This function finds all induced subgraph isomorphisms between
    9497      graphs <tt>graph_small</tt> and <tt>graph_large</tt> and outputs them to
    9598      <tt>user_callback</tt>. It continues until <tt>user_callback</tt>
    96       returns true or the search space has been fully explored. <tt>vf2_subgraph_iso</tt>
     99      returns false or the search space has been fully explored. <tt>vf2_subgraph_iso</tt>
    97100      returns true if a graph-subgraph isomorphism exists and false otherwise.
    98101      <tt>EdgeEquivalencePredicate</tt> and
    99102      <tt>VertexEquivalencePredicate</tt> predicates are used to test whether
     
    182185        and <tt>CorresondenceMap2To1</tt> types are models
    183186        of <a href="../../property_map/doc/ReadablePropertyMap.html">Readable
    184187          Property Map</a> and map equivalent vertices across the two
    185         graphs given to <tt>vf2_subgraph_iso</tt> (or <tt>vf2_graph_iso</tt>). For
    186         instance, if <tt>v</tt> is
     188        graphs given to <tt>vf2_subgraph_iso</tt> (or <tt>vf2_graph_iso</tt> or
     189        <tt>vf2_subgraph_mono</tt>). For instance, if <tt>v</tt> is
    187190        from <tt>graph_small</tt>, <tt>w</tt> is from <tt>graph_large</tt>,
    188191        and the vertices can be considered equivalent,
    189192        then <tt>get(f, v)</tt> will be <tt>w</tt> and <tt>get(g, w)</tt>
     
    279282      function
    280283    </p>
    281284    <p><tt>vf2_graph_iso(...)</tt></p>
     285    <p><tt>vf2_subgraph_mono(...)</tt></p>
    282286    <p>
    283       for isomorphism testing take the same parameters as the corresponding
    284       functions <tt>vf2_subgraph_iso</tt> for subgraph isomorphism testing.
    285       The algorithm finds all isomorphism mappings between graphs
    286       <tt>graph1</tt> and <tt>graph2</tt> and outputs them to
    287       <tt>user_callback</tt>. It continues until <tt>user_callback</tt>
    288       returns true or the search space has been fully explored. As before,
     287      for isomorphism and (not necessarily induced) subgraph isomorphism testing,
     288      taking the same parameters as the corresponding functions <tt>vf2_subgraph_iso</tt>
     289      for induced subgraph isomorphism testing.
     290      For <tt>vf2_graph_iso</tt> the algorithm finds all isomorphism mappings between
     291      graphs <tt>graph1</tt> and <tt>graph2</tt> and outputs them to
     292      <tt>user_callback</tt>.
     293      For <tt>vf2_graph_mono</tt> the algorithm finds all mappings of <tt>graph_small</tt>
     294      to subgraphs of <tt>graph_large</tt>.
     295      Note that, as opposed to <tt>vf2_subgraph_iso</tt>,
     296      these subgraphs need not to be induced subgraphs.
     297    </p>
     298    <p>
     299      Both algorithms continues until <tt>user_callback</tt>
     300      returns false or the search space has been fully explored. As before,
    289301      <tt>EdgeEquivalencePredicate</tt> and
    290302      <tt>VertexEquivalencePredicate</tt> predicates are used to test
    291303      whether edges and vertices are equivalent. By default