class_docstr: This is an inference class for performing Causal Inference over Bayesian
  Networks or Structural Equation Models.
  
  Parameters
  ----------
  model: pgmpy.base.DAG | pgmpy.models.BayesianNetwork
      The model that we'll perform inference over.
  
  set_nodes: list[node:str] or None
      A list (or set/tuple) of nodes in the Bayesian Network which have been
      set to a specific value per the do-operator.
  
  Examples
  --------
  Create a small Bayesian Network.
  
  >>> from pgmpy.models import BayesianNetwork
  >>> game = BayesianNetwork([('X', 'A'),
  ...                         ('A', 'Y'),
  ...                         ('A', 'B')])
  
  Load the graph into the CausalInference object to make causal queries.
  
  >>> from pgmpy.inference.CausalInference import CausalInference
  >>> inference = CausalInference(game)
  >>> inference.get_all_backdoor_adjustment_sets(X="X", Y="Y")
  >>> inference.get_all_frontdoor_adjustment_sets(X="X", Y="Y")
  
  References
  ----------
  'Causality: Models, Reasoning, and Inference' - Judea Pearl (2000)
class_docstr_tok: ["This","is","an","inference","class","for","performing","Causal","Inference","over","Bayesian","Networks","or","Structural","Equation","Models",".","Parameters","--","--","--","--","--","model",":","pgmpy.base.DAG","|","pgmpy.models.BayesianNetwork","The","model","that","we","'ll","perform","inference","over",".","set_nodes",":","list","[","node",":","str","]","or","None","A","list","(","or","set\/tuple",")","of","nodes","in","the","Bayesian","Network","which","have","been","set","to","a","specific","value","per","the","do-operator",".","Examples","--","--","--","--","Create","a","small","Bayesian","Network",".",">",">",">","from","pgmpy.models","import","BayesianNetwork",">",">",">","game","=","BayesianNetwork","(","[","(","'","X","'",",","'","A","'",")",",","...","(","'","A","'",",","'","Y","'",")",",","...","(","'","A","'",",","'","B","'",")","]",")","Load","the","graph","into","the","CausalInference","object","to","make","causal","queries",".",">",">",">","from","pgmpy.inference.CausalInference","import","CausalInference",">",">",">","inference","=","CausalInference","(","game",")",">",">",">","inference.get_all_backdoor_adjustment_sets","(","X=","''","X","''",",","Y=","''","Y","''",")",">",">",">","inference.get_all_frontdoor_adjustment_sets","(","X=","''","X","''",",","Y=","''","Y","''",")","References","--","--","--","--","--","'Causality",":","Models",",","Reasoning",",","and","Inference","'","-","Judea","Pearl","(","2000",")"]
docstr: Performs a query on the model of the form :math:`P(X | do(Y), Z)` where :math:`X`
  is `variables`, :math:`Y` is `do` and `Z` is the `evidence`.
  
  Parameters
  ----------
  variables: list
      list of variables in the query i.e. `X` in :math:`P(X | do(Y), Z)`.
  
  do: dict (default: None)
      Dictionary of the form {variable_name: variable_state} representing
      the variables on which to apply the do operation i.e. `Y` in
      :math:`P(X | do(Y), Z)`.
  
  evidence: dict (default: None)
      Dictionary of the form {variable_name: variable_state} repesenting
      the conditional variables in the query i.e. `Z` in :math:`P(X |
      do(Y), Z)`.
  
  adjustment_set: str or list (default=None)
      Specifies the adjustment set to use. If None, uses the parents of the
      do variables as the adjustment set.
  
  inference_algo: str or pgmpy.inference.Inference instance
      The inference algorithm to use to compute the probability values.
      String options are: 1) ve: Variable Elimination 2) bp: Belief
      Propagation.
  
  kwargs: Any
      Additional paramters which needs to be passed to inference
      algorithms.  Please refer to the pgmpy.inference.Inference for
      details.
  
  Returns
  -------
  Queried distribution: pgmpy.factor.discrete.DiscreteFactor
      A factor object representing the joint distribution over the variables in `variables`.
  
  Examples
  --------
  >>> from pgmpy.utils import get_example_model
  >>> model = get_example_model('alarm')
  >>> infer = CausalInference(model)
  >>> infer.query(['HISTORY'], do={'CVP': 'LOW'}, evidence={'HR': 'LOW'})
  <DiscreteFactor representing phi(HISTORY:2) at 0x7f4e0874c2e0>
docstr_tok: ["Performs","a","query","on","the","model","of","the","form",":","math",":","`","P","(","X","|","do","(","Y",")",",","Z",")","`","where",":","math",":","`","X","`","is","`","variables","`",",",":","math",":","`","Y","`","is","`","do","`","and","`","Z","`","is","the","`","evidence","`",".","Parameters","--","--","--","--","--","variables",":","list","list","of","variables","in","the","query","i.e",".","`","X","`","in",":","math",":","`","P","(","X","|","do","(","Y",")",",","Z",")","`",".","do",":","dict","(","default",":","None",")","Dictionary","of","the","form","{","variable_name",":","variable_state","}","representing","the","variables","on","which","to","apply","the","do","operation","i.e",".","`","Y","`","in",":","math",":","`","P","(","X","|","do","(","Y",")",",","Z",")","`",".","evidence",":","dict","(","default",":","None",")","Dictionary","of","the","form","{","variable_name",":","variable_state","}","repesenting","the","conditional","variables","in","the","query","i.e",".","`","Z","`","in",":","math",":","`","P","(","X","|","do","(","Y",")",",","Z",")","`",".","adjustment_set",":","str","or","list","(","default=None",")","Specifies","the","adjustment","set","to","use",".","If","None",",","uses","the","parents","of","the","do","variables","as","the","adjustment","set",".","inference_algo",":","str","or","pgmpy.inference.Inference","instance","The","inference","algorithm","to","use","to","compute","the","probability","values",".","String","options","are",":","1",")","ve",":","Variable","Elimination","2",")","bp",":","Belief","Propagation",".","kwargs",":","Any","Additional","paramters","which","needs","to","be","passed","to","inference","algorithms",".","Please","refer","to","the","pgmpy.inference.Inference","for","details",".","Returns","--","--","--","-","Queried","distribution",":","pgmpy.factor.discrete.DiscreteFactor","A","factor","object","representing","the","joint","distribution","over","the","variables","in","`","variables","`",".","Examples","--","--","--","--",">",">",">","from","pgmpy.utils","import","get_example_model",">",">",">","model","=","get_example_model","(","'alarm","'",")",">",">",">","infer","=","CausalInference","(","model",")",">",">",">","infer.query","(","[","'HISTORY","'","]",",","do=","{","'CVP","'",":","'LOW","'","}",",","evidence=","{","'HR","'",":","'LOW","'","}",")","<","DiscreteFactor","representing","phi","(","HISTORY:2",")","at","0x7f4e0874c2e0",">"]
code: def query(
      self,
      variables,
      do=None,
      evidence=None,
      adjustment_set=None,
      inference_algo="ve",
      show_progress=True,
      **kwargs,
  ):
      """
      Performs a query on the model of the form :math:`P(X | do(Y), Z)` where :math:`X`
      is `variables`, :math:`Y` is `do` and `Z` is the `evidence`.
  
      Parameters
      ----------
      variables: list
          list of variables in the query i.e. `X` in :math:`P(X | do(Y), Z)`.
  
      do: dict (default: None)
          Dictionary of the form {variable_name: variable_state} representing
          the variables on which to apply the do operation i.e. `Y` in
          :math:`P(X | do(Y), Z)`.
  
      evidence: dict (default: None)
          Dictionary of the form {variable_name: variable_state} repesenting
          the conditional variables in the query i.e. `Z` in :math:`P(X |
          do(Y), Z)`.
  
      adjustment_set: str or list (default=None)
          Specifies the adjustment set to use. If None, uses the parents of the
          do variables as the adjustment set.
  
      inference_algo: str or pgmpy.inference.Inference instance
          The inference algorithm to use to compute the probability values.
          String options are: 1) ve: Variable Elimination 2) bp: Belief
          Propagation.
  
      kwargs: Any
          Additional paramters which needs to be passed to inference
          algorithms.  Please refer to the pgmpy.inference.Inference for
          details.
  
      Returns
      -------
      Queried distribution: pgmpy.factor.discrete.DiscreteFactor
          A factor object representing the joint distribution over the variables in `variables`.
  
      Examples
      --------
      >>> from pgmpy.utils import get_example_model
      >>> model = get_example_model('alarm')
      >>> infer = CausalInference(model)
      >>> infer.query(['HISTORY'], do={'CVP': 'LOW'}, evidence={'HR': 'LOW'})
      <DiscreteFactor representing phi(HISTORY:2) at 0x7f4e0874c2e0>
      """
      # Step 1: Check if all the arguments are valid and get them to uniform types.
      if (not isinstance(variables, Iterable)) or (
          isinstance(variables, str)
      ):
          raise ValueError(
              f"variables much be a list (array-like). Got type: {type(variables)}."
          )
      elif not all([node in self.model.nodes() for node in variables]):
          raise ValueError(
              f"Some of the variables in `variables` are not in the model."
          )
      else:
          variables = list(variables)
  
      if do is None:
          do = {}
      elif not isinstance(do, dict):
          raise ValueError(
              "`do` must be a dict of the form: {variable_name: variable_state}"
          )
      if evidence is None:
          evidence = {}
      elif not isinstance(evidence, dict):
          raise ValueError(
              "`evidence` must be a dict of the form: {variable_name: variable_state}"
          )
  
      from pgmpy.inference import Inference
  
      if inference_algo == "ve":
          from pgmpy.inference import VariableElimination
  
          inference_algo = VariableElimination
      elif inference_algo == "bp":
          from pgmpy.inference import BeliefPropagation
  
          inference_algo = BeliefPropagation
      elif not isinstance(inference_algo, Inference):
          raise ValueError(
              f"inference_algo must be one of: 've', 'bp', or an instance of pgmpy.inference.Inference. Got: {inference_algo}"
          )
  
      # Step 2: Check if adjustment set is provided, otherwise try calculating it.
      if adjustment_set is None:
          do_vars = [var for var, state in do.items()]
          adjustment_set = set(
              chain(*[self.model.predecessors(var) for var in do_vars])
          )
          if len(adjustment_set.intersection(self.model.latents)) != 0:
              raise ValueError(
                  "Not all parents of do variables are observed. Please specify an adjustment set."
              )
  
      infer = inference_algo(self.model)
  
      # Step 3.1: If no do variable specified, do a normal probabilistic inference.
      if do == {}:
          return infer.query(variables, evidence, show_progress=False)
      # Step 3.2: If no adjustment is required, do a normal probabilistic
      #           inference with do variables as the evidence.
      elif len(adjustment_set) == 0:
          evidence = {**evidence, **do}
          return infer.query(variables, evidence, show_progress=False)
  
      # Step 4: For other cases, compute \sum_{z} p(variables | do, z) p(z)
      values = []
  
      # Step 4.1: Compute p_z and states of z to iterate over.
      # For computing p_z, if evidence variables also in adjustment set,
      # manually do reduce else inference will throw error.
      evidence_adj_inter = {
          var: state
          for var, state in evidence.items()
          if var in adjustment_set.intersection(evidence.keys())
      }
      if len(evidence_adj_inter) != 0:
          p_z = infer.query(adjustment_set, show_progress=False).reduce(
              [
                  (key, value)
                  for key, value in evidence_adj_inter.items()
              ],
              inplace=False,
          )
          # Since we are doing reduce over some of the variables, they are
          # going to be removed from the factor but would be required to get
          # values later. A hackish solution to reintroduce those variables in p_z
  
          if set(p_z.variables) != adjustment_set:
              p_z = DiscreteFactor(
                  p_z.variables + list(evidence_adj_inter.keys()),
                  list(p_z.cardinality) + [1] * len(evidence_adj_inter),
                  p_z.values,
                  state_names={
                      **p_z.state_names,
                      **{
                          var: [state]
                          for var, state in evidence_adj_inter.items()
                      },
                  },
              )
      else:
          p_z = infer.query(
              adjustment_set, evidence=evidence, show_progress=False
          )
  
      adj_states = []
      for var in adjustment_set:
          if var in evidence_adj_inter.keys():
              adj_states.append([evidence_adj_inter[var]])
          else:
              adj_states.append(
                  self.model.get_cpds(var).state_names[var]
              )
  
      # Step 4.2: Iterate over states of adjustment set and compute values.
      if show_progress and config.SHOW_PROGRESS:
          pbar = tqdm(
              total=np.prod([len(states) for states in adj_states])
          )
  
      for state_comb in product(*adj_states):
          adj_evidence = {
              var: state
              for var, state in zip(adjustment_set, state_comb)
          }
          evidence = {**do, **adj_evidence}
          values.append(
              infer.query(
                  variables, evidence=evidence, show_progress=False
              )
              * p_z.get_value(**adj_evidence)
          )
  
          if show_progress and config.SHOW_PROGRESS:
              pbar.update(1)
  
      return sum(values).normalize(inplace=False)
  
imports: from collections.abc import Iterable
  from itertools import chain, product
  import networkx
  import numpy
  from tqdm.auto import tqdm
  from pgmpy import config
  from pgmpy.estimators.LinearModel import LinearEstimator
  from pgmpy.factors.discrete import DiscreteFactor
  from pgmpy.models import BayesianNetwork
  from pgmpy.utils.sets import _powerset, _variable_or_iterable_to_set
label_desc: Use image node_id 12 for calling the CausalInference obj's underlying member method code with example usage: obj.query(variables, do, evidence, adjustment_set, inference_algo, show_progress) and returns: sum, infer, infer