Ticket #8166: vf2_subgraph_mono.2.patch

File vf2_subgraph_mono.2.patch, 21.5 KB (added by Jakob Lykke Andersen <jlandersen@…>, 10 years ago)

Updated patch

  • boost/graph/vf2_sub_graph_iso.hpp

     
    11//=======================================================================
    22// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com)
     3// Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark (jlandersen@imada.sdu.dk)
    34//
    45// The algorithm implemented here is derived from original ideas by
    56// Pasquale Foggia and colaborators. For further information see
     
    372373    };
    373374
    374375
    375     enum problem_selector { subgraph_iso, isomorphism };
     376    enum problem_selector {subgraph_mono, subgraph_iso, isomorphism };
    376377   
    377378    // The actual state associated with both graphs
    378379    template<typename Graph1,
     
    405406      base_state<Graph1, Graph2, IndexMap1, IndexMap2> state1_;
    406407      base_state<Graph2, Graph1, IndexMap2, IndexMap1> state2_;
    407408
    408       // Two helper functions used in Feasibility and Valid functions to test
     409      // Three helper functions used in Feasibility and Valid functions to test
    409410      // terminal set counts when testing for:
     411          // - graph sub-graph monomorphism, or
     412      inline bool comp_term_sets(graph1_size_type a,
     413                                 graph2_size_type b,
     414                                 boost::mpl::int_<subgraph_mono>) const {
     415        return a <= b;
     416      }
     417         
    410418      // - graph sub-graph isomorphism, or
    411419      inline bool comp_term_sets(graph1_size_type a,
    412420                                 graph2_size_type b,
     
    519527          BGL_FORALL_INEDGES_T(w_new, e2, graph2_, Graph2) {
    520528            vertex2_type w = source(e2, graph2_);
    521529            if (state2_.in_core(w) || (w == w_new)) {
    522               vertex1_type v = v_new;
    523               if (w != w_new)
    524                 v = state2_.core(w);
     530              if (problem_selection != subgraph_mono) {
     531                vertex1_type v = v_new;
     532                if (w != w_new)
     533                  v = state2_.core(w);
    525534             
    526               if (!edge1_exists(v, v_new,
    527                                 edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
    528                                 graph1_))
    529                 return false;
    530              
     535                if (!edge1_exists(v, v_new,
     536                                  edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
     537                                  graph1_))
     538                  return false;
     539              }
    531540            } else {
    532541              if (0 < state2_.in_depth(w))
    533542                ++term_in2_count;
     
    545554          BGL_FORALL_OUTEDGES_T(w_new, e2, graph2_, Graph2) {
    546555            vertex2_type w = target(e2, graph2_);
    547556            if (state2_.in_core(w) || (w == w_new)) {
    548               vertex1_type v = v_new;
    549               if (w != w_new)
    550                 v = state2_.core(w);
     557              if (problem_selection != subgraph_mono) {
     558                vertex1_type v = v_new;
     559                if (w != w_new)
     560                  v = state2_.core(w);
    551561             
    552               if (!edge1_exists(v_new, v,
    553                                 edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
    554                                 graph1_))
    555                 return false;
    556              
     562                if (!edge1_exists(v_new, v,
     563                                  edge1_predicate<Graph1, Graph2, EdgeEquivalencePredicate>(edge_comp_, e2),
     564                                  graph1_))
     565                  return false;
     566              }
    557567            } else {
    558568              if (0 < state2_.in_depth(w))
    559569                ++term_in2_count;
     
    564574            }
    565575          }
    566576        }
    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>());
     577               
     578        if (problem_selection != subgraph_mono) { // subgraph_iso and isomorphism
     579          return comp_term_sets(term_in1_count, term_in2_count,
     580                                boost::mpl::int_<problem_selection>()) &&
     581                 comp_term_sets(term_out1_count, term_out2_count,
     582                                boost::mpl::int_<problem_selection>()) &&
     583                 comp_term_sets(rest1_count, rest2_count,
     584                                boost::mpl::int_<problem_selection>());
     585        } else { // subgraph_mono
     586          return comp_term_sets(term_in1_count, term_in2_count,
     587                                boost::mpl::int_<problem_selection>()) &&
     588                 comp_term_sets(term_out1_count, term_out2_count,
     589                                boost::mpl::int_<problem_selection>()) &&
     590                 comp_term_sets(term_in1_count + term_out1_count + rest1_count,
     591                                term_in2_count + term_out2_count + rest2_count,
     592                                boost::mpl::int_<problem_selection>());
     593        }
    574594      }
    575595     
    576596      // Returns true if vertex v in graph1 is a possible candidate to
     
    790810
    791811    }
    792812
     813    // Enumerates all graph sub-graph mono-/iso-morphism mappings between graphs
     814    // graph_small and graph_large. Continues until user_callback returns true or the
     815    // search space has been fully explored.
     816    template <problem_selector problem_selection,
     817              typename GraphSmall,
     818              typename GraphLarge,
     819              typename IndexMapSmall,
     820              typename IndexMapLarge,
     821              typename VertexOrderSmall,
     822              typename EdgeEquivalencePredicate,
     823              typename VertexEquivalencePredicate,
     824              typename SubGraphIsoMapCallback>
     825    bool vf2_subgraph_morphism(const GraphSmall& graph_small, const GraphLarge& graph_large,
     826                          SubGraphIsoMapCallback user_callback,
     827                          IndexMapSmall index_map_small, IndexMapLarge index_map_large,
     828                          const VertexOrderSmall& vertex_order_small,
     829                          EdgeEquivalencePredicate edge_comp,
     830                          VertexEquivalencePredicate vertex_comp) {
     831
     832      // Graph requirements
     833      BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<GraphSmall> ));
     834      BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<GraphSmall> ));
     835      BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<GraphSmall> ));
     836      BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<GraphSmall> ));
     837
     838      BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<GraphLarge> ));
     839      BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<GraphLarge> ));
     840      BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<GraphLarge> ));
     841      BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<GraphLarge> ));
     842
     843      typedef typename graph_traits<GraphSmall>::vertex_descriptor vertex_small_type;
     844      typedef typename graph_traits<GraphLarge>::vertex_descriptor vertex_large_type;
     845
     846      typedef typename graph_traits<GraphSmall>::vertices_size_type size_type_small;
     847      typedef typename graph_traits<GraphLarge>::vertices_size_type size_type_large;
     848       
     849      // Property map requirements
     850      BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMapSmall, vertex_small_type> ));
     851      typedef typename property_traits<IndexMapSmall>::value_type IndexMapSmallValue;
     852      BOOST_STATIC_ASSERT(( is_convertible<IndexMapSmallValue, size_type_small>::value ));
     853       
     854      BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMapLarge, vertex_large_type> ));
     855      typedef typename property_traits<IndexMapLarge>::value_type IndexMapLargeValue;
     856      BOOST_STATIC_ASSERT(( is_convertible<IndexMapLargeValue, size_type_large>::value ));
     857
     858      // Edge & vertex requirements
     859      typedef typename graph_traits<GraphSmall>::edge_descriptor edge_small_type;
     860      typedef typename graph_traits<GraphLarge>::edge_descriptor edge_large_type;
     861
     862      BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept<EdgeEquivalencePredicate,
     863                             edge_small_type, edge_large_type> ));
     864
     865      BOOST_CONCEPT_ASSERT(( BinaryPredicateConcept<VertexEquivalencePredicate,
     866                             vertex_small_type, vertex_large_type> ));
     867
     868      // Vertex order requirements
     869      BOOST_CONCEPT_ASSERT(( ContainerConcept<VertexOrderSmall> ));
     870      typedef typename VertexOrderSmall::value_type order_value_type;
     871      BOOST_STATIC_ASSERT(( is_same<vertex_small_type, order_value_type>::value ));
     872      BOOST_ASSERT( num_vertices(graph_small) == vertex_order_small.size() );
     873
     874      if (num_vertices(graph_small) > num_vertices(graph_large))
     875        return false;
     876
     877      typename graph_traits<GraphSmall>::edges_size_type num_edges_small = num_edges(graph_small);
     878      typename graph_traits<GraphLarge>::edges_size_type num_edges_large = num_edges(graph_large);
     879
     880      // Double the number of edges for undirected graphs: each edge counts as
     881      // in-edge and out-edge
     882      if (is_undirected(graph_small)) num_edges_small *= 2;
     883      if (is_undirected(graph_large)) num_edges_large *= 2;
     884      if (num_edges_small > num_edges_large)
     885        return false;
     886   
     887      if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0))
     888        return true;
     889
     890      detail::state<GraphSmall, GraphLarge, IndexMapSmall, IndexMapLarge,
     891                    EdgeEquivalencePredicate, VertexEquivalencePredicate,
     892                    SubGraphIsoMapCallback, problem_selection>
     893        s(graph_small, graph_large, index_map_small, index_map_large, edge_comp, vertex_comp);
     894
     895      return detail::match(graph_small, graph_large, user_callback, vertex_order_small, s);
     896    }
     897       
    793898  } // namespace detail
    794899
    795900
     
    805910    return vertex_order;
    806911  }
    807912
     913
     914  // Enumerates all graph sub-graph monomorphism mappings between graphs
     915  // graph_small and graph_large. Continues until user_callback returns true or the
     916  // search space has been fully explored.
     917  template <typename GraphSmall,
     918            typename GraphLarge,
     919            typename IndexMapSmall,
     920            typename IndexMapLarge,
     921            typename VertexOrderSmall,
     922            typename EdgeEquivalencePredicate,
     923            typename VertexEquivalencePredicate,
     924            typename SubGraphIsoMapCallback>
     925  bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large,
     926                         SubGraphIsoMapCallback user_callback,
     927                         IndexMapSmall index_map_small, IndexMapLarge index_map_large,
     928                         const VertexOrderSmall& vertex_order_small,
     929                         EdgeEquivalencePredicate edge_comp,
     930                         VertexEquivalencePredicate vertex_comp) {
     931    return detail::vf2_subgraph_morphism<detail::subgraph_mono>
     932                                        (graph_small, graph_large,
     933                                         user_callback,
     934                                         index_map_small, index_map_large,
     935                                         vertex_order_small,
     936                                         edge_comp,
     937                                         vertex_comp);
     938  }
     939
     940
     941  // All default interface for vf2_subgraph_iso
     942  template <typename GraphSmall,
     943            typename GraphLarge,
     944            typename SubGraphIsoMapCallback>
     945  bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large,
     946                         SubGraphIsoMapCallback user_callback) {
     947    return vf2_subgraph_mono(graph_small, graph_large, user_callback,
     948                             get(vertex_index, graph_small), get(vertex_index, graph_large),
     949                             vertex_order_by_mult(graph_small),
     950                             always_equivalent(), always_equivalent());
     951  }
     952
     953
     954  // Named parameter interface of vf2_subgraph_iso
     955  template <typename GraphSmall,
     956            typename GraphLarge,
     957            typename VertexOrderSmall,
     958            typename SubGraphIsoMapCallback,
     959            typename Param,
     960            typename Tag,
     961            typename Rest>
     962  bool vf2_subgraph_mono(const GraphSmall& graph_small, const GraphLarge& graph_large,
     963                         SubGraphIsoMapCallback user_callback,
     964                         const VertexOrderSmall& vertex_order_small,
     965                         const bgl_named_params<Param, Tag, Rest>& params) {
     966    return vf2_subgraph_mono(graph_small, graph_large, user_callback,
     967                             choose_const_pmap(get_param(params, vertex_index1),
     968                                               graph_small, vertex_index),
     969                             choose_const_pmap(get_param(params, vertex_index2),
     970                                               graph_large, vertex_index),
     971                             vertex_order_small,
     972                             choose_param(get_param(params, edges_equivalent_t()),
     973                                          always_equivalent()),
     974                             choose_param(get_param(params, vertices_equivalent_t()),
     975                                          always_equivalent())
     976                             );
     977  }
    808978 
     979 
    809980  // Enumerates all graph sub-graph isomorphism mappings between graphs
    810981  // graph_small and graph_large. Continues until user_callback returns true or the
    811982  // search space has been fully explored.
     
    823994                        const VertexOrderSmall& vertex_order_small,
    824995                        EdgeEquivalencePredicate edge_comp,
    825996                        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);
     997    return detail::vf2_subgraph_morphism<detail::subgraph_iso>
     998                                        (graph_small, graph_large,
     999                                         user_callback,
     1000                                         index_map_small, index_map_large,
     1001                                         vertex_order_small,
     1002                                         edge_comp,
     1003                                         vertex_comp);
    8911004  }
    8921005
    8931006
  • 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
     
    511523    <hr>
    512524    <p>
    513525      Copyright &copy; 2012, Flavio De Lorenzi
    514       (<a href="mailto:fdlorenzi@gmail.com">fdlorenzi@gmail.com</a>)
     526      (<a href="mailto:fdlorenzi@gmail.com">fdlorenzi@gmail.com</a>) <br />
     527      Copyright &copy; 2013, Jakob Lykke Andersen, University of Southern Denmark
     528      (<a href="mailto:jlandersen@imada.sdu.dk">jlandersen@imada.sdu.dk</a>)
    515529    </p>
    516530  </body>
    517531</html>