causal-testing-framework 14.1.0__tar.gz → 14.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.
Files changed (197) hide show
  1. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/ci-tests-drafts.yaml +1 -1
  2. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/ci-tests.yaml +1 -1
  3. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/publish-to-dafni.yaml +1 -1
  4. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/publish-to-pypi.yaml +1 -1
  5. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.gitignore +2 -0
  6. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.pre-commit-config.yaml +1 -1
  7. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.readthedocs.yaml +3 -3
  8. {causal_testing_framework-14.1.0/causal_testing_framework.egg-info → causal_testing_framework-14.3.0}/PKG-INFO +14 -15
  9. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/README.md +3 -3
  10. causal_testing_framework-14.3.0/causal_testing/__main__.py +137 -0
  11. causal_testing_framework-14.3.0/causal_testing/_version.py +24 -0
  12. causal_testing_framework-14.3.0/causal_testing/discovery/abstract_discovery.py +236 -0
  13. causal_testing_framework-14.3.0/causal_testing/discovery/hill_climber_discovery.py +155 -0
  14. causal_testing_framework-14.3.0/causal_testing/discovery/nsga_discovery.py +131 -0
  15. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/abstract_regression_estimator.py +15 -1
  16. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/ipcw_estimator.py +1 -1
  17. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/linear_regression_estimator.py +5 -5
  18. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/logistic_regression_estimator.py +2 -8
  19. causal_testing_framework-14.3.0/causal_testing/estimation/multinomial_regression_estimator.py +56 -0
  20. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/main.py +87 -44
  21. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/specification/causal_dag.py +5 -4
  22. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/causal_effect.py +2 -2
  23. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/metamorphic_relation.py +40 -15
  24. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0/causal_testing_framework.egg-info}/PKG-INFO +14 -15
  25. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing_framework.egg-info/SOURCES.txt +16 -0
  26. causal_testing_framework-14.3.0/causal_testing_framework.egg-info/entry_points.txt +21 -0
  27. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing_framework.egg-info/requires.txt +9 -14
  28. causal_testing_framework-14.3.0/causal_testing_framework.egg-info/scm_file_list.json +188 -0
  29. causal_testing_framework-14.3.0/causal_testing_framework.egg-info/scm_version.json +8 -0
  30. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/entrypoint.sh +3 -3
  31. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/index.rst +2 -0
  32. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/installation.rst +3 -3
  33. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/modules/causal_testing.rst +1 -1
  34. causal_testing_framework-14.3.0/docs/source/modules/custom_estimators.rst +65 -0
  35. causal_testing_framework-14.3.0/docs/source/modules/discovery.rst +82 -0
  36. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/modules/estimators.rst +14 -0
  37. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/poisson_line_process/poisson_line_process_tutorial.ipynb +2 -10
  38. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/vaccinating_elderly/causal_test_results.json +5 -5
  39. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/vaccinating_elderly/vaccinating_elderly_tutorial.ipynb +24 -21
  40. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/README.md +1 -1
  41. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/example_pure_python.py +22 -18
  42. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/pyproject.toml +41 -20
  43. causal_testing_framework-14.3.0/tests/__init__.py +0 -0
  44. causal_testing_framework-14.3.0/tests/discovery_tests/test_abstract_discovery.py +262 -0
  45. causal_testing_framework-14.3.0/tests/discovery_tests/test_hill_climber_discovery.py +132 -0
  46. causal_testing_framework-14.3.0/tests/discovery_tests/test_nsga_discovery.py +53 -0
  47. causal_testing_framework-14.3.0/tests/estimation_tests/test_multinomial_regression_estimator.py +42 -0
  48. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/main_tests/test_main.py +118 -4
  49. causal_testing_framework-14.3.0/tests/resources/data/exclude_edges.dot +3 -0
  50. causal_testing_framework-14.3.0/tests/resources/data/include_edges.dot +3 -0
  51. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/tests.json +10 -6
  52. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/testing_tests/test_causal_test_adequacy.py +7 -6
  53. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/testing_tests/test_metamorphic_relations.py +44 -66
  54. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/tutorial_tests/test_tutorials.py +1 -1
  55. causal_testing_framework-14.1.0/causal_testing/__main__.py +0 -94
  56. causal_testing_framework-14.1.0/causal_testing/_version.py +0 -34
  57. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  58. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  59. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/figshare.yaml +0 -0
  60. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/joss.yaml +0 -0
  61. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.github/workflows/lint-format.yaml +0 -0
  62. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.mega-linter.yaml +0 -0
  63. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/.pylintrc +0 -0
  64. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/CITATION.cff +0 -0
  65. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/CONTRIBUTING.md +0 -0
  66. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/LICENSE +0 -0
  67. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/__init__.py +0 -0
  68. {causal_testing_framework-14.1.0/causal_testing/estimation → causal_testing_framework-14.3.0/causal_testing/discovery}/__init__.py +0 -0
  69. {causal_testing_framework-14.1.0/causal_testing/specification → causal_testing_framework-14.3.0/causal_testing/estimation}/__init__.py +0 -0
  70. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/abstract_estimator.py +0 -0
  71. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/cubic_spline_estimator.py +0 -0
  72. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/effect_estimate.py +0 -0
  73. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/experimental_estimator.py +0 -0
  74. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/genetic_programming_regression_fitter.py +0 -0
  75. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/estimation/instrumental_variable_estimator.py +0 -0
  76. {causal_testing_framework-14.1.0/causal_testing/surrogate → causal_testing_framework-14.3.0/causal_testing/specification}/__init__.py +0 -0
  77. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/specification/scenario.py +0 -0
  78. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/specification/variable.py +0 -0
  79. {causal_testing_framework-14.1.0/causal_testing/testing → causal_testing_framework-14.3.0/causal_testing/surrogate}/__init__.py +0 -0
  80. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/surrogate/causal_surrogate_assisted.py +0 -0
  81. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/surrogate/surrogate_search_algorithms.py +0 -0
  82. {causal_testing_framework-14.1.0/causal_testing/utils → causal_testing_framework-14.3.0/causal_testing/testing}/__init__.py +0 -0
  83. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/base_test_case.py +0 -0
  84. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/causal_test_adequacy.py +0 -0
  85. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/causal_test_case.py +0 -0
  86. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/causal_test_result.py +0 -0
  87. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/effect.py +0 -0
  88. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/testing/intervention.py +0 -0
  89. {causal_testing_framework-14.1.0/tests → causal_testing_framework-14.3.0/causal_testing/utils}/__init__.py +0 -0
  90. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing/utils/validation.py +0 -0
  91. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing_framework.egg-info/dependency_links.txt +0 -0
  92. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/causal_testing_framework.egg-info/top_level.txt +0 -0
  93. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/codecov.yml +0 -0
  94. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/.dockerignore +0 -0
  95. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/.env +0 -0
  96. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/Dockerfile +0 -0
  97. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/README.md +0 -0
  98. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/data/inputs/causal-tests/causal_tests.json +0 -0
  99. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/data/inputs/dag-data/dag.dot +0 -0
  100. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/data/inputs/runtime-data/runtime_data.csv +0 -0
  101. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/data/outputs/causal_test_results.json +0 -0
  102. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/docker-compose.yaml +0 -0
  103. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/dafni/model_definition.yaml +0 -0
  104. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/Makefile +0 -0
  105. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/README.md +0 -0
  106. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/make.bat +0 -0
  107. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/_static/css/custom.css +0 -0
  108. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/_static/images/CITCOM-logo-white.png +0 -0
  109. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/_static/images/CITCOM-logo.png +0 -0
  110. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/_static/images/Sheffield-logo.png +0 -0
  111. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/_static/images/example_dag.png +0 -0
  112. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/background.rst +0 -0
  113. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/conf.py +0 -0
  114. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/credits.rst +0 -0
  115. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/dev/actions_and_webhooks.rst +0 -0
  116. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/dev/documentation.rst +0 -0
  117. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/dev/version_release.rst +0 -0
  118. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/glossary.rst +0 -0
  119. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/modules/causal_specification.rst +0 -0
  120. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/requirements.txt +0 -0
  121. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/poisson_line_process/causal_tests.json +0 -0
  122. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/poisson_line_process/dag.dot +0 -0
  123. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/poisson_line_process/dag.png +0 -0
  124. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/poisson_line_process/data/random/data_random_1000.csv +0 -0
  125. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/vaccinating_elderly/causal_tests.json +0 -0
  126. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/vaccinating_elderly/dag.dot +0 -0
  127. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/vaccinating_elderly/dag_image.png +0 -0
  128. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/vaccinating_elderly/simulated_data.csv +0 -0
  129. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials/visualising_causal_test_results/visualise_causal_test_results.ipynb +0 -0
  130. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/docs/source/tutorials.rst +0 -0
  131. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/.gitignore +0 -0
  132. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/README.md +0 -0
  133. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/dag.dot +0 -0
  134. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/dag.png +0 -0
  135. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/10k_observational_data.csv +0 -0
  136. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/high_contacts_avg_age_22.2.csv +0 -0
  137. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/high_contacts_avg_age_30.1.csv +0 -0
  138. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/low_contacts_avg_age_22.2.csv +0 -0
  139. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/low_contacts_avg_age_30.1.csv +0 -0
  140. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/older_population.csv +0 -0
  141. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/data/younger_population.csv +0 -0
  142. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/doubling_beta/example_beta.py +0 -0
  143. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/vaccinating_elderly/README.md +0 -0
  144. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/vaccinating_elderly/dag.dot +0 -0
  145. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/vaccinating_elderly/dag.png +0 -0
  146. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/vaccinating_elderly/example_vaccine.py +0 -0
  147. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/covasim_/vaccinating_elderly/simulated_data.csv +0 -0
  148. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/lr91/README.md +0 -0
  149. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/lr91/dag.dot +0 -0
  150. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/lr91/dag.png +0 -0
  151. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/lr91/data/normalised_results.csv +0 -0
  152. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/lr91/data/results.csv +0 -0
  153. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/lr91/example_max_conductances.py +0 -0
  154. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/.gitignore +0 -0
  155. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/causal_tests.json +0 -0
  156. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/dag.dot +0 -0
  157. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/dag.png +0 -0
  158. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/random/data_random_1000.csv +0 -0
  159. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh10_100.csv +0 -0
  160. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh1_100.csv +0 -0
  161. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh2_100.csv +0 -0
  162. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh3_100.csv +0 -0
  163. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh4_100.csv +0 -0
  164. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh5_100.csv +0 -0
  165. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh6_100.csv +0 -0
  166. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh7_100.csv +0 -0
  167. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh8_100.csv +0 -0
  168. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/data/smt_100/data_smt_wh9_100.csv +0 -0
  169. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/examples/poisson-line-process/poisson_line_process.ipynb +0 -0
  170. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/images/.gitignore +0 -0
  171. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/images/schematic-dark.png +0 -0
  172. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/images/schematic.png +0 -0
  173. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/images/schematic.tex +0 -0
  174. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/paper/paper.bib +0 -0
  175. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/paper/paper.md +0 -0
  176. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/setup.cfg +0 -0
  177. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_cubic_spline_estimator.py +0 -0
  178. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_experimental_estimator.py +0 -0
  179. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_genetic_programming_regression_fitter.py +0 -0
  180. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_instrumental_variable_estimator.py +0 -0
  181. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_ipcw_estimator.py +0 -0
  182. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_linear_regression_estimator.py +0 -0
  183. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/estimation_tests/test_logistic_regression_estimator.py +0 -0
  184. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/dag.dot +0 -0
  185. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/dag.xml +0 -0
  186. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/data.csv +0 -0
  187. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/data.pqt +0 -0
  188. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/data_with_categorical.csv +0 -0
  189. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/data_with_meta.csv +0 -0
  190. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/nhefs.csv +0 -0
  191. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/scarf_data.csv +0 -0
  192. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/resources/data/temporal_data.csv +0 -0
  193. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/specification_tests/test_causal_dag.py +0 -0
  194. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/specification_tests/test_variable.py +0 -0
  195. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/surrogate_tests/test_causal_surrogate_assisted.py +0 -0
  196. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/testing_tests/test_causal_effect.py +0 -0
  197. {causal_testing_framework-14.1.0 → causal_testing_framework-14.3.0}/tests/testing_tests/test_causal_test_case.py +0 -0
@@ -13,7 +13,7 @@ jobs:
13
13
  strategy:
14
14
  matrix:
15
15
  os: ["ubuntu-latest", "windows-latest", "macos-latest"]
16
- python-version: ["3.10", "3.11", "3.12"]
16
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
17
17
  steps:
18
18
  - uses: actions/checkout@v4
19
19
  - name: Set up Python
@@ -18,7 +18,7 @@ jobs:
18
18
  strategy:
19
19
  matrix:
20
20
  os: ["ubuntu-latest", "windows-latest", "macos-latest"]
21
- python-version: ["3.10", "3.11", "3.12", "3.13"]
21
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
22
22
  steps:
23
23
  - uses: actions/checkout@v4
24
24
  - name: Set up Python
@@ -40,7 +40,7 @@ jobs:
40
40
 
41
41
  - uses: actions/setup-python@v3
42
42
  with:
43
- python-version: '3.10'
43
+ python-version: '3.11'
44
44
 
45
45
  - name: Install dependencies
46
46
  run: |
@@ -16,7 +16,7 @@ jobs:
16
16
  - name: Set up Python
17
17
  uses: actions/setup-python@v3
18
18
  with:
19
- python-version: '3.10'
19
+ python-version: '3.11'
20
20
 
21
21
  - name: Install build tools
22
22
  run: |
@@ -67,3 +67,5 @@ temp/
67
67
 
68
68
  # log files
69
69
  *.log
70
+
71
+ causal_test_results.json
@@ -19,7 +19,7 @@ repos:
19
19
  rev: 25.9.0
20
20
  hooks:
21
21
  - id: black
22
- args: ['--line-length=120', '--target-version=py310']
22
+ args: ['--line-length=120', '--target-version=py311']
23
23
  files: ^causal_testing/
24
24
 
25
25
  - repo: https://github.com/pycqa/isort
@@ -7,9 +7,9 @@ version: 2
7
7
 
8
8
  # Set the version of Python
9
9
  build:
10
- os: ubuntu-20.04
10
+ os: ubuntu-24.04
11
11
  tools:
12
- python: "3.10"
12
+ python: "3.11"
13
13
 
14
14
  # Build documentation in the docs/ directory with Sphinx
15
15
  sphinx:
@@ -24,4 +24,4 @@ python:
24
24
  install:
25
25
  - requirements: docs/source/requirements.txt
26
26
  - method: pip
27
- path: . # This should tell RTD to install the CTF from root to render the Estimators page correctly.
27
+ path: . # This should tell RTD to install the CTF from root to render the Estimators page correctly.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: causal_testing_framework
3
- Version: 14.1.0
3
+ Version: 14.3.0
4
4
  Summary: A framework for causal testing using causal directed acyclic graphs.
5
5
  Author: The CITCOM team
6
6
  License: MIT
@@ -9,26 +9,25 @@ Project-URL: Documentation, https://causal-testing-framework.readthedocs.io/
9
9
  Project-URL: Repository, https://github.com/CITCOM-project/CausalTestingFramework
10
10
  Project-URL: Issues, https://github.com/CITCOM-project/CausalTestingFramework/issues
11
11
  Keywords: causal inference,verification
12
- Requires-Python: <3.14,>=3.10
12
+ Requires-Python: <3.15,>=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: lifelines<=0.28.0; python_version <= "3.10"
16
- Requires-Dist: lifelines; python_version > "3.10"
17
- Requires-Dist: networkx<3.5,>=3.4
18
- Requires-Dist: numpy<=2.2.0,>=1.26.0
19
- Requires-Dist: pandas<3,>=2.1
15
+ Requires-Dist: lifelines
16
+ Requires-Dist: networkx<3.7,>=3.4
17
+ Requires-Dist: numpy<=2.4.4,>=1.26.0
18
+ Requires-Dist: pandas>=2.1
20
19
  Requires-Dist: scikit_learn~=1.4
21
- Requires-Dist: scipy<1.14,>=1.12.0; python_version <= "3.10"
22
- Requires-Dist: scipy<=1.16.2,>=1.12.0; python_version > "3.10"
20
+ Requires-Dist: scipy<=1.17.1,>=1.12.0
23
21
  Requires-Dist: statsmodels~=0.14
24
22
  Requires-Dist: tabulate~=0.9
25
23
  Requires-Dist: pydot~=2.0
26
24
  Requires-Dist: pygad~=3.3
27
25
  Requires-Dist: deap~=1.4.1
28
- Requires-Dist: sympy~=1.13.1
29
- Requires-Dist: pyarrow~=19.0.1
30
- Requires-Dist: fastparquet~=2024.11.0
26
+ Requires-Dist: sympy~=1.14.0
27
+ Requires-Dist: pyarrow<25,>=19.0.1
28
+ Requires-Dist: fastparquet>=2024.11.0
31
29
  Requires-Dist: tqdm~=4.67.1
30
+ Requires-Dist: rustworkx>=0.18.0
32
31
  Provides-Extra: dev
33
32
  Requires-Dist: astroid==3.3.8; extra == "dev"
34
33
  Requires-Dist: isort; extra == "dev"
@@ -80,7 +79,7 @@ a deliberate modification to the input configuration expected to produce a corre
80
79
  ## Installation
81
80
 
82
81
  ### Requirements
83
- - Python 3.10, 3.11, 3.12 and 3.13
82
+ - Python 3.11, 3.12, 3.13 and 3.14
84
83
 
85
84
  ### Recommended: Install from conda-forge
86
85
 
@@ -142,12 +141,12 @@ For more information on how to use the Causal Testing Framework, please refer to
142
141
 
143
142
  2. If you do not already have causal test cases, you can convert your causal DAG to causal tests by running the following command.
144
143
  ```
145
- python -m causal_testing generate --dag-path $PATH_TO_DAG --output $PATH_TO_TESTS
144
+ causal-testing generate --dag-path $PATH_TO_DAG --output $PATH_TO_TESTS
146
145
  ```
147
146
 
148
147
  3. You can now execute your tests by running the following command.
149
148
  ```
150
- python -m causal_testing test --dag-path $PATH_TO_DAG --data-paths $PATH_TO_DATA --test-config $PATH_TO_TESTS --output $OUTPUT
149
+ causal-testing test --dag-path $PATH_TO_DAG --data-paths $PATH_TO_DATA --test-config $PATH_TO_TESTS --output $OUTPUT
151
150
  ```
152
151
  The results will be saved for inspection in a JSON file located at `$OUTPUT`.
153
152
  In the future, we hope to add a visualisation tool to assist with this.
@@ -27,7 +27,7 @@ a deliberate modification to the input configuration expected to produce a corre
27
27
  ## Installation
28
28
 
29
29
  ### Requirements
30
- - Python 3.10, 3.11, 3.12 and 3.13
30
+ - Python 3.11, 3.12, 3.13 and 3.14
31
31
 
32
32
  ### Recommended: Install from conda-forge
33
33
 
@@ -89,12 +89,12 @@ For more information on how to use the Causal Testing Framework, please refer to
89
89
 
90
90
  2. If you do not already have causal test cases, you can convert your causal DAG to causal tests by running the following command.
91
91
  ```
92
- python -m causal_testing generate --dag-path $PATH_TO_DAG --output $PATH_TO_TESTS
92
+ causal-testing generate --dag-path $PATH_TO_DAG --output $PATH_TO_TESTS
93
93
  ```
94
94
 
95
95
  3. You can now execute your tests by running the following command.
96
96
  ```
97
- python -m causal_testing test --dag-path $PATH_TO_DAG --data-paths $PATH_TO_DATA --test-config $PATH_TO_TESTS --output $OUTPUT
97
+ causal-testing test --dag-path $PATH_TO_DAG --data-paths $PATH_TO_DATA --test-config $PATH_TO_TESTS --output $OUTPUT
98
98
  ```
99
99
  The results will be saved for inspection in a JSON file located at `$OUTPUT`.
100
100
  In the future, we hope to add a visualisation tool to assist with this.
@@ -0,0 +1,137 @@
1
+ """This module contains the main entrypoint functionality to the Causal Testing Framework."""
2
+
3
+ import json
4
+ import logging
5
+ import os
6
+ import tempfile
7
+ from importlib.metadata import entry_points
8
+ from pathlib import Path
9
+
10
+ import networkx as nx
11
+ import pandas as pd
12
+
13
+ from causal_testing.testing.metamorphic_relation import generate_causal_tests
14
+
15
+ from .main import CausalTestingFramework, CausalTestingPaths, Command, parse_args, setup_logging
16
+
17
+
18
+ def main() -> None:
19
+ """
20
+
21
+ Main entry point for the Causal Testing Framework
22
+
23
+ """
24
+
25
+ # Parse arguments
26
+ args = parse_args()
27
+ # Setup logging
28
+ setup_logging(args.log_level)
29
+
30
+ match args.command:
31
+ case Command.GENERATE:
32
+ logging.info("Generating causal tests")
33
+ generate_causal_tests(
34
+ args.dag_path,
35
+ args.output,
36
+ args.ignore_cycles,
37
+ args.threads,
38
+ effect_type=args.effect_type,
39
+ estimate_type=args.estimate_type,
40
+ estimator=args.estimator,
41
+ skip=False,
42
+ )
43
+ logging.info("Causal test generation completed successfully.")
44
+
45
+ case Command.DISCOVER:
46
+ discover_map = {ff.name: ff for ff in entry_points(group="discovery")}
47
+ if args.technique not in discover_map:
48
+ raise ValueError(
49
+ f"Unsupported technique {args.technique}. Supported: {sorted(discover_map)}. "
50
+ "If you have implemented a custom technique, you will need to add this to your entrypoints via "
51
+ "your pyproject.toml file."
52
+ )
53
+ kwargs = {}
54
+ for argument in args.technique_kwargs:
55
+ split = argument.split("=")
56
+ if len(split) != 2:
57
+ raise ValueError(f"Malformed argument {argument}. Should be specified as `arg_name=arg_value`")
58
+ kwargs[split[0]] = split[1]
59
+
60
+ logging.info("Discovering causal structure")
61
+ # Need to reset index to allow for multiple files having the same index (i.e. starting at zero).
62
+ # Otherwise you end up with duplicate indices, which causes problems further down the line
63
+ df = pd.concat([pd.read_csv(path) for path in args.data_paths]).reset_index()
64
+ if args.variables:
65
+ df = df[args.variables]
66
+
67
+ discover_class = discover_map[args.technique].load()
68
+ discover = discover_class(
69
+ df=df,
70
+ exclude_edges=(
71
+ list(nx.nx_pydot.read_dot(args.exclude_edges).edges()) if args.exclude_edges is not None else []
72
+ ),
73
+ include_edges=(
74
+ list(nx.nx_pydot.read_dot(args.include_edges).edges()) if args.include_edges is not None else []
75
+ ),
76
+ alpha=args.alpha,
77
+ **kwargs,
78
+ )
79
+ evolved_dag = discover.discover()
80
+ discover.write_dot(evolved_dag, args.output)
81
+ logging.info("Causal structure discovery completed successfully.")
82
+ case Command.TEST:
83
+ # Create paths object
84
+ paths = CausalTestingPaths(
85
+ dag_path=args.dag_path,
86
+ data_paths=args.data_paths,
87
+ test_config_path=args.test_config,
88
+ output_path=args.output,
89
+ )
90
+
91
+ # Create and setup framework
92
+ framework = CausalTestingFramework(paths, ignore_cycles=args.ignore_cycles, query=args.query)
93
+ framework.setup()
94
+
95
+ # Load and run tests
96
+ framework.load_tests()
97
+
98
+ if args.batch_size > 0:
99
+ logging.info(f"Running tests in batches of size {args.batch_size}")
100
+ with tempfile.TemporaryDirectory() as tmpdir:
101
+ output_files = []
102
+ for i, results in enumerate(
103
+ framework.run_tests_in_batches(
104
+ batch_size=args.batch_size,
105
+ silent=args.silent,
106
+ adequacy=args.adequacy,
107
+ bootstrap_size=args.bootstrap_size,
108
+ )
109
+ ):
110
+ temp_file_path = os.path.join(tmpdir, f"output_{i}.json")
111
+ framework.save_results(results, temp_file_path)
112
+ output_files.append(temp_file_path)
113
+ del results
114
+
115
+ # Now stitch the results together from the temporary files
116
+ all_results = []
117
+ for file_path in output_files:
118
+ with open(file_path, "r", encoding="utf-8") as f:
119
+ all_results.extend(json.load(f))
120
+
121
+ output_path = Path(args.output)
122
+ output_path.parent.mkdir(parents=True, exist_ok=True)
123
+
124
+ with open(args.output, "w", encoding="utf-8") as f:
125
+ json.dump(all_results, f, indent=4)
126
+ else:
127
+ logging.info("Running tests in regular mode")
128
+ results = framework.run_tests(
129
+ silent=args.silent, adequacy=args.adequacy, bootstrap_size=args.bootstrap_size
130
+ )
131
+ framework.save_results(results)
132
+
133
+ logging.info("Causal testing completed successfully.")
134
+
135
+
136
+ if __name__ == "__main__":
137
+ main()
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '14.3.0'
22
+ __version_tuple__ = version_tuple = (14, 3, 0)
23
+
24
+ __commit_id__ = commit_id = 'ge6a19c77b'
@@ -0,0 +1,236 @@
1
+ """
2
+ This module implements the abstract Discovery class to infer causal DAGs from data.
3
+ """
4
+
5
+ import random
6
+ import re
7
+ import warnings
8
+ from abc import ABC, abstractmethod
9
+ from enum import Enum
10
+ from itertools import permutations
11
+
12
+ import networkx as nx
13
+ import pandas as pd
14
+ import rustworkx as rx
15
+
16
+ from causal_testing.main import CausalTestingFramework
17
+ from causal_testing.specification.causal_dag import CausalDAG
18
+ from causal_testing.specification.scenario import Scenario
19
+ from causal_testing.testing.causal_effect import Negative, Positive
20
+ from causal_testing.testing.causal_test_result import CausalTestResult
21
+ from causal_testing.testing.metamorphic_relation import generate_metamorphic_relations
22
+
23
+ TestResult = Enum("TestResult", [("PASS", 2), ("FAIL", 0), ("INESTIMABLE", 1)])
24
+
25
+ # Ignore warnings from statsmodels when we try to evaluate test cases
26
+ warnings.simplefilter("ignore")
27
+
28
+
29
+ def simple_cycle(causal_dag: CausalDAG):
30
+ """
31
+ Find a cycle in the given CausalDAG, if one exists, returns the first found.
32
+
33
+ :param causal_dag: The CausalDAG to check for cycles.
34
+ :returns: A list of edges in the cycle, or an empty list if there are no cycles.
35
+ """
36
+ rx_graph = rx.networkx_converter(causal_dag)
37
+ return [(rx_graph[i], rx_graph[j]) for i, j in rx.digraph_find_cycle(rx_graph)]
38
+
39
+
40
+ def effect_direction(result: CausalTestResult) -> str:
41
+ """
42
+ Check whether the estimated causal effect is negative or positive.
43
+
44
+ :param result: The causal test result object.
45
+ :returns: Whether the estimated causal test is positive or negative (or no effect).
46
+ """
47
+ if pd.api.types.is_numeric_dtype(
48
+ result.estimator.df[result.estimator.base_test_case.treatment_variable.name]
49
+ ) and pd.api.types.is_numeric_dtype(result.estimator.df[result.estimator.base_test_case.outcome_variable.name]):
50
+ if Negative().apply(result):
51
+ return "negative"
52
+ if Positive().apply(result):
53
+ return "positive"
54
+ return None
55
+
56
+
57
+ def is_match(u: str, v: str, patterns: list[str]):
58
+ """
59
+ Check whether a given edge matches a given pattern.
60
+
61
+ :param u: The origin node of the edge.
62
+ :param v: The destination node of the edge.
63
+ :param patterns: A list of tuples containing the patterns to check against.
64
+ :returns: True if the edge matches the pattern, False otherwise.
65
+ """
66
+ return any(re.fullmatch(pat_u, u) and re.fullmatch(pat_v, v) for pat_u, pat_v in patterns)
67
+
68
+
69
+ class Discovery(ABC):
70
+ """
71
+ Abstract class for causal discovery.
72
+ """
73
+
74
+ def __init__(
75
+ self,
76
+ df: pd.DataFrame,
77
+ random_seed: int = 0,
78
+ exclude_edges: str = None,
79
+ include_edges: str = None,
80
+ alpha: float = 0.05,
81
+ ):
82
+
83
+ random.seed(random_seed)
84
+ self.df = df
85
+ self.random_seed = int(random_seed)
86
+ self.alpha = float(alpha)
87
+
88
+ self.possible_edges = []
89
+ self.include_edges = []
90
+ self.exclude_edges = []
91
+
92
+ for u, v in permutations(df.columns, 2):
93
+ if exclude_edges and is_match(u, v, exclude_edges):
94
+ self.exclude_edges.append((u, v))
95
+ else:
96
+ self.possible_edges.append((u, v))
97
+
98
+ if include_edges and is_match(u, v, include_edges):
99
+ self.include_edges.append((u, v))
100
+
101
+ if self.include_edges:
102
+ # Check to make sure that the include edges don't specify a cycle
103
+ initial_dag = CausalDAG()
104
+ initial_dag.add_edges_from(self.include_edges)
105
+
106
+ if not initial_dag.is_acyclic():
107
+ raise ValueError(
108
+ "Specified include edges include a cycle, making it impossible to infer a DAG. "
109
+ "Please resolve this and try again."
110
+ )
111
+
112
+ @abstractmethod
113
+ def discover(self) -> CausalDAG:
114
+ """
115
+ Discover the causal DAG.
116
+
117
+ :returns: The inferred causal DAG.
118
+ """
119
+
120
+ def remove_cycles(self, causal_dag: CausalDAG):
121
+ """
122
+ Remove cycles from individuals by iteratively deleting a random edge from each cycle until there are no more
123
+ cycles.
124
+
125
+ :param causal_dag: The CausalDAG to be repaired.
126
+ """
127
+ nodes = causal_dag.nodes
128
+ cycle = simple_cycle(causal_dag)
129
+ while cycle:
130
+ idx = random.choice(range(len(cycle)))
131
+ while cycle[idx] in self.include_edges:
132
+ idx = (idx + 1) % len(cycle)
133
+ causal_dag.remove_edge(cycle[idx][0], cycle[idx][1])
134
+ cycle = simple_cycle(causal_dag)
135
+ causal_dag.add_nodes_from(nodes)
136
+
137
+ def write_dot(self, individual: CausalDAG, output_file: str):
138
+ """
139
+ Write the given individual to the given output file.
140
+
141
+ :param individual: The causal DAG to output.
142
+ :param output_file: The name of the file to write to.
143
+ """
144
+ if hasattr(individual, "test_results"):
145
+ for _, test in individual.test_results.iterrows():
146
+ if (test["treatment"], test["outcome"]) in individual.edges:
147
+ if test["result"] == TestResult.PASS:
148
+ individual[test["treatment"]][test["outcome"]]["color"] = "green"
149
+ elif test["result"] == TestResult.INESTIMABLE:
150
+ individual[test["treatment"]][test["outcome"]]["color"] = "orange"
151
+ elif test["result"] == TestResult.FAIL:
152
+ individual[test["treatment"]][test["outcome"]]["color"] = "red"
153
+ else:
154
+ raise ValueError(f"Invalid test outcome {test['result']}")
155
+ else:
156
+ individual.add_edge(test["treatment"], test["outcome"], ignore_cycles=True)
157
+ individual[test["treatment"]][test["outcome"]]["style"] = "dashed"
158
+ if test["result"] == TestResult.PASS:
159
+ individual[test["treatment"]][test["outcome"]]["style"] = "invis"
160
+ individual[test["treatment"]][test["outcome"]]["constraint"] = False
161
+ elif test["result"] == TestResult.INESTIMABLE:
162
+ individual[test["treatment"]][test["outcome"]]["color"] = "orange"
163
+ elif test["result"] == TestResult.FAIL:
164
+ individual[test["treatment"]][test["outcome"]]["color"] = "red"
165
+ else:
166
+ raise ValueError(f"Invalid test outcome {test['result']}")
167
+
168
+ nx.drawing.nx_pydot.write_dot(individual, output_file)
169
+
170
+ def _json_stub_params(self, outcome: str) -> str:
171
+ if pd.api.types.is_bool_dtype(self.df[outcome]):
172
+ return {"estimator": "LogisticRegressionEstimator", "estimate_type": "unit_odds_ratio"}
173
+ if pd.api.types.is_categorical_dtype(self.df[outcome]) or pd.api.types.is_object_dtype(self.df[outcome]):
174
+ return {"estimator": "MultinomialRegressionEstimator", "estimate_type": "unit_odds_ratio"}
175
+ if pd.api.types.is_numeric_dtype(self.df[outcome]):
176
+ return {"estimator": "LinearRegressionEstimator", "estimate_type": "coefficient"}
177
+ raise ValueError(f"Invalid datatype {self.df.dtypes[outcome]}")
178
+
179
+ def evaluate_tests(self, causal_dag: CausalDAG) -> pd.DataFrame:
180
+ """
181
+ Generate and evaluate causal test cases from the supplied CausalDAG and return a list of edges for which the
182
+ corresponding causal test case failed.
183
+ These results are then assigned to a new attribute `test_results` within the individual for later reuse.
184
+
185
+ :param causal_dag: The CausalDAG to evaluate.
186
+ :returns: Pandas dataframe with test outcome details
187
+ (result, expected effect, treatment, outcome, effect direction).
188
+ """
189
+
190
+ ctf = CausalTestingFramework(None)
191
+ ctf.dag = causal_dag
192
+ ctf.data = self.df
193
+ ctf.create_variables()
194
+ ctf.scenario = Scenario(list(ctf.variables["inputs"].values()) + list(ctf.variables["outputs"].values()))
195
+
196
+ ctf.test_cases = ctf.create_test_cases(
197
+ {
198
+ "tests": [
199
+ relation.to_json_stub(
200
+ alpha=self.alpha,
201
+ **self._json_stub_params(relation.base_test_case.outcome_variable),
202
+ )
203
+ for relation in generate_metamorphic_relations(causal_dag)
204
+ ]
205
+ }
206
+ )
207
+
208
+ results = []
209
+
210
+ # We use "silent=False" here to allow for inestimable edges, but it'd be good to have a more stringent
211
+ # error catching strategy to catch "genuine" problems (e.g. to do with the structure of the data)
212
+ for test_case, result in zip(ctf.test_cases, ctf.run_tests(silent=False)):
213
+ if result.effect_estimate is None:
214
+ results.append(
215
+ {
216
+ "result": TestResult.INESTIMABLE,
217
+ "expected_effect": test_case.expected_causal_effect.__class__.__name__,
218
+ "treatment": test_case.base_test_case.treatment_variable.name,
219
+ "outcome": test_case.base_test_case.outcome_variable.name,
220
+ }
221
+ )
222
+ else:
223
+ results.append(
224
+ {
225
+ "result": (
226
+ TestResult.PASS if test_case.expected_causal_effect.apply(result) else TestResult.FAIL
227
+ ),
228
+ "expected_effect": test_case.expected_causal_effect.__class__.__name__,
229
+ "treatment": test_case.base_test_case.treatment_variable.name,
230
+ "outcome": test_case.base_test_case.outcome_variable.name,
231
+ "effect": effect_direction(result),
232
+ }
233
+ )
234
+
235
+ causal_dag.test_results = pd.DataFrame(results)
236
+ return pd.DataFrame(results)