Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions dowhy/causal_refuter.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ def perform_normal_distribution_test(estimate, simulations: List):
mean_refute_values = np.mean(simulations)
# Get the standard deviation for the simulations
std_dev_refute_values = np.std(simulations)

# Degenerate case: all simulations returned the same value (zero variance).
# Division by zero would produce NaN. Return p_value=1 to indicate that the
# original estimate is indistinguishable from the simulation distribution.
if std_dev_refute_values == 0:
logger.warning(
"All simulation values are identical (std = 0). "
"The normal-distribution p-value is undefined; returning p_value=1."
)
return 1.0

# Get the Z Score [(val - mean)/ std_dev ]
z_score = (estimate.value - mean_refute_values) / std_dev_refute_values

Expand Down
13 changes: 12 additions & 1 deletion tests/test_causal_refuter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from dowhy.causal_estimator import CausalEstimate
from dowhy.causal_identifier.identified_estimand import IdentifiedEstimand
from dowhy.causal_refuter import CausalRefuter
from dowhy.causal_refuter import CausalRefuter, perform_normal_distribution_test


class MockRefuter(CausalRefuter):
Expand All @@ -24,3 +24,14 @@ def test_causal_refuter_bootstrap_test():
simulations = np.random.normal(0, 1, 5000)
pvalue = refuter.perform_bootstrap_test(estimator, simulations)
assert pvalue > 0.95


def test_normal_distribution_test_zero_std_returns_one():
"""Regression test for issue #807: when all simulations have the same value (std=0),
perform_normal_distribution_test must return 1.0 instead of NaN."""
estimate = CausalEstimate(None, None, None, 5.0, None, None, None, None)
# All simulations return the same value as the estimate → std=0, p-value should be 1.0
simulations_identical = [5.0] * 20
p_value = perform_normal_distribution_test(estimate, simulations_identical)
assert not np.isnan(p_value), "p-value must not be NaN when std of simulations is 0"
assert p_value == 1.0, f"Expected p_value=1.0 for zero-variance simulations, got {p_value}"
Loading