class_docstr: Class for representing Junction Tree.
  
  Junction tree is undirected graph where each node represents a clique
  (list, tuple or set of nodes) and edges represent sepset between two cliques.
  Each sepset in G separates the variables strictly on one side of edge to
  other.
  
  Parameters
  ----------
  data: input graph
      Data to initialize graph. If data=None (default) an empty graph is
      created. The data is an edge list.
  
  Examples
  --------
  Create an empty JunctionTree with no nodes and no edges
  
  >>> from pgmpy.models import JunctionTree
  >>> G = JunctionTree()
  
  G can be grown by adding clique nodes.
  
  **Nodes:**
  
  Add a tuple (or list or set) of nodes as single clique node.
  
  >>> G.add_node(('a', 'b', 'c'))
  >>> G.add_nodes_from([('a', 'b'), ('a', 'b', 'c')])
  
  **Edges:**
  
  G can also be grown by adding edges.
  
  >>> G.add_edge(('a', 'b', 'c'), ('a', 'b'))
  
  or a list of edges
  
  >>> G.add_edges_from([(('a', 'b', 'c'), ('a', 'b')),
  ...                   (('a', 'b', 'c'), ('a', 'c'))])
docstr: Add an edge between two clique nodes.
  
  Parameters
  ----------
  u, v: nodes
      Nodes can be any list or set or tuple of nodes forming a clique.
  
  Examples
  --------
  >>> from pgmpy.models import JunctionTree
  >>> G = JunctionTree()
  >>> G.add_nodes_from([('a', 'b', 'c'), ('a', 'b'), ('a', 'c')])
  >>> G.add_edges_from([(('a', 'b', 'c'), ('a', 'b')),
  ...                   (('a', 'b', 'c'), ('a', 'c'))])
code: def add_edge(self, u, v, **kwargs):
      """
      Add an edge between two clique nodes.
  
      Parameters
      ----------
      u, v: nodes
          Nodes can be any list or set or tuple of nodes forming a clique.
  
      Examples
      --------
      >>> from pgmpy.models import JunctionTree
      >>> G = JunctionTree()
      >>> G.add_nodes_from([('a', 'b', 'c'), ('a', 'b'), ('a', 'c')])
      >>> G.add_edges_from([(('a', 'b', 'c'), ('a', 'b')),
      ...                   (('a', 'b', 'c'), ('a', 'c'))])
      """
      if (
          u in self.nodes()
          and v in self.nodes()
          and nx.has_path(self, u, v)
      ):
          raise ValueError(
              f"Addition of edge between {str(u)} and {str(v)} forms a cycle breaking the properties of Junction Tree"
          )
  
      super(JunctionTree, self).add_edge(u, v, **kwargs)
  
file_path: pgmpy/pgmpy/models/JunctionTree.py
imports: import networkx
  from pgmpy.models import ClusterGraph
label_desc: Use image node_id 2 for calling the JunctionTree obj's underlying member method code with example usage: obj.add_edge(u, v) without return types