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