To answer my own question, in case someone has a similar problem: you can create a custom distribution as above and define a function sample_posterior.
class RF(Discrete):
def __init__(self, cliques, **kwargs):
# cliques is a list of list of indexes
...
def sample_posterior(self, point=None):
# Gibbs sample from P(A | B)
...
def logp():
# actually never need in my case
return -np.inf
Then create a custom sampler:
class RandomFieldGibbs(ArrayStep):
...
def step(point):
# sample from P(A | B)
point['A'] = self.var.sample_posterior(point)
return point
One can then sample as:
with model:
step1 = pm.RandomFieldGibbs([A])
step2 = pm.Metropolis([B])
trace = NDArray(model)
for i in range(draws):
point = step1.step(point)
point, states = step2.step(point)
trace.record(point, state)