-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ENH] Add the ability to check the validity of a PAG (#100)
* Added a _proper_pag function * Added some test for legal_pag * [pre-commit.ci] auto fixes from pre-commit.com hooks * Update examples/intro/checking_validity_of_a_pag.py --------- Signed-off-by: Aryan Roy <[email protected]> Co-authored-by: Adam Li <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
71a18e7
commit 31ad037
Showing
10 changed files
with
480 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,29 @@ | ||
name: CircleCI artifacts redirector | ||
on: [status] | ||
|
||
# Restrict the permissions granted to the use of secrets.GITHUB_TOKEN in this | ||
# github actions workflow: | ||
# https://docs.github.com/en/actions/security-guides/automatic-token-authentication | ||
permissions: read-all | ||
|
||
jobs: | ||
circleci_artifacts_redirector_job: | ||
if: "${{ startsWith(github.event.context, 'ci/circleci: build_doc') }}" | ||
runs-on: ubuntu-20.04 | ||
if: "github.repository == 'py-why/pywhy-graphs' && github.event.context == 'ci/circleci: build_doc'" | ||
permissions: | ||
statuses: write | ||
name: Run CircleCI artifacts redirector | ||
steps: | ||
- name: GitHub Action step | ||
uses: larsoner/circleci-artifacts-redirector-action@master | ||
with: | ||
repo-token: ${{ secrets.GITHUB_TOKEN }} | ||
api-token: ${{ secrets.CIRCLECI_TOKEN }} | ||
artifact-path: 0/dev/index.html | ||
circleci-jobs: build_doc | ||
job-title: Check the rendered docs here! | ||
|
||
- name: Check the URL | ||
if: github.event.status != 'pending' | ||
run: | | ||
curl --fail ${{ steps.step1.outputs.url }} | grep $GITHUB_SHA |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
""" | ||
=========================== | ||
On PAGs and their validity | ||
=========================== | ||
A PAG or a Partial Ancestral Graph is a type of mixed edge | ||
graph that can represent, in a single graph, the causal relationship | ||
between several nodes as defined by an equivalence class of MAGs. | ||
PAGs account for possible unobserved confounding and selection bias | ||
in the underlying equivalence class of SCMs. | ||
Another way to understand this is that PAGs encode conditional independence | ||
constraints stemming from Causal Graphs. Since these constraints do not lead to a | ||
unique graph, a PAG, in essence, represents a class of graphs that encode | ||
the same conditional independence constraints. | ||
PAGs model this relationship by displaying all common edge marks (tail and arrowhead) shared | ||
by all members in the equivalence class and displaying circle endpoints for those marks | ||
that are not common. That is, a circular endpoint (``*-o``) can represent both a directed | ||
(``*->``) and tail (``*—``) endpoint in causal graphs within the equivalence class. | ||
More details on PAGs can be found at :footcite:`Zhang2008`. | ||
""" | ||
|
||
import pywhy_graphs | ||
from pywhy_graphs.viz import draw | ||
from pywhy_graphs import PAG | ||
|
||
try: | ||
from dodiscover import FCI, make_context | ||
from dodiscover.ci import Oracle | ||
from dodiscover.constraint.utils import dummy_sample | ||
except ImportError as e: | ||
raise ImportError("The 'dodiscover' package is required to convert a MAG to a PAG.") | ||
|
||
|
||
# %% | ||
# PAGs in pywhy-graphs | ||
# --------------------------- | ||
# Constructing a PAG in pywhy-graphs is an easy task since | ||
# the library provides a separate class for this purpose. | ||
# True to the definition of PAGs, the class can contain | ||
# directed edges, bidirected edges, undirected edges and | ||
# cicle edges. To illustrate this, we construct an example PAG | ||
# as described in :footcite:`Zhang2008`, figure 4: | ||
|
||
pag = PAG() | ||
pag.add_edge("I", "S", pag.directed_edge_name) | ||
pag.add_edge("G", "S", pag.directed_edge_name) | ||
pag.add_edge("G", "L", pag.directed_edge_name) | ||
pag.add_edge("S", "L", pag.directed_edge_name) | ||
pag.add_edge("PSH", "S", pag.directed_edge_name) | ||
pag.add_edge("S", "PSH", pag.circle_edge_name) | ||
pag.add_edge("S", "G", pag.circle_edge_name) | ||
pag.add_edge("S", "I", pag.circle_edge_name) | ||
|
||
|
||
# Finally, the graph looks like this: | ||
dot_graph = draw(pag) | ||
dot_graph.render(outfile="valid_pag.png", view=True) | ||
|
||
|
||
# %% | ||
# Validity of a PAG | ||
# --------------------------- | ||
# For a PAG to be valid, it must represent a valid | ||
# equivalent class of MAGs. This can be verified by | ||
# turning the PAG into an MAG and then checking the | ||
# validity of the MAG. | ||
# Theorem 2 in :footcite:`Zhang2008` provides a method for checking the validity of a PAG. | ||
# To check if the constructed PAG is a valid one in pywhy-graphs, we can simply do: | ||
|
||
|
||
# returns True | ||
print(pywhy_graphs.valid_pag(pag)) | ||
|
||
# %% | ||
# If we want to test whether this algorithm is working correctly or not, we can change | ||
# a single mark in the graph such that the PAG. By removing a circle edge, we are removing | ||
# the representation of multiple marks as encoded by the different MAGs this PAG represents. | ||
# In this specific case, by removing the circle endpoint ``S *-o I``, we are saying that ``S`` | ||
# directly causes ``I``. However, there is no way of determining this using the FCI logical rules. | ||
# One would not be able to determine that the adjacency is due to a direct | ||
# causal relationship (directed edge), confounded relationship (bidirected edge), or an inducing path | ||
# relationship. As such, the resulting graph is no longer a valid PAG. | ||
|
||
pag.remove_edge("S", "I", pag.circle_edge_name) | ||
|
||
# returns False | ||
print(pywhy_graphs.valid_pag(pag)) | ||
|
||
# %% | ||
# References | ||
# ---------- | ||
# .. footbibliography:: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,7 @@ doc = [ | |
'graphviz', | ||
'pygraphviz', | ||
'pgmpy', | ||
'dowhy', | ||
] | ||
style = [ | ||
"pre-commit", | ||
|
Oops, something went wrong.