Commit a6a09e6b authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Fix motifs() for undirected graphs

This fixes a bug where the isomorphism class for undirected subgraphs
was wrongly computed using their directed view.
parent dcfbada3
Pipeline #98 failed with stage
...@@ -32,15 +32,10 @@ using namespace graph_tool; ...@@ -32,15 +32,10 @@ using namespace graph_tool;
struct append_to_list struct append_to_list
{ {
template <class Graph> template <class Graph>
void operator()(Graph& g, boost::any& list) const void operator()(Graph& g, vector<d_graph_t>& glist) const
{ {
typedef typename boost::mpl::if_<typename is_directed::apply<Graph>::type, glist.emplace_back();
d_graph_t,
u_graph_t>::type graph_t;
vector<graph_t>& glist = any_cast<vector<graph_t>&>(list);
glist.push_back(graph_t());
graph_copy(g, glist.back()); graph_copy(g, glist.back());
} }
}; };
...@@ -48,18 +43,16 @@ struct append_to_list ...@@ -48,18 +43,16 @@ struct append_to_list
struct retrieve_from_list struct retrieve_from_list
{ {
template <class Graph> template <class Graph>
void operator()(Graph& g, boost::any& list, bool& done) const void operator()(Graph& g, vector<d_graph_t>& glist, bool& done) const
{ {
typedef typename boost::mpl::if_<typename is_directed::apply<Graph>::type,
d_graph_t,
u_graph_t>::type graph_t;
vector<graph_t>& glist = any_cast<vector<graph_t>&>(list);
if (glist.empty()) if (glist.empty())
{ {
done = true; done = true;
return; return;
} }
graph_copy(glist.back(), g); typename wrap_directed::apply<Graph,d_graph_t>::type
uback(glist.back());
graph_copy(uback, g);
glist.pop_back(); glist.pop_back();
} }
}; };
...@@ -69,26 +62,14 @@ void get_motifs(GraphInterface& g, size_t k, boost::python::list subgraph_list, ...@@ -69,26 +62,14 @@ void get_motifs(GraphInterface& g, size_t k, boost::python::list subgraph_list,
bool collect_vmaps, boost::python::list p, bool comp_iso, bool collect_vmaps, boost::python::list p, bool comp_iso,
bool fill_list, rng_t& rng) bool fill_list, rng_t& rng)
{ {
boost::any list; vector<d_graph_t> list;
if (g.get_directed()) for (int i = 0; i < boost::python::len(subgraph_list); ++i)
list = vector<d_graph_t>();
else
list = vector<u_graph_t>();
try
{
for (int i = 0; i < boost::python::len(subgraph_list); ++i)
{
GraphInterface& sub =
boost::python::extract<GraphInterface&>(subgraph_list[i]);
run_action<>()(sub, std::bind(append_to_list(),
std::placeholders::_1,
std::ref(list)))();
}
}
catch (bad_any_cast&)
{ {
throw ValueException("All motif graphs must be either directed or " GraphInterface& sub =
"undirected!"); boost::python::extract<GraphInterface&>(subgraph_list[i]);
run_action<>()(sub, std::bind(append_to_list(),
std::placeholders::_1,
std::ref(list)))();
} }
vector<size_t> phist; vector<size_t> phist;
......
...@@ -251,9 +251,8 @@ bool graph_cmp(Graph& g1, Graph& g2) ...@@ -251,9 +251,8 @@ bool graph_cmp(Graph& g1, Graph& g2)
return true; return true;
} }
// short hand for both types of subgraphs // short hand for subgraph types
typedef adj_list<size_t> d_graph_t; typedef adj_list<size_t> d_graph_t;
typedef adj_list<size_t> u_graph_t;
// we need this wrap to use the UndirectedAdaptor only on directed graphs // we need this wrap to use the UndirectedAdaptor only on directed graphs
struct wrap_undirected struct wrap_undirected
...@@ -267,6 +266,18 @@ struct wrap_undirected ...@@ -267,6 +266,18 @@ struct wrap_undirected
}; };
}; };
struct wrap_directed
{
template <class Graph, class Sub>
struct apply
{
typedef typename mpl::if_<typename is_directed::apply<Graph>::type,
Sub&,
UndirectedAdaptor<Sub>>::type type;
};
};
// get the signature of the graph: sorted degree sequence // get the signature of the graph: sorted degree sequence
template <class Graph> template <class Graph>
void get_sig(Graph& g, std::vector<size_t>& sig) void get_sig(Graph& g, std::vector<size_t>& sig)
...@@ -299,28 +310,23 @@ struct get_all_motifs ...@@ -299,28 +310,23 @@ struct get_all_motifs
rng_t& rng; rng_t& rng;
template <class Graph, class Sampler, class VMap> template <class Graph, class Sampler, class VMap>
void operator()(Graph& g, size_t k, boost::any& list, void operator()(Graph& g, size_t k, std::vector<d_graph_t>& subgraph_list,
std::vector<size_t>& hist, std::vector<std::vector<VMap> >& vmaps, std::vector<size_t>& hist, std::vector<std::vector<VMap> >& vmaps,
Sampler sampler) const Sampler sampler) const
{ {
typedef typename mpl::if_<typename is_directed::apply<Graph>::type,
d_graph_t,
u_graph_t>::type graph_sg_t;
// the main subgraph lists
std::vector<graph_sg_t>& subgraph_list =
any_cast<std::vector<graph_sg_t>&>(list);
// this hashes subgraphs according to their signature // this hashes subgraphs according to their signature
gt_hash_map<std::vector<size_t>, gt_hash_map<std::vector<size_t>,
std::vector<pair<size_t, graph_sg_t> >, std::vector<pair<size_t, d_graph_t> >,
std::hash<std::vector<size_t>>> sub_list; std::hash<std::vector<size_t>>> sub_list;
std::vector<size_t> sig; // current signature std::vector<size_t> sig; // current signature
for (size_t i = 0; i < subgraph_list.size(); ++i) for (size_t i = 0; i < subgraph_list.size(); ++i)
{ {
get_sig(subgraph_list[i], sig); auto& sub = subgraph_list[i];
sub_list[sig].push_back(make_pair(i,subgraph_list[i])); typename wrap_directed::apply<Graph,d_graph_t>::type
usub(sub);
get_sig(usub, sig);
sub_list[sig].push_back(make_pair(i, sub));
} }
// the subgraph count // the subgraph count
...@@ -373,9 +379,11 @@ struct get_all_motifs ...@@ -373,9 +379,11 @@ struct get_all_motifs
{ {
for (size_t j = 0; j < subgraphs.size(); ++j) for (size_t j = 0; j < subgraphs.size(); ++j)
{ {
graph_sg_t sub; d_graph_t sub;
make_subgraph(subgraphs[j], g, sub); typename wrap_directed::apply<Graph,d_graph_t>::type
get_sig(sub, sig); usub(sub);
make_subgraph(subgraphs[j], g, usub);
get_sig(usub, sig);
auto iter = sub_list.find(sig); auto iter = sub_list.find(sig);
if(iter == sub_list.end()) if(iter == sub_list.end())
...@@ -390,24 +398,26 @@ struct get_all_motifs ...@@ -390,24 +398,26 @@ struct get_all_motifs
auto sl = sub_list.find(sig); auto sl = sub_list.find(sig);
if (sl != sub_list.end()) if (sl != sub_list.end())
{ {
for (size_t l = 0; l < sl->second.size(); ++l) for (auto& mpos : sl->second)
{ {
graph_sg_t& motif = sl->second[l].second; d_graph_t& motif = mpos.second;
typename wrap_directed::apply<Graph,d_graph_t>::type
umotif(motif);
if (comp_iso) if (comp_iso)
{ {
if (isomorphism(motif, sub, if (isomorphism(umotif, usub,
vertex_index1_map(get(vertex_index, motif)). vertex_index1_map(get(vertex_index, umotif)).
vertex_index2_map(get(vertex_index, sub)))) vertex_index2_map(get(vertex_index, usub))))
found = true; found = true;
} }
else else
{ {
if (graph_cmp(motif, sub)) if (graph_cmp(umotif, usub))
found = true; found = true;
} }
if (found) if (found)
{ {
pos = sl->second[l].first; pos = mpos.first;
hist[pos]++; hist[pos]++;
break; break;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment