gpt4 book ai didi

c++ - Boost:列出GraphML中指定的顶点和边属性

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:39:13 26 4
gpt4 key购买 nike

我希望能够使用 Boost 库的 read_graphml 读取自定义 graphml 文件。然而,这要求我在读取文件时先验指定属性/属性名称。

有没有办法代替列出文件中指定的属性或检查特定属性是否存在?我可能可以通过解析文件来做到这一点,但想知道是否可以通过 Boost 来完成。

最佳答案

我有以下入门概念:

Live On 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 supported\n";
}
}
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);
}

例如,样本输入 this 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 to erase the mapped types of _edge_properties :

Live On 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 supported\n";
}
}
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 supported\n";
}
} 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 来查找刚刚按名称添加的属性要安全得多。如果存在 同名 的边/顶点属性,这可能会严重破坏

第二个版本添加了一个帮助函数来避免这种不准确 (add_property)。

关于c++ - Boost:列出GraphML中指定的顶点和边属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55200517/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com