class_docstr: Base class for independencies.
  independencies class represents a set of Conditional Independence
  assertions (eg: "X is independent of Y given Z" where X, Y and Z
  are random variables) or Independence assertions (eg: "X is
  independent of Y" where X and Y are random variables).
  Initialize the independencies Class with Conditional Independence
  assertions or Independence assertions.
  
  Parameters
  ----------
  assertions: Lists or Tuples
          Each assertion is a list or tuple of the form: [event1,
          event2 and event3]
          eg: assertion ['X', 'Y', 'Z'] would be X is independent
          of Y given Z.
  
  Examples
  --------
  Creating an independencies object with one independence assertion:
  Random Variable X is independent of Y
  
  >>> independencies = independencies(['X', 'Y'])
  
  Creating an independencies object with three conditional
  independence assertions:
  First assertion is Random Variable X is independent of Y given Z.
  
  >>> independencies = independencies(['X', 'Y', 'Z'],
  ...             ['a', ['b', 'c'], 'd'],
  ...             ['l', ['m', 'n'], 'o'])
  
  Public Methods
  --------------
  add_assertions
  get_assertions
  get_factorized_product
  closure
  entails
  is_equivalent
class_docstr_tok: ["Base","class","for","independencies",".","independencies","class","represents","a","set","of","Conditional","Independence","assertions","(","eg",":","``","X","is","independent","of","Y","given","Z","''","where","X",",","Y","and","Z","are","random","variables",")","or","Independence","assertions","(","eg",":","``","X","is","independent","of","Y","''","where","X","and","Y","are","random","variables",")",".","Initialize","the","independencies","Class","with","Conditional","Independence","assertions","or","Independence","assertions",".","Parameters","--","--","--","--","--","assertions",":","Lists","or","Tuples","Each","assertion","is","a","list","or","tuple","of","the","form",":","[","event1",",","event2","and","event3","]","eg",":","assertion","[","'","X","'",",","'","Y","'",",","'","Z","'","]","would","be","X","is","independent","of","Y","given","Z",".","Examples","--","--","--","--","Creating","an","independencies","object","with","one","independence","assertion",":","Random","Variable","X","is","independent","of","Y",">",">",">","independencies","=","independencies","(","[","'","X","'",",","'","Y","'","]",")","Creating","an","independencies","object","with","three","conditional","independence","assertions",":","First","assertion","is","Random","Variable","X","is","independent","of","Y","given","Z",".",">",">",">","independencies","=","independencies","(","[","'","X","'",",","'","Y","'",",","'","Z","'","]",",","...","[","'","a","'",",","[","'","b","'",",","'","c","'","]",",","'d","'","]",",","...","[","'","l","'",",","[","'m","'",",","'n","'","]",",","'","o","'","]",")","Public","Methods","--","--","--","--","--","--","--","add_assertions","get_assertions","get_factorized_product","closure","entails","is_equivalent"]
docstr: Returns a new `Independencies()`-object that additionally contains those `IndependenceAssertions`
  that are implied by the current independencies (using with the `semi-graphoid axioms
  <https://en.wikipedia.org/w/index.php?title=Conditional_independence&oldid=708760689#Rules_of_conditional_independence>`_;
  see (Pearl, 1989, `Conditional Independence and its representations
  <http://www.cs.technion.ac.il/~dang/journal_papers/pearl1989conditional.pdf>`_)).
  
  Might be very slow if more than six variables are involved.
  
  Examples
  --------
  >>> from pgmpy.independencies import Independencies
  >>> ind1 = Independencies(('A', ['B', 'C'], 'D'))
  >>> ind1.closure()
  (A ⟂ B | D, C)
  (A ⟂ B, C | D)
  (A ⟂ B | D)
  (A ⟂ C | D, B)
  (A ⟂ C | D)
  
  >>> ind2 = Independencies(('W', ['X', 'Y', 'Z']))
  >>> ind2.closure()
  (W ⟂ Y)
  (W ⟂ Y | X)
  (W ⟂ Z | Y)
  (W ⟂ Z, X, Y)
  (W ⟂ Z)
  (W ⟂ Z, X)
  (W ⟂ X, Y)
  (W ⟂ Z | X)
  (W ⟂ Z, Y | X)
  [..]
docstr_tok: ["Returns","a","new","`","Independencies","(",")","`","-object","that","additionally","contains","those","`","IndependenceAssertions","`","that","are","implied","by","the","current","independencies","(","using","with","the","`","semi-graphoid","axioms","<","https",":","\/\/en.wikipedia.org\/w\/index.php","?","title=Conditional_independence","&","oldid=708760689","#","Rules_of_conditional_independence",">","`","_",";","see","(","Pearl",",","1989",",","`","Conditional","Independence","and","its","representations","<","http",":","\/\/www.cs.technion.ac.il\/~dang\/journal_papers\/pearl1989conditional.pdf",">","`","_",")",")",".","Might","be","very","slow","if","more","than","six","variables","are","involved",".","Examples","--","--","--","--",">",">",">","from","pgmpy.independencies","import","Independencies",">",">",">","ind1","=","Independencies","(","(","'","A","'",",","[","'","B","'",",","'","C","'","]",",","'D","'",")",")",">",">",">","ind1.closure","(",")","(","A","\u27c2","B","|","D",",","C",")","(","A","\u27c2","B",",","C","|","D",")","(","A","\u27c2","B","|","D",")","(","A","\u27c2","C","|","D",",","B",")","(","A","\u27c2","C","|","D",")",">",">",">","ind2","=","Independencies","(","(","'","W","'",",","[","'","X","'",",","'","Y","'",",","'","Z","'","]",")",")",">",">",">","ind2.closure","(",")","(","W","\u27c2","Y",")","(","W","\u27c2","Y","|","X",")","(","W","\u27c2","Z","|","Y",")","(","W","\u27c2","Z",",","X",",","Y",")","(","W","\u27c2","Z",")","(","W","\u27c2","Z",",","X",")","(","W","\u27c2","X",",","Y",")","(","W","\u27c2","Z","|","X",")","(","W","\u27c2","Z",",","Y","|","X",")","[","..","]"]
code: def closure(self):
      """
      Returns a new `Independencies()`-object that additionally contains those `IndependenceAssertions`
      that are implied by the current independencies (using with the `semi-graphoid axioms
      <https://en.wikipedia.org/w/index.php?title=Conditional_independence&oldid=708760689#Rules_of_conditional_independence>`_;
      see (Pearl, 1989, `Conditional Independence and its representations
      <http://www.cs.technion.ac.il/~dang/journal_papers/pearl1989conditional.pdf>`_)).
  
      Might be very slow if more than six variables are involved.
  
      Examples
      --------
      >>> from pgmpy.independencies import Independencies
      >>> ind1 = Independencies(('A', ['B', 'C'], 'D'))
      >>> ind1.closure()
      (A \u27C2 B | D, C)
      (A \u27C2 B, C | D)
      (A \u27C2 B | D)
      (A \u27C2 C | D, B)
      (A \u27C2 C | D)
  
      >>> ind2 = Independencies(('W', ['X', 'Y', 'Z']))
      >>> ind2.closure()
      (W \u27C2 Y)
      (W \u27C2 Y | X)
      (W \u27C2 Z | Y)
      (W \u27C2 Z, X, Y)
      (W \u27C2 Z)
      (W \u27C2 Z, X)
      (W \u27C2 X, Y)
      (W \u27C2 Z | X)
      (W \u27C2 Z, Y | X)
      [..]
      """
  
      def single_var(var):
          "Checks if var represents a single variable"
          if not hasattr(var, "__iter__"):
              return True
          else:
              return len(var) == 1
  
      def sg0(ind):
          "Symmetry rule: 'X ⟂ Y | Z' -> 'Y ⟂ X | Z'"
          return IndependenceAssertion(
              ind.event2, ind.event1, ind.event3
          )
  
      # since X⟂Y|Z == Y⟂X|Z in pgmpy, sg0 (symmetry) is not used as an axiom/rule.
      # instead we use a decorator for the other axioms to apply them on both sides
      def apply_left_and_right(func):
          def symmetric_func(*args):
              if len(args) == 1:
                  return func(args[0]) + func(sg0(args[0]))
              if len(args) == 2:
                  return (
                      func(*args)
                      + func(args[0], sg0(args[1]))
                      + func(sg0(args[0]), args[1])
                      + func(sg0(args[0]), sg0(args[1]))
                  )
  
          return symmetric_func
  
      @apply_left_and_right
      def sg1(ind):
          "Decomposition rule: 'X ⟂ Y,W | Z' -> 'X ⟂ Y | Z', 'X ⟂ W | Z'"
          if single_var(ind.event2):
              return []
          else:
              return [
                  IndependenceAssertion(
                      ind.event1, ind.event2 - {elem}, ind.event3
                  )
                  for elem in ind.event2
              ]
  
      @apply_left_and_right
      def sg2(ind):
          "Weak Union rule: 'X ⟂ Y,W | Z' -> 'X ⟂ Y | W,Z', 'X ⟂ W | Y,Z'"
          if single_var(ind.event2):
              return []
          else:
              return [
                  IndependenceAssertion(
                      ind.event1,
                      ind.event2 - {elem},
                      {elem} | ind.event3,
                  )
                  for elem in ind.event2
              ]
  
      @apply_left_and_right
      def sg3(ind1, ind2):
          "Contraction rule: 'X ⟂ W | Y,Z' & 'X ⟂ Y | Z' -> 'X ⟂ W,Y | Z'"
          if ind1.event1 != ind2.event1:
              return []
  
          Y = ind2.event2
          Z = ind2.event3
          Y_Z = ind1.event3
          if Y < Y_Z and Z < Y_Z and Y.isdisjoint(Z):
              return [
                  IndependenceAssertion(ind1.event1, ind1.event2 | Y, Z)
              ]
          else:
              return []
  
      # apply semi-graphoid axioms as long as new independencies are found.
      all_independencies = set()
      new_inds = set(self.independencies)
  
      while new_inds:
          new_pairs = (
              set(itertools.permutations(new_inds, 2))
              | set(itertools.product(new_inds, all_independencies))
              | set(itertools.product(all_independencies, new_inds))
          )
  
          all_independencies |= new_inds
          new_inds = set(
              sum(
                  [sg1(ind) for ind in new_inds]
                  + [sg2(ind) for ind in new_inds]
                  + [sg3(*inds) for inds in new_pairs],
                  [],
              )
          )
          new_inds -= all_independencies
  
      return Independencies(*list(all_independencies))
  
imports: import itertools
label_desc: Use image node_id 9 for calling the Independencies obj's underlying member method code with example usage: obj.closure() and returns: Independencies, IndependenceAssertion, symmetric_func, True, unknown, list, unknown, list, unknown, list, list, list, unknown, unknown