Historical validation and benchmark records
Contents
- Historical validation and benchmark records
- Published a13 validation (October 26, 2026; bd14e4dc)
- Historical documentation validation (a9)
- Candidate 0.1.0a10 verification
- Earlier checkout-organization record (October 26, 2026)
- Candidate 0.1.0a11 verification (October 26, 2026)
- UCA component performance pilot
- Graph-free mean estimators (introduced in a12)
- Effects and whole-call pilot (a13)
- Earlier README inference notes (a13; original experiment date not recorded)
- Retained confounding-power demonstration
These are retained records, not current pass counts or coverage guarantees. They preserve the versions, dates, source pins, counts and limitations recorded before the October 27 documentation reorganization. A record with no original execution date is not assigned an invented date. Earlier source layouts and commands may differ from the current tree. Use current checks for the consolidated source layout.
Published a13 validation (October 26, 2026; bd14e4dc)
The implementation published at bd14e4dc passed 60 distinct tests (38 installed
API/graphless/effects/default/weight/component tests and 22 separate graph-engine
regressions), with zero skips. Seven API-guide Python blocks executed. The regular
wheel contained 36 payload files, matching installed bytes; 17 generated modules
matched canonical sources. The whole-call pilot completed 20/20 trials. These
are bounded implementation checks, not accuracy or coverage guarantees.
New documentation walkthrough checks are recorded in the maintained tutorial and this refresh report; the old records below remain historical.
Historical documentation validation (a9)
This section preserves the earlier 0.1.0a9 documentation-pass record. The
new candidate’s build, weighting, and HTML checks are recorded separately below.
On 2026-10-25, checks used the existing Python 3.11.14 interpreter at
/Users/yonghanjung/.venvs/causalpy-py311/bin/python. The system python3
did not have the required numerical dependencies. No dependencies were added.
An existing installation target at
/tmp/causalengine_api_docs_20261025/site contained 0.1.0a9. Its 28 package
source/data files matched the inspected working tree, applying setup.py’s
normal import rewrite for bundled root/vendor modules. Public checks ran from
/tmp, using that installation target on PYTHONPATH, not checkout modules.
The temporary target is a verification artifact and may disappear; users should
follow the regular installation instructions above. No new wheel was built in
this documentation pass.
# From the CausalEngine checkout, in the existing dependency environment:
PYTHONDONTWRITEBYTECODE=1 python -B -m unittest -q \
test_scm test_graph_editor test_adjustment test_frontdoor \
test_SBD test_identification test_indexed_identification
# 204 run; 202 passed; 2 skipped.
# From outside the checkout, with the matching package already installed:
PYTHONDONTWRITEBYTECODE=1 python -B -m unittest discover \
-s /absolute/path/to/CausalEngine/tests -p 'test_public_api.py' -q
# 8 run; 8 passed.
PYTHONDONTWRITEBYTECODE=1 python -B -m unittest discover \
-s /absolute/path/to/CausalEngine/tests -p 'test_cscm.py' -q
# 13 run; 13 passed.
PYTHONDONTWRITEBYTECODE=1 python -B /absolute/path/to/CausalEngine/tests/test_bdscm.py
# 12 checks; 12 passed.
For this run, the installed commands additionally used
PYTHONPATH=/tmp/causalengine_api_docs_20261025/site and the interpreter above.
The two checkout class-level skips request an optional flat-import UCA engine;
the installed namespace contract was tested separately and passed. A skipped
class does not mean all of its individual tests ran. See the
Wiki validation table for each check’s scope.
That historical checkout command used the file layout then available. Current
source-only suites live in tests/checkout/; use the current Wiki commands rather
than copying historical root-module names into a fresh clone.
The new mean example executed through public imports and returned
(1000, 7) BD (1,). The CSCM query smoke confirmed UNKNOWN with default
confounding and ACCEPT/BD with unconfounded=True. This pass also executed
the guide’s existing Python examples, with the documented prerequisite imports.
Generator-truth and finite-fixture checks are bounded regression evidence;
they do not establish all-graph completeness or statistical coverage. The local
graph-editor handler was exercised by tests; browser interaction/layout was not.
Candidate 0.1.0a10 verification
The candidate was built from tracked base 4caaa741 with only approved code,
tests, assets, and documentation overlaid in /tmp. Existing unrelated dirty
files were excluded. Wheel and source-distribution builds succeeded, including
the HTML asset despite the checkout’s general HTML ignore rule. The wheel was
installed offline with --no-deps into a temporary target using the existing
Python 3.11.14 dependency runtime; the user’s environments were not upgraded.
tests/test_weighting.py: 7 passed, including nonuniform source-metric optimality, normalization, signed weights, compatible/incompatible rank, actual finite-stage indicator balance, missing-target support failure, and actual affine-stage hard balance.tests/test_graph_tool.py: 4 passed, covering actual HTTP identification, negative/unfinished statuses, hidden/vector metadata, browser invocation mock, loopback request errors, and closeable server lifecycle.tests/test_public_api.py: 8 passed, including the additional public export and the existing scalar/vector identification/estimation contracts.
Headed browser QA confirmed node/edge editing, dragging, cycle rejection, vector/hidden roles, actual identification, and invalid-query errors. Desktop and 390-pixel mobile layouts passed; the final reload had no console errors or warnings. This QA covers the candidate HTML tool, separately from the historical graph-editor handler checks above.
The mathematical implementation review approved the Q-weighted objective, explicit normalization, finite support check, and preservation of the estimator selection. Exact fitted-design balance is not a guarantee of population balance or confidence-interval coverage. Fresh dependency resolution and other operating systems remain outside this validation.
Earlier checkout-organization record (October 26, 2026)
The text below retains the earlier organization record and its 212 executed cases. The source command has since been updated for the consolidated layout; it is not the command that produced that historical count:
PYTHONPATH=src python -B -m unittest discover -s tests/checkout -p 'test_*.py' -v
Run installed-package contracts separately, from outside the checkout, using
the absolute test directory (for example python -B -m unittest discover -s
/path/to/CausalEngine/tests -p test_public_api.py -v). Mixing flat-import source
tests with the installed lazy-import contract in one process changes its premise.
The source-only SCM editor is grouped at tutorials/graph_editor.py beside its
HTML asset. Launch python -B -m tutorials.graph_editor --port 8765 from the
repository root; see the tutorial guide.
Its experimental Korean UI generates models and sample rows. It is separate from
the installed English identification tool. Retired estimation/simulation sources
remain under archived/ as reference, preserving their pending compatibility edits.
No estimator, weight solver, or installed tool behavior changes in this organization pass.
Organization validation passed all 212 executed test cases across the checkout, SCM, and installed public-API suites. Two optional flat-import UCA classes (22 methods) were not run; see the current validation record.
Candidate 0.1.0a11 verification (October 26, 2026)
A tracked 3ca36462 snapshot plus the approved 18-path overlay was built as a
wheel and source distribution, then the wheel was installed offline with
--no-deps in a temporary target using the existing Python 3.11.14 dependency
runtime and XGBoost 2.0.3. Fresh dependency resolution and other OS/Python
versions were not tested. Existing a9/a10 records above are historical.
tests/test_uca_defaults.py: 5 run, 5 passed, 0 skipped. Actual XGBoost training occurred for default BD (2 calls), default FD (3), and explicit FD (3). The embedded front-door fixture completedNO_FIXED_PARTITIONfollowed byMC ACCEPTand full-score execution with unlimited order/wall budgets. Its bounded order search can instead reportUNKNOWN, which remains distinct from rejecting the criterion. Vector continuous covariates/outcomes, discrete action support, native/custom overrides and budget/scope guards were checked.tests/test_weighting.py: 7 run, 7 passed, 0 skipped; normalized minimum-L2 weights and finite/affine contracts remain intact.tests/test_public_api.py: 8 run, 8 passed, 0 skipped; old continuous-action pipeline checks now explicitly select the native backend.tests/checkout/test_identification.py’sCommonEngineTests: 19 run, 19 passed, 0 skipped, using this snapshot’s bundled engine explicitly. These optional tests were executed here, rather than inheriting earlier skips.tests/checkout/test_frontdoor.py’sUCAAdapterTests: 3 run, 3 passed, 0 skipped, using the bundled compiler for finite front-door expression checks.
The installed scalar/cluster demo retained native estimation and both cases
returned ACCEPT. The new discrete-action default example also executed.
Minimum-L2/fit_weights implementation bodies were unchanged, and the mathematical
review approved the routing, learner/weight separation and point-score boundaries.
These checks establish executable paths, not statistical accuracy or causal coverage.
UCA component performance pilot
The four-graph pilot compares Outcome/UCA plug-in, terminal IPW and the augmented UCA full score on paired data and exact binary-SCM truth. Its timing tables profile shared weight/regression/evaluation phases, rather than three independently executed estimators. Raw per-seed results and the reproduction command are linked from that report.
Graph-free mean estimators (introduced in a12)
Use estimate_bd, estimate_sbd, estimate_fd(covariates=...) or estimate_uca
when the identifying functional is supplied by the user rather than found from
a graph. The current a13 implementation uses the same XGBoost/minimum-L2 score engine,
records user-assumed identification and does not synthesize graph verification.
The earlier a11 pilot above remains a historical snapshot.
estimate_sbd declares ordered actions and new joint covariate blocks at each
stage. It retains action-dependent time-varying covariate distributions and uses
the same user-assumed point-score path, without graph verification.
Effects and whole-call pilot (a13)
estimate_ate and estimate_cate
use paired regime scores. CATE regresses them on structurally supported baseline
modifiers with a separate train/validation split; causal inference and conditional
nuisance calibration remain assumed. The four-API pilot
measures full public-call time, separately from the older shared-component timing.
Earlier README inference notes (a13; original experiment date not recorded)
The default backend='score', score_model=None returns a UCA point estimate and
a conditional fitted-score summary, with no automatic causal confidence interval.
It supports declared discrete actions and finite or continuous/vector covariates
and outcomes where the compiler and weight design support the expression.
Continuous fixed-point actions remain unsupported in this default: a Dirac target
is not dominated by a diffuse source design. backend='native' explicitly retains
the earlier plug-in estimators; the random-SCM demo above uses it. Explicit
method='FD' also runs the default UCA/XGBoost score instead of a direct native
front-door shortcut. XGBoost options use params and num_boost_round; an explicit
regression_factory replaces the backward learner.
Opt-in backend='score', score_model='affine' executes the UCA full score under declared affine backward/feature closure, iid sampling, full-rank population designs, finite moments and nuisance-rate/stability assumptions. score_model='finite' instead requires fixed finite alphabets and positive population support. Intervals are coordinatewise and assumption-conditional, not data-certified causal coverage or simultaneous vector intervals; existing weak continuous-cluster FD cases achieved only 83–92% coverage.
Retained confounding-power demonstration
This is a generator diagnostic, not evidence that increasing power isolates one statistical difficulty.
Since 0.1.0a8, signed finite confounding_power=1.0 scales only the direct
U term in the treatment logit. Its absolute value controls loading magnitude;
its sign reverses that term’s direction. It leaves X, U, outcome mechanisms,
Y0/Y1, and the ATE unchanged for the same task/data seeds. strength_range still
samples the base loadings; task.loadings['A'] reports the actual scaled value.
Zero uses the same no-U-to-A path as unconfounded=True; the explicit flag
overrides every power. task.confounding_power, task.unconfounded, and
task.confounder_metadata report the effective setting. This is a structural
assignment control, not a promise of monotonic observational bias. At zero,
X-to-A and X-to-Y paths can still make an unadjusted observed difference biased.
The following deliberately specified Gaussian example has population ATE 0.25.
Its base treatment is independent, and its outcome is
Y = 0.25*A + loading_Y*U + 0.1*noise_Y. The power direction is fixed using
mechanism coefficients before observing outcomes. There is no seed search.
All rows and potential outcomes are shared across powers. It illustrates sign
reversal; it is not a guarantee for every randomly generated outcome mechanism.
import numpy as np
from causalengine import CSCM, ConfounderOptions
from causalengine.bdscm import CovariateOptions, TreatmentOptions, OutcomeOptions, F_Y
class LinearOutcome:
def __init__(self, **options):
pass
def mean(self, x, a, *, score_offset=0):
return np.full(len(x), .25*a) + score_offset
def __call__(self, x, a, noise, *, score_offset=0):
return self.mean(x, a, score_offset=score_offset) + .1*noise
assert 'power_demo' not in F_Y
F_Y['power_demo'] = LinearOutcome
try:
options = dict(d_X=5, task_seed=42,
covariates=CovariateOptions(mechanism='mixed'),
treatment=TreatmentOptions(mechanism='independent'),
outcome=OutcomeOptions(family='power_demo'),
confounder=ConfounderOptions(strength_range=(1., 1.)))
base = CSCM(**options)
direction = -np.sign(base.loadings['A']*base.loadings['Y'])
print('power observed_difference oracle_ATE gap treated_fraction e01 e99 extreme_fraction')
for magnitude in (0., .5, 1., 2.):
power = float(direction*magnitude)
observed, truth = CSCM(**options, confounding_power=power).sample(30_000, data_seed=7)
a, y, e = observed['A'], observed['Y'], truth['e_xu']
difference = y[a==1].mean()-y[a==0].mean()
ate = np.mean(truth['mu1_xu']-truth['mu0_xu'])
e01, e99 = np.quantile(e, [.01, .99])
print(*(round(float(v), 4) for v in (power, difference, ate, difference-ate,
a.mean(), e01, e99, np.mean((e<.01)|(e>.99)))))
finally:
del F_Y['power_demo']
The observed difference compares treated/control sample means; oracle ATE uses generator potential-outcome means and is not learned from observational data. Propensity quantiles and the fraction outside [0.01,0.99] expose worsening overlap. Greater power can make causal estimation harder even though the target ATE is unchanged. Custom registry entries should use a fresh name; this example removes its temporary entry afterward.