Ticket #9246: vf2_fixes.diff

File vf2_fixes.diff, 10.7 KB (added by Jakob Lykke Andersen <jlandersen@…>, 9 years ago)
  • boost/graph/vf2_sub_graph_iso.hpp

     
    690690   
    691691      typedef vf2_match_continuation<Graph1, Graph2, VertexOrder1> match_continuation_type;
    692692      std::vector<match_continuation_type> k;
     693      bool found_match = false;
    693694 
    694695      recur:
    695696      if (s.success()) {
     697        found_match = true;
    696698        if (!s.call_back(user_callback))
    697           return false;
     699          return found_match;
    698700
    699701        goto back_track;
    700702      }
     
    726728
    727729      back_track:
    728730      if (k.empty())
    729         return true;   
     731        return found_match;
    730732     
    731733      const match_continuation_type kk = k.back();
    732734      graph1_verts_iter = kk.graph1_verts_iter;
     
    887889      if (num_edges_small > num_edges_large)
    888890        return false;
    889891   
    890       if ((num_vertices(graph_small) == 0) && (num_vertices(graph_large) == 0))
     892      if (num_vertices(graph_small) == 0)
    891893        return true;
    892894
    893895      detail::state<GraphSmall, GraphLarge, IndexMapSmall, IndexMapLarge,
  • libs/graph/doc/vf2_sub_graph_iso.html

     
    9595    <p>
    9696      This function finds all induced subgraph isomorphisms between
    9797      graphs <tt>graph_small</tt> and <tt>graph_large</tt> and outputs them to
    98       <tt>user_callback</tt>. It continues until <tt>user_callback</tt>
     98      <tt>user_callback</tt> (except when <tt>graph_small</tt> is empty, see
     99      <a href="#notes">Notes</a>). It continues until <tt>user_callback</tt>
    99100      returns false or the search space has been fully explored. <tt>vf2_subgraph_iso</tt>
    100101      returns true if a graph-subgraph isomorphism exists and false otherwise.
    101102      <tt>EdgeEquivalencePredicate</tt> and
     
    294295      to subgraphs of <tt>graph_large</tt>.
    295296      Note that, as opposed to <tt>vf2_subgraph_iso</tt>,
    296297      these subgraphs need not to be induced subgraphs.
     298      See <a href="#notes">Notes</a> for information on the special case of empty graphs.
    297299    </p>
    298300    <p>
    299301      Both algorithms continues until <tt>user_callback</tt>
     
    495497      parallel edges, e.g. by using <tt>setS</tt>, the lookup function falls back
    496498      to <tt>edge()</tt> without performing any bookkeeping.
    497499    </p>
     500    <p>
     501      An empty graph is isomorphic to another empty graph, and thus <tt>vf2_graph_iso</tt>
     502      will return <tt>true</tt> in this case. Similarly, an empty graph is subgraph isomorphic
     503      to any other graph, so <tt>vf2_subgraph_iso</tt> and <tt>vf2_subgraph_mono</tt> will
     504      return <tt>true</tt> if <tt>graph_small</tt> is empty.
     505      However, the morphism will <em>not</em> be reported to <tt>user_callback</tt> in these cases.
     506    </p>
    498507
    499508    <h3>Bibliography</h3>
    500509
  • libs/graph/test/Jamfile.v2

     
    128128    [ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ]
    129129    [ compile filtered_graph_properties_dijkstra.cpp ]
    130130    [ run vf2_sub_graph_iso_test.cpp ]
     131    [ run vf2_sub_graph_iso_test_2.cpp ]
    131132    [ run hawick_circuits.cpp ]
    132133    [ run successive_shortest_path_nonnegative_weights_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
    133134    [ run cycle_canceling_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
  • libs/graph/test/vf2_sub_graph_iso_test_2.cpp

     
     1//=======================================================================
     2// Boost.Graph library vf2_sub_graph_iso test 2
     3// Test of return value and behaviour with empty graphs
     4//
     5// Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark (jlandersen@imada.sdu.dk)
     6//
     7// Distributed under the Boost Software License, Version 1.0. (See
     8// accompanying file LICENSE_1_0.txt or copy at
     9// http://www.boost.org/LICENSE_1_0.txt)
     10//=======================================================================
     11
     12#include <iostream>
     13#include <boost/test/minimal.hpp>
     14#include <boost/graph/adjacency_list.hpp>
     15#include <boost/graph/vf2_sub_graph_iso.hpp>
     16
     17struct test_callback {
     18  test_callback(bool &got_hit, bool stop) : got_hit(got_hit), stop(stop) { }
     19
     20  template<typename Map1To2, typename Map2To1>
     21  bool operator()(Map1To2 map1to2, Map2To1 map2to1) {
     22    got_hit = true;
     23    return stop;
     24  }
     25
     26  bool &got_hit;
     27  bool stop;
     28};
     29
     30struct false_predicate {
     31  template<typename VertexOrEdge1, typename VertexOrEdge2>
     32  bool operator()(VertexOrEdge1 ve1, VertexOrEdge2 ve2) const {
     33    return false;
     34  }
     35};
     36
     37void test_empty_graph_cases() {
     38  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS> Graph;
     39  typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
     40  typedef boost::graph_traits<Graph>::edge_descriptor Edge;
     41  Graph gEmpty, gLarge;
     42  add_vertex(gLarge);
     43
     44  { // isomorphism
     45    bool got_hit = false;
     46    test_callback callback(got_hit, true);
     47    bool exists = vf2_graph_iso(gEmpty, gEmpty, callback);
     48    BOOST_CHECK(exists);
     49    BOOST_CHECK(!got_hit); // only non-empty matches are reported
     50  }
     51  { // subgraph isomorphism (induced)
     52    { // empty vs. empty
     53      bool got_hit = false;
     54      test_callback callback(got_hit, true);
     55      bool exists = vf2_subgraph_iso(gEmpty, gEmpty, callback);
     56      BOOST_CHECK(exists);
     57      BOOST_CHECK(!got_hit); // only non-empty matches are reported
     58    }
     59    { // empty vs. non-empty
     60      bool got_hit = false;
     61      test_callback callback(got_hit, true);
     62      bool exists = vf2_subgraph_iso(gEmpty, gLarge, callback);
     63      BOOST_CHECK(exists);
     64      BOOST_CHECK(!got_hit); // only non-empty matches are reported
     65    }
     66  }
     67  { // subgraph monomorphism (non-induced subgraph isomorphism)
     68    { // empty vs. empty
     69      bool got_hit = false;
     70      test_callback callback(got_hit, true);
     71      bool exists = vf2_subgraph_mono(gEmpty, gEmpty, callback);
     72      BOOST_CHECK(exists);
     73      BOOST_CHECK(!got_hit); // only non-empty matches are reported
     74    }
     75    { // empty vs. non-empty
     76      bool got_hit = false;
     77      test_callback callback(got_hit, true);
     78      bool exists = vf2_subgraph_mono(gEmpty, gLarge, callback);
     79      BOOST_CHECK(exists);
     80      BOOST_CHECK(!got_hit); // only non-empty matches are reported
     81    }
     82  }
     83}
     84
     85void test_return_value() {
     86  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS> Graph;
     87  typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
     88  typedef boost::graph_traits<Graph>::edge_descriptor Edge;
     89  Graph gSmall, gLarge;
     90  add_vertex(gSmall);
     91  Vertex v1 = add_vertex(gLarge);
     92  Vertex v2 = add_vertex(gLarge);
     93  add_edge(v1, v2, gLarge);
     94
     95  { // isomorphism
     96    { // no morphism due to sizes
     97      bool got_hit = false;
     98      test_callback callback(got_hit, true);
     99      bool exists = vf2_graph_iso(gSmall, gLarge, callback);
     100      BOOST_CHECK(!exists);
     101      BOOST_CHECK(!got_hit);
     102    }
     103    { // no morphism due to vertex mismatches
     104      bool got_hit = false;
     105      test_callback callback(got_hit, true);
     106      false_predicate pred;
     107      bool exists = vf2_graph_iso(gLarge, gLarge, callback, vertex_order_by_mult(gLarge),
     108                                  boost::edges_equivalent(pred).vertices_equivalent(pred));
     109      BOOST_CHECK(!exists);
     110      BOOST_CHECK(!got_hit);
     111    }
     112    { // morphism, find all
     113      bool got_hit = false;
     114      test_callback callback(got_hit, false);
     115      bool exists = vf2_graph_iso(gLarge, gLarge, callback);
     116      BOOST_CHECK(exists);
     117      BOOST_CHECK(got_hit);
     118    }
     119    { // morphism, stop after first hit
     120      bool got_hit = false;
     121      test_callback callback(got_hit, true);
     122      bool exists = vf2_graph_iso(gLarge, gLarge, callback);
     123      BOOST_CHECK(exists);
     124      BOOST_CHECK(got_hit);
     125    }
     126  }
     127  { // subgraph isomorphism (induced)
     128    { // no morphism due to sizes
     129      bool got_hit = false;
     130      test_callback callback(got_hit, true);
     131      bool exists = vf2_subgraph_iso(gLarge, gSmall, callback);
     132      BOOST_CHECK(!exists);
     133      BOOST_CHECK(!got_hit);
     134    }
     135    { // no morphism due to vertex mismatches
     136      bool got_hit = false;
     137      test_callback callback(got_hit, true);
     138      false_predicate pred;
     139      bool exists = vf2_subgraph_iso(gLarge, gLarge, callback, vertex_order_by_mult(gLarge),
     140                                  boost::edges_equivalent(pred).vertices_equivalent(pred));
     141      BOOST_CHECK(!exists);
     142      BOOST_CHECK(!got_hit);
     143    }
     144    { // morphism, find all
     145      bool got_hit = false;
     146      test_callback callback(got_hit, false);
     147      bool exists = vf2_subgraph_iso(gLarge, gLarge, callback);
     148      BOOST_CHECK(exists);
     149      BOOST_CHECK(got_hit);
     150    }
     151    { // morphism, stop after first hit
     152      bool got_hit = false;
     153      test_callback callback(got_hit, true);
     154      bool exists = vf2_subgraph_iso(gLarge, gLarge, callback);
     155      BOOST_CHECK(exists);
     156      BOOST_CHECK(got_hit);
     157    }
     158  }
     159  { // subgraph monomorphism (non-induced subgraph isomorphism)
     160    { // no morphism due to sizes
     161      bool got_hit = false;
     162      test_callback callback(got_hit, true);
     163      bool exists = vf2_subgraph_mono(gLarge, gSmall, callback);
     164      BOOST_CHECK(!exists);
     165      BOOST_CHECK(!got_hit);
     166    }
     167    { // no morphism due to vertex mismatches
     168      bool got_hit = false;
     169      test_callback callback(got_hit, true);
     170      false_predicate pred;
     171      bool exists = vf2_subgraph_mono(gLarge, gLarge, callback, vertex_order_by_mult(gLarge),
     172                                  boost::edges_equivalent(pred).vertices_equivalent(pred));
     173      BOOST_CHECK(!exists);
     174      BOOST_CHECK(!got_hit);
     175    }
     176    { // morphism, find all
     177      bool got_hit = false;
     178      test_callback callback(got_hit, false);
     179      bool exists = vf2_subgraph_mono(gLarge, gLarge, callback);
     180      BOOST_CHECK(exists);
     181      BOOST_CHECK(got_hit);
     182    }
     183    { // morphism, stop after first hit
     184      bool got_hit = false;
     185      test_callback callback(got_hit, true);
     186      bool exists = vf2_subgraph_mono(gLarge, gLarge, callback);
     187      BOOST_CHECK(exists);
     188      BOOST_CHECK(got_hit);
     189    }
     190  }
     191}
     192
     193int test_main(int argc, char* argv[]) {
     194  test_empty_graph_cases();
     195  test_return_value();
     196  return 0;
     197}