boost.graph:fruchterman_reingold_force_directed_layout导致节点卡在左上角
我在fruchterman_reingold_force_directed_layout
算法上遇到了一些问题。
- 许多节点总是最终在左上角包装。
- 如果我使用非矩形拓扑,我只会得到NAN的位置。
- 布局完全根据初始位置变化;我看到的其他实现似乎总是融合到相同的最终位置。
这是我的布局代码,我在做什么错?:
using edge_property_t = boost::property<boost::edge_weight_t, float>;
using graph_t = boost::adjacency_list<boost::vecS,
boost::vecS,
boost::directedS,
boost::no_property,
edge_property_t>;
using topology_type = boost::rectangle_topology<std::mt19937>;
using point_type = topology_type::point_type;
using pos_map = boost::iterator_property_map<
std::vector<point_type>::iterator,
boost::property_map<graph_t, boost::vertex_index_t>::type>;
graph_t graph_;
pos_map position_;
const auto N = 1234; // vertex count
std::vector<point_type> targetPositions_(N);
// ... vertices are added to the graph ... //
// ... positions are randomized in an initial step ... //
position_ = pos_map{targetPositions_.begin(), get(boost::vertex_index, graph_)};
topology_type topo{0,0,1000,1000};
const auto attraction =
[this](auto e, double k, double d, const auto& g) -> double {
return this->attraction_ * std::pow(d, this->attractionPower_) / k;
};
const auto repulsion =
[this](auto v1, auto v2, double k, double d, const auto&) -> double {
return this->repulsion_ * std::pow(k, this->repulsionPower_) / d;
};
const auto force_pairs = all_force_pairs();
const auto cooling = linear_cooling<double>(this->coolingIterations_, this->coolingTemp_);
auto displacements = std::vector<typename topology_type::point_difference_type>(N);
fruchterman_reingold_force_directed_layout(
graph_, // graph_t
position_, // pos_map
topo,
attraction,
repulsion,
force_pairs,
cooling,
make_iterator_property_map(displacements.begin(),
boost::identity_property_map{}));
我尝试了各种值的吸引力和排斥常数,但无法使任何远程满足。
I'm having a few issues with the fruchterman_reingold_force_directed_layout
algorithm.
- A lot of nodes always end up packing in the top-left corner.
- If I use a non-rectangle topology, I get only NaNs for the positions.
- The layout entirely changes depending on the initial positions ; other implementations I've seen seem to always converge to the same final positions.
Here is my layout code, what am I doing wrong ?:
using edge_property_t = boost::property<boost::edge_weight_t, float>;
using graph_t = boost::adjacency_list<boost::vecS,
boost::vecS,
boost::directedS,
boost::no_property,
edge_property_t>;
using topology_type = boost::rectangle_topology<std::mt19937>;
using point_type = topology_type::point_type;
using pos_map = boost::iterator_property_map<
std::vector<point_type>::iterator,
boost::property_map<graph_t, boost::vertex_index_t>::type>;
graph_t graph_;
pos_map position_;
const auto N = 1234; // vertex count
std::vector<point_type> targetPositions_(N);
// ... vertices are added to the graph ... //
// ... positions are randomized in an initial step ... //
position_ = pos_map{targetPositions_.begin(), get(boost::vertex_index, graph_)};
topology_type topo{0,0,1000,1000};
const auto attraction =
[this](auto e, double k, double d, const auto& g) -> double {
return this->attraction_ * std::pow(d, this->attractionPower_) / k;
};
const auto repulsion =
[this](auto v1, auto v2, double k, double d, const auto&) -> double {
return this->repulsion_ * std::pow(k, this->repulsionPower_) / d;
};
const auto force_pairs = all_force_pairs();
const auto cooling = linear_cooling<double>(this->coolingIterations_, this->coolingTemp_);
auto displacements = std::vector<typename topology_type::point_difference_type>(N);
fruchterman_reingold_force_directed_layout(
graph_, // graph_t
position_, // pos_map
topo,
attraction,
repulsion,
force_pairs,
cooling,
make_iterator_property_map(displacements.begin(),
boost::identity_property_map{}));
I've tried all sort of values for my attraction and repulsion constants but am not able to get anything remotely satisfying.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我已经拿走了您的(原始)代码,并使其独立。然后,我继续添加逐帧输出。在高温下看起来确实很忙,但是当它冷却时,一切看起来都很好。
这是一个可管理的尺寸:
在编译器探险家
时
,
测试
small.gif
喜欢:始终使用
-fsanitize = undefined,地址
构建。I've taken your (original) code and made it self-contained. Then I proceeded to add frame-by-frame output. It does seem very hectic at high temperatures, but then when it cools off everything looks fine.
Here's a manageable size:
Live On Compiler Explorer
When testing with
Shows
And a
small.gif
like:Perhaps you can use this testbed to tune your intuitions and perhaps see what you did differently. Always build with
-fsanitize=undefined,address
for sanity.