加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – boost :: dynamic_properties和不可变图形对象

发布时间:2020-12-16 09:55:21 所属栏目:百科 来源:网络整理
导读:在使用BGL实现一些算法之后,我试图使用GraphML提供io功能.但是,我没有设法编译一个合适的运算符采用const Graph参考. 这是一个简单的例子: // use bundled properties for vertices and edgesstruct VertexProperty{ double error;};typedef boost::adjacen
在使用BGL实现一些算法之后,我试图使用GraphML提供io功能.但是,我没有设法编译一个合适的运算符<<采用const Graph参考. 这是一个简单的例子:

// use bundled properties for vertices and edges
struct VertexProperty
{
   double error;
};

typedef boost::adjacency_list< boost::setS,boost::setS,boost::undirectedS,VertexProperty> Graph;

typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;

std::ostream& operator<<(std::ostream& os,const Graph& graph)
{
    typedef std::map<vertex_descriptor,std::size_t> IndexMap;
    IndexMap index_map;
    boost::associative_property_map<IndexMap> index_properties(index_map);

    std::size_t i = 0;
    for (const vertex_descriptor& v : boost::make_iterator_range(boost::vertices(graph)))
        index_properties[v] = i++;

    boost::dynamic_properties dp;
    typename boost::property_map<Graph,double VertexProperty::*>::const_type error_map = get(&VertexProperty::error,graph);

    dp.property("error",error_map);

    boost::write_graphml(os,graph,index_properties,dp);

    return os;
}

int main()
{
  Graph g;
  std::cout << g <<std::endl;
}

编译失败:

boost/property_map/property_map.hpp:309:44: error: assignment of
read-only location ‘(&((const
boost::adj_list_vertex_property_map,double,const
double&,double
VertexProperty::*>&)pa))->boost::adj_list_vertex_property_map::operator[],const double&,double
VertexProperty::*>(k)’
static_cast(pa)[k] = v;

据我所知,dynamic_properties文档,那些只读检查应该在运行时发生(这不是整个类型擦除的目标之一).当然,如果尝试修改不可变属性,它们应该会失败.但是对wirte write_graphml()的调用需要const参考动力学属性,并且不应该改变任何东西.

陈述问题:

>为什么编译失败?
>我如何正确地做到这一点?
>通过使用其他一些property_map(是/否/哪一个)?

对于(不)运行的示例@coliru.stacked-crooked.com:See here!

问候,
马蒂

解决方法

手头的真正问题是顶点属性映射的类别被推导为LvaluePropertyMap(它是).

但是,LvaluePropertyMap概念有望成为ReadablePropertyMap和WritablePropertyMap的超集.当使用图形属性的const_type时,这会产生问题:它们是左值,但它们是不可写的.

我想出的唯一可行解决方案是将属性映射类型包装为否决类别:

namespace detail {
    template <typename Map>
        struct readable_only_pmap : Map {
            readable_only_pmap(Map map) : Map(map) { }

            // overrule the category tag
            typedef boost::readable_property_map_tag category;
        };
}

现在,您可以像这样使用它:

using pmap_t = typename boost::property_map<Graph,double VertexProperty::*>::const_type;
detail::readable_only_pmap<pmap_t> error_map = get(&VertexProperty::error,graph);

虽然它几乎相同,但现在dynamic_properties :: property检测到映射只是可读的,并且不会尝试生成put帮助程序(相反,如果尝试put,则会引发异常).

完整代码与演示图:

Live On Coliru

#include <iostream>
#include <string>
#include <vector>
#include <functional>

#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
// #include <Eigen/Core>

// use bundled properties for vertices and edges
struct VertexProperty
{
    double error;
    // Eigen::Matrix<real,dim,1> location;
};

typedef boost::adjacency_list< boost::setS,VertexProperty> Graph;

typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;

namespace detail {
    template <typename Map>
        struct readable_only_pmap : Map {
            readable_only_pmap(Map map) : Map(map) { }

            // overrule the category tag
            typedef boost::readable_property_map_tag category;
        };
}

std::ostream& operator<<(std::ostream& os,std::size_t> IndexMap;
    IndexMap index_map;
    boost::associative_property_map<IndexMap> index_properties(index_map);

    std::size_t i = 0;
    for (const vertex_descriptor& v : boost::make_iterator_range(boost::vertices(graph)))
        index_properties[v] = i++;

    using pmap_t = typename boost::property_map<Graph,double VertexProperty::*>::const_type;
    detail::readable_only_pmap<pmap_t> error_map = get(&VertexProperty::error,graph);

    boost::dynamic_properties dp;
    dp.property("error",error_map);
    boost::write_graphml(os,dp);

    return os;
}

int main()
{
  Graph g;
  auto v1 = boost::add_vertex(VertexProperty{0.1},g);
  auto v2 = boost::add_vertex(VertexProperty{0.2},g);
  auto v3 = boost::add_vertex(VertexProperty{0.3},g);
  auto v4 = boost::add_vertex(VertexProperty{0.4},g);
  auto v5 = boost::add_vertex(VertexProperty{0.5},g);

  add_edge(v1,v2,g);
  add_edge(v5,g);
  add_edge(v4,g);
  add_edge(v2,v3,g);
  add_edge(v3,v4,v1,g);

  std::cout << g <<std::endl;
}

输出:(略微重新格式化)

<?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="node" attr.name="error" attr.type="double" />
<graph id="G" edgedefault="undirected" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
    <node id="n0"> <data key="key0">0.1</data> </node>
    <node id="n1"> <data key="key0">0.2</data> </node>
    <node id="n2"> <data key="key0">0.3</data> </node>
    <node id="n3"> <data key="key0">0.4</data> </node>
    <node id="n4"> <data key="key0">0.5</data> </node>
    <edge id="e0" source="n0" target="n1"> </edge>
    <edge id="e1" source="n4" target="n1"> </edge>
    <edge id="e2" source="n3" target="n1"> </edge>
    <edge id="e3" source="n1" target="n2"> </edge>
    <edge id="e4" source="n2" target="n3"> </edge>
    <edge id="e5" source="n3" target="n0"> </edge>
</graph>
</graphml>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读