Boost:列出GraphMl中指定的顶点和边缘属性
Boost: List the vertex and edge attributes specified in GraphML
我希望能够使用Boost Library的read_graphml
读取自定义GraphMl文件。但是,这要求我在阅读文件时指定a-priori属性/属性名称。
有没有办法列出文件中指定的属性或检查特定属性是否存在?我可能可以通过解析文件来做到这一点,但是想知道它是否可以通过Boost完成。
我有以下启动器概念:
活在coliru
#include <boost/graph/graphml.hpp>
#include <boost/core/demangle.hpp>
using namespace boost;
using Graph = adjacency_list<vecS, vecS, undirectedS>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
struct MyGraph {
Graph g;
dynamic_properties dp { [=](auto const&... args) { return detect_properties(dp, args...); } };
using Name = std::string;
using EdgePropMap = std::map<Edge, std::string>;
std::map<Name, std::shared_ptr<EdgePropMap> > _edge_properties;
void read(std::istream& graphml) {
::boost::read_graphml(graphml, g, dp);
}
private:
boost::shared_ptr<boost::dynamic_property_map> detect_properties(dynamic_properties& dp, Name const& name, boost::any const& key, boost::any const& value) {
auto value_type = core::demangled_name(value.type());
if (key.type() == typeid(Graph)) {
std::cout << "Vertex property: " << name << ", " << value_type << "n" << std::flush;
//dp.property(name, boost::make_vector_property_map<Graph>(identity_property_map{}));
//return dp.lower_bound(name)->second;
}
else if (key.type() == typeid(Edge)) {
std::cout << "Edge property: " << name << ", " << value_type << "n" << std::flush;
if (value.type() == typeid(std::string)) {
auto& map = *_edge_properties.emplace(name, std::make_shared<EdgePropMap>()).first->second;
dp.property(name, boost::make_assoc_property_map(map));
return dp.lower_bound(name)->second;
} else {
std::cerr << "Value type (" << value_type << ") not supportedn";
}
}
else if (key.type() == typeid(Vertex)) {
std::cout << "Vertex property: " << name << ", " << value_type << "n" << std::flush;
/*if (value.type() == typeid(std::string))*/ {
dp.property(name, boost::make_vector_property_map<std::string>(get(vertex_index, g)));
return dp.lower_bound(name)->second;
}
} else {
std::cout << "Unknown property (" << core::demangled_name(key.type()) << ") " << name << ", " << value_type << "n" << std::flush;
}
return nullptr;
}
};
int main() {
MyGraph g;
g.read(std::cin);
}
例如,使用此GraphMl的示例输入,输出为( live on Coliru ):
Vertex property: color, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
Edge property: weight, double
Value type (double) not supported
Edge property: weight, double
Value type (double) not supported
Edge property: weight, double
Value type (double) not supported
Edge property: weight, double
Value type (double) not supported
改进...
在设置边缘属性映射或希望与它们不同的价值类型时,它变得更加复杂。我建议将dynamic_properties
用作对动态属性映射的唯一访问,因为我们可以使用shared_ptr删除映射的 _edge_properties
类型:
活在coliru
#include <boost/graph/graphml.hpp>
#include <boost/core/demangle.hpp>
using namespace boost;
using Graph = adjacency_list<vecS, vecS, undirectedS>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
struct MyGraph {
Graph g;
dynamic_properties dp { [=](auto const&... args) { return detect_properties(args...); } };
using Name = std::string;
std::map<Name, std::shared_ptr<void> > _edge_properties;
void read(std::istream& graphml) {
::boost::read_graphml(graphml, g, dp);
}
private:
template<typename Map>
auto add_property(const std::string& name, Map pmap)
{
boost::shared_ptr<dynamic_property_map> pm(
boost::static_pointer_cast<dynamic_property_map>(
boost::make_shared<detail::dynamic_property_map_adaptor<Map> >(pmap)));
dp.insert(name, pm);
return pm;
}
template <typename V>
auto add_edge_property(std::string const& name) {
auto map = std::make_shared<std::map<Edge, V> >();
_edge_properties.emplace(name, map);
return add_property(name, boost::make_assoc_property_map(*map));
}
template <typename V>
auto add_vertex_property(std::string const& name) {
// NOTE, if vertex_index isn't present you might want to use
// make_assoc_property_map as with the edge properties
return add_property(name, boost::make_vector_property_map<V>(get(vertex_index, g)));
}
boost::shared_ptr<dynamic_property_map> detect_properties(Name const& name, boost::any const& key, boost::any const& value) {
auto value_type = core::demangled_name(value.type());
if (key.type() == typeid(Graph)) {
std::cout << "Graph property detected: " << name << ", " << value_type << "n" << std::flush;
//dp.property(name, boost::make_vector_property_map<Graph>(identity_property_map{}));
//return dp.lower_bound(name)->second;
}
else if (key.type() == typeid(Edge)) {
std::cout << "Edge property detected: " << name << ", " << value_type << "n" << std::flush;
if (value.type() == typeid(std::string)) {
return add_edge_property<std::string>(name);
} else if (value.type() == typeid(double)) {
return add_edge_property<double>(name);
} else {
std::cerr << "Value type (" << value_type << ") not supportedn";
}
}
else if (key.type() == typeid(Vertex)) {
std::cout << "Vertex property detected: " << name << ", " << value_type << "n" << std::flush;
if (value.type() == typeid(std::string)) {
return add_vertex_property<std::string>(name);
} else if (value.type() == typeid(double)) {
return add_vertex_property<double>(name);
} else {
std::cerr << "Value type (" << value_type << ") not supportedn";
}
} else {
std::cout << "Unknown property (" << core::demangled_name(key.type()) << ") " << name << ", " << value_type << "n" << std::flush;
}
return nullptr;
}
};
int main() {
MyGraph g;
g.read(std::cin);
}
现在打印:
Vertex property detected: color, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
Edge property detected: weight, double
注意:
第二版实际上更安全,因为第一个"错误使用"的lower_bound
可以找到刚刚添加的属性。如果有Edge/vertex属性使用相同名称。。
第二个版本添加了一个助手功能,该功能避免了这种不准确性(add_property
)。
相关文章:
- 如何循环打印顶点结构
- D3D11-将混合权重和索引传递到顶点着色器
- 从返回的顶点缓冲区查询顶点结构
- Vulkan 中的动态顶点缓冲区格式设置
- 在顶点着色器中使用 OpenGl 的未声明标识符,我在顶点着色器中绘制三角形时遇到问题
- 如何获取边缘窗口句柄 (HWND)?
- 如何将一半传递给顶点着色器?
- 提升如何在图形可视化中写入边缘的权重?
- 在 c++ 中使用 Tensorflow Lite 在边缘 TPU 上运行"mobilenet_ssd_v2_coco_quant_postprocess_edgetpu.tflite"时出现问题
- 分数背包边缘箱
- 在 DirectX 11 中从 GPU 读回顶点缓冲区(并获取顶点)
- QT QOpenGLWidget:如何在不使用数据块复制的情况下修改VBO中的单个顶点值?
- 使用 OpenGL 4.5 更改所选顶点的颜色
- Boost:列出GraphMl中指定的顶点和边缘属性
- Boost:如何移除顶点的所有外边缘
- 将边缘节点添加到没有边缘的顶点时出现 Seg 错误
- 如何访问图中顶点边缘的数据
- 如何使用boost::graph算法与listS,setS作为顶点/边缘容器
- 在boost图lib中,如何在不迭代顶点的所有外边缘的情况下获得该顶点的特定外边缘
- 在边缘上迭代并使用OpenMesh获得顶点