docs: def reduce(self, values, inplace=True):
          """
          Reduces the distribution to the context of the given variable values.
  
          The formula for the obtained conditional distribution is given by -
  
          For,
          .. math:: N(X_j | X_i = x_i) ~ N(mu_{j.i} ; sig_{j.i})
  
          where,
          .. math:: mu_{j.i} = mu_j + sig_{j, i} * {sig_{i, i}^{-1}} * (x_i - mu_i)
          .. math:: sig_{j.i} = sig_{j, j} - sig_{j, i} * {sig_{i, i}^{-1}} * sig_{i, j}
  
          Parameters
          ----------
          values: list, array-like
              A list of tuples of the form (variable_name, variable_value).
  
          inplace: boolean
              If inplace=True it will modify the factor itself, else would return
              a new ContinuosFactor object.
  
          Returns
          -------
          GaussianDistribution or None:
                  if inplace=True (default) returns None
                  if inplace=False returns a new GaussianDistribution instance.
  
          Examples
          --------
          >>> import numpy as np
          >>> from pgmpy.factors.distributions import GaussianDistribution as GD
          >>> dis = GD(variables=['x1', 'x2', 'x3'],
          ...             mean=[1, -3, 4],
          ...             cov=[[4, 2, -2],
          ...                  [2, 5, -5],
          ...                  [-2, -5, 8]])
          >>> dis.variables
          ['x1', 'x2', 'x3']
          >>> dis.mean
          array([[ 1.],
                 [-3.],
                 [ 4.]])
          >>> dis.covariance
          array([[ 4.,  2., -2.],
                 [ 2.,  5., -5.],
                 [-2., -5.,  8.]])
  
          >>> dis.reduce([('x1', 7)])
          >>> dis.variables
          ['x2', 'x3']
          >>> dis.mean
          array([[ 0.],
                 [ 1.]])
          >>> dis.covariance
          array([[ 4., -4.],
                 [-4.,  7.]])
  
          """
          if not isinstance(values, list):
              raise TypeError("values: Expected type list or array-like, ",
                              "got type {var_type}".format(
                                  var_type=type(values)))
  
          phi = self if inplace else self.copy()
  
          var_to_reduce = [var for var, value in values]
  
          # index_to_keep -> j vector
          index_to_keep = [self.variables.index(var) for var in self.variables
                           if var not in var_to_reduce]
          # index_to_reduce -> i vector
          index_to_reduce = [self.variables.index(var) for var in var_to_reduce]
  
          mu_j = self.mean[index_to_keep]
          mu_i = self.mean[index_to_reduce]
          x_i = np.array([value for var, value in values]).reshape(len(index_to_reduce), 1)
  
          sig_i_j = self.covariance[np.ix_(index_to_reduce, index_to_keep)]
          sig_j_i = self.covariance[np.ix_(index_to_keep, index_to_reduce)]
          sig_i_i_inv = np.linalg.inv(self.covariance[np.ix_(index_to_reduce, index_to_reduce)])
          sig_j_j = self.covariance[np.ix_(index_to_keep, index_to_keep)]
  
          phi.variables = [self.variables[index] for index in index_to_keep]
          phi.mean = mu_j + np.dot(np.dot(sig_j_i, sig_i_i_inv), x_i - mu_i)
          phi.covariance = sig_j_j - np.dot(np.dot(sig_j_i, sig_i_i_inv), sig_i_j)
          phi._precision_matrix = None
  
          if not inplace:
              return phi