'return conditional distribution
indices are the variables to keep, the complement is the conditioning
set
values are the values of the conditioning variables
ar{\mu} = \mu_1 + \Sigma_{12} \Sigma_{22}^{-1} \left( a - \mu_2 ight)
and covariance matrix
\overline{\Sigma} = \Sigma_{11} - \Sigma_{12} \Sigma_{22}^{-1} \Sigma_{21}.T
Parameters
indices : array_like, int
list of indices of variables in the marginal distribution
given : array_like
values of the conditioning variables
Returns
mvn : instance of MVNormal
new instance of the MVNormal class that contains the conditional
distribution of the variables given in indices for given
values of the excluded variables.'

def conditional(self, indices, values):

    keep = np.asarray(indices)
    given = np.asarray([i for i in range(self.nvars) if (not (i in keep))])
    sigmakk = self.sigma[(keep[:, None], keep)]
    sigmagg = self.sigma[(given[:, None], given)]
    sigmakg = self.sigma[(keep[:, None], given)]
    sigmagk = self.sigma[(given[:, None], keep)]
    sigma_new = (sigmakk - np.dot(sigmakg, np.linalg.solve(sigmagg, sigmagk)))
    mean_new = (self.mean[keep] + np.dot(sigmakg, np.linalg.solve(sigmagg, (values - self.mean[given]))))
    return MVNormal(mean_new, sigma_new)
