Commit 0abe5a7c authored by Tiago Peixoto's avatar Tiago Peixoto

Randomize sweep order in sfdp_layout()

This fixes some strange bugs where deterministic position updates lead
to strange artifacts.
parent 566d6dd8
...@@ -33,7 +33,7 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight, ...@@ -33,7 +33,7 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight,
boost::any eweight, boost::any pin, python::object spring_parms, boost::any eweight, boost::any pin, python::object spring_parms,
double theta, double init_step, double step_schedule, double theta, double init_step, double step_schedule,
size_t max_level, double epsilon, size_t max_iter, size_t max_level, double epsilon, size_t max_iter,
bool adaptive, bool verbose) bool adaptive, bool verbose, rng_t& rng)
{ {
typedef ConstantPropertyMap<int32_t,GraphInterface::vertex_t> vweight_map_t; typedef ConstantPropertyMap<int32_t,GraphInterface::vertex_t> vweight_map_t;
typedef ConstantPropertyMap<int32_t,GraphInterface::edge_t> eweight_map_t; typedef ConstantPropertyMap<int32_t,GraphInterface::edge_t> eweight_map_t;
...@@ -68,12 +68,13 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight, ...@@ -68,12 +68,13 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight,
run_action<graph_tool::detail::never_directed>() run_action<graph_tool::detail::never_directed>()
(g, (g,
std::bind(get_sfdp_layout(C, K, p, theta, gamma, mu, mu_p, init_step, std::bind(get_sfdp_layout(C, K, p, theta, gamma, mu, mu_p, init_step,
step_schedule, max_level, epsilon, step_schedule, max_level, epsilon,
max_iter, adaptive), max_iter, adaptive),
placeholders::_1, g.GetVertexIndex(), placeholders::_2, placeholders::_1, g.GetVertexIndex(), placeholders::_2,
placeholders::_3, placeholders::_4, placeholders::_3, placeholders::_4,
pin_map.get_unchecked(num_vertices(g.GetGraph())), pin_map.get_unchecked(num_vertices(g.GetGraph())),
groups.get_unchecked(num_vertices(g.GetGraph())), verbose), groups.get_unchecked(num_vertices(g.GetGraph())), verbose,
std::ref(rng)),
vertex_floating_vector_properties(), vertex_props_t(), edge_props_t()) vertex_floating_vector_properties(), vertex_props_t(), edge_props_t())
(pos, vweight, eweight); (pos, vweight, eweight);
} }
......
...@@ -200,10 +200,10 @@ struct get_sfdp_layout ...@@ -200,10 +200,10 @@ struct get_sfdp_layout
bool simple; bool simple;
template <class Graph, class VertexIndex, class PosMap, class VertexWeightMap, template <class Graph, class VertexIndex, class PosMap, class VertexWeightMap,
class EdgeWeightMap, class PinMap, class GroupMap> class EdgeWeightMap, class PinMap, class GroupMap, class RNG>
void operator()(Graph& g, VertexIndex vertex_index, PosMap pos, void operator()(Graph& g, VertexIndex vertex_index, PosMap pos,
VertexWeightMap vweight, EdgeWeightMap eweight, PinMap pin, VertexWeightMap vweight, EdgeWeightMap eweight, PinMap pin,
GroupMap group, bool verbose) const GroupMap group, bool verbose, RNG& rng) const
{ {
typedef typename property_traits<PosMap>::value_type pos_t; typedef typename property_traits<PosMap>::value_type pos_t;
typedef typename property_traits<PosMap>::value_type::value_type val_t; typedef typename property_traits<PosMap>::value_type::value_type val_t;
...@@ -215,6 +215,7 @@ struct get_sfdp_layout ...@@ -215,6 +215,7 @@ struct get_sfdp_layout
vector<pos_t> group_cm; vector<pos_t> group_cm;
vector<vweight_t> group_size; vector<vweight_t> group_size;
vector<size_t> vertices;
int i, N = num_vertices(g), HN=0; int i, N = num_vertices(g), HN=0;
for (i = 0; i < N; ++i) for (i = 0; i < N; ++i)
...@@ -223,6 +224,8 @@ struct get_sfdp_layout ...@@ -223,6 +224,8 @@ struct get_sfdp_layout
vertex(i, g); vertex(i, g);
if (v == graph_traits<Graph>::null_vertex()) if (v == graph_traits<Graph>::null_vertex())
continue; continue;
if (!pin[v])
vertices.push_back(v);
pos[v].resize(2, 0); pos[v].resize(2, 0);
size_t s = group[v]; size_t s = group[v];
...@@ -280,21 +283,19 @@ struct get_sfdp_layout ...@@ -280,21 +283,19 @@ struct get_sfdp_layout
qt.put_pos(pos[v], vweight[v]); qt.put_pos(pos[v], vweight[v]);
} }
std::shuffle(vertices.begin(), vertices.end(), rng);
pos_t diff(2, 0), pos_u(2, 0), ftot(2, 0), cm(2, 0); pos_t diff(2, 0), pos_u(2, 0), ftot(2, 0), cm(2, 0);
size_t nmoves = 0; size_t nmoves = 0;
N = vertices.size();
#pragma omp parallel for default(shared) private(i) \ #pragma omp parallel for default(shared) private(i) \
firstprivate(Q, diff, pos_u, ftot, cm) \ firstprivate(Q, diff, pos_u, ftot, cm) \
reduction(+:E, delta, nmoves) schedule(static) if (N > 100) reduction(+:E, delta, nmoves) schedule(static) if (N > 100)
for (i = 0; i < N; ++i) for (i = 0; i < N; ++i)
{ {
typename graph_traits<Graph>::vertex_descriptor v = typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g); vertex(vertices[i], g);
if (v == graph_traits<Graph>::null_vertex())
continue;
if (pin[v])
continue;
ftot[0] = ftot[1] = 0; ftot[0] = ftot[1] = 0;
...@@ -357,8 +358,8 @@ struct get_sfdp_layout ...@@ -357,8 +358,8 @@ struct get_sfdp_layout
target(*e, g); target(*e, g);
if (u == v) if (u == v)
continue; continue;
#pragma omp critical
{ {
#pragma omp critical
for (size_t l = 0; l < 2; ++l) for (size_t l = 0; l < 2; ++l)
pos_u[l] = pos[u][l]; pos_u[l] = pos[u][l];
} }
...@@ -424,8 +425,8 @@ struct get_sfdp_layout ...@@ -424,8 +425,8 @@ struct get_sfdp_layout
E += power(norm(ftot), 2); E += power(norm(ftot), 2);
#pragma omp critical
{ {
#pragma omp critical
for (size_t l = 0; l < 2; ++l) for (size_t l = 0; l < 2; ++l)
{ {
group_cm[group[v]][l] *= group_size[group[v]]; group_cm[group[v]][l] *= group_size[group[v]];
......
...@@ -507,7 +507,7 @@ def coarse_graph_stack(g, c, coarse_stack, eweight=None, vweight=None, ...@@ -507,7 +507,7 @@ def coarse_graph_stack(g, c, coarse_stack, eweight=None, vweight=None,
def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2, def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
K=None, p=2., theta=0.6, max_level=11, gamma=1., mu=0., mu_p=1., K=None, p=2., theta=0.6, max_level=11, gamma=1., mu=0., mu_p=1.,
init_step=None, cooling_step=0.9, adaptive_cooling=True, init_step=None, cooling_step=0.95, adaptive_cooling=True,
epsilon=1e-2, max_iter=0, pos=None, multilevel=None, epsilon=1e-2, max_iter=0, pos=None, multilevel=None,
coarse_method="hybrid", mivs_thres=0.9, ec_thres=0.75, coarse_method="hybrid", mivs_thres=0.9, ec_thres=0.75,
coarse_stack=None, weighted_coarse=False, verbose=False): coarse_stack=None, weighted_coarse=False, verbose=False):
...@@ -549,7 +549,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2, ...@@ -549,7 +549,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
connected component, or group assignment. connected component, or group assignment.
init_step : float (optional, default: ``None``) init_step : float (optional, default: ``None``)
Initial update step. If not provided, it will be chosen automatically. Initial update step. If not provided, it will be chosen automatically.
cooling_step : float (optional, default: ``0.9``) cooling_step : float (optional, default: ``0.95``)
Cooling update step. Cooling update step.
adaptive_cooling : bool (optional, default: ``True``) adaptive_cooling : bool (optional, default: ``True``)
Use an adaptive cooling scheme. Use an adaptive cooling scheme.
...@@ -634,7 +634,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2, ...@@ -634,7 +634,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
K = _avg_edge_distance(g, pos) K = _avg_edge_distance(g, pos)
if init_step is None: if init_step is None:
init_step = 10 * max(_avg_edge_distance(g, pos), K) init_step = 2 * max(_avg_edge_distance(g, pos), K)
if multilevel is None: if multilevel is None:
multilevel = g.num_vertices() > 1000 multilevel = g.num_vertices() > 1000
...@@ -671,8 +671,8 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2, ...@@ -671,8 +671,8 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
max_iter=max_iter, max_iter=max_iter,
cooling_step=cooling_step, cooling_step=cooling_step,
adaptive_cooling=False, adaptive_cooling=False,
init_step=max(2 * K, # init_step=max(2 * K,
_avg_edge_distance(u, pos) / 10), # _avg_edge_distance(u, pos)),
multilevel=False, multilevel=False,
verbose=False) verbose=False)
#graph_draw(u, pos) #graph_draw(u, pos)
...@@ -699,7 +699,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2, ...@@ -699,7 +699,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
(C, K, p, gamma, mu, mu_p, _prop("v", g, groups)), (C, K, p, gamma, mu, mu_p, _prop("v", g, groups)),
theta, init_step, cooling_step, max_level, theta, init_step, cooling_step, max_level,
epsilon, max_iter, not adaptive_cooling, epsilon, max_iter, not adaptive_cooling,
verbose) verbose, _get_rng())
return pos return pos
def radial_tree_layout(g, root, weighted=False, r=1.): def radial_tree_layout(g, root, weighted=False, r=1.):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment