Repository: pgmpy/pgmpy

Issue:
CausalInference.query() ValueError exception
evidence = {'W': 'True'}
counterfactual_intervention = {'S': 'False'}

counterfactual_query = causal_inference.query(
    variables=['R'],
    evidence=evidence,
    do=counterfactual_intervention
)

The above code throws the following exception:
ValueError: Can't have the same variables in both `variables` and `evidence`. Found in both: {'R'}

Hints from issue comments:
@ankurankan: @dtchang Could you please also share your model structure so that I can reproduce the error?  @dtchang: ```python
from pgmpy.models import DiscreteBayesianNetwork
from pgmpy.inference import CausalInference
from pgmpy.factors.discrete import TabularCPD
# 1. Define the structure of the Bayesian Network
model = DiscreteBayesianNetwork([('R', 'W'), ('S', 'W'), ('R', 'S')])
model.to_daft().render()
# 2. Define the Conditional Probability Distributions (CPDs)
# P(Rain)
cpd_rain = TabularCPD(variable='R', variable_card=2,
                      values=[[0.6], [0.4]],
                      state_names={'R': ['True', 'False']})
# P(Sprinkler | Rain)
cpd_sprinkler = TabularCPD(variable='S', variable_card=2,
                           values=[[0.1, 0.5],
                                   [0.9, 0.5]],
                           evidence=['R'],
                           evidence_card=[2],
                           state_names={'S': ['True', 'False'], 'R': ['True', 'False']})
# P(Wet Grass | Rain, Sprinkler)
cpd_wet_grass = TabularCPD(variable='W', variable_card=2,
                           values=[[0.99, 0.9, 0.9, 0.01],
                                   [0.01, 0.1, 0.1, 0.99]],
                           evidence=['R', 'S'],
                           evidence_card=[2, 2],
                           state_names={'W': ['True', 'False'], 'R': ['True', 'False'], 'S': ['True', 'False']})
# Add the CPDs to the model
model.add_cpds(cpd_rain, cpd_sprinkler, cpd_wet_grass)
# Check if the model is valid
model.check_model()
# Initialize CausalInference
causal_inference = CausalInference(model)
# --- Counterfactual Reasoning ---
# Step 1: Evidence Instantiation
evidence = {'W': 'True'}
print("Observed Evidence:", evidence)
# Step 2: Counterfactual Intervention
counterfactual_intervention = {'S': 'False'}
print("Counterfactual Intervention:", counterfactual_intervention)
# Step 3: Inference (Counterfactual Query)
# We want to find the probability of Rain being True in the counterfactual world
counterfactual_query = causal_inference.query(
    variables=['R'],
    evidence=evidence,
    do=counterfactual_intervention
)
print("\nCounterfactual Probability of Rain (if Sprinkler was Off, given Grass was Wet):\n", counterfactual_query)
```@ankurankan: @dtchang In the example, we are intervening on the variable S while querying for the variable R, which implies that we trying to estimate the effect of S -> R. But in the model, R is an ancestor of S, so the causal effect of S on R is not really defined and hence throws an error.  It will work if, for example, you try estimate the effect of S -> W while conditioning on  R.
```python
In [7]: counterfactual_query = causal_inference.query(variables=['W'], evidence={'R': 'True'}, do={'S': 'True'})
In [8]: print(counterfactual_query)
+----------+----------+
| W        |   phi(W) |
+==========+==========+
| W(True)  |   0.9900 |
+----------+----------+
| W(False) |   0.0100 |
+----------+----------+

```

**Potential Fix:**  Improve the error message to detect these cases and throw a more meaningful error.@dtchang: The fix will resolve this issue. Thanks.

Solution patch:
diff --git a/pgmpy/inference/CausalInference.py b/pgmpy/inference/CausalInference.py
index 60320e73..1b692c17 100644
--- a/pgmpy/inference/CausalInference.py
+++ b/pgmpy/inference/CausalInference.py
@@ -986,6 +986,14 @@ class CausalInference(object):
                 "`evidence` must be a dict of the form: {variable_name: variable_state}"
             )
 
+        if do:
+            for var, do_var in product(variables, do):
+                if do_var in nx.descendants(self.dag, var):
+                    raise ValueError(
+                        f"Invalid causal query: There is a direct edge from the query variable '{var}' to the intervention variable '{do_var}'. "
+                        f"In causal inference, you can typically only query the effect on variables that are descendants of the intervention."
+                    )
+
         from pgmpy.inference import Inference
 
         if inference_algo == "ve":
diff --git a/pgmpy/utils/compat_fns.py b/pgmpy/utils/compat_fns.py
index b5848aae..2618e00e 100644
--- a/pgmpy/utils/compat_fns.py
+++ b/pgmpy/utils/compat_fns.py
@@ -139,7 +139,7 @@ def exp(arr):
 
 def sum(arr):
     if isinstance(arr, np.ndarray):
-        return np.sum(arr)
+        return arr.sum()
     else:
         return torch.sum(arr)
 
diff --git a/pyproject.toml b/pyproject.toml
index 081b1769..9827e8cb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -87,4 +87,11 @@ build-backend = "setuptools.build_meta"
 exclude = ["tests"]
 
 [tool.setuptools.package-data]
-pgmpy = ["utils/example_models/*"]
+pgmpy = [
+  "utils/example_models/*.bif.gz",
+  "utils/example_models/*.json",
+  "utils/example_models/*.txt"
+]
+[tool.setuptools]
+include-package-data = true
+


Test patch:
diff --git a/pgmpy/tests/test_inference/test_CausalInference.py b/pgmpy/tests/test_inference/test_CausalInference.py
index 9ddfe0c0..a07fe4c9 100644
--- a/pgmpy/tests/test_inference/test_CausalInference.py
+++ b/pgmpy/tests/test_inference/test_CausalInference.py
@@ -1243,6 +1243,49 @@ class TestDoQuery(unittest.TestCase):
             inference_algo="random",
         )
 
+    def test_invalid_causal_query_direct_descendant_intervention(self):
+        # Model: R -> S -> W & R -> W. We intervene on S and query R.
+        model = DiscreteBayesianNetwork([("R", "W"), ("S", "W"), ("R", "S")])
+        cpd_rain = TabularCPD(
+            variable="R",
+            variable_card=2,
+            values=[[0.6], [0.4]],
+            state_names={"R": ["True", "False"]},
+        )
+        cpd_sprinkler = TabularCPD(
+            variable="S",
+            variable_card=2,
+            values=[[0.1, 0.5], [0.9, 0.5]],
+            evidence=["R"],
+            evidence_card=[2],
+            state_names={"S": ["True", "False"], "R": ["True", "False"]},
+        )
+        cpd_wet_grass = TabularCPD(
+            variable="W",
+            variable_card=2,
+            values=[[0.99, 0.9, 0.9, 0.01], [0.01, 0.1, 0.1, 0.99]],
+            evidence=["R", "S"],
+            evidence_card=[2, 2],
+            state_names={
+                "W": ["True", "False"],
+                "R": ["True", "False"],
+                "S": ["True", "False"],
+            },
+        )
+        model.add_cpds(cpd_rain, cpd_sprinkler, cpd_wet_grass)
+        causal_inference = CausalInference(model)
+
+        evidence = {"W": "True"}
+        counterfactual_intervention = {"S": "False"}
+        with self.assertRaises(ValueError) as cm:
+            causal_inference.query(
+                variables=["R"], evidence=evidence, do=counterfactual_intervention
+            )
+        self.assertIn(
+            "Invalid causal query: There is a direct edge from the query variable 'R' to the intervention variable 'S'.",
+            str(cm.exception),
+        )
+
 
 class TestEstimator(unittest.TestCase):
     def test_create_estimator(self):