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
62055e30
Commit
62055e30
authored
Aug 08, 2016
by
Tiago Peixoto
Browse files
inference.blockmodel: simplify and speedup vertex movements
parent
74cfb8a4
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/graph/inference/graph_blockmodel.cc
View file @
62055e30
...
...
@@ -153,6 +153,8 @@ void export_blockmodel_state()
&
state_t
::
remove_vertex
;
void
(
state_t
::*
add_vertex
)(
size_t
,
size_t
)
=
&
state_t
::
add_vertex
;
void
(
state_t
::*
move_vertex
)(
size_t
,
size_t
)
=
&
state_t
::
move_vertex
;
void
(
state_t
::*
remove_vertices
)(
python
::
object
)
=
&
state_t
::
remove_vertices
;
void
(
state_t
::*
add_vertices
)(
python
::
object
,
python
::
object
)
=
...
...
@@ -180,7 +182,7 @@ void export_blockmodel_state()
.
def
(
"add_vertex"
,
add_vertex
)
.
def
(
"remove_vertices"
,
remove_vertices
)
.
def
(
"add_vertices"
,
add_vertices
)
.
def
(
"move_vertex"
,
&
state_t
::
move_vertex
)
.
def
(
"move_vertex"
,
move_vertex
)
.
def
(
"move_vertices"
,
move_vertices
)
.
def
(
"set_partition"
,
set_partition
)
.
def
(
"virtual_move"
,
virtual_move
)
...
...
src/graph/inference/graph_blockmodel.hh
View file @
62055e30
...
...
@@ -110,10 +110,11 @@ public:
_c_bdrec
(
_bdrec
.
get_checked
()),
_vweight
(
uncheck
(
__avweight
,
typename
std
::
add_pointer
<
vweight_t
>::
type
())),
_eweight
(
uncheck
(
__aeweight
,
typename
std
::
add_pointer
<
eweight_t
>::
type
())),
_emat
(
_g
,
_b
,
_bg
,
rng
),
_emat
(
_bg
,
rng
),
_neighbour_sampler
(
get
(
vertex_index_t
(),
_g
),
num_vertices
(
_g
)),
_m_entries
(
num_vertices
(
_bg
)),
_coupled_state
(
nullptr
)
_coupled_state
(
nullptr
),
_gstate
(
this
)
{
rebuild_neighbour_sampler
();
_empty_blocks
.
clear
();
...
...
@@ -139,158 +140,125 @@ public:
_emat
(
other
.
_emat
),
_neighbour_sampler
(
other
.
_neighbour_sampler
),
_m_entries
(
num_vertices
(
_bg
)),
_coupled_state
(
nullptr
)
_coupled_state
(
nullptr
),
_gstate
(
other
.
_gstate
==
&
other
?
this
:
other
.
_gstate
)
{
if
(
other
.
is_partition_stats_enabled
())
enable_partition_stats
();
}
template
<
bool
Add
,
class
BEdge
,
class
EFilt
,
class
EOP
>
void
modify_vertex
(
size_t
v
,
size_t
r
,
BEdge
&&
bedge
,
EFilt
&&
efilt
,
EOP
&&
eop
)
{
typedef
typename
graph_traits
<
g_t
>::
vertex_descriptor
vertex_t
;
for
(
auto
e
:
out_edges_range
(
v
,
_g
))
{
if
(
efilt
(
e
)
||
_eweight
[
e
]
==
0
)
continue
;
vertex_t
u
=
target
(
e
,
_g
);
vertex_t
s
=
_b
[
u
];
auto
&
me
=
bedge
[
e
];
if
(
Add
)
{
if
(
me
!=
_emat
.
get_null_edge
())
{
assert
(
u
==
v
);
continue
;
}
if
(
u
==
v
)
s
=
r
;
me
=
_emat
.
get_me
(
r
,
s
);
if
(
me
==
_emat
.
get_null_edge
())
{
me
=
add_edge
(
r
,
s
,
_bg
).
first
;
_emat
.
put_me
(
r
,
s
,
me
);
_c_mrs
[
me
]
=
0
;
_c_brec
[
me
]
=
0
;
_c_bdrec
[
me
]
=
0
;
}
// =========================================================================
// State modification
// =========================================================================
assert
(
_emat
.
get_bedge
(
e
)
!=
_emat
.
get_null_edge
());
}
else
{
if
(
me
==
_emat
.
get_null_edge
())
{
assert
(
u
==
v
);
continue
;
}
}
assert
(
me
!=
_emat
.
get_null_edge
());
assert
(
me
==
_emat
.
get_me
(
r
,
s
));
assert
(
std
::
min
(
source
(
me
,
_bg
),
target
(
me
,
_bg
))
==
std
::
min
(
r
,
s
));
assert
(
std
::
max
(
source
(
me
,
_bg
),
target
(
me
,
_bg
))
==
std
::
max
(
r
,
s
));
auto
ew
=
_eweight
[
e
];
if
(
Add
)
{
_mrs
[
me
]
+=
ew
;
_mrp
[
r
]
+=
ew
;
_mrm
[
s
]
+=
ew
;
eop
(
e
,
me
);
}
else
template
<
class
MEntries
,
class
Efilt
,
class
GetB
>
void
get_move_entries
(
size_t
v
,
size_t
r
,
size_t
nr
,
MEntries
&
m_entries
,
Efilt
&&
efilt
,
GetB
&&
get_b
)
{
auto
&
gs
=
*
_gstate
;
auto
mv_entries
=
[
&
](
auto
&&
...
args
)
{
_mrs
[
me
]
-=
ew
;
_mrp
[
r
]
-=
ew
;
_mrm
[
s
]
-=
ew
;
eop
(
e
,
me
);
assert
(
_mrs
[
me
]
>=
0
);
if
(
_mrs
[
me
]
==
0
)
_emat
.
remove_me
(
r
,
s
,
me
,
_bg
);
me
=
_emat
.
get_null_edge
();
}
}
move_entries
(
v
,
r
,
nr
,
get_b
,
gs
.
_g
,
gs
.
_eweight
,
m_entries
,
efilt
,
is_loop_nop
(),
args
...);
};
for
(
auto
e
:
in_edges_range
(
v
,
_g
)
)
switch
(
_rec_type
)
{
if
(
efilt
(
e
))
continue
;
vertex_t
u
=
source
(
e
,
_g
);
if
(
u
==
v
)
continue
;
vertex_t
s
=
_b
[
u
];
auto
&
me
=
_emat
.
get_bedge
(
e
);
case
weight_type
::
POSITIVE
:
// positive weights
mv_entries
(
gs
.
_rec
);
break
;
case
weight_type
::
SIGNED
:
// positive and negative weights
mv_entries
(
gs
.
_rec
,
gs
.
_drec
);
break
;
default:
// no weights
mv_entries
();
}
}
if
(
Add
)
{
me
=
_emat
.
get_me
(
s
,
r
);
if
(
me
==
_emat
.
get_null_edge
())
{
me
=
add_edge
(
s
,
r
,
_bg
).
first
;
_emat
.
put_me
(
s
,
r
,
me
);
_c_mrs
[
me
]
=
0
;
_c_brec
[
me
]
=
0
;
_c_bdrec
[
me
]
=
0
;
}
assert
(
_emat
.
get_bedge
(
e
)
!=
_emat
.
get_null_edge
());
}
template
<
class
MEntries
>
void
get_move_entries
(
size_t
v
,
size_t
r
,
size_t
nr
,
MEntries
&
m_entries
)
{
get_move_entries
(
v
,
r
,
nr
,
m_entries
,
[](
auto
)
{
return
false
;
},
[
&
](
auto
u
)
->
auto
&
{
return
this
->
_b
[
u
];
});
}
assert
(
me
!=
_emat
.
get_null_edge
());
assert
(
me
==
_emat
.
get_me
(
s
,
r
));
assert
(
std
::
min
(
source
(
me
,
_bg
),
target
(
me
,
_bg
))
==
std
::
min
(
r
,
s
));
assert
(
std
::
max
(
source
(
me
,
_bg
),
target
(
me
,
_bg
))
==
std
::
max
(
r
,
s
));
auto
ew
=
_eweight
[
e
];
template
<
bool
Add
,
class
EFilt
,
class
GetB
>
void
modify_vertex
(
size_t
v
,
size_t
r
,
EFilt
&&
efilt
,
GetB
&&
get_b
)
{
_m_entries
.
clear
();
if
(
Add
)
get_move_entries
(
v
,
null_group
,
r
,
_m_entries
,
efilt
,
get_b
);
else
get_move_entries
(
v
,
r
,
null_group
,
_m_entries
,
efilt
,
get_b
);
if
(
Add
)
{
_mrs
[
me
]
+=
ew
;
_mrp
[
s
]
+=
ew
;
_mrm
[
r
]
+=
ew
;
eop
(
e
,
me
);
}
else
entries_op
(
_m_entries
,
_emat
,
[
&
](
auto
r
,
auto
s
,
auto
&
me
,
auto
&
delta
)
{
if
(
Add
&&
me
==
this
->
_emat
.
get_null_edge
())
{
me
=
add_edge
(
r
,
s
,
this
->
_bg
).
first
;
_emat
.
put_me
(
r
,
s
,
me
);
this
->
_c_mrs
[
me
]
=
0
;
this
->
_c_brec
[
me
]
=
0
;
this
->
_c_bdrec
[
me
]
=
0
;
}
this
->
_mrs
[
me
]
+=
get
<
0
>
(
delta
);
this
->
_mrp
[
r
]
+=
get
<
0
>
(
delta
);
this
->
_mrm
[
s
]
+=
get
<
0
>
(
delta
);
switch
(
this
->
_rec_type
)
{
case
weight_type
::
SIGNED
:
// signed weights
this
->
_bdrec
[
me
]
+=
get
<
2
>
(
delta
);
case
weight_type
::
POSITIVE
:
// positive weights
this
->
_brec
[
me
]
+=
get
<
1
>
(
delta
);
}
});
if
(
_rec_type
==
weight_type
::
DELTA_T
)
// waiting times
{
if
(
_ignore_degrees
[
v
]
>
0
)
{
_mrs
[
me
]
-=
ew
;
_mrp
[
s
]
-=
ew
;
_mrm
[
r
]
-=
ew
;
eop
(
e
,
me
);
if
(
_mrs
[
me
]
==
0
)
_emat
.
remove_me
(
s
,
r
,
me
,
_bg
);
me
=
_emat
.
get_null_edge
();
double
dt
=
out_degreeS
()(
v
,
_g
,
_rec
);
auto
r
=
_b
[
v
];
if
(
Add
)
_brecsum
[
r
]
+=
dt
;
else
_brecsum
[
r
]
-=
dt
;
}
}
if
(
Add
)
{
auto
&
b_v
=
get_b
(
v
);
b_v
=
r
;
add_partition_node
(
v
,
r
);
}
else
{
remove_partition_node
(
v
,
r
);
}
}
void
remove_partition_node
(
size_t
v
,
size_t
r
)
{
_wr
[
r
]
-=
_vweight
[
v
];
auto
&
gs
=
*
_gstate
;
_wr
[
r
]
-=
gs
.
_vweight
[
v
];
if
(
!
_egroups
.
empty
())
_egroups
.
remove_vertex
(
v
,
r
,
_g
);
_egroups
.
remove_vertex
(
v
,
r
,
gs
.
_g
);
if
(
is_partition_stats_enabled
())
get_partition_stats
(
v
).
remove_vertex
(
v
,
r
,
_deg_corr
,
_g
,
_vweight
,
_eweight
,
_degs
);
get_partition_stats
(
v
).
remove_vertex
(
v
,
r
,
_deg_corr
,
gs
.
_g
,
gs
.
_vweight
,
gs
.
_eweight
,
gs
.
_degs
);
if
(
_vweight
[
v
]
>
0
&&
_wr
[
r
]
==
0
)
if
(
gs
.
_vweight
[
v
]
>
0
&&
_wr
[
r
]
==
0
)
{
remove_element
(
_candidate_blocks
,
_candidate_pos
,
r
);
add_element
(
_empty_blocks
,
_empty_pos
,
r
);
...
...
@@ -299,64 +267,50 @@ public:
void
add_partition_node
(
size_t
v
,
size_t
r
)
{
_b
[
v
]
=
r
;
_wr
[
r
]
+=
_vweight
[
v
];
auto
&
gs
=
*
_gstate
;
_wr
[
r
]
+=
gs
.
_vweight
[
v
];
if
(
!
_egroups
.
empty
())
_egroups
.
add_vertex
(
v
,
r
,
_eweight
,
_g
);
_egroups
.
add_vertex
(
v
,
r
,
gs
.
_eweight
,
gs
.
_g
);
if
(
is_partition_stats_enabled
())
get_partition_stats
(
v
).
add_vertex
(
v
,
r
,
_deg_corr
,
_g
,
_vweight
,
_eweight
,
_degs
);
get_partition_stats
(
v
).
add_vertex
(
v
,
r
,
_deg_corr
,
gs
.
_g
,
gs
.
_vweight
,
gs
.
_eweight
,
gs
.
_degs
);
if
(
_vweight
[
v
]
>
0
&&
_wr
[
r
]
==
_vweight
[
v
])
if
(
gs
.
_vweight
[
v
]
>
0
&&
_wr
[
r
]
==
gs
.
_vweight
[
v
])
{
remove_element
(
_empty_blocks
,
_empty_pos
,
r
);
add_element
(
_candidate_blocks
,
_candidate_pos
,
r
);
}
}
template
<
class
BEdge
,
class
EFilt
>
void
remove_vertex
(
size_t
v
,
BEdge
&&
bedge
,
EFilt
&&
efilt
)
template
<
class
EFilt
,
class
GetB
>
void
remove_vertex
(
size_t
v
,
size_t
r
,
EFilt
&&
efilt
,
GetB
&&
get_b
)
{
size_t
r
=
_b
[
v
];
switch
(
_rec_type
)
{
case
weight_type
::
POSITIVE
:
// positive weights
modify_vertex
<
false
>
(
v
,
r
,
bedge
,
efilt
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
-=
this
->
_rec
[
e
];
});
break
;
case
weight_type
::
SIGNED
:
// positive and negative weights
modify_vertex
<
false
>
(
v
,
r
,
bedge
,
efilt
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
-=
this
->
_rec
[
e
];
this
->
_bdrec
[
me
]
-=
this
->
_drec
[
e
];
});
break
;
case
weight_type
::
DELTA_T
:
// waiting times
if
(
_ignore_degrees
[
v
]
>
0
)
{
double
dt
=
out_degreeS
()(
v
,
_g
,
_rec
);
auto
r
=
_b
[
v
];
_brecsum
[
r
]
-=
dt
;
}
case
weight_type
::
NONE
:
// no weights
modify_vertex
<
false
>
(
v
,
r
,
bedge
,
efilt
,
[](
auto
&
,
auto
&
){});
}
modify_vertex
<
false
>
(
v
,
r
,
efilt
,
get_b
);
}
template
<
class
EFilt
>
void
remove_vertex
(
size_t
v
,
size_t
r
,
EFilt
&&
efilt
)
{
remove_vertex
(
v
,
r
,
efilt
,
[
&
](
auto
u
)
->
auto
&
{
return
this
->
_b
[
u
];
});
}
void
remove_vertex
(
size_t
v
,
size_t
r
)
{
remove_vertex
(
v
,
r
,
[](
auto
&
)
{
return
false
;
});
}
void
remove_vertex
(
size_t
v
)
{
remove_vertex
(
v
,
_emat
.
get_bedge_map
(),
[](
auto
&
){
return
false
;
}
);
size_t
r
=
_b
[
v
];
remove_vertex
(
v
,
r
);
}
template
<
class
Vlist
,
class
EOP
>
void
remove_vertices
(
Vlist
&
vs
,
EOP
&&
eop
)
template
<
class
Vlist
>
void
remove_vertices
(
Vlist
&
vs
)
{
typedef
typename
graph_traits
<
g_t
>::
vertex_descriptor
vertex_t
;
typedef
typename
graph_traits
<
g_t
>::
edge_descriptor
edges_t
;
...
...
@@ -374,9 +328,8 @@ public:
}
}
auto
&
bedge
=
_emat
.
get_bedge_map
();
for
(
auto
v
:
vset
)
remove_vertex
(
v
,
bedge
,
remove_vertex
(
v
,
_b
[
v
]
,
[
&
](
auto
&
e
)
{
return
eset
.
find
(
e
)
!=
eset
.
end
();
});
for
(
auto
&
e
:
eset
)
...
...
@@ -386,7 +339,7 @@ public:
vertex_t
r
=
_b
[
v
];
vertex_t
s
=
_b
[
u
];
auto
&
me
=
_emat
.
get_
bedge
(
e
);
auto
me
=
_emat
.
get_
me
(
r
,
s
);
auto
ew
=
_eweight
[
e
];
_mrs
[
me
]
-=
ew
;
...
...
@@ -396,88 +349,49 @@ public:
_mrp
[
r
]
-=
ew
;
_mrm
[
s
]
-=
ew
;
eop
(
e
,
me
);
switch
(
_rec_type
)
{
case
weight_type
::
SIGNED
:
// signed weights
_bdrec
[
me
]
-=
_drec
[
e
];
case
weight_type
::
POSITIVE
:
// positive weights
_brec
[
me
]
-=
_rec
[
e
];
}
if
(
_mrs
[
me
]
==
0
)
_emat
.
remove_me
(
r
,
s
,
me
,
_bg
);
}
}
template
<
class
Vec
>
void
remove_vertices
(
Vec
&
vs
)
{
switch
(
_rec_type
)
{
case
weight_type
::
POSITIVE
:
// positive weights
remove_vertices
(
vs
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
-=
this
->
_rec
[
e
];
});
break
;
case
weight_type
::
SIGNED
:
// positive and negative weights
remove_vertices
(
vs
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
-=
this
->
_rec
[
e
];
this
->
_bdrec
[
me
]
-=
this
->
_drec
[
e
];});
break
;
case
weight_type
::
DELTA_T
:
// waiting times
for
(
auto
v
:
vs
)
{
if
(
_ignore_degrees
[
v
]
>
0
)
{
double
dt
=
out_degreeS
()(
v
,
_g
,
_rec
);
auto
r
=
_b
[
v
];
_brecsum
[
r
]
-=
dt
;
}
}
case
weight_type
::
NONE
:
// no weights
remove_vertices
(
vs
,
[
&
](
auto
&
,
auto
&
)
{});
}
}
void
remove_vertices
(
python
::
object
ovs
)
{
multi_array_ref
<
uint64_t
,
1
>
vs
=
get_array
<
uint64_t
,
1
>
(
ovs
);
remove_vertices
(
vs
);
}
template
<
class
BEdge
,
class
Efilt
>
void
add_vertex
(
size_t
v
,
size_t
r
,
BEdge
&&
bedge
,
Efilt
&&
efilt
)
template
<
class
Efilt
,
class
GetB
>
void
add_vertex
(
size_t
v
,
size_t
r
,
Efilt
&&
efilt
,
GetB
&&
get_b
)
{
switch
(
_rec_type
)
{
case
weight_type
::
POSITIVE
:
// positive weights
modify_vertex
<
true
>
(
v
,
r
,
bedge
,
efilt
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
+=
this
->
_rec
[
e
];
});
break
;
case
weight_type
::
SIGNED
:
// positive and negative weights
modify_vertex
<
true
>
(
v
,
r
,
bedge
,
efilt
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
+=
this
->
_rec
[
e
];
this
->
_bdrec
[
me
]
+=
this
->
_drec
[
e
];
});
break
;
case
weight_type
::
DELTA_T
:
// waiting times
if
(
_ignore_degrees
[
v
]
>
0
)
{
double
dt
=
out_degreeS
()(
v
,
_g
,
_rec
);
_brecsum
[
r
]
+=
dt
;
}
case
weight_type
::
NONE
:
// no weights
modify_vertex
<
true
>
(
v
,
r
,
bedge
,
efilt
,
[](
auto
&
,
auto
&
){});
}
modify_vertex
<
true
>
(
v
,
r
,
efilt
,
get_b
);
}
template
<
class
Efilt
>
void
add_vertex
(
size_t
v
,
size_t
r
,
Efilt
&&
efilt
)
{
add_vertex
(
v
,
r
,
efilt
,
[
&
](
auto
u
)
->
auto
&
{
return
this
->
_b
[
u
];
});
}
void
add_vertex
(
size_t
v
,
size_t
r
)
{
add_vertex
(
v
,
r
,
_emat
.
get_bedge_map
(),
[](
auto
&
){
return
false
;
});
add_vertex
(
v
,
r
,
[](
auto
&
){
return
false
;
});
}
template
<
class
Vlist
,
class
Blist
,
class
EOP
>
void
add_vertices
(
Vlist
&
vs
,
Blist
&
rs
,
EOP
&&
eop
)
template
<
class
Vlist
,
class
Blist
>
void
add_vertices
(
Vlist
&
vs
,
Blist
&
rs
)
{
if
(
vs
.
size
()
!=
rs
.
size
())
throw
ValueException
(
"vertex and group lists do not have the same size"
);
typedef
typename
graph_traits
<
g_t
>::
vertex_descriptor
vertex_t
;
gt_hash_map
<
vertex_t
,
size_t
>
vset
;
...
...
@@ -498,10 +412,8 @@ public:
}
}
auto
bedge
=
_emat
.
get_bedge_map
().
get_checked
();
for
(
auto
vr
:
vset
)
add_vertex
(
vr
.
first
,
vr
.
second
,
bedge
,
add_vertex
(
vr
.
first
,
vr
.
second
,
[
&
](
auto
&
e
){
return
eset
.
find
(
e
)
!=
eset
.
end
();
});
for
(
auto
e
:
eset
)
...
...
@@ -522,9 +434,6 @@ public:
_c_bdrec
[
me
]
=
0
;
}
bedge
[
e
]
=
me
;
assert
(
_emat
.
get_bedge
(
e
)
!=
_emat
.
get_null_edge
());
assert
(
me
==
_emat
.
get_me
(
r
,
s
));
auto
ew
=
_eweight
[
e
];
...
...
@@ -533,39 +442,13 @@ public:
_mrp
[
r
]
+=
ew
;
_mrm
[
s
]
+=
ew
;
eop
(
e
,
me
);
}
}
template
<
class
Vs
,
class
Rs
>
void
add_vertices
(
Vs
&
vs
,
Rs
&
rs
)
{
if
(
vs
.
size
()
!=
rs
.
size
())
throw
ValueException
(
"vertex and group lists do not have the same size"
);
switch
(
_rec_type
)
{
case
weight_type
::
POSITIVE
:
// positive weights
add_vertices
(
vs
,
rs
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
+=
this
->
_rec
[
e
];
});
break
;
case
weight_type
::
SIGNED
:
// positive and negative weights
add_vertices
(
vs
,
rs
,
[
&
](
auto
&
e
,
auto
&
me
)
{
this
->
_brec
[
me
]
+=
this
->
_rec
[
e
];
this
->
_bdrec
[
me
]
+=
this
->
_drec
[
e
];});
break
;
case
weight_type
::
DELTA_T
:
// waiting times
for
(
size_t
i
=
0
;
i
<
rs
.
size
();
++
i
)
switch
(
_rec_type
)
{
auto
v
=
vs
[
i
];
if
(
_ignore_degrees
[
v
]
>
0
)
{
double
dt
=
out_degreeS
()(
v
,
_g
,
_rec
);
auto
r
=
rs
[
i
];
_brecsum
[
r
]
+=
dt
;
}
case
weight_type
::
SIGNED
:
// signed weights
_bdrec
[
me
]
+=
_drec
[
e
];
case
weight_type
::
POSITIVE
:
// positive weights
_brec
[
me
]
+=
_rec
[
e
];
}
case
weight_type
::
NONE
:
// no weights
add_vertices
(
vs
,
rs
,
[
&
](
auto
&
,
auto
&
)
{});
}
}
...
...
@@ -585,9 +468,10 @@ public:
}
// move a vertex from its current block to block nr
void
move_vertex
(
size_t
v
,
size_t
nr
)
template
<
class
GetB
>
void
move_vertex
(
size_t
v
,
size_t
nr
,
GetB
&&
get_b
)
{
size_t
r
=
_b
[
v
]
;
size_t
r
=
get_b
(
v
)
;
if
(
r
==
nr
)
return
;
...
...
@@ -595,8 +479,8 @@ public:
if
(
!
allow_move
(
r
,
nr
))
throw
ValueException
(
"cannot move vertex across clabel barriers"
);
remove_vertex
(
v
);
add_vertex
(
v
,
nr
);
remove_vertex
(
v
,
r
,
[](
auto
&
)
{
return
false
;},
get_b
);
add_vertex
(
v
,
nr
,
[](
auto
&
)
{
return
false
;},
get_b
);