I have a boost graph with custom properties. I want to make a copy of it. I tried it by following way but got many compilation error.
Here is what I did :
using BGType = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
// Vertex Properties...
vertexProps,
// Edge Propereties...
edgeProps,
// Graph Properties
graphProps>;
vertexProps.h
class vertexProps {
public:
explicit vertexProps(const std::string *moduleName = nullptr, const std::string *name = nullptr,
long refPtr = 0 )
: _refPtr(refPtr),
{
_moduleName = moduleName ? *moduleName : "";
_name = name ? *name : "";
};
struct CustomVertexCopy {
void operator()(const vertexProps& source_vertex, vertexProps& target_vertex) const {
target_vertex._refPtr = source_vertex._refPtr;
target_vertex._moduleName = source_vertex._moduleName;
target_vertex._name = source_vertex._name;
}
edgeProps.h
class edgeProps {
public:
explicit edgeProps(std::string name = "")
: _name(name){};
std::string _name;
};
struct CustomEdgeCopy {
void operator()(const edgeProps& source_edge, edgeProps& target_edge) const {
target_edge._name = source_edge._name;
}
};
someFunction.cpp
OnClick(BGType* bGraph)
{
// some code
BGType* oldBg = new BGType;
boost::copy_graph(bGraph, oldBg, boost::vertex_copy(CustomVertexCopy()));
boost::copy_graph(bGraph, oldBg, boost::edge_copy(CustomEdgeCopy()));
// some code
}
Where am I wrong ?
I have a one more doubt.
Will such deep copying impact on performance if grpah is big ?
If yes, is there any way to avoid it ?
@sehe : I tried your answer, but I was getting compilation error. So I tried to change code little bit and now there is no compilation error. But please look into my changes and suggest me whther changes are right or wrong.
OnClick(BGType* bGraph)
{
// some code
BGType* oldBg = new BGType;
boost::copy_graph(*bGraph, *oldBg,
boost::vertex_copy(CustomVertexCopy{*bGraph,*oldBg})
.edge_copy(CustomEdgeCopy{*bGraph, *oldBg}));
// some code
}
@sehe: I have graph properties also along with vertex and edge property. How to copy that properties also ?
class graphProps {
public:
explicit graphProps(std::string *name = nullptr) { _name = name ? *name : ""; };
std::string _name;
std::map<std::string, std::tuple<std::vector<schPinInfo *>, // input Pins
std::vector<schPinInfo *>, // inout pins
std::vector<schPinInfo *>> // output pins
>
_modInfo;
std::map<std::string, std::vector<std::string>> _altNames;
std::map<std::string, schSymbol> _modSymbol;
}
Named parameters are chained so you can pass arbitrary number of arguments in one place:
boost::copy_graph( //
g1, g2, //
boost::vertex_copy(CustomVertexCopy{}) //
.edge_copy(CustomEdgeCopy{}));
Note that .edge_copy
is chained on the vertex_copy()
named parameter object.
Then, still things wouldn't compiler because the custom copiers should take descriptors, not bundle references:
struct CustomVertexCopy {
BGType const& g1;
BGType& g2;
void operator()(BGType::vertex_descriptor v1, BGType::vertex_descriptor v2) const {
vertexProps const& p1 = g1[v1];
vertexProps& p2 = g2[v2];
p2._refPtr = p1._refPtr;
p2._moduleName = p1._moduleName;
p2._name = p1._name;
}
};
Now it will all work:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/copy.hpp>
#include <boost/graph/graphviz.hpp>
class vertexProps {
public:
explicit vertexProps(std::string const* mn = nullptr, std::string const* n = nullptr, long refPtr = 0)
: _refPtr(refPtr) {
_moduleName = mn ? *mn : "";
_name = n ? *n : "";
}
std::string _moduleName;
std::string _name;
long _refPtr;
};
class edgeProps {
public:
explicit edgeProps(std::string name = "") : _name(name){};
std::string _name;
};
struct graphProps {};
using BGType = boost::adjacency_list< //
boost::vecS, boost::vecS, boost::bidirectionalS, //
vertexProps, edgeProps, graphProps>;
struct CustomVertexCopy {
BGType const& g1;
BGType& g2;
void operator()(BGType::vertex_descriptor v1, BGType::vertex_descriptor v2) const {
vertexProps const& p1 = g1[v1];
vertexProps& p2 = g2[v2];
p2._refPtr = p1._refPtr;
p2._moduleName = p1._moduleName;
p2._name = p1._name;
}
};
struct CustomEdgeCopy {
BGType const& g1;
BGType& g2;
void operator()(BGType::edge_descriptor e1, BGType::edge_descriptor e2) const {
g2[e2]._name = g1[e1]._name;
}
};
int main() {
BGType g1(3);
std::string const names[] {"Hello", "world", "Goodbye", "moon", "Greetings", "Cosmos"};
g1[0] = vertexProps{names + 0, names + 1, 111};
g1[1] = vertexProps{names + 2, names + 3, 222};
g1[2] = vertexProps{names + 4, names + 5, 333};
add_edge(0, 1, edgeProps{"one"}, g1);
add_edge(2, 0, edgeProps{"two"}, g1);
BGType g2;
boost::copy_graph( //
g1, g2, //
boost::vertex_copy(CustomVertexCopy{g1, g2}) //
.edge_copy(CustomEdgeCopy{g1, g2}));
boost::dynamic_properties dp;
dp.property("node_id", get(boost::vertex_index, g2));
dp.property("moduleName", get(&vertexProps::_moduleName, g2));
dp.property("name", get(&vertexProps::_name, g2));
dp.property("ref", get(&vertexProps::_refPtr, g2));
dp.property("name", get(&edgeProps::_name, g2));
write_graphviz_dp(std::cout, g2, dp);
}
Prints
digraph G {
0 [moduleName=Hello, name=world, ref=111];
1 [moduleName=Goodbye, name=moon, ref=222];
2 [moduleName=Greetings, name=Cosmos, ref=333];
0->1 [name=one];
2->0 [name=two];
}
Simplify! Just make the properties copyable, and you're done, with 20 fewer lines of code, which is roughly 30% less room for error/pessimizations:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/copy.hpp>
#include <boost/graph/graphviz.hpp>
class vertexProps {
public:
vertexProps(vertexProps const&) = default;
vertexProps& operator=(vertexProps const&) = default;
explicit vertexProps(std::string const* mn = nullptr, std::string const* n = nullptr, long refPtr = 0)
: _refPtr(refPtr) {
_moduleName = mn ? *mn : "";
_name = n ? *n : "";
}
std::string _moduleName;
std::string _name;
long _refPtr;
};
class edgeProps {
public:
edgeProps(edgeProps const&) = default;
edgeProps& operator=(edgeProps const&) = default;
explicit edgeProps(std::string name = "") : _name(name){};
std::string _name;
};
struct graphProps {};
using BGType = boost::adjacency_list< //
boost::vecS, boost::vecS, boost::bidirectionalS, //
vertexProps, edgeProps, graphProps>;
int main() {
BGType g1(3);
std::string const names[] {"Hello", "world", "Goodbye", "moon", "Greetings", "Cosmos"};
g1[0] = vertexProps{names + 0, names + 1, 111};
g1[1] = vertexProps{names + 2, names + 3, 222};
g1[2] = vertexProps{names + 4, names + 5, 333};
add_edge(0, 1, edgeProps{"one"}, g1);
add_edge(2, 0, edgeProps{"two"}, g1);
BGType g2;
boost::copy_graph(g1, g2);
boost::dynamic_properties dp;
dp.property("node_id", get(boost::vertex_index, g2));
dp.property("moduleName", get(&vertexProps::_moduleName, g2));
dp.property("name", get(&vertexProps::_name, g2));
dp.property("ref", get(&vertexProps::_refPtr, g2));
dp.property("name", get(&edgeProps::_name, g2));
write_graphviz_dp(std::cout, g2, dp);
}
Still printing
digraph G {
0 [moduleName=Hello, name=world, ref=111];
1 [moduleName=Goodbye, name=moon, ref=222];
2 [moduleName=Greetings, name=Cosmos, ref=333];
0->1 [name=one];
2->0 [name=two];
}