Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tiago Peixoto
graph-tool
Commits
b0f284a9
Commit
b0f284a9
authored
Oct 27, 2012
by
Tiago Peixoto
Browse files
Include support for intra/iter-group attraction/repulsive forces in sfdp_layout()
parent
8d5b50b8
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/graph/layout/graph_sfdp.cc
View file @
b0f284a9
...
...
@@ -57,32 +57,31 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight,
double
K
=
python
::
extract
<
double
>
(
spring_parms
[
1
]);
double
p
=
python
::
extract
<
double
>
(
spring_parms
[
2
]);
double
gamma
=
python
::
extract
<
double
>
(
spring_parms
[
3
]);
double
mu
=
python
::
extract
<
double
>
(
spring_parms
[
4
]);
double
mu_p
=
python
::
extract
<
double
>
(
spring_parms
[
5
]);
group_map_t
groups
=
any_cast
<
group_map_t
>
(
python
::
extract
<
any
>
(
spring_parms
[
4
]));
any_cast
<
group_map_t
>
(
python
::
extract
<
any
>
(
spring_parms
[
6
]));
if
(
vweight
.
empty
())
vweight
=
vweight_map_t
(
1
);
if
(
eweight
.
empty
())
eweight
=
eweight_map_t
(
1
);
typedef
property_map_type
::
apply
<
uint8_t
,
GraphInterface
::
vertex_index_map_t
>::
type
pin_map_t
;
pin_map_t
pin_map
=
any_cast
<
pin_map_t
>
(
pin
);
typedef
ConstantPropertyMap
<
bool
,
GraphInterface
::
vertex_t
>
pin_map_t
;
typedef
mpl
::
vector
<
property_map_type
::
apply
<
uint8_t
,
GraphInterface
::
vertex_index_map_t
>::
type
,
pin_map_t
>::
type
pin_props_t
;
if
(
pin
.
empty
())
pin
=
pin_map_t
(
false
);
run_action
<
graph_tool
::
detail
::
never_directed
>
()
(
g
,
bind
<
void
>
(
get_sfdp_layout
(
C
,
K
,
p
,
theta
,
gamma
,
init_step
,
bind
<
void
>
(
get_sfdp_layout
(
C
,
K
,
p
,
theta
,
gamma
,
mu
,
mu_p
,
init_step
,
step_schedule
,
max_level
,
epsilon
,
max_iter
,
adaptive
),
_1
,
g
.
GetVertexIndex
(),
_2
,
_3
,
_4
,
_5
,
groups
,
verbose
),
vertex_floating_vector_properties
(),
vertex_props_t
(),
edge_props_t
(),
pin_props_t
())(
pos
,
vweight
,
eweight
,
pin
);
_1
,
g
.
GetVertexIndex
(),
_2
,
_3
,
_4
,
pin_map
.
get_unchecked
(
num_vertices
(
g
.
GetGraph
())),
groups
.
get_unchecked
(
num_vertices
(
g
.
GetGraph
())),
verbose
),
vertex_floating_vector_properties
(),
vertex_props_t
(),
edge_props_t
())
(
pos
,
vweight
,
eweight
);
}
struct
do_propagate_pos
...
...
src/graph/layout/graph_sfdp.hh
View file @
b0f284a9
...
...
@@ -177,13 +177,15 @@ inline double norm(Pos& x)
struct
get_sfdp_layout
{
get_sfdp_layout
(
double
C
,
double
K
,
double
p
,
double
theta
,
double
gamma
,
double
init_step
,
double
step_schedule
,
size_t
max_level
,
double
epsilon
,
size_t
max_iter
,
bool
simple
)
:
C
(
C
),
K
(
K
),
p
(
p
),
theta
(
theta
),
gamma
(
gamma
),
init_step
(
init_step
),
step_schedule
(
step_schedule
),
epsilon
(
epsilon
),
max_level
(
max_level
),
max_iter
(
max_iter
),
simple
(
simple
)
{}
double
C
,
K
,
p
,
theta
,
gamma
,
init_step
,
step_schedule
,
epsilon
;
double
mu
,
double
mu_p
,
double
init_step
,
double
step_schedule
,
size_t
max_level
,
double
epsilon
,
size_t
max_iter
,
bool
simple
)
:
C
(
C
),
K
(
K
),
p
(
p
),
theta
(
theta
),
gamma
(
gamma
),
mu
(
mu
),
mu_p
(
mu_p
),
init_step
(
init_step
),
step_schedule
(
step_schedule
),
epsilon
(
epsilon
),
max_level
(
max_level
),
max_iter
(
max_iter
),
simple
(
simple
)
{}
double
C
,
K
,
p
,
theta
,
gamma
,
mu
,
mu_p
,
init_step
,
step_schedule
,
epsilon
;
size_t
max_level
,
max_iter
;
bool
simple
;
...
...
@@ -201,7 +203,7 @@ struct get_sfdp_layout
pos_t
ll
(
2
,
numeric_limits
<
val_t
>::
max
()),
ur
(
2
,
-
numeric_limits
<
val_t
>::
max
());
vector
<
pos_t
>
group_cm
,
group_cm_tmp
;
vector
<
pos_t
>
group_cm
;
vector
<
vweight_t
>
group_size
;
int
i
,
N
=
num_vertices
(
g
),
HN
=
0
;
...
...
@@ -214,17 +216,13 @@ struct get_sfdp_layout
pos
[
v
].
resize
(
2
,
0
);
size_t
s
=
group
[
v
];
if
(
s
>=
group_cm
.
size
())
{
if
(
s
>=
group_cm
.
size
())
{
group_cm
.
resize
(
s
+
1
);
group_cm_tmp
.
resize
(
s
+
1
);
group_size
.
resize
(
s
+
1
,
0
);
}
group_cm
[
s
].
resize
(
2
,
0
);
group_cm_tmp
[
s
].
resize
(
2
,
0
);
group_size
[
s
]
+=
get
(
vweight
,
v
);
group_cm
.
resize
(
s
+
1
);
group_size
.
resize
(
s
+
1
,
0
);
}
group_cm
[
s
].
resize
(
2
,
0
);
group_size
[
s
]
+=
get
(
vweight
,
v
);
for
(
size_t
j
=
0
;
j
<
2
;
++
j
)
{
...
...
@@ -237,6 +235,8 @@ struct get_sfdp_layout
for
(
size_t
s
=
0
;
s
<
group_size
.
size
();
++
s
)
{
if
(
group_size
[
s
]
==
0
)
continue
;
group_cm
[
s
].
resize
(
2
,
0
);
for
(
size_t
j
=
0
;
j
<
2
;
++
j
)
group_cm
[
s
][
j
]
/=
group_size
[
s
];
...
...
@@ -284,15 +284,7 @@ struct get_sfdp_layout
continue
;
if
(
pin
[
v
])
{
#pragma omp critical
group_cm_tmp
[
group
[
v
]].
resize
(
2
,
0
);
for
(
size_t
l
=
0
;
l
<
2
;
++
l
)
{
group_cm_tmp
[
group
[
v
]][
l
]
+=
pos
[
v
][
l
]
*
get
(
vweight
,
v
);
}
continue
;
}
ftot
[
0
]
=
ftot
[
1
]
=
0
;
...
...
@@ -368,35 +360,75 @@ struct get_sfdp_layout
}
// inter-group attractive forces
for
(
size_t
s
=
0
;
s
<
group_cm
.
size
();
++
s
)
if
(
gamma
>
0
)
{
if
(
s
==
size_t
(
group
[
v
]))
continue
;
val_t
d
=
get_diff
(
group_cm
[
s
],
pos
[
v
],
diff
);
if
(
d
==
0
)
continue
;
double
Kp
=
K
*
pow
(
HN
,
2.
);
val_t
f
=
f_a
(
Kp
,
group_cm
[
s
],
pos
[
v
])
*
gamma
*
\
group_size
[
s
]
*
get
(
vweight
,
v
);
for
(
size_t
l
=
0
;
l
<
2
;
++
l
)
ftot
[
l
]
+=
f
*
diff
[
l
];
for
(
size_t
s
=
0
;
s
<
group_cm
.
size
();
++
s
)
{
if
(
group_size
[
s
]
==
0
)
continue
;
if
(
s
==
size_t
(
group
[
v
]))
continue
;
val_t
d
=
get_diff
(
group_cm
[
s
],
pos
[
v
],
diff
);
if
(
d
==
0
)
continue
;
double
Kp
=
K
*
pow
(
HN
,
2.
);
val_t
f
=
f_a
(
Kp
,
group_cm
[
s
],
pos
[
v
])
*
gamma
*
\
group_size
[
s
]
*
get
(
vweight
,
v
);
for
(
size_t
l
=
0
;
l
<
2
;
++
l
)
ftot
[
l
]
+=
f
*
diff
[
l
];
}
}
// inter-group repulsive forces
if
(
gamma
<
0
)
{
for
(
size_t
s
=
0
;
s
<
group_cm
.
size
();
++
s
)
{
if
(
group_size
[
s
]
==
0
)
continue
;
if
(
s
==
size_t
(
group
[
v
]))
continue
;
val_t
d
=
get_diff
(
group_cm
[
s
],
pos
[
v
],
diff
);
if
(
d
==
0
)
continue
;
val_t
f
=
f_r
(
C
,
K
,
p
,
cm
,
pos
[
v
]);
f
*=
group_size
[
s
]
*
get
(
vweight
,
v
)
*
abs
(
gamma
);
for
(
size_t
l
=
0
;
l
<
2
;
++
l
)
ftot
[
l
]
+=
f
*
diff
[
l
];
}
}
// intra-group attractive forces
if
(
group_size
[
group
[
v
]]
>
1
&&
mu
>
0
)
{
val_t
d
=
get_diff
(
group_cm
[
group
[
v
]],
pos
[
v
],
diff
);
if
(
d
>
0
)
{
double
Kp
=
K
*
pow
(
group_size
[
group
[
v
]],
mu_p
);
val_t
f
=
f_a
(
Kp
,
group_cm
[
group
[
v
]],
pos
[
v
])
*
mu
*
\
group_size
[
group
[
v
]]
*
get
(
vweight
,
v
);
for
(
size_t
l
=
0
;
l
<
2
;
++
l
)
ftot
[
l
]
+=
f
*
diff
[
l
];
}
}
E
+=
pow
(
norm
(
ftot
),
2
);
{
#pragma omp critical
group_cm_tmp
[
group
[
v
]].
resize
(
2
,
0
);
for
(
size_t
l
=
0
;
l
<
2
;
++
l
)
{
group_cm
[
group
[
v
]][
l
]
*=
group_size
[
group
[
v
]];
group_cm
[
group
[
v
]][
l
]
-=
pos
[
v
][
l
];
ftot
[
l
]
*=
step
;
pos
[
v
][
l
]
+=
ftot
[
l
];
nll
[
l
]
=
min
(
pos
[
v
][
l
],
nll
[
l
]);
nur
[
l
]
=
max
(
pos
[
v
][
l
],
nur
[
l
]);
group_cm_tmp
[
group
[
v
]][
l
]
+=
pos
[
v
][
l
]
*
get
(
vweight
,
v
);
group_cm
[
group
[
v
]][
l
]
+=
pos
[
v
][
l
];
group_cm
[
group
[
v
]][
l
]
/=
group_size
[
group
[
v
]];
}
}
delta
+=
norm
(
ftot
);
...
...
@@ -407,16 +439,6 @@ struct get_sfdp_layout
ur
=
nur
;
delta
/=
nmoves
;
for
(
size_t
s
=
0
;
s
<
group_size
.
size
();
++
s
)
{
for
(
size_t
j
=
0
;
j
<
2
;
++
j
)
{
group_cm_tmp
[
s
][
j
]
/=
group_size
[
s
];
group_cm
[
s
][
j
]
=
0
;
}
}
group_cm
.
swap
(
group_cm_tmp
);
if
(
verbose
)
cout
<<
n_iter
<<
" "
<<
E
<<
" "
<<
step
<<
" "
<<
delta
<<
" "
<<
max_level
<<
endl
;
...
...
src/graph_tool/draw/__init__.py
View file @
b0f284a9
...
...
@@ -309,26 +309,30 @@ def arf_layout(g, weight=None, d=0.5, a=10, dt=0.001, epsilon=1e-6,
return
pos
def
_coarse_graph
(
g
,
vweight
,
eweight
,
mivs
=
False
):
if
mivs
:
mivs
=
max_independent_vertex_set
(
g
,
high_deg
=
True
)
u
=
GraphView
(
g
,
vfilt
=
mivs
,
directed
=
False
)
c
=
label_components
(
u
)[
0
]
c
.
fa
+=
1
u
=
GraphView
(
g
,
directed
=
False
)
infect_vertex_property
(
u
,
c
,
list
(
range
(
1
,
c
.
fa
.
max
()
+
1
)))
c
=
g
.
own_property
(
c
)
def
_coarse_graph
(
g
,
vweight
,
eweight
,
mivs
=
False
,
groups
=
None
):
if
groups
is
None
:
if
mivs
:
mivs
=
max_independent_vertex_set
(
g
,
high_deg
=
True
)
u
=
GraphView
(
g
,
vfilt
=
mivs
,
directed
=
False
)
c
=
label_components
(
u
)[
0
]
c
.
fa
+=
1
u
=
GraphView
(
g
,
directed
=
False
)
infect_vertex_property
(
u
,
c
,
list
(
range
(
1
,
c
.
fa
.
max
()
+
1
)))
c
=
g
.
own_property
(
c
)
else
:
mivs
=
None
m
=
max_cardinality_matching
(
GraphView
(
g
,
directed
=
False
),
heuristic
=
True
,
weight
=
eweight
,
minimize
=
False
)
u
=
GraphView
(
g
,
efilt
=
m
,
directed
=
False
)
c
=
label_components
(
u
)[
0
]
c
=
g
.
own_property
(
c
)
u
=
GraphView
(
g
,
directed
=
False
)
else
:
mivs
=
None
m
=
max_cardinality_matching
(
GraphView
(
g
,
directed
=
False
),
heuristic
=
True
,
weight
=
eweight
,
minimize
=
False
)
u
=
GraphView
(
g
,
efilt
=
m
,
directed
=
False
)
c
=
label_components
(
u
)[
0
]
c
=
g
.
own_property
(
c
)
u
=
GraphView
(
g
,
directed
=
False
)
cg
,
cc
,
vcount
,
ecount
=
condensation_graph
(
u
,
c
,
vweight
,
eweight
)
c
=
groups
cg
,
cc
,
vcount
,
ecount
=
condensation_graph
(
g
,
c
,
vweight
,
eweight
)
return
cg
,
cc
,
vcount
,
ecount
,
c
,
mivs
...
...
@@ -368,13 +372,14 @@ def _avg_edge_distance(g, pos):
def
coarse_graphs
(
g
,
method
=
"hybrid"
,
mivs_thres
=
0.9
,
ec_thres
=
0.75
,
weighted_coarse
=
False
,
eweight
=
None
,
vweight
=
None
,
verbose
=
False
):
groups
=
None
,
verbose
=
False
):
cg
=
[[
g
,
None
,
None
,
None
,
None
,
None
]]
if
weighted_coarse
:
cg
[
-
1
][
2
],
cg
[
-
1
][
3
]
=
vweight
,
eweight
mivs
=
not
(
method
in
[
"hybrid"
,
"ec"
])
while
True
:
u
=
_coarse_graph
(
cg
[
-
1
][
0
],
cg
[
-
1
][
2
],
cg
[
-
1
][
3
],
mivs
)
u
=
_coarse_graph
(
cg
[
-
1
][
0
],
cg
[
-
1
][
2
],
cg
[
-
1
][
3
],
mivs
,
groups
)
groups
=
None
thres
=
mivs_thres
if
mivs
else
ec_thres
if
u
[
0
].
num_vertices
()
>=
thres
*
cg
[
-
1
][
0
].
num_vertices
():
if
method
==
"hybrid"
and
not
mivs
:
...
...
@@ -425,12 +430,12 @@ def coarse_graphs(g, method="hybrid", mivs_thres=0.9, ec_thres=0.75,
Ks
[
i
]
/
1000.
,
mivs
)
def
sfdp_layout
(
g
,
vweight
=
None
,
eweight
=
None
,
pin
=
None
,
C
=
0.2
,
K
=
None
,
p
=
2.
,
theta
=
0.6
,
max_level
=
11
,
gamma
=
1.
,
init_step
=
None
,
cooling_step
=
0.9
,
adaptive_cooling
=
True
,
epsilon
=
1e-1
,
max_iter
=
0
,
pos
=
None
,
multilevel
=
None
,
coarse_method
=
"hybrid"
,
mivs_thres
=
0.9
,
ec_thres
=
0.75
,
weighted_coarse
=
False
,
verbose
=
False
):
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.
,
init_step
=
None
,
cooling_step
=
0.9
,
adaptive_cooling
=
True
,
epsilon
=
1e-1
,
max_iter
=
0
,
pos
=
None
,
multilevel
=
None
,
coarse_method
=
"hybrid"
,
mivs_thres
=
0.9
,
ec_thres
=
0.75
,
weighted_coarse
=
False
,
verbose
=
False
):
r
"""Obtain the SFDP spring-block layout of the graph.
Parameters
...
...
@@ -442,8 +447,11 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
eweight : :class:`~graph_tool.PropertyMap` (optional, default: ``None``)
An edge property map with the respective weights.
pin : :class:`~graph_tool.PropertyMap` (optional, default: ``None``)
A vertex property map with with boolean values, which, if given,
specifies the vertices which will not have their positions modified.
A vertex property map with boolean values, which, if given,
specify the vertices which will not have their positions modified.
groups : :class:`~graph_tool.PropertyMap` (optional, default: ``None``)
A vertex property map with group assignments. Vertices belonging to the
same group will be put close together.
C : float (optional, default: ``0.2``)
Relative strength of repulsive forces.
K : float (optional, default: ``None``)
...
...
@@ -456,7 +464,14 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
max_level : int (optional, default: ``11``)
Maximum quadtree level.
gamma : float (optional, default: ``1.0``)
Strength of the attractive force between connected components.
Strength of the attractive force between connected components, or group
assignments.
mu : float (optional, default: ``0.0``)
Strength of the attractive force between vertices of the same connected
component, or group assignment.
mu_p : float (optional, default: ``1.0``)
Scaling exponent of the attractive force between vertices of the same
connected component, or group assignment.
init_step : float (optional, default: ``None``)
Initial update step. If not provided, it will be chosen automatically.
cooling_step : float (optional, default: ``0.9``)
...
...
@@ -525,8 +540,11 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
g
=
GraphView
(
g
,
directed
=
False
)
if
pin
is
not
None
and
pin
.
value_type
()
!=
"bool"
:
raise
ValueError
(
"'pin' property must be of type 'bool'."
)
if
pin
is
not
None
:
if
pin
.
value_type
()
!=
"bool"
:
raise
ValueError
(
"'pin' property must be of type 'bool'."
)
else
:
pin
=
g
.
new_vertex_property
(
"bool"
)
if
K
is
None
:
K
=
_avg_edge_distance
(
g
,
pos
)
...
...
@@ -546,9 +564,9 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
weighted_coarse
=
weighted_coarse
,
eweight
=
eweight
,
vweight
=
vweight
,
groups
=
groups
,
verbose
=
verbose
)
count
=
0
for
u
,
pos
,
K
,
vcount
,
ecount
in
cgs
:
for
count
,
(
u
,
pos
,
K
,
vcount
,
ecount
)
in
enumerate
(
cgs
):
if
verbose
:
print
(
"Positioning level:"
,
count
,
u
.
num_vertices
(),
end
=
' '
)
print
(
"with K ="
,
K
,
"..."
)
...
...
@@ -557,8 +575,10 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
pos
=
sfdp_layout
(
u
,
pos
=
pos
,
vweight
=
vcount
if
weighted_coarse
else
None
,
eweight
=
ecount
if
weighted_coarse
else
None
,
groups
=
None
if
u
.
num_vertices
()
<
g
.
num_vertices
()
else
groups
,
C
=
C
,
K
=
K
,
p
=
p
,
theta
=
theta
,
gamma
=
gamma
,
epsilon
=
epsilon
,
theta
=
theta
,
gamma
=
gamma
,
mu
=
mu
,
mu_p
=
mu_p
,
epsilon
=
epsilon
,
max_iter
=
max_iter
,
cooling_step
=
cooling_step
,
adaptive_cooling
=
False
,
...
...
@@ -578,12 +598,15 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
return
pos
if
g
.
num_vertices
()
<=
50
:
max_level
=
0
groups
=
label_components
(
g
)[
0
]
if
groups
is
None
:
groups
=
label_components
(
g
)[
0
]
elif
groups
.
value_type
()
!=
"int32_t"
:
raise
ValueError
(
"'groups' property must be of type 'int32_t'."
)
libgraph_tool_layout
.
sfdp_layout
(
g
.
_Graph__graph
,
_prop
(
"v"
,
g
,
pos
),
_prop
(
"v"
,
g
,
vweight
),
_prop
(
"e"
,
g
,
eweight
),
_prop
(
"v"
,
g
,
pin
),
(
C
,
K
,
p
,
gamma
,
_prop
(
"v"
,
g
,
groups
)),
(
C
,
K
,
p
,
gamma
,
mu
,
mu_p
,
_prop
(
"v"
,
g
,
groups
)),
theta
,
init_step
,
cooling_step
,
max_level
,
epsilon
,
max_iter
,
not
adaptive_cooling
,
verbose
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment