Question about potential bugs and input format

Hi,

I couldn’t log in to Gitlab for some reason, so I decided to post this here.

I have a few questions regarding graph-tool. The first two questions are about potential bugs.

  1. In graph-tool (version 2.58), it doesn’t allow me to use PPBlockState as a base_type for the lowermost level of NestedBlockState. It didn’t work in version 2.55 either. It returns the following error:
TypeError: PPBlockState.__init__() got an unexpected keyword argument 'Lrecdx'

Is this a bug or just a missing implementation?

  1. In version 2.55, B_max worked correctly, but in version 2.58, when provided for multilevel_mcmc_sweep in minimize_nested_blockmodel_dl(), it doesn’t follow the B_max value. It returns partitions with a larger number of blocks than the predefined B_max. Bug?

  2. It is very unclear to me how to provide the initial partition for bs in NestedBlockState. I have tried multiple approaches, but all of them fail to return the correct summary (print_summary()). I already have a partition, and I just want to compute the entropy for it. My approach was the following:

Assume I have a graph with 1000 nodes. On the first level, I have four blocks. On the second level, I have two blocks, and finally, on the third level, one block containing all the nodes.

I created a VertexPropertyMap for each level that contains 1000 elements. For each level, there is a VPM that indicates the membership of all the 1000 nodes. Obviously, the number of unique elements is, for the first level, 4; for the second level, 2; and for the third level, 1. This doesn’t seem to be the right approach, as the print_summary() returns the wrong number of blocks for each level. How am I supposed to “encode” my initial partition correctly?

Thanks!

Neither. It does not make sense to use PPBlockState as the base type for NestedBlockState. This is not mentioned anywhere in the documentation, and it was never supposed to work.

This has been fixed in the current git version.

The nodes in a given level are the groups in the level below. Therefore the number of nodes will decrease in the higher levels. For example, the following is a valid nested partition:

bs = [[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3],
      [0, 0, 1, 2],
      [0, 0, 1],
      [0, 0],
      [0]]

Much appreciated, all makes sense now. Thank you Tiago.

I am using python 3.12.0, graph-tool 2.68 and providing initial partition in a way you propose. However, I am getting the following error now:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[34], line 1
----> 1 state = minimize_nested_blockmodel_dl(g, init_bs=bs)

File ~/miniconda3/envs/gt3/lib/python3.12/site-packages/graph_tool/inference/minimize.py:227, in minimize_nested_blockmodel_dl(g, init_bs, state, state_args, multilevel_mcmc_args)
    137 def minimize_nested_blockmodel_dl(g, init_bs=None,
    138                                   state=NestedBlockState, state_args={},
    139                                   multilevel_mcmc_args={}):
    140     r"""Fit the nested stochastic block model, by minimizing its description length
    141     using an agglomerative heuristic.
    142 
   (...)
    224 
    225     """
--> 227     state = state(g, bs=init_bs, **state_args)
    229     args = dict(niter=1, beta=numpy.inf)
    230     args.update(multilevel_mcmc_args)

File ~/miniconda3/envs/gt3/lib/python3.12/site-packages/graph_tool/inference/nested_blockmodel.py:97, in NestedBlockState.__init__(self, g, bs, base_type, state_args, hstate_args, hentropy_args, **kwargs)
     82 self.hentropy_args = dict(hentropy_args,
     83                           adjacency=True,
     84                           dense=True,
   (...)
     93                           recs_dl=False,
     94                           beta_dl=1.)
     96 g_ = self.state_args.pop("g", g) # for OverlapBlockState
---> 97 self.levels = [base_type(g_, b=bs[0] if bs is not None else None,
     98                          **self.state_args)]
    100 if bs is None:
    101     if base_type is OverlapBlockState:

File ~/miniconda3/envs/gt3/lib/python3.12/site-packages/graph_tool/inference/blockmodel.py:268, in BlockState.__init__(self, g, b, B, eweight, vweight, recs, rec_types, rec_params, clabel, pclabel, bfield, Bfield, deg_corr, dense_bg, entropy_args, **kwargs)
    266     self.b.fa = ba
    267 else:
--> 268     self.b = b = g.own_property(b.copy(value_type="int32_t"))
    269 if B is None:
    270     B = int(self.b.fa.max()) + 1

TypeError: list.copy() takes no keyword arguments

Unfortunately, it’s not possible to provide a solution to your problem or an answer to your question with the information provided.

To enable us to understand the situation, you need to provide all the items below:

  1. Your exact graph-tool version.
  2. Your operating system.
  3. A minimal working example that shows the problem.

Item 3 above is very important! If you provide us only with a vague description, or only with the part of the code that you believe causes the problem, then it is not possible to understand the context that may have contributed to it.

You need to provide us a complete example that runs and reproduces the problem you are observing.

I understand.

  1. 2.68
  2. Ubuntu 22.04.4 LTS
from graph_tool.all import *

g = load_graph("./my_network.graphml")

initial_partition =[[0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 2, 3],
                    [0, 0, 2, 2],
                    [0]]

state = minimize_nested_blockmodel_dl(g, init_bs=initial_partition)

And this produces the error above.

By the way, is there any alternative way to encode the initial partition? This requires heavy preprocessing as the nodes need to be in a specific order. I mean can’t I just provide as dict the group memberships on layer 0, and then another dict for the layer 1, and so on.

Thank you!

That’s not a minimal working example, because it’s not a working example if you don’t provide the file you are using.

Sure, sure, sorry for vague description. This should be a minimal working example:

from graph_tool.all import *

### Create toy example
g = Graph(directed=False)
vcolor = g.new_vp("string")
vgroup = g.new_vp("int")

# Block 0
v11 = g.add_vertex()
v12 = g.add_vertex()
v13 = g.add_vertex()

vcolor[v11] = "red"
vcolor[v12] = "red"
vcolor[v13] = "red"

vgroup[v11] = 0
vgroup[v12] = 0
vgroup[v13] = 0


e = g.add_edge(v11, v12)
e = g.add_edge(v12, v13)
e = g.add_edge(v11, v13)

# Block 1
v21 = g.add_vertex()
v22 = g.add_vertex()
v23 = g.add_vertex()

vcolor[v21] = "blue"
vcolor[v22] = "blue"
vcolor[v23] = "blue"

vgroup[v21] = 1
vgroup[v22] = 1
vgroup[v23] = 1


e = g.add_edge(v21, v22)
e = g.add_edge(v22, v23)
e = g.add_edge(v21, v23)

# Block 2
v31 = g.add_vertex()
v32 = g.add_vertex()
v33 = g.add_vertex()

vcolor[v31] = "lightblue"
vcolor[v32] = "lightblue"
vcolor[v33] = "lightblue"

vgroup[v31] = 2
vgroup[v32] = 2
vgroup[v33] = 2

e = g.add_edge(v31, v21)
e = g.add_edge(v32, v22)
e = g.add_edge(v33, v23)

# Block 3
v41 = g.add_vertex()
v42 = g.add_vertex()
v43 = g.add_vertex()

vcolor[v41] = "pink"
vcolor[v42] = "pink"
vcolor[v43] = "pink"

vgroup[v41] = 3
vgroup[v42] = 3
vgroup[v43] = 3

e = g.add_edge(v41, v11)
e = g.add_edge(v42, v12)
e = g.add_edge(v43, v13)

# One bridge edge
e = g.add_edge(v11, v22)

# Draw
graph_draw(g, vertex_fill_color=vcolor)

### Encode layers

# Encode the levels for initial partition

layer0 = list(vgroup)
layer1 = [0, 0, 2, 2]
layer2 = [0]

# Then block0+block1=block0 and block2+block3=block2

bs = [layer0,
      layer1,
      layer2]

# Provide for inference function
state = minimize_nested_blockmodel_dl(g, init_bs=bs)

Additional question: If I wanted instead block0+block2=block0 and block1+block3=block1, then I would need to reorganize the nodes to correspond to the order, right? There is no shortcut for that? Anyways, the main issue is the error with the minimize_nested_blockmodel_dl()

Thanks a lot!!

You need to pass arrays instead of lists:

bs = [array(layer0),
      array(layer1),
      array(layer2)]

This is a bug… Please open an issue in gitlab and I will fix it for next release.

I’ll do that, but I get the following error when trying sign up with my

Github account:

Sign-in using GitHub auth failed

Email is not allowed for sign-up. Please use your regular email address. Check with your administrator.

And the following when just using my regular email address:

1 error prohibited this user from being saved:

  • Email is not allowed for sign-up. Please use your regular email address. Check with your administrator.*