Skip to content

Commit

Permalink
feat(API): updated documentation, overhauled API
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Total API overhaul for final (at this time) release
  • Loading branch information
bradendubois committed May 4, 2022
1 parent 274fa52 commit 43b0429
Show file tree
Hide file tree
Showing 46 changed files with 413 additions and 40 deletions.
34 changes: 3 additions & 31 deletions .github/workflows/update_wiki.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ name: Deploy Wiki
on:
workflow_dispatch:
push:
# Trigger only when wiki directory changes
paths:
- 'wiki/pages/**'

# Trigger only on main
- 'wiki/**'
branches: [ main ]

jobs:
Expand All @@ -16,35 +13,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install tools to build whl package
run: |
pip install sdist
- name: Build whl package
run: |
python setup.py sdist bdist_wheel
env:
SEMANTIC_VERSION: 1.0.0 # not actually 1.0.0, but has no impact on wiki-building

- name: Install do-calculus package
run: |
pip install -e .
env:
SEMANTIC_VERSION: 1.0.0 # not actually 1.0.0, but has no impact on wiki-building

- name: Build Pages (replace stubs)
run: |
python ./wiki/build_wiki.py
- name: Push Wiki Changes
uses: Andrew-Chen-Wang/github-wiki-action@v2
uses: Andrew-Chen-Wang/github-wiki-action@v3
env:
WIKI_DIR: wiki/pages/
WIKI_DIR: wiki/
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_MAIL: ${{ secrets.EMAIL }}
GH_NAME: ${{ github.repository_owner }}
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,12 @@
* **Contact**: [braden.dubois@usask.ca](mailto:braden.dubois@usask.ca)

See the [wiki](https://github.com/bradendubois/do-calculus/wiki) to get started.


## Development Status

A full overhaul has been completed, and marks important milestones in my life and (consequently) this project's. Development on this project is halted until further notice, barring further changes to my own life, or necessary bug fixes and/or security fixes.

## Acknowledgements

This project represents approximately two years of part- and full-time work as part of an indescribably fulfilling undergraduate research project. This project was done under the supervision of Dr. Eric Neufeld from approximately Spring 2020 - Winter 2022. Without Dr. Neufeld's support, guidance, patience, expertise (and of course, funding), this project would never have been started, let alone completed. I cannot overstate my appreciation - you've changed my academic and professional path, and provided me with so many wonderful experiences and memories that I will never forget. Thanks, Eric.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions archive/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Archive

Contained here is some old code that built a (now-outdated) wiki that I don't have the heart to delete.

Don't rely on it expecting accurate information.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 1 addition & 2 deletions do/identification/API.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from ..core.Variables import Intervention, Outcome

from .LatentGraph import latent_transform
from .Identification import Identification
from .Identification import Identification, simplify_expression
from .PExpression import PExpression, TemplateExpression


Expand Down Expand Up @@ -62,7 +62,6 @@ def _process(current: Union[PExpression, TemplateExpression], known: Mapping[str
return t

result = _process(expression, {v.name: v.outcome for v in y} | {v.name: v.outcome for v in x})

return (result, expression.proof()) if include_proof else result

def proof(self, y: Set[Outcome], x: Set[Intervention], model: Model) -> str:
Expand Down
13 changes: 7 additions & 6 deletions do/identification/LatentGraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,29 +179,29 @@ def latent_transform(g: Graph, u: Set[str]):
reduction = False

remove = set()
for u in Un:
for un in Un:

parents = [edge[0] for edge in E if edge[1] == u] # Edges : parent -> u
children = [edge[1] for edge in E if edge[0] == u] # Edges : u -> child
parents = [edge[0] for edge in E if edge[1] == un] # Edges : parent -> u
children = [edge[1] for edge in E if edge[0] == un] # Edges : u -> child

# All parents are unobservable, all children are observable, at least one parent
if all(x in u for x in parents) and len(parents) > 0 and all(x not in u for x in children):
reduction = True

# Remove edges from parents to u
for parent in parents:
E.remove((parent, u))
E.remove((parent, un))

# Remove edges from u to children
for child in children:
E.remove((u, child))
E.remove((un, child))

# Replace with edge from edge parent to each child
for cr in product(parents, children):
E.add((cr[0], cr[1]))

# U can be removed entirely from graph
remove.add(u)
remove.add(un)

V -= remove
Un -= remove
Expand Down Expand Up @@ -229,4 +229,5 @@ def latent_transform(g: Graph, u: Set[str]):
a, b = child_edges[i], child_edges[(i + 1) % len(child_edges)]
E_Bidirected.add((a[1], b[1]))

print(V, u)
return LatentGraph(V, E, E_Bidirected, [x for x in g.topology_sort() if x in V - u])
19 changes: 19 additions & 0 deletions examples/2-backdoor-paths/deconfound.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from pathlib import Path

from do import API

api = API()

file = Path("pearl-3.4.yml")
model = api.instantiate_model(file)

backdoors = api.backdoors({"Xi"}, {"Xj"}, model.graph())
assert len(backdoors) > 0, "No backdoor paths detected!"
assert not api.blocks({"Xi"}, {"Xj"}, model.graph(), set()), "This should not block all paths!"

for path in backdoors:
print("Path:", path)

backdoors = api.backdoors({"Xi"}, {"Xj"}, model.graph(), {"X1", "X4"})
assert len(backdoors) == 0, "Expected this to block!"
assert api.blocks({"Xi"}, {"Xj"}, model.graph(), {"X1", "X4"}), "This should block!"
116 changes: 116 additions & 0 deletions examples/2-backdoor-paths/pearl-3.4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: 'Pearl: Figure 3.4'
endogenous:
X1:
outcomes:
- x1
- ~x1
parents: []
table: [
[x1, 0.4],
[~x1, 0.6]
]
X2:
outcomes:
- x2
- ~x2
parents: []
table: [
[x2, 0.15],
[~x2, 0.85]
]
X3:
outcomes:
- x3
- ~x3
parents:
- X1
table: [
[x3, x1, 0.1],
[x3, ~x1, 0.3],
[~x3, x1, 0.9],
[~x3, ~x1, 0.7]
]
X4:
outcomes:
- x4
- ~x4
parents:
- X1
- X2
table: [
[x4, x1, x2, 0.7],
[x4, x1, ~x2, 0.9],
[x4, ~x1, x2, 0.55],
[x4, ~x1, ~x2, 0.15],
[~x4, x1, x2, 0.3],
[~x4, x1, ~x2, 0.1],
[~x4, ~x1, x2, 0.45],
[~x4, ~x1, ~x2, 0.85]
]
X5:
outcomes:
- x5
- ~x5
parents:
- X2
table: [
[x5, x2, 0.8],
[x5, ~x2, 0.25],
[~x5, x2, 0.2],
[~x5, ~x2, 0.75]
]
X6:
outcomes:
- x6
- ~x6
parents:
- Xi
table: [
[x6, xi, 0.9],
[x6, ~xi, 0.25],
[~x6, xi, 0.1],
[~x6, ~xi, 0.75]
]
Xi:
outcomes:
- xi
- ~xi
parents:
- X3
- X4
table: [
[xi, x3, x4, 0.5],
[xi, x3, ~x4, 0.65],
[xi, ~x3, x4, 0.1],
[xi, ~x3, ~x4, 0.25],
[~xi, x3, x4, 0.5],
[~xi, x3, ~x4, 0.35],
[~xi, ~x3, x4, 0.9],
[~xi, ~x3, ~x4, 0.75]
]
Xj:
outcomes:
- xj
- ~xj
parents:
- X6
- X4
- X5
table: [
[xj, x6, x4, x5, 0.0],
[xj, x6, x4, ~x5, 0.25],
[xj, x6, ~x4, x5, 0.7],
[xj, x6, ~x4, ~x5, 0.45],
[xj, ~x6, x4, x5, 0.15],
[xj, ~x6, x4, ~x5, 0.8],
[xj, ~x6, ~x4, x5, 0.95],
[xj, ~x6, ~x4, ~x5, 0.05],
[~xj, x6, x4, x5, 1.0],
[~xj, x6, x4, ~x5, 0.75],
[~xj, x6, ~x4, x5, 0.3],
[~xj, x6, ~x4, ~x5, 0.55],
[~xj, ~x6, x4, x5, 0.85],
[~xj, ~x6, x4, ~x5, 0.2],
[~xj, ~x6, ~x4, x5, 0.05],
[~xj, ~x6, ~x4, ~x5, 0.95]
]
90 changes: 90 additions & 0 deletions examples/3-latent/3.4-latent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: 'Pearl: Figure 3.4'
endogenous:
X1:
outcomes:
- x1
- ~x1
parents: []
table: [
[x1, 0.4],
[~x1, 0.6]
]
X2:
outcomes:
- x2
- ~x2
parents: []
table: [
[x2, 0.15],
[~x2, 0.85]
]
X3:
outcomes:
- x3
- ~x3
table: [
[x3, 0.1],
[~x3, 0.9],
]
X4:
outcomes:
- x4
- ~x4
parents:
- Xi
table: [
[x4, xi, 0.9],
[x4, ~xi, 0.25],
[~x4, xi, 0.1],
[~x4, ~xi, 0.75]
]
Xi:
outcomes:
- xi
- ~xi
parents:
- X1
- X2
table: [
[xi, x1, x2, 0.5],
[xi, x1, ~x2, 0.65],
[xi, ~x1, x2, 0.1],
[xi, ~x1, ~x2, 0.25],
[~xi, x1, x2, 0.5],
[~xi, x1, ~x2, 0.35],
[~xi, ~x1, x2, 0.9],
[~xi, ~x1, ~x2, 0.75]
]
Xj:
outcomes:
- xj
- ~xj
parents:
- X2
- X3
- X4
table: [
[xj, x2, x3, x4, 0.0],
[xj, x2, x3, ~x4, 0.25],
[xj, x2, ~x3, x4, 0.7],
[xj, x2, ~x3, ~x4, 0.45],
[xj, ~x2, x3, x4, 0.15],
[xj, ~x2, x3, ~x4, 0.8],
[xj, ~x2, ~x3, x4, 0.95],
[xj, ~x2, ~x3, ~x4, 0.05],
[~xj, x2, x3, x4, 1.0],
[~xj, x2, x3, ~x4, 0.75],
[~xj, x2, ~x3, x4, 0.3],
[~xj, x2, ~x3, ~x4, 0.55],
[~xj, ~x2, x3, x4, 0.85],
[~xj, ~x2, x3, ~x4, 0.2],
[~xj, ~x2, ~x3, x4, 0.05],
[~xj, ~x2, ~x3, ~x4, 0.95]
]
exogenous:
U1:
- X1
- X2
U2:
- X2
- X3
16 changes: 16 additions & 0 deletions examples/3-latent/deconfound.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pathlib import Path

from do import API, Expression, Intervention, Outcome

api = API()

file = Path("3.4-latent.yml")
model = api.instantiate_model(file)

xj = Outcome("Xj", "xj")
xi = Intervention("Xi", "xi")
e = Expression(xj, [xi])

result, proof = api.identification([xj], [xi], model)
print(result)
print(proof)
1 change: 0 additions & 1 deletion tests/identification/test_PExpression.py

This file was deleted.

Loading

0 comments on commit 43b0429

Please sign in to comment.