Aligning partition modes

Hi Prof. Peixoto,

OS: ubuntu 22

Graph-tool version: 2.98

My question is the following:

We can find partition-modes from an ensemble of partitions by aligning community labels and then clustering the aligned partitions, using ModeClusterState().

Can we align the modes also?

I collect an ensemble from an MCMC chain and find clusters, i.e. partition modes.

I collect another ensemble from a second MCMC chain and find clusters, i.e. partition modes.

How do we align these two sets of modes?

Many thanks,

Govinda

You can access the partition of partitions via state.b.a of a ModeClusterState instance. With that, you align them as usual, using align_partition_labels().

Perhaps I did not put my question clearly.

MWE:

import numpy as np
import graph_tool.all as gt

def get_pi_matrix(mrgnls):
    '''marginals matrix'''
    num_comms = np.max([len(mrgnl) for mrgnl in mrgnls])
    pi = np.zeros((len(mrgnls), num_comms))

    for idx_node, mrgnl in enumerate(mrgnls):
        mrgnl = np.array(mrgnl)
        pi[idx_node, np.where(mrgnl)[0]] = mrgnl[mrgnl > 0]

    pi = pi / np.expand_dims(pi.sum(axis=-1), axis=-1)
    return pi

# dummy graph
g = gt.Graph(6, directed=False)

# ensemble 1
all_bs_1 = []
b = np.array([1, 1, 1, 2, 2, 2])
all_bs_1 += [b]*5
b = np.array([1, 1, 1, 1, 1, 1])
all_bs_1 += [b]*10

# ensemble 2
all_bs_2 = []
b = np.array([1, 1, 1, 2, 2, 2])
all_bs_2 += [b]*10
b = np.array([1, 1, 1, 1, 1, 1])
all_bs_2 += [b]*5

# align both ensembles
all_bs = all_bs_1 + all_bs_2
pmode = gt.PartitionModeState(bs=all_bs, relabel=True, nested=False, converge=True)
all_bs = list(pmode.bs.values())

num_bs = len(all_bs)
all_bs_1 = [all_bs[i][0] for i in range(num_bs // 2)]
all_bs_2 = [all_bs[i][0] for i in range(num_bs // 2, num_bs)]


# cluster partitions within each ensemble, SEPARATELY
cmode1 = gt.ModeClusterState(bs=all_bs_1, nested=False, relabel=True)
gt.mcmc_equilibrate(cmode1, wait=1, mcmc_args=dict(niter=1, beta=np.inf))

cmode2 = gt.ModeClusterState(bs=all_bs_2, nested=False, relabel=True)
gt.mcmc_equilibrate(cmode2, wait=1, mcmc_args=dict(niter=1, beta=np.inf))

# omega's and marginal matrices
modes1 = cmode1.get_modes()
omegas1 = np.array([mode.get_M() for mode in modes1])
omegas1 = omegas1 / omegas1.sum()

marginals1 = [get_pi_matrix(mode.get_marginal(g)) for mode in modes1]


modes2 = cmode2.get_modes()
omegas2 = np.array([mode.get_M() for mode in modes2])
omegas2 = omegas2 / omegas2.sum()

marginals2 = [get_pi_matrix(mode.get_marginal(g)) for mode in modes2]

The output is:

marginals1
[array([[1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.]]),
 array([[1., 0.],
        [1., 0.],
        [1., 0.],
        [0., 1.],
        [0., 1.],
        [0., 1.]])]

omegas1
array([0.66666667, 0.33333333])

marginals2
[array([[1., 0.],
        [1., 0.],
        [1., 0.],
        [0., 1.],
        [0., 1.],
        [0., 1.]]),
 array([[1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.]])]

omegas2
array([0.66666667, 0.33333333])

Clearly, the modes are sorted by their weight (\\omega_k). Since the weights differ between the two ensembles, the mode indices do not correspond (Index 0 in cmode1 is structurally different from Index 0 in cmode2.

Is there a native graph-tool function to align the modes across two different ModeClusterState instances? Or is the recommended approach to extract the marginals (as above) and align them manually (e.g. using the Hungarian algorithm).

Many thanks,

Govinda