Fruchterman Reingold布局不会收敛

时间:2012-05-05 23:32:37

标签: c++ boost boost-graph

我想用BGL布置RNA折叠图,它有一个保证平面结构,所有边都应该有相同的长度(有两种边:正常序列,红色边键),像这样:

rna secondary structure http://www.ncrna.org/frnadb/sec_structure/png/FR096703.png

namespace boost {
    enum vertex_position_t { vertex_position };
    BOOST_INSTALL_PROPERTY(vertex, position);
};

template<class PairIterator>
void layout(std::string seq, PairIterator begin, PairIterator end) {
    using namespace boost; using namespace std;

    // backbone edges + bonding edges
    vector<pair<size_t,size_t>> edge_list(begin, end);
    for(size_t i = 0 ; i < seq.size() - 1 ; i++)
        edge_list.push_back(make_pair(i, i + 1));

    typedef rectangle_topology<> topology;
    typedef topology::point_type point;
    boost::minstd_rand random;
    topology space(random, -1000, -1000, 2000, 2000);

    adjacency_list<vecS, vecS, undirectedS,
        property<vertex_position_t, point>
    > g(edge_list.begin(), edge_list.end(), seq.size());

    random_graph_layout(g, get(vertex_position, g), space);
    fruchterman_reingold_force_directed_layout(g, get(vertex_position, g), space,
        cooling(linear_cooling<double>(100)));

    // draw
}

但是,这给了我一个非常随机的布局(冷却时间为100,200,400)。较长的冷却时间只需将顶点按入角落(图像显示完整的布局)。边缘似乎一直太长......

output

我想指定边缘的目标长度,并且在某个边距内达到之前不要停止模拟。

我的代码是从增强样本拼凑而成的,但我不需要坚持使用属性贴图等,我只需要一个布局而不必使用GraphViz。

1 个答案:

答案 0 :(得分:3)

看起来布局开始在右手 - 大多数图像中起作用,但是空间太小而无法展开成正确的形状:也许尝试使用更紧凑的随机布局开始?

或者更强大的吸引力也可能有所帮助。请注意,根据the documentation默认吸引力函数,square_distance_attractive_force 通过边描述符划分吸引力 - 因此较小的边描述符意味着更接近的顶点。


通过考虑到,对于布局合理的平面图,每个顶点仅靠近它通过边链接的顶点,可以计算边的“目标长度”(种类)。这非常类似于我们有两个由单个边连接的顶点的简单情况(如果你有一个规则的顶点网格,它不会超出4倍):

  • 所有顶点对的(默认)排斥力函数为(vertex descriptor value, V)^2/distance
  • 对于由边链接的顶点,(默认)吸引力函数为distance^2/(edge descriptor value, E)

这些在以下情况下处于平衡状态:

V 2 / distance =距离 2 / E

这样:

距离= V (2/3) E (1/3)