如何从graphMl中获得边缘权重到boost :: dijkstra_shortest_paths?

发布于 2025-02-08 15:52:31 字数 3180 浏览 3 评论 0原文

我正在尝试练习一些C ++,以与图形/网络一起使用。我以为我会编写一个快速程序,该程序读取具有边缘权重的网络的GraphMl描述,并计算其直径(或者,首先,仅计算从某个节点到其他节点的最短距离)。 但是,我不继续进行提升文档。阅读 =“ https://www.boost.org/doc/libs/1_79_0/libs/property_map/doc/doc/associative_property_map.html” www.boost.org/doc/libs/1_79_0/libs/property_map/doc/dynamic_property_map.html“ rel =“ nofollow noreferrer”> dynamicic , and 't了解如何将下面的非功能代码弯曲到提交中,因此它读取这样的简单GraphMl文件

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns 
        http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="d0" for="node" attr.name="color" attr.type="string">
    <default>yellow</default>
  </key>
  <key id="d1" for="edge" attr.name="weight" attr.type="double"/>
  <graph id="G" edgedefault="undirected">
    <node id="n0"/> <node id="n1"/> <node id="n2"/>
    <edge id="e0" source="n0" target="n1">
      <data key="d1">3.2</data>
    </edge>
    <edge id="e1" source="n0" target="n2"/>
  </graph>
</graphml>

,并在其上进行一些距离计算。我什至不知道如何进行调试输出(例如。我可以弄清楚dp是否有任何条目d1,还是name name “权重”控制属性最终的位置)。

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/graph/named_function_params.hpp>
#include <ios>
#include <iostream>
#include <list>
#include <map>

#include "cmcmc/tmp.hpp"
#include <string>

using namespace std;

using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;
using Edge = boost::graph_traits<Graph>::edge_descriptor;
using IndexMap = boost::property_map<Graph, boost::vertex_index_t>::type;
using VertexIter = boost::graph_traits<Graph>::vertex_iterator;

int main(int argc, char *argv[])
{
  if (argc <= 1)
  {
    cout << "No GraphML file given.";
    return 1;
  }

  Graph g;
  boost::dynamic_properties dp{ boost::ignore_other_properties };
  // Read the d1 property of the graph
  boost::associative_property_map<std::map<Edge, double>> d1map{};
  dp.property("d1", d1map);
  ifstream in{ argv[1] };
  boost::read_graphml(in, g, dp);

  IndexMap index = get(boost::vertex_index, g);
  Vertex random_node = *vertices(g).first;
  boost::dijkstra_shortest_paths(g, random_node, boost::distance_map(boost::get(d1map, g)));
}

当前,执行此操作是在“抛出'boost :: wrapexceptboost :: bad_any_cast'的实例之后,我该如何工作?

I am trying to practice some C++ for use with graphs/networks. I thought I would write a quick program that reads a GraphML description of a network with edge weights and computes its diameter (or, to start with, just computes the shortest distance from some node to some other node).
However, I don't get on with the Boost documentation. Reading up on graphs, associative, dynamic,
and general property maps, I still don't understand how to bend the non-functional code below into submission so it reads a simple GraphML file like this

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns 
        http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="d0" for="node" attr.name="color" attr.type="string">
    <default>yellow</default>
  </key>
  <key id="d1" for="edge" attr.name="weight" attr.type="double"/>
  <graph id="G" edgedefault="undirected">
    <node id="n0"/> <node id="n1"/> <node id="n2"/>
    <edge id="e0" source="n0" target="n1">
      <data key="d1">3.2</data>
    </edge>
    <edge id="e1" source="n0" target="n2"/>
  </graph>
</graphml>

and does some distance computations on it. I don't even know how to do debug outputs (eg. so I can figure out whether dp has any entry for d1, or whether the name "weight" governs where the properties would end up).

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/graph/named_function_params.hpp>
#include <ios>
#include <iostream>
#include <list>
#include <map>

#include "cmcmc/tmp.hpp"
#include <string>

using namespace std;

using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
using Vertex = boost::graph_traits<Graph>::vertex_descriptor;
using Edge = boost::graph_traits<Graph>::edge_descriptor;
using IndexMap = boost::property_map<Graph, boost::vertex_index_t>::type;
using VertexIter = boost::graph_traits<Graph>::vertex_iterator;

int main(int argc, char *argv[])
{
  if (argc <= 1)
  {
    cout << "No GraphML file given.";
    return 1;
  }

  Graph g;
  boost::dynamic_properties dp{ boost::ignore_other_properties };
  // Read the d1 property of the graph
  boost::associative_property_map<std::map<Edge, double>> d1map{};
  dp.property("d1", d1map);
  ifstream in{ argv[1] };
  boost::read_graphml(in, g, dp);

  IndexMap index = get(boost::vertex_index, g);
  Vertex random_node = *vertices(g).first;
  boost::dijkstra_shortest_paths(g, random_node, boost::distance_map(boost::get(d1map, g)));
}

Currently, executing this dies after “throwing an instance of 'boost::wrapexceptboost::bad_any_cast'”, how do I get it to work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一花一树开 2025-02-15 15:52:31

您走在正确的道路上。很少有注意:

  • 属性映射通常是在调整其他数据架构,因此请实例化Associative_property_map没有初始化就像未经实现的参考
  • ,请参考属性名称,而不是键

,我在这里工作起作用,倾倒std :: Map 以及往返XML。请注意,往返保留信息,而不是表示:

live on Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_map/property_map.hpp>

#define FMT_DEPRECATED_OSTREAM
#include <fmt/ranges.h>
#include <fmt/ostream.h>

using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;

int main() {
  G g;
  std::map<E, double> d1;

  boost::dynamic_properties dp(boost::ignore_other_properties);
  dp.property("weight", boost::make_assoc_property_map(d1));

  {
      std::ifstream ifs("input.xml");
      read_graphml(ifs, g, dp);
  }

  fmt::print("Weight map: {}\n", d1);

  // roundtrip
  write_graphml(std::cout, g, dp);
}

打印

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_graph -lfmt && ./a.out
Weight map: {(0,1): 3.2}
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="key0" for="edge" attr.name="weight" attr.type="double" />
  <graph id="G" edgedefault="undirected" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
    <node id="n0">
    </node>
    <node id="n1">
    </node>
    <node id="n2">
    </node>
    <edge id="e0" source="n0" target="n1">
      <data key="key0">3.2</data>
    </edge>
    <edge id="e1" source="n0" target="n2">
      <data key="key0">0</data>
    </edge>
  </graph>
</graphml>

奖金:捆绑的属性

通常会更简单:

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_map/property_map.hpp>

struct VertexProperties {
    double weight;
};
struct EdgeProperties {
    double weight;
};
using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
                                VertexProperties, EdgeProperties>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;

int main() {
  G g;

  boost::dynamic_properties dp(boost::ignore_other_properties);
  dp.property("weight", get(&EdgeProperties::weight, g));

  {
      std::ifstream ifs("input.xml");
      read_graphml(ifs, g, dp);
  }

  // roundtrip
  write_graphml(std::cout, g, dp);
}

prints

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_graph && ./a.out
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="key0" for="edge" attr.name="weight" attr.type="double" />
  <graph id="G" edgedefault="undirected" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
    <node id="n0">
    </node>
    <node id="n1">
    </node>
    <node id="n2">
    </node>
    <edge id="e0" source="n0" target="n1">
      <data key="key0">3.2</data>
    </edge>
    <edge id="e1" source="n0" target="n2">
      <data key="key0">0</data>
    </edge>
  </graph>
</graphml>

You're on the right path. Few notes:

  • property maps are usually adapting other datastructures, so instantiating that associative_property_map with no initialization is like an uninitalized reference
  • refer to the attribute name, not key

Here I made it work, dumping the std::map as well as roundtripping the XML. Note that the roundtrips preserves information, not representation:

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_map/property_map.hpp>

#define FMT_DEPRECATED_OSTREAM
#include <fmt/ranges.h>
#include <fmt/ostream.h>

using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;

int main() {
  G g;
  std::map<E, double> d1;

  boost::dynamic_properties dp(boost::ignore_other_properties);
  dp.property("weight", boost::make_assoc_property_map(d1));

  {
      std::ifstream ifs("input.xml");
      read_graphml(ifs, g, dp);
  }

  fmt::print("Weight map: {}\n", d1);

  // roundtrip
  write_graphml(std::cout, g, dp);
}

Prints

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_graph -lfmt && ./a.out
Weight map: {(0,1): 3.2}
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="key0" for="edge" attr.name="weight" attr.type="double" />
  <graph id="G" edgedefault="undirected" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
    <node id="n0">
    </node>
    <node id="n1">
    </node>
    <node id="n2">
    </node>
    <edge id="e0" source="n0" target="n1">
      <data key="key0">3.2</data>
    </edge>
    <edge id="e1" source="n0" target="n2">
      <data key="key0">0</data>
    </edge>
  </graph>
</graphml>

BONUS: Bundled Properties

As you suspected will usually be simpler:

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_map/property_map.hpp>

struct VertexProperties {
    double weight;
};
struct EdgeProperties {
    double weight;
};
using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
                                VertexProperties, EdgeProperties>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;

int main() {
  G g;

  boost::dynamic_properties dp(boost::ignore_other_properties);
  dp.property("weight", get(&EdgeProperties::weight, g));

  {
      std::ifstream ifs("input.xml");
      read_graphml(ifs, g, dp);
  }

  // roundtrip
  write_graphml(std::cout, g, dp);
}

Prints

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_graph && ./a.out
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="key0" for="edge" attr.name="weight" attr.type="double" />
  <graph id="G" edgedefault="undirected" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
    <node id="n0">
    </node>
    <node id="n1">
    </node>
    <node id="n2">
    </node>
    <edge id="e0" source="n0" target="n1">
      <data key="key0">3.2</data>
    </edge>
    <edge id="e1" source="n0" target="n2">
      <data key="key0">0</data>
    </edge>
  </graph>
</graphml>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文