formative-ds 2.2.5__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {formative_ds-2.2.5 → formative_ds-2.3.0}/.github/workflows/ci.yml +1 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/CLAUDE.md +3 -3
- {formative_ds-2.2.5 → formative_ds-2.3.0}/Makefile +3 -3
- {formative_ds-2.2.5 → formative_ds-2.3.0}/PKG-INFO +1 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/design/policy_learning.md +3 -4
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/index.rst +0 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/_base.py +7 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/_cate.py +2 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/did.py +2 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/iv.py +2 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/matching.py +2 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/ols.py +2 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/policy.py +5 -29
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/rct.py +2 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/rdd.py +7 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/pyproject.toml +2 -3
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/documentation_options.js +1 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/benchmarks.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/dag.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/decisions.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/estimands.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/estimators.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/introduction.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/motivation.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/refutations.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/causal/wizard.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/game/decision_rules.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/game/introduction.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/game/single_player.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/genindex.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/index.html +2 -2
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/search.html +2 -2
- formative_ds-2.3.0/tests/test_missing_values.py +86 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_policy.py +2 -1
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_rdd_refutation.py +26 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/uv.lock +98 -1722
- formative_ds-2.2.5/docs/causal/benchmarks.rst +0 -431
- formative_ds-2.2.5/notebooks/card_krueger_benchmark.ipynb +0 -452
- formative_ds-2.2.5/notebooks/lalonde_benchmark.ipynb +0 -538
- {formative_ds-2.2.5 → formative_ds-2.3.0}/.gitattributes +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/.github/workflows/publish.yml +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/.gitignore +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/LICENSE +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/README.md +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/TODO.md +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/_static/version_switcher.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/_static/version_switcher.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/dag.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/decisions.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/estimands.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/estimators.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/introduction.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/motivation.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/refutations.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/causal/wizard.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/conf.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/game/decision_rules.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/game/introduction.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/docs/game/single_player.rst +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/decision/01_decision_basic.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/did/01_did_basic.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/iv/01_iv_basic.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/iv/02_iv_vs_ols_bias.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/iv/03_iv_with_observed_confounder.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/iv/04_iv_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/matching/01_basic_matching.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/matching/02_matching_vs_naive.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/matching/03_matching_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/ols/01_ols_basic.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/ols/02_ols_unobserved_confounder.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/ols/03_ols_multiple_confounders.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/rct/01_rct_basic.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/rdd/01_rdd_basic.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/examples/rdd/02_rdd_positive_running_var.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/__init__.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/__init__.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/_assumptions.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/_exceptions.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/_explain.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/dag.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/decision.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/estimators/__init__.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/__init__.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/_check.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/cate.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/did.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/iv.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/matching.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/ols.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/policy.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/rct.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/causal/refutations/rdd.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/__init__.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/expected_value.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/hurwicz.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/laplace.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/maximax.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/maximin.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/formative/game/minimax.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/scripts/snapshot_docs.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/benchmarks.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/dag.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/decisions.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/estimands.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/estimators.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/introduction.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/motivation.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/refutations.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/causal/wizard.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/game/decision_rules.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/game/introduction.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/game/single_player.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_sources/index.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/_sphinx_javascript_frameworks_compat.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/base-stemmer.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/basic.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/check-solid.svg +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/clipboard.min.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/copy-button.svg +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/copybutton.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/copybutton.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/copybutton_funcs.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/badge_only.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/fontawesome-webfont.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/fontawesome-webfont.svg +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/fontawesome-webfont.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-bold-italic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-normal-italic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-normal.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/fonts/lato-normal.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/css/theme.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/doctools.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/documentation_options.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/english-stemmer.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/file.png +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bold.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bold.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-italic.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-italic.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-italic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-italic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-regular.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-regular.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-regular.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/Lato/lato-regular.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/jquery.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/js/badge_only.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/js/theme.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/js/versions.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/language_data.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/minus.png +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/plus.png +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/pygments.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/searchtools.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/sphinx_highlight.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/version_switcher.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/_static/version_switcher.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/benchmarks.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/dag.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/decisions.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/estimands.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/estimators.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/introduction.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/motivation.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/refutations.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/causal/wizard.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/game/decision_rules.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/game/introduction.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/game/single_player.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/genindex.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/index.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/objects.inv +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/search.html +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.1/searchindex.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/benchmarks.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/dag.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/decisions.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/estimands.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/estimators.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/introduction.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/motivation.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/refutations.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/causal/wizard.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/game/decision_rules.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/game/introduction.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/game/single_player.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_sources/index.rst.txt +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/_sphinx_javascript_frameworks_compat.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/base-stemmer.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/basic.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/check-solid.svg +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/clipboard.min.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/copy-button.svg +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/copybutton.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/copybutton.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/copybutton_funcs.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/badge_only.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/fontawesome-webfont.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/fontawesome-webfont.svg +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/fontawesome-webfont.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-bold-italic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-normal-italic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-normal.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/fonts/lato-normal.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/css/theme.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/doctools.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/english-stemmer.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/file.png +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bold.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bold.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-italic.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-italic.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-italic.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-italic.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-regular.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-regular.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-regular.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/Lato/lato-regular.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/jquery.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/js/badge_only.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/js/theme.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/js/versions.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/language_data.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/minus.png +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/plus.png +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/pygments.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/searchtools.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/sphinx_highlight.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/version_switcher.css +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/_static/version_switcher.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/objects.inv +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/2.2/searchindex.js +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/site/versions.json +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_cate.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_cate_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_dag.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_decision.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_did.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_did_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_game.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_iv.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_iv_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_matching.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_matching_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_ols.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_ols_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_policy_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_rct.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_rct_refutation.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/tests/test_rdd.py +0 -0
- {formative_ds-2.2.5 → formative_ds-2.3.0}/vercel.json +0 -0
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
run: uv sync --dev --group docs
|
|
17
17
|
|
|
18
18
|
- name: Lint
|
|
19
|
-
run: uv run ruff check
|
|
19
|
+
run: uv run ruff check . && uv run ruff format --check --exclude notebooks .
|
|
20
20
|
|
|
21
21
|
- name: Run tests
|
|
22
22
|
run: uv run pytest --cov=formative --cov-report=term-missing --cov-fail-under=80
|
|
@@ -9,7 +9,7 @@ uv sync --dev # install dependencies
|
|
|
9
9
|
uv run pytest # run all tests
|
|
10
10
|
uv run pytest tests/test_iv.py # run one file
|
|
11
11
|
uv run pytest tests/test_iv.py::TestIV2SLSEstimation::test_iv_recovers_true_effect # run one test
|
|
12
|
-
make lint # ruff check
|
|
12
|
+
make lint # ruff check
|
|
13
13
|
make fmt # ruff format
|
|
14
14
|
make check # lint + format check + tests with coverage (CI requires ≥80%)
|
|
15
15
|
make build-docs # sphinx with -W: warnings are errors in CI
|
|
@@ -66,7 +66,7 @@ Do not change `_RCC_SEED` or `_PLACEBO_SEED` to 42 — the generated noise colli
|
|
|
66
66
|
|
|
67
67
|
**Heterogeneous effects (CATE)** — `OLSObservational` and `RCT` accept `effect_modifier=` (a discrete, pre-treatment column). `fit()` then returns `OLSCATEResult`/`RCTCATEResult` with `effect_by_group`, a homogeneity F-test, and `decide_by_group()`. The headline `effect` is the sample-share-weighted average of group effects (the raw treatment coefficient under interaction coding is only the reference group's effect). Shared machinery lives in `estimators/_cate.py`; DAG validation rejects modifiers that are descendants of the treatment (mediators) or not ancestors of the outcome.
|
|
68
68
|
|
|
69
|
-
**Policy learning** — `RCTResult.learn_policy(df, modifiers=[...], cost=, benefit=, max_depth=1|2)` (design note: `docs/design/policy_learning.md`) does Athey–Wager doubly robust policy learning: cross-fitted AIPW scores, exhaustive shallow-tree search over discrete features, honest (out-of-fold) value reported as the advantage over the best constant policy. Returns `PolicyResult` (`rules`, `value`, `assign()`, `refute()`). Refutation checks test the honest *value*, not tree structure — in-sample search happily splits on noise within its depth budget, so structural checks would be flaky.
|
|
69
|
+
**Policy learning** — `RCTResult.learn_policy(df, modifiers=[...], cost=, benefit=, max_depth=1|2)` (design note: `docs/design/policy_learning.md`) does Athey–Wager doubly robust policy learning: cross-fitted AIPW scores, exhaustive shallow-tree search over discrete features, honest (out-of-fold) value reported as the advantage over the best constant policy. Returns `PolicyResult` (`rules`, `value`, `assign()`, `refute()`). Refutation checks test the honest *value*, not tree structure — in-sample search happily splits on noise within its depth budget, so structural checks would be flaky. The depth-2 search starts from the best depth-1 tree, so a deeper tree must strictly beat it — otherwise equal-value trees with redundant conditions can win on candidate order.
|
|
70
70
|
|
|
71
71
|
**Package layout:**
|
|
72
72
|
- `formative/causal/dag.py` — `DAG`, `_Node`
|
|
@@ -98,7 +98,7 @@ Do not change `_RCC_SEED` or `_PLACEBO_SEED` to 42 — the generated noise colli
|
|
|
98
98
|
|
|
99
99
|
**Bootstrap-heavy tests:** matching tests use `setup_class` (not `setup_method`) so `.fit()` runs once per class. Use N=1_000 — larger N widens bootstrap SE faster than NN noise shrinks, causing refutation checks to fail even on well-specified data.
|
|
100
100
|
|
|
101
|
-
**
|
|
101
|
+
**Examples:** runnable per-estimator example scripts live in `examples/`.
|
|
102
102
|
|
|
103
103
|
**Planned estimators:** the goal is to cover all methods in the causal inference decision tree at https://www.maxpagels.com/prototypes/causal-wizard. Remaining: **Synthetic Control**.
|
|
104
104
|
|
|
@@ -8,13 +8,13 @@ test:
|
|
|
8
8
|
uv run pytest --cov=formative --cov-report=term-missing --cov-fail-under=80
|
|
9
9
|
|
|
10
10
|
lint:
|
|
11
|
-
uv run ruff check
|
|
11
|
+
uv run ruff check .
|
|
12
12
|
|
|
13
13
|
fmt:
|
|
14
|
-
uv run ruff format
|
|
14
|
+
uv run ruff format .
|
|
15
15
|
|
|
16
16
|
check: lint
|
|
17
|
-
uv run ruff format --check
|
|
17
|
+
uv run ruff format --check .
|
|
18
18
|
uv run pytest --cov=formative --cov-report=term-missing --cov-fail-under=80
|
|
19
19
|
|
|
20
20
|
release: # usage: make release BUMP=patch|minor|major
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** implemented (see `formative/causal/estimators/policy.py`); deviations from this
|
|
4
4
|
note: refutation checks test the honest value rather than tree structure (in-sample search
|
|
5
|
-
splits on noise within its depth budget, so structural checks are flaky), and
|
|
6
|
-
|
|
5
|
+
splits on noise within its depth budget, so structural checks are flaky), and a deeper tree
|
|
6
|
+
must strictly beat the best shallower one, so equal-value trees with redundant splits never win.
|
|
7
7
|
**Date:** 2026-07-11
|
|
8
8
|
|
|
9
9
|
## Motivation
|
|
@@ -115,8 +115,7 @@ print(policy.summary())
|
|
|
115
115
|
- Narrative rendering in `_explain.py`.
|
|
116
116
|
- Tests in `tests/test_policy.py` + `tests/test_policy_refutation.py`; cross-fitting
|
|
117
117
|
makes fitting expensive, so use `setup_class` like the matching tests.
|
|
118
|
-
- Docs page under `docs/causal/` with a worked example
|
|
119
|
-
once a public dataset with a known-good policy exists.
|
|
118
|
+
- Docs page under `docs/causal/` with a worked example.
|
|
120
119
|
|
|
121
120
|
## Open questions
|
|
122
121
|
|
|
@@ -28,6 +28,13 @@ def _missing_confounders_error(missing: set[str], treatment: str, outcome: str)
|
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def _reject_missing(data, columns, action: str = "fitting") -> None:
|
|
32
|
+
"""Raise if any used column has NaNs: statsmodels formulas drop those rows silently, our own code doesn't."""
|
|
33
|
+
with_nan = [c for c in dict.fromkeys(columns) if data[c].isna().any()]
|
|
34
|
+
if with_nan:
|
|
35
|
+
raise ValueError(f"Columns {with_nan} contain missing values — drop or impute them before {action}.")
|
|
36
|
+
|
|
37
|
+
|
|
31
38
|
class _BaseResult:
|
|
32
39
|
"""
|
|
33
40
|
Shared behaviour for estimation result classes.
|
|
@@ -18,6 +18,7 @@ import statsmodels.formula.api as smf
|
|
|
18
18
|
|
|
19
19
|
from .._assumptions import Assumption
|
|
20
20
|
from ..dag import DAG
|
|
21
|
+
from ._base import _reject_missing
|
|
21
22
|
|
|
22
23
|
CATE_ASSUMPTIONS: list[Assumption] = [
|
|
23
24
|
Assumption("Correct specification of effect modification (linear interaction form)", testable=False),
|
|
@@ -86,6 +87,7 @@ def _validate_modifier_data(data: pd.DataFrame, treatment: str, modifier: str) -
|
|
|
86
87
|
"""Data checks on the effect modifier column. Raises ``ValueError`` on violation."""
|
|
87
88
|
if modifier not in data.columns:
|
|
88
89
|
raise ValueError(f"Effect modifier column '{modifier}' not found in dataframe.")
|
|
90
|
+
_reject_missing(data, [modifier])
|
|
89
91
|
levels = data[modifier].dropna().unique()
|
|
90
92
|
if len(levels) < 2:
|
|
91
93
|
raise ValueError(f"Effect modifier '{modifier}' must have at least 2 levels. Found: {list(levels)}")
|
|
@@ -5,7 +5,7 @@ import statsmodels.formula.api as smf
|
|
|
5
5
|
|
|
6
6
|
from .._assumptions import Assumption
|
|
7
7
|
from ..dag import DAG
|
|
8
|
-
from ._base import _StatsmodelsResult
|
|
8
|
+
from ._base import _reject_missing, _StatsmodelsResult
|
|
9
9
|
|
|
10
10
|
DID_ASSUMPTIONS: list[Assumption] = [
|
|
11
11
|
Assumption(
|
|
@@ -227,6 +227,7 @@ class DiD:
|
|
|
227
227
|
]:
|
|
228
228
|
if var not in data.columns:
|
|
229
229
|
raise ValueError(f"{label} column '{var}' not found in dataframe.")
|
|
230
|
+
_reject_missing(data, [self._group, self._time, self._outcome])
|
|
230
231
|
|
|
231
232
|
for label, var in [("Group", self._group), ("Time", self._time)]:
|
|
232
233
|
vals = set(data[var].dropna().unique())
|
|
@@ -7,7 +7,7 @@ from statsmodels.sandbox.regression.gmm import IV2SLS as _IV2SLS
|
|
|
7
7
|
|
|
8
8
|
from .._assumptions import Assumption
|
|
9
9
|
from ..dag import DAG
|
|
10
|
-
from ._base import _backdoor_confounders, _StatsmodelsResult
|
|
10
|
+
from ._base import _backdoor_confounders, _reject_missing, _StatsmodelsResult
|
|
11
11
|
|
|
12
12
|
IV_ASSUMPTIONS: list[Assumption] = [
|
|
13
13
|
Assumption("Relevance: the instrument strongly affects treatment", testable=True),
|
|
@@ -267,6 +267,7 @@ class IV2SLS:
|
|
|
267
267
|
controls = sorted(adjustment_set)
|
|
268
268
|
|
|
269
269
|
T, Y, Z = self._treatment, self._outcome, self._instrument
|
|
270
|
+
_reject_missing(data, [T, Y, Z, *controls])
|
|
270
271
|
|
|
271
272
|
# Build design matrices for 2SLS:
|
|
272
273
|
# exog: [const, T, controls] — includes endogenous treatment
|
|
@@ -7,7 +7,7 @@ import statsmodels.formula.api as smf
|
|
|
7
7
|
|
|
8
8
|
from .._assumptions import Assumption
|
|
9
9
|
from ..dag import DAG
|
|
10
|
-
from ._base import _backdoor_confounders, _BaseResult, _missing_confounders_error
|
|
10
|
+
from ._base import _backdoor_confounders, _BaseResult, _missing_confounders_error, _reject_missing
|
|
11
11
|
|
|
12
12
|
MATCHING_ASSUMPTIONS: list[Assumption] = [
|
|
13
13
|
Assumption("Conditional independence: no unobserved confounders given matched variables", testable=False),
|
|
@@ -323,6 +323,7 @@ class PropensityScoreMatching:
|
|
|
323
323
|
raise _missing_confounders_error(missing, self._treatment, self._outcome)
|
|
324
324
|
|
|
325
325
|
T, Y = self._treatment, self._outcome
|
|
326
|
+
_reject_missing(data, [T, Y, *sorted(adjustment_set)])
|
|
326
327
|
|
|
327
328
|
# Unadjusted estimate: naive mean difference, no matching.
|
|
328
329
|
unadjusted = data.loc[data[T] == 1, Y].mean() - data.loc[data[T] == 0, Y].mean()
|
|
@@ -5,7 +5,7 @@ import statsmodels.formula.api as smf
|
|
|
5
5
|
|
|
6
6
|
from .._assumptions import Assumption
|
|
7
7
|
from ..dag import DAG
|
|
8
|
-
from ._base import _backdoor_confounders, _missing_confounders_error, _StatsmodelsResult
|
|
8
|
+
from ._base import _backdoor_confounders, _missing_confounders_error, _reject_missing, _StatsmodelsResult
|
|
9
9
|
from ._cate import (
|
|
10
10
|
CATE_ASSUMPTIONS,
|
|
11
11
|
_CATEResultMixin,
|
|
@@ -329,6 +329,7 @@ class OLSObservational:
|
|
|
329
329
|
if dag_confounders_not_in_data:
|
|
330
330
|
raise _missing_confounders_error(dag_confounders_not_in_data, self._treatment, self._outcome)
|
|
331
331
|
|
|
332
|
+
_reject_missing(data, [self._treatment, self._outcome, *sorted(adjustment_set)])
|
|
332
333
|
unadjusted_result = smf.ols(f"{self._outcome} ~ {self._treatment}", data=data).fit()
|
|
333
334
|
|
|
334
335
|
if self._modifier is not None:
|
|
@@ -23,6 +23,7 @@ import numpy as np
|
|
|
23
23
|
import pandas as pd
|
|
24
24
|
|
|
25
25
|
from .._assumptions import Assumption
|
|
26
|
+
from ._base import _reject_missing
|
|
26
27
|
from ._cate import _validate_modifier_dag
|
|
27
28
|
|
|
28
29
|
_FOLD_SEED = 13579
|
|
@@ -101,30 +102,6 @@ def _rules_lines(tree: PolicyNode | bool) -> list[str]:
|
|
|
101
102
|
return [f"treat if {' and '.join(conds)}" for conds in paths] + ["otherwise don't treat"]
|
|
102
103
|
|
|
103
104
|
|
|
104
|
-
def _simplify_tree(tree: PolicyNode | bool, data: pd.DataFrame) -> PolicyNode | bool:
|
|
105
|
-
"""
|
|
106
|
-
Drop splits that don't change the assignment on *data*.
|
|
107
|
-
|
|
108
|
-
The exhaustive search keeps the first of several equal-value trees, which
|
|
109
|
-
can carry redundant conditions (e.g. a root split whose subtree already
|
|
110
|
-
implies it). Replacing a node by one of its children is safe whenever the
|
|
111
|
-
assignment is identical over the sample — same assignment, same value.
|
|
112
|
-
"""
|
|
113
|
-
if isinstance(tree, bool):
|
|
114
|
-
return tree
|
|
115
|
-
cond = data[tree.feature].to_numpy() == tree.level
|
|
116
|
-
left = _simplify_tree(tree.if_true, data.loc[cond])
|
|
117
|
-
right = _simplify_tree(tree.if_false, data.loc[~cond])
|
|
118
|
-
if isinstance(left, bool) and isinstance(right, bool) and left == right:
|
|
119
|
-
return left
|
|
120
|
-
tree = PolicyNode(tree.feature, tree.level, left, right)
|
|
121
|
-
full = _assign_tree(tree, data)
|
|
122
|
-
for child in (left, right):
|
|
123
|
-
if np.array_equal(_assign_tree(child, data), full):
|
|
124
|
-
return child
|
|
125
|
-
return tree
|
|
126
|
-
|
|
127
|
-
|
|
128
105
|
def _dr_scores(
|
|
129
106
|
W: np.ndarray,
|
|
130
107
|
Y: np.ndarray,
|
|
@@ -188,6 +165,9 @@ def _learn_tree(
|
|
|
188
165
|
best_val = float(vals[i])
|
|
189
166
|
return best_tree, best_val
|
|
190
167
|
|
|
168
|
+
# A deeper tree must strictly beat the best shallower one, or an equal-value
|
|
169
|
+
# tree with redundant splits can win on candidate order.
|
|
170
|
+
best_tree, best_val = _learn_tree(gamma, M, candidates, max_depth - 1)
|
|
191
171
|
for i, (feature, level) in enumerate(candidates):
|
|
192
172
|
mask = M[i].astype(bool)
|
|
193
173
|
left_tree, left_val = _learn_tree(gamma[mask], M[:, mask], candidates, max_depth - 1)
|
|
@@ -260,7 +240,6 @@ def _fit_policy(
|
|
|
260
240
|
value_ci = (value - 1.96 * value_se, value + 1.96 * value_se)
|
|
261
241
|
|
|
262
242
|
tree, _ = _learn_tree(gamma, M, candidates, max_depth)
|
|
263
|
-
tree = _simplify_tree(tree, data)
|
|
264
243
|
coverage = float(_assign_tree(tree, data).mean())
|
|
265
244
|
|
|
266
245
|
return _PolicyFit(tree=tree, value=value, value_se=value_se, value_ci=value_ci, coverage=coverage)
|
|
@@ -458,10 +437,7 @@ def _validate_policy_inputs(
|
|
|
458
437
|
f"Policy trees need discrete features — bin continuous or high-cardinality columns first."
|
|
459
438
|
)
|
|
460
439
|
|
|
461
|
-
|
|
462
|
-
with_nan = [c for c in used if data[c].isna().any()]
|
|
463
|
-
if with_nan:
|
|
464
|
-
raise ValueError(f"Columns {with_nan} contain missing values — drop or impute them before learning a policy.")
|
|
440
|
+
_reject_missing(data, [treatment, outcome, *modifiers], action="learning a policy")
|
|
465
441
|
|
|
466
442
|
w = set(data[treatment].unique())
|
|
467
443
|
if w != {0, 1}:
|
|
@@ -5,7 +5,7 @@ import statsmodels.formula.api as smf
|
|
|
5
5
|
|
|
6
6
|
from .._assumptions import Assumption
|
|
7
7
|
from ..dag import DAG
|
|
8
|
-
from ._base import _StatsmodelsResult
|
|
8
|
+
from ._base import _reject_missing, _StatsmodelsResult
|
|
9
9
|
from ._cate import (
|
|
10
10
|
CATE_ASSUMPTIONS,
|
|
11
11
|
_CATEResultMixin,
|
|
@@ -305,6 +305,7 @@ class RCT:
|
|
|
305
305
|
for label, var in [("Treatment", self._treatment), ("Outcome", self._outcome)]:
|
|
306
306
|
if var not in data.columns:
|
|
307
307
|
raise ValueError(f"{label} column '{var}' not found in dataframe.")
|
|
308
|
+
_reject_missing(data, [self._treatment, self._outcome])
|
|
308
309
|
|
|
309
310
|
if self._modifier is not None:
|
|
310
311
|
_validate_modifier_data(data, self._treatment, self._modifier)
|
|
@@ -5,7 +5,7 @@ import statsmodels.formula.api as smf
|
|
|
5
5
|
|
|
6
6
|
from .._assumptions import Assumption
|
|
7
7
|
from ..dag import DAG
|
|
8
|
-
from ._base import _StatsmodelsResult
|
|
8
|
+
from ._base import _reject_missing, _StatsmodelsResult
|
|
9
9
|
|
|
10
10
|
RDD_ASSUMPTIONS: list[Assumption] = [
|
|
11
11
|
Assumption(
|
|
@@ -131,6 +131,10 @@ class RDDResult(_StatsmodelsResult):
|
|
|
131
131
|
_check_random_common_cause,
|
|
132
132
|
)
|
|
133
133
|
|
|
134
|
+
# Refute on the same rows fit() used, not the whole dataframe.
|
|
135
|
+
if self._bandwidth is not None:
|
|
136
|
+
data = data.loc[(data[self._running_var] - self._cutoff).abs() <= self._bandwidth]
|
|
137
|
+
|
|
134
138
|
checks = [
|
|
135
139
|
_check_placebo_cutoff(
|
|
136
140
|
data,
|
|
@@ -256,6 +260,8 @@ class RDD:
|
|
|
256
260
|
filtered = data.loc[mask]
|
|
257
261
|
else:
|
|
258
262
|
filtered = data
|
|
263
|
+
# Rows outside the bandwidth are never used, so their gaps don't matter.
|
|
264
|
+
_reject_missing(filtered, [self._running_var, self._outcome])
|
|
259
265
|
|
|
260
266
|
# Unadjusted effect: naive mean difference above vs below cutoff
|
|
261
267
|
above = filtered.loc[filtered[self._running_var] >= self._cutoff, self._outcome].mean()
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "formative-ds"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.3.0"
|
|
8
8
|
description = "A Python library for quantitative reasoning."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -37,7 +37,6 @@ Repository = "https://github.com/maxpagels/formative"
|
|
|
37
37
|
|
|
38
38
|
[dependency-groups]
|
|
39
39
|
dev = [
|
|
40
|
-
"jupyter>=1.1.1",
|
|
41
40
|
"pytest>=9,<10",
|
|
42
41
|
"pytest-cov",
|
|
43
42
|
"ruff>=0.9",
|
|
@@ -48,7 +47,7 @@ docs = ["sphinx>=7,<10", "sphinx-rtd-theme>=2,<4", "sphinx-copybutton>=0.5,<0.6"
|
|
|
48
47
|
packages = ["formative"]
|
|
49
48
|
|
|
50
49
|
[tool.bumpversion]
|
|
51
|
-
current_version = "2.
|
|
50
|
+
current_version = "2.3.0"
|
|
52
51
|
commit = true
|
|
53
52
|
tag = true
|
|
54
53
|
tag_name = "v{new_version}"
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Benchmarks — formative 2.2.
|
|
9
|
+
<title>Benchmarks — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/benchmarks.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>DAG — formative 2.2.
|
|
9
|
+
<title>DAG — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/dag.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Decisions — formative 2.2.
|
|
9
|
+
<title>Decisions — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/decisions.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Estimands — formative 2.2.
|
|
9
|
+
<title>Estimands — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/estimands.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Estimators — formative 2.2.
|
|
9
|
+
<title>Estimators — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/estimators.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Introduction — formative 2.2.
|
|
9
|
+
<title>Introduction — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/introduction.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Motivation — formative 2.2.
|
|
9
|
+
<title>Motivation — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/motivation.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Refutations — formative 2.2.
|
|
9
|
+
<title>Refutations — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/refutations.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Choosing an estimator — formative 2.2.
|
|
9
|
+
<title>Choosing an estimator — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/causal/wizard.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Decision rules — formative 2.2.
|
|
9
|
+
<title>Decision rules — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/game/decision_rules.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Introduction — formative 2.2.
|
|
9
|
+
<title>Introduction — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/game/introduction.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>Single-player — formative 2.2.
|
|
9
|
+
<title>Single-player — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/game/single_player.html" />
|
|
17
17
|
<script src="../_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="../_static/documentation_options.js?v=
|
|
19
|
+
<script src="../_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="../_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="../_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="../_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="utf-8" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
-
<title>Index — formative 2.2.
|
|
8
|
+
<title>Index — formative 2.2.5 documentation</title>
|
|
9
9
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=b86133f3" />
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=9edc463e" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<link rel="canonical" href="https://docs.getformative.dev/genindex.html" />
|
|
16
16
|
<script src="_static/jquery.js?v=5d32c60e"></script>
|
|
17
17
|
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
18
|
-
<script src="_static/documentation_options.js?v=
|
|
18
|
+
<script src="_static/documentation_options.js?v=ea147abf"></script>
|
|
19
19
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
|
20
20
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
21
21
|
<script src="_static/clipboard.min.js?v=a7894cd8"></script>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
7
|
|
|
8
8
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
-
<title>formative — formative 2.2.
|
|
9
|
+
<title>formative — formative 2.2.5 documentation</title>
|
|
10
10
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=b86133f3" />
|
|
11
11
|
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=9edc463e" />
|
|
12
12
|
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<link rel="canonical" href="https://docs.getformative.dev/index.html" />
|
|
17
17
|
<script src="_static/jquery.js?v=5d32c60e"></script>
|
|
18
18
|
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
|
|
19
|
-
<script src="_static/documentation_options.js?v=
|
|
19
|
+
<script src="_static/documentation_options.js?v=ea147abf"></script>
|
|
20
20
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
|
21
21
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
|
22
22
|
<script src="_static/clipboard.min.js?v=a7894cd8"></script>
|