class_docstr: Initializes a Bayesian Network.
  A models stores nodes and edges with conditional probability
  distribution (cpd) and other attributes.
  
  models hold directed edges.  Self loops are not allowed neither
  multiple (parallel) edges.
  
  Nodes can be any hashable python object.
  
  Edges are represented as links between nodes.
  
  Parameters
  ----------
  ebunch: input graph
      Data to initialize graph.  If ebunch=None (default) an empty
      graph is created.  The ebunch can be an edge list, or any
      NetworkX graph object.
  
  latents: list, array-like
      List of variables which are latent (i.e. unobserved) in the model.
  
  Examples
  --------
  Create an empty Bayesian Network with no nodes and no edges.
  
  >>> from pgmpy.models import BayesianNetwork
  >>> G = BayesianNetwork()
  
  G can be grown in several ways.
  
  **Nodes:**
  
  Add one node at a time:
  
  >>> G.add_node('a')
  
  Add the nodes from any container (a list, set or tuple or the nodes
  from another graph).
  
  >>> G.add_nodes_from(['a', 'b'])
  
  **Edges:**
  
  G can also be grown by adding edges.
  
  Add one edge,
  
  >>> G.add_edge('a', 'b')
  
  a list of edges,
  
  >>> G.add_edges_from([('a', 'b'), ('b', 'c')])
  
  If some edges connect nodes not yet in the model, the nodes
  are added automatically.  There are no errors when adding
  nodes or edges that already exist.
  
  **Shortcuts:**
  
  Many common graph features allow python syntax for speed reporting.
  
  >>> 'a' in G     # check if node in graph
  True
  >>> len(G)  # number of nodes in graph
  3
class_docstr_tok: ["Initializes","a","Bayesian","Network",".","A","models","stores","nodes","and","edges","with","conditional","probability","distribution","(","cpd",")","and","other","attributes",".","models","hold","directed","edges",".","Self","loops","are","not","allowed","neither","multiple","(","parallel",")","edges",".","Nodes","can","be","any","hashable","python","object",".","Edges","are","represented","as","links","between","nodes",".","Parameters","--","--","--","--","--","ebunch",":","input","graph","Data","to","initialize","graph",".","If","ebunch=None","(","default",")","an","empty","graph","is","created",".","The","ebunch","can","be","an","edge","list",",","or","any","NetworkX","graph","object",".","latents",":","list",",","array-like","List","of","variables","which","are","latent","(","i.e",".","unobserved",")","in","the","model",".","Examples","--","--","--","--","Create","an","empty","Bayesian","Network","with","no","nodes","and","no","edges",".",">",">",">","from","pgmpy.models","import","BayesianNetwork",">",">",">","G","=","BayesianNetwork","(",")","G","can","be","grown","in","several","ways",".","*","*","Nodes",":","*","*","Add","one","node","at","a","time",":",">",">",">","G.add_node","(","'","a","'",")","Add","the","nodes","from","any","container","(","a","list",",","set","or","tuple","or","the","nodes","from","another","graph",")",".",">",">",">","G.add_nodes_from","(","[","'","a","'",",","'","b","'","]",")","*","*","Edges",":","*","*","G","can","also","be","grown","by","adding","edges",".","Add","one","edge",",",">",">",">","G.add_edge","(","'","a","'",",","'","b","'",")","a","list","of","edges",",",">",">",">","G.add_edges_from","(","[","(","'","a","'",",","'","b","'",")",",","(","'","b","'",",","'","c","'",")","]",")","If","some","edges","connect","nodes","not","yet","in","the","model",",","the","nodes","are","added","automatically",".","There","are","no","errors","when","adding","nodes","or","edges","that","already","exist",".","*","*","Shortcuts",":","*","*","Many","common","graph","features","allow","python","syntax","for","speed","reporting",".",">",">",">","'","a","'","in","G","#","check","if","node","in","graph","True",">",">",">","len","(","G",")","#","number","of","nodes","in","graph","3"]
docstr: Check the model for various errors. This method checks for the following
  errors.
  
  * Checks if the sum of the probabilities for each state is equal to 1 (tol=0.01).
  * Checks if the CPDs associated with nodes are consistent with their parents.
  
  Returns
  -------
  check: boolean
      True if all the checks pass otherwise should throw an error.
code: def check_model(self):
      """
      Check the model for various errors. This method checks for the following
      errors.
  
      * Checks if the sum of the probabilities for each state is equal to 1 (tol=0.01).
      * Checks if the CPDs associated with nodes are consistent with their parents.
  
      Returns
      -------
      check: boolean
          True if all the checks pass otherwise should throw an error.
      """
      for node in self.nodes():
          cpd = self.get_cpds(node=node)
  
          # Check if a CPD is associated with every node.
          if cpd is None:
              raise ValueError(f"No CPD associated with {node}")
  
          # Check if the CPD is an instance of either TabularCPD or ContinuousFactor.
          elif isinstance(cpd, (TabularCPD, ContinuousFactor)):
              evidence = cpd.get_evidence()
              parents = self.get_parents(node)
  
              # Check if the evidence set of the CPD is same as its parents.
              if set(evidence) != set(parents):
                  raise ValueError(
                      f"CPD associated with {node} doesn't have proper parents associated with it."
                  )
  
              if (
                  len(set(cpd.variables) - set(cpd.state_names.keys()))
                  > 0
              ):
                  raise ValueError(
                      f"CPD for {node} doesn't have state names defined for all the variables."
                  )
  
              # Check if the values of the CPD sum to 1.
              if not cpd.is_valid_cpd():
                  raise ValueError(
                      f"Sum or integral of conditional probabilities for node {node} is not equal to 1."
                  )
  
      for node in self.nodes():
          cpd = self.get_cpds(node=node)
          for index, node in enumerate(cpd.variables[1:]):
              parent_cpd = self.get_cpds(node)
              # Check if the evidence cardinality specified is same as parent's cardinality
              if (
                  parent_cpd.cardinality[0]
                  != cpd.cardinality[1 + index]
              ):
                  raise ValueError(
                      f"The cardinality of {node} doesn't match in it's child nodes."
                  )
              # Check if the state_names are the same in parent and child CPDs.
              if parent_cpd.state_names[node] != cpd.state_names[node]:
                  raise ValueError(
                      f"The state names of {node} doesn't match in it's child nodes."
                  )
  
      return True
  
imports: import itertools
  from collections import defaultdict
  from functools import reduce
  from operator import mul
  import networkx
  import numpy
  import pandas
  from joblib import Parallel, delayed
  from tqdm.auto import tqdm
  from pgmpy.base import DAG
  from pgmpy.factors.continuous import ContinuousFactor
  from pgmpy.factors.discrete import DiscreteFactor, JointProbabilityDistribution, TabularCPD
  from pgmpy.global_vars import logger
  from pgmpy.models.MarkovNetwork import MarkovNetwork
  from pgmpy.utils import compat_fns
label_desc: Use image node_id 10 for calling the BayesianNetwork obj's underlying member method code with example usage: obj.check_model() and returns: True