Question about overlapping DCSBM with independent layers

Dear Professor Peixoto,

Could you please provide the code for generating Figure 9 in your paper <Inferring the mesoscale structure of layered, edge-valued and time-varying networks> ? That could be very helpful as a nice example for how to generate similar figures for my paper :slight_smile:

I have used following code to model a time varying (5 time point) weighted edge network.

state = gt.minimize_blockmodel_dl(
    g,
    state = gt.LayeredBlockState,
    state_args=dict(
        deg_corr=True,        
        overlap=True,         
        ec=g.ep.layer,
        layers=True,
        recs=[g.ep.weight],
        rec_types=["real-normal"]  
    )
)

[bv,r1,r2,r3] = state.get_overlap_blocks()

for v in g.vertices():
    community_ids = bv[v]
    print(f"node {int(v)} is in: {community_ids}")

And I got the print for each node’s membership:

node 0 is in: array([ 555, 1631, 9441], dtype=int32)
node 1 is in: array([ 555, 1631, 9441], dtype=int32)
node 2 is in: array([ 555, 1631, 9441], dtype=int32)
node 3 is in: array([ 555, 1631, 9441], dtype=int32)
node 4 is in: array([ 555, 1631, 9441], dtype=int32)
node 5 is in: array([ 555, 1631, 9441], dtype=int32)
…

Could I know how to draw each layer’s figure in Figure 9 ? Should I do sth like this ?:

# only draw layer 0 
layer_index = 0
sub = gt.GraphView(g, efilt=lambda e: g.ep.layer[e] == layer_index)
g = sub
state.draw(
    edge_color=g.ep.weight.copy("double"),
    edge_gradient=[],
    edge_pen_width=gt.prop_to_size(g.ep.weight, 1, 5),
    eorder=g.ep.weight,
    output=f"layer_{layer_index}.svg"
)

Could I know how can I know which node’s membership belongs to which time point (layer) ? Should I do sth like this ?:

from collections import defaultdict
membership_per_layer = defaultdict(set)

edge_blocks_map = state.get_edge_blocks()
layer_prop = g.ep["layer"]

for e in g.edges():
    L = layer_prop[e] 
    edge_halfedges = edge_blocks_map[e]

    node0 = int(e.source())
    node1 = int(e.target())

    half0_groups = edge_halfedges[0]
    half1_groups = edge_halfedges[1]

    if isinstance(half0_groups, int):
        membership_per_layer[(node0, L)].add(half0_groups)
    else:
        for gr in half0_groups:
            membership_per_layer[(node0, L)].add(gr)

    if isinstance(half1_groups, int):
        membership_per_layer[(node1, L)].add(half1_groups)
    else:
        for gr in half1_groups:
            membership_per_layer[(node1, L)].add(gr)

Thank you so much for your kind help !

Your approach seems valid, as far as I can tell.