Boost Graph Library,简称BGL,库中有各种各样经典的Graph算法,这里介绍其中的VF2算法——vf2_subgraph_iso。
数据怎么存
- 在BGL中,图是用adjacency_list类型数据存储,也就是邻接列表,里面可以存顶点信息,连接边信息,以下面的代码为例,介绍下这个接口的使用方法,具体详情如下代码所示:
#include<string>
#include<iostream>
#include<vector>
#include<stack>
#include<boost/property_map/property_map.hpp>
#include<boost/graph/adjacency_list.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/vf2_sub_graph_iso.hpp>
using namespace std;
using namespace boost;
//自定义顶点信息结构体
struct V {
string m_name;
int m_id;
bool operator==(const V& other) // 这里需要重写这个运算符,当使用自定义类型作为顶点类型时,算法判断顶点是否相等,最终会走到顶点的==运算符中。
{
return m_id == other.m_id;
}
};
struct E {
string m_name;
double m_wight;
bool operator==(const E& other)// 同顶点信息的运算符
{
return m_wight == other.m_wight;
}
};
template < typename Graph1, typename Graph2 >
struct MyVF2Callback // 自定义回调函数,当算法运算完毕需要输出结果时,是采用回调的方式输出结果,所以会在重载的运算符()输出结果,
{
MyVF2Callback(const Graph1& graph1, const Graph2& graph2)
: graph1_(graph1), graph2_(graph2)
{
}
template < typename CorrespondenceMap1To2, typename CorrespondenceMap2To1 >
bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const
{
// Print (sub)graph isomorphism map
BGL_FORALL_VERTICES_T(v, graph1_, Graph1)
std::cout << '(' << get(vertex_index_t(), graph1_, v) << ", "
<< get(vertex_index_t(), graph2_, get(f, v)) << ") ";
return true;
}
private:
const Graph1& graph1_;
const Graph2& graph2_;
};
// 自定义比较函数,根据顶点属性中的m_id进行排序,这里只是随便例举了一个属性,当然可以使用任意的属性作比较
template<typename PropertyMap>
struct CompareById {
const PropertyMap& property_map;
CompareById(const PropertyMap& map)
: property_map(map) {}
// 是以自定义顶点结构体的m_id作为判断依据
bool operator()(const typename boost::property_traits<PropertyMap>::key_type& u,
const typename boost::property_traits<PropertyMap>::key_type& v) const {
return property_map[u].m_id < property_map[v].m_id;
}
};
// 自定义顶点排序搜索函数
template<typename Graph>
std::vector<typename boost::graph_traits<Graph>::vertex_descriptor>
vertex_order_by_id(const Graph& graph) {
auto property_map = get(vertex_name, graph);
typedef decltype(property_map) PropertyMap;
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
std::vector<Vertex> vertex_order;
std::copy(boost::vertices(graph).first, boost::vertices(graph).second,
std::back_inserter(vertex_order));
std::sort(vertex_order.begin(), vertex_order.end(), CompareById<PropertyMap>(property_map));
return vertex_order;
}
void main()
{
typedef property< edge_name_t, E > edge_property; //定义边的属性,其中E是自定义类型,在途中使用get(edge_name, Graph)返回的就是E类型的property_map。
typedef property< vertex_name_t, V, property< vertex_index_t, int > > //定义顶点的属性,property< vertex_index_t, int >表示顶点容器的索引值为int类型
vertex_property;
// Using a vecS graphs => the index maps are implicit.
typedef adjacency_list< vecS, vecS, bidirectionalS, vertex_property,
edge_property >
graph_type;
// Build graph1
graph_type graph1;
add_vertex(V({ "1", 1 }), graph1); // 加入第一个顶点信息,顶点属性数据是V({ "1", 1 })
add_vertex(V({ "2", 2 }), graph1);// 加入第二个顶点信息,顶点属性数据是V({ "2", 2 })
add_vertex(V({ "3", 3 }), graph1);
add_edge(0, 1, E({ "e0", 11 }), graph1);// 加入边信息,边的两个顶点idx是0和1,边的属性数据是E({ "e0", 11 })
// Build graph2
graph_type graph2;
add_vertex(V({ "11", 1 }), graph2); // 同graph1
add_vertex(V({ "22", 2 }), graph2);
add_vertex(V({ "33", 3 }), graph2);
add_edge(2, 2, E({"e1", 10}), graph2);
// create predicates
typedef property_map< graph_type, vertex_name_t >::type vertex_name_map_t;
typedef property_map_equivalent< vertex_name_map_t, vertex_name_map_t >
vertex_comp_t;
vertex_comp_t vertex_comp = make_property_map_equivalent(
get(vertex_name, graph1), get(vertex_name, graph2)); // 定义顶点的比较器,最终会走到顶点类型中operator()里
typedef property_map< graph_type, edge_name_t >::type edge_name_map_t;
typedef property_map_equivalent< edge_name_map_t, edge_name_map_t >
edge_comp_t;
edge_comp_t edge_comp = make_property_map_equivalent(
get(edge_name, graph1), get(edge_name, graph2));// 定义边的比较器,最终会走到边类型中operator()里
// Create callback
MyVF2Callback< graph_type, graph_type > callback(graph1, graph2); /*定义回调函数,算法匹配结果会在这里输出,
如果使用BGL默认的 “vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);”是没办法以自己的方式去处理输出数据,默认的只是将输出输出在控制平台*/
/*
*这里是算法的入口,主要是callback 和vertex_order_by_id(graph1)参数我们可以修改,callback是回调函数,算法结果输出的位置;
* vertex_order_by_id这个是小图搜索顶点的数组,也就是这里容器的顺序就是算法搜索顶点的顺序,默认的是 vertex_order_by_mult(graph1),
* 是以顶点的入读和出度的乘积作为排序的参数,如果希望自定义排序,就需要按照要求定义一个排序,参照上述代码中的vertex_order_by_id,
也就是输出的类型需要时是 std::vector< typename graph_traits< Graph >::vertex_descriptor >,就是小图 vertex_descriptor(可以理解为索引)的数组。
*/
vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_id(graph1),
edges_equivalent(edge_comp).vertices_equivalent(vertex_comp));
}
详细的接口与参数的含义都在代码中注释了,如果还有不理解的问题,请留言一起讨论~