| 1 | // graph-tool -- a general graph modification and manipulation thingy |
|---|
| 2 | // |
|---|
| 3 | // Copyright (C) 2007-2011 Tiago de Paula Peixoto <tiago@skewed.de> |
|---|
| 4 | // |
|---|
| 5 | // This program is free software; you can redistribute it and/or |
|---|
| 6 | // modify it under the terms of the GNU General Public License |
|---|
| 7 | // as published by the Free Software Foundation; either version 3 |
|---|
| 8 | // of the License, or (at your option) any later version. |
|---|
| 9 | // |
|---|
| 10 | // This program is distributed in the hope that it will be useful, |
|---|
| 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | // GNU General Public License for more details. |
|---|
| 14 | // |
|---|
| 15 | // You should have received a copy of the GNU General Public License |
|---|
| 16 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 17 | |
|---|
| 18 | #include "graph_filtering.hh" |
|---|
| 19 | |
|---|
| 20 | #include "graph.hh" |
|---|
| 21 | #include "graph_selectors.hh" |
|---|
| 22 | #include "graph_properties.hh" |
|---|
| 23 | |
|---|
| 24 | #include "graph_motifs.hh" |
|---|
| 25 | |
|---|
| 26 | #include <boost/python.hpp> |
|---|
| 27 | |
|---|
| 28 | using namespace std; |
|---|
| 29 | using namespace boost; |
|---|
| 30 | using namespace graph_tool; |
|---|
| 31 | |
|---|
| 32 | struct null_copy |
|---|
| 33 | { |
|---|
| 34 | template <class T1, class T2> |
|---|
| 35 | void operator()(const T1& t1, const T2& t2) const {} |
|---|
| 36 | }; |
|---|
| 37 | |
|---|
| 38 | struct append_to_list |
|---|
| 39 | { |
|---|
| 40 | |
|---|
| 41 | template <class Graph> |
|---|
| 42 | void operator()(Graph& g, boost::any& list) const |
|---|
| 43 | { |
|---|
| 44 | typedef typename mpl::if_<typename is_directed::apply<Graph>::type, |
|---|
| 45 | d_graph_t, |
|---|
| 46 | u_graph_t>::type graph_t; |
|---|
| 47 | vector<graph_t>& glist = any_cast<vector<graph_t>&>(list); |
|---|
| 48 | glist.push_back(graph_t()); |
|---|
| 49 | copy_graph(g, glist.back(), vertex_copy(null_copy()). |
|---|
| 50 | edge_copy(null_copy())); |
|---|
| 51 | } |
|---|
| 52 | }; |
|---|
| 53 | |
|---|
| 54 | struct retrieve_from_list |
|---|
| 55 | { |
|---|
| 56 | template <class Graph> |
|---|
| 57 | void operator()(Graph& g, boost::any& list, bool& done) const |
|---|
| 58 | { |
|---|
| 59 | typedef typename mpl::if_<typename is_directed::apply<Graph>::type, |
|---|
| 60 | d_graph_t, |
|---|
| 61 | u_graph_t>::type graph_t; |
|---|
| 62 | vector<graph_t>& glist = any_cast<vector<graph_t>&>(list); |
|---|
| 63 | if (glist.empty()) |
|---|
| 64 | { |
|---|
| 65 | done = true; |
|---|
| 66 | return; |
|---|
| 67 | } |
|---|
| 68 | copy_graph(glist.back(), g, edge_copy(null_copy())); |
|---|
| 69 | glist.pop_back(); |
|---|
| 70 | } |
|---|
| 71 | }; |
|---|
| 72 | |
|---|
| 73 | void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list, |
|---|
| 74 | python::list hist, python::list p, bool comp_iso, |
|---|
| 75 | bool fill_list, size_t seed) |
|---|
| 76 | { |
|---|
| 77 | rng_t rng(static_cast<rng_t::result_type>(seed)); |
|---|
| 78 | |
|---|
| 79 | boost::any list; |
|---|
| 80 | if (g.GetDirected()) |
|---|
| 81 | list = vector<d_graph_t>(); |
|---|
| 82 | else |
|---|
| 83 | list = vector<u_graph_t>(); |
|---|
| 84 | try |
|---|
| 85 | { |
|---|
| 86 | for (int i = 0; i < python::len(subgraph_list); ++i) |
|---|
| 87 | { |
|---|
| 88 | GraphInterface& sub = |
|---|
| 89 | python::extract<GraphInterface&>(subgraph_list[i]); |
|---|
| 90 | run_action<>()(sub, bind<void>(append_to_list(), _1, |
|---|
| 91 | boost::ref(list)))(); |
|---|
| 92 | } |
|---|
| 93 | } |
|---|
| 94 | catch (bad_any_cast&) |
|---|
| 95 | { |
|---|
| 96 | throw ValueException("All motif graphs must be either directed or " |
|---|
| 97 | "undirected!"); |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | vector<size_t> phist; |
|---|
| 101 | vector<double> plist; |
|---|
| 102 | double total = 1; |
|---|
| 103 | for (int i = 0; i < python::len(p); ++i) |
|---|
| 104 | { |
|---|
| 105 | plist.push_back(python::extract<double>(p[i])); |
|---|
| 106 | total *= plist[i]; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | boost::any sampler; |
|---|
| 110 | if (total == 1.0) |
|---|
| 111 | sampler = sample_all(); |
|---|
| 112 | else |
|---|
| 113 | sampler = sample_some(plist, rng); |
|---|
| 114 | |
|---|
| 115 | run_action<>() |
|---|
| 116 | (g, boost::bind<void>(get_all_motifs(), _1, k, boost::ref(list), |
|---|
| 117 | boost::ref(phist), _2, |
|---|
| 118 | plist[0], comp_iso, fill_list, boost::ref(rng)), |
|---|
| 119 | mpl::vector<sample_all,sample_some>())(sampler); |
|---|
| 120 | |
|---|
| 121 | for (size_t i = 0; i < phist.size(); ++i) |
|---|
| 122 | hist.append(phist[i]); |
|---|
| 123 | |
|---|
| 124 | if (fill_list) |
|---|
| 125 | { |
|---|
| 126 | for (int i = 0; i < python::len(subgraph_list); ++i) |
|---|
| 127 | subgraph_list.pop(); |
|---|
| 128 | |
|---|
| 129 | bool done = false; |
|---|
| 130 | while (!done) |
|---|
| 131 | { |
|---|
| 132 | |
|---|
| 133 | GraphInterface sub; |
|---|
| 134 | sub.SetDirected(g.GetDirected()); |
|---|
| 135 | typedef graph_tool::detail::get_all_graph_views::apply |
|---|
| 136 | <graph_tool::detail::scalar_pairs, |
|---|
| 137 | mpl::bool_<false>,mpl::bool_<false>, |
|---|
| 138 | mpl::bool_<false>,mpl::bool_<true>, |
|---|
| 139 | mpl::bool_<true> >::type gviews; |
|---|
| 140 | run_action<gviews>() |
|---|
| 141 | (sub, boost::bind<void>(retrieve_from_list(), _1, |
|---|
| 142 | boost::ref(list), boost::ref(done)))(); |
|---|
| 143 | if (!done) |
|---|
| 144 | { |
|---|
| 145 | sub.ReIndexEdges(); |
|---|
| 146 | subgraph_list.append(sub); |
|---|
| 147 | } |
|---|
| 148 | } |
|---|
| 149 | subgraph_list.reverse(); |
|---|
| 150 | } |
|---|
| 151 | } |
|---|
| 152 | |
|---|