class_docstr: The intermediate factors in a Gaussian network can be described
  compactly using a simple parametric representation called the
  canonical form. This representation is closed under the basic
  operations used in inference: factor product, factor division,
  factor reduction, and marginalization. Thus, we define this
  CanonicalDistribution class that allows the inference process to be
  performed on joint Gaussian networks.
  
  A canonical form C (X; K,h,g) is defined as
  
  C (X; K,h,g) = exp( ((-1/2) * X.T * K * X) + (h.T * X) + g)
  
  References
  ----------
  Probabilistic Graphical Models, Principles and Techniques,
  Daphne Koller and Nir Friedman, Section 14.2, Chapter 14.
class_docstr_tok: ["The","intermediate","factors","in","a","Gaussian","network","can","be","described","compactly","using","a","simple","parametric","representation","called","the","canonical","form",".","This","representation","is","closed","under","the","basic","operations","used","in","inference",":","factor","product",",","factor","division",",","factor","reduction",",","and","marginalization",".","Thus",",","we","define","this","CanonicalDistribution","class","that","allows","the","inference","process","to","be","performed","on","joint","Gaussian","networks",".","A","canonical","form","C","(","X\u037e","K",",","h",",","g",")","is","defined","as","C","(","X\u037e","K",",","h",",","g",")","=","exp","(","(","(","-1\/2",")","*","X.T","*","K","*","X",")","+","(","h.T","*","X",")","+","g",")","References","--","--","--","--","--","Probabilistic","Graphical","Models",",","Principles","and","Techniques",",","Daphne","Koller","and","Nir","Friedman",",","Section","14.2",",","Chapter","14","."]
docstr: Reduces the distribution to the context of the given variable values.
  
  Let C(X,Y ; K, h, g) be some canonical form over X,Y where,
  
  k = [[K_XX, K_XY],        ;       h = [[h_X],
       [K_YX, K_YY]]                     [h_Y]]
  
  The formula for the obtained conditional distribution for setting
  Y = y is given by,
  
  .. math:: K' = K_{XX}
  .. math:: h' = h_X - K_{XY} * y
  .. math:: g' = g + {h^T}_Y * y - 0.5 * y^T * K_{YY} * y
  
  
  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 CanonicalFactor object.
  
  Returns
  -------
  CanonicalDistribution or None:
          if inplace=True (default) returns None
          if inplace=False returns a new CanonicalDistribution instance.
  
  Examples
  --------
  >>> import numpy as np
  >>> from pgmpy.factors.continuous import CanonicalDistribution
  >>> phi = CanonicalDistribution(['X1', 'X2', 'X3'],
  ...                       np.array([[1, -1, 0], [-1, 4, -2], [0, -2, 4]]),
  ...                       np.array([[1], [4], [-1]]), -2)
  >>> phi.variables
  ['X1', 'X2', 'X3']
  
  >>> phi.K
  array([[ 1., -1.],
         [-1.,  3.]])
  
  >>> phi.h
  array([[ 1. ],
         [ 3.5]])
  
  >>> phi.g
  -2
  
  >>> phi.reduce([('X3', 0.25)])
  
  >>> phi.variables
  ['X1', 'X2']
  
  >>> phi.K
  array([[ 1, -1],
         [-1,  4]])
  
  >>> phi.h
  array([[ 1. ],
         [ 4.5]])
  
  >>> phi.g
  -2.375
docstr_tok: ["Reduces","the","distribution","to","the","context","of","the","given","variable","values",".","Let","C","(","X",",","Y","\u037e","K",",","h",",","g",")","be","some","canonical","form","over","X",",","Y","where",",","k","=","[","[","K_XX",",","K_XY","]",",",";","h","=","[","[","h_X","]",",","[","K_YX",",","K_YY","]","]","[","h_Y","]","]","The","formula","for","the","obtained","conditional","distribution","for","setting","Y","=","y","is","given","by",",","..","math",":",":","K","'","=","K_","{","XX","}","..","math",":",":","h","'","=","h_X","-","K_","{","XY","}","*","y","..","math",":",":","g","'","=","g","+","{","h^T","}","_Y","*","y","-","0.5","*","y^T","*","K_","{","YY","}","*","y","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","CanonicalFactor","object",".","Returns","--","--","--","-","CanonicalDistribution","or","None",":","if","inplace=True","(","default",")","returns","None","if","inplace=False","returns","a","new","CanonicalDistribution","instance",".","Examples","--","--","--","--",">",">",">","import","numpy","as","np",">",">",">","from","pgmpy.factors.continuous","import","CanonicalDistribution",">",">",">","phi","=","CanonicalDistribution","(","[","'X1","'",",","'X2","'",",","'X3","'","]",",","...","np.array","(","[","[","1",",","-1",",","0","]",",","[","-1",",","4",",","-2","]",",","[","0",",","-2",",","4","]","]",")",",","...","np.array","(","[","[","1","]",",","[","4","]",",","[","-1","]","]",")",",","-2",")",">",">",">","phi.variables","[","'X1","'",",","'X2","'",",","'X3","'","]",">",">",">","phi.K","array","(","[","[","1.",",","-1",".","]",",","[","-1.",",","3",".","]","]",")",">",">",">","phi.h","array","(","[","[","1",".","]",",","[","3.5","]","]",")",">",">",">","phi.g","-2",">",">",">","phi.reduce","(","[","(","'X3","'",",","0.25",")","]",")",">",">",">","phi.variables","[","'X1","'",",","'X2","'","]",">",">",">","phi.K","array","(","[","[","1",",","-1","]",",","[","-1",",","4","]","]",")",">",">",">","phi.h","array","(","[","[","1",".","]",",","[","4.5","]","]",")",">",">",">","phi.g","-2.375"]
code: def reduce(self, values, inplace=True):
      """
      Reduces the distribution to the context of the given variable values.
  
      Let C(X,Y ; K, h, g) be some canonical form over X,Y where,
  
      k = [[K_XX, K_XY],        ;       h = [[h_X],
           [K_YX, K_YY]]                     [h_Y]]
  
      The formula for the obtained conditional distribution for setting
      Y = y is given by,
  
      .. math:: K' = K_{XX}
      .. math:: h' = h_X - K_{XY} * y
      .. math:: g' = g + {h^T}_Y * y - 0.5 * y^T * K_{YY} * y
  
  
      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 CanonicalFactor object.
  
      Returns
      -------
      CanonicalDistribution or None:
              if inplace=True (default) returns None
              if inplace=False returns a new CanonicalDistribution instance.
  
      Examples
      --------
      >>> import numpy as np
      >>> from pgmpy.factors.continuous import CanonicalDistribution
      >>> phi = CanonicalDistribution(['X1', 'X2', 'X3'],
      ...                       np.array([[1, -1, 0], [-1, 4, -2], [0, -2, 4]]),
      ...                       np.array([[1], [4], [-1]]), -2)
      >>> phi.variables
      ['X1', 'X2', 'X3']
  
      >>> phi.K
      array([[ 1., -1.],
             [-1.,  3.]])
  
      >>> phi.h
      array([[ 1. ],
             [ 3.5]])
  
      >>> phi.g
      -2
  
      >>> phi.reduce([('X3', 0.25)])
  
      >>> phi.variables
      ['X1', 'X2']
  
      >>> phi.K
      array([[ 1, -1],
             [-1,  4]])
  
      >>> phi.h
      array([[ 1. ],
             [ 4.5]])
  
      >>> phi.g
      -2.375
      """
      if not isinstance(values, (list, tuple, np.ndarray)):
          raise TypeError(
              f"variables: Expected type list or array-like, got type {type(values)}"
          )
  
      if not all([var in self.variables for var, value in values]):
          raise ValueError("Variable not in scope.")
  
      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
      ]
  
      K_i_i = self.K[np.ix_(index_to_keep, index_to_keep)]
      K_i_j = self.K[np.ix_(index_to_keep, index_to_reduce)]
      K_j_j = self.K[np.ix_(index_to_reduce, index_to_reduce)]
      h_i = self.h[index_to_keep]
      h_j = self.h[index_to_reduce]
  
      # The values for the reduced variables.
      y = np.array([value for var, value in values]).reshape(
          len(index_to_reduce), 1
      )
  
      phi.variables = [self.variables[index] for index in index_to_keep]
      phi.K = K_i_i
      phi.h = h_i - np.dot(K_i_j, y)
      phi.g = (
          self.g
          + (
              np.dot(h_j.T, y)
              - (0.5 * np.linalg.multi_dot([y.T, K_j_j, y]))
          )[0][0]
      )
  
      if not inplace:
          return phi
  
file_path: pgmpy/pgmpy/factors/distributions/CanonicalDistribution.py
imports: import numpy
  from pgmpy.factors.distributions import BaseDistribution
  from pgmpy.factors.distributions import GaussianDistribution
label_desc: Use image node_id 6 for calling the CanonicalDistribution obj's underlying member method code with example usage: obj.reduce(values, inplace) and returns: phi