API reference
causalprog package.
algorithms
Algorithms.
do
Algorithms for applying do to a graph.
do(graph, node, value, label=None)
Apply do to a graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph
|
Graph
|
The graph to apply do to. This will be copied. |
required |
node
|
str
|
The label of the node to apply do to. |
required |
value
|
float
|
The value to set the node to. |
required |
label
|
str | None
|
The label of the new graph |
None
|
Returns:
| Type | Description |
|---|---|
Graph
|
A copy of the graph with do applied |
Source code in src/causalprog/algorithms/do.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
get_included_excluded_successors(graph, node_list, successors_of)
Split successors of a node into nodes included and not included in a list.
Split the successorts of a node into a list of nodes that are included in the input node list and a list of nodes that are not in the list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph
|
Graph
|
The graph |
required |
node_list
|
dict[str, Node]
|
A dictionary of nodes, indexed by label |
required |
successors_of
|
str
|
The node to check the successors of |
required |
Returns:
| Type | Description |
|---|---|
tuple[tuple[str, ...], tuple[str, ...]]
|
Lists of included and excluded nodes |
Source code in src/causalprog/algorithms/do.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
removable_nodes(graph, nodes)
Generate list of nodes that can be removed from the graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph
|
Graph
|
The graph |
required |
nodes
|
dict[str, Node]
|
A dictionary of nodes, indexed by label |
required |
Returns:
| Type | Description |
|---|---|
tuple[str, ...]
|
List of labels of removable nodes |
Source code in src/causalprog/algorithms/do.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
moments
Algorithms for estimating the expectation and standard deviation.
expectation(graph, outcome_node_label, samples, *, parameter_values=None, rng_key)
Estimate the expectation of (a random variable attached to) a node in a graph.
Source code in src/causalprog/algorithms/moments.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
moment(order, graph, outcome_node_label, samples, *, parameter_values=None, rng_key)
Estimate a moment of (a random variable attached to) a node in a graph.
Source code in src/causalprog/algorithms/moments.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | |
sample(graph, outcome_node_label, samples, *, parameter_values=None, rng_key)
Sample data from (a random variable attached to) a node in a graph.
Source code in src/causalprog/algorithms/moments.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
standard_deviation(graph, outcome_node_label, samples, *, parameter_values=None, rng_key, rng_key_first_moment=None)
Estimate the standard deviation of (a RV attached to) a node in a graph.
Source code in src/causalprog/algorithms/moments.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
backend
Helper functionality for incorporating different backends.
causal_problem
Classes for defining causal problems.
CausalEstimand
Bases: _CPComponent
A Causal Estimand.
The causal estimand is the function that we want to minimise (and maximise) as part of a causal problem. It should be a scalar-valued function of the random variables appearing in a graph.
Source code in src/causalprog/causal_problem/components.py
16 17 18 19 20 21 22 23 | |
CausalProblem
Defines a causal problem.
Source code in src/causalprog/causal_problem/causal_problem.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
__init__(graph, *constraints, causal_estimand)
Create a new causal problem.
Source code in src/causalprog/causal_problem/causal_problem.py
52 53 54 55 56 57 58 59 60 61 | |
lagrangian(n_samples=1000, *, maximum_problem=False)
Return a function that evaluates the Lagrangian of this CausalProblem.
Following the KKT theorem, given the causal estimand and the constraints we can assemble a Lagrangian and seek its stationary points, to in turn identify minimisers of the constrained optimisation problem that we started with.
The Lagrangian returned is a mathematical function of its first two arguments.
The first argument is the same dictionary of parameters that is passed to models
like Graph.model, and is the values the parameters (represented by the
ParameterNodes) are taking. The second argument is a 1D vector of Lagrange
multipliers, whose length is equal to the number of constraints.
The remaining argument of the Lagrangian is the PRNG Key that should be used when drawing samples.
Note that our current implementation assumes there are no equality constraints being imposed (in which case, we would need a 3-argument Lagrangian function).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_samples
|
int
|
The number of random samples to be drawn when estimating the value of functions of the RVs. |
1000
|
maximum_problem
|
bool
|
If passed as |
False
|
Returns:
| Type | Description |
|---|---|
Callable[[dict[str, ArrayLike], ArrayLike, Array], ArrayLike]
|
The Lagrangian, as a function of the model parameters, Lagrange multipliers, and PRNG key. |
Source code in src/causalprog/causal_problem/causal_problem.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
Constraint
Bases: _CPComponent
A Constraint that forms part of a causal problem.
Constraints of a causal problem are derived properties of RVs for which we have observed data. The causal estimand is minimised (or maximised) subject to the predicted values of the constraints being close to their observed values in the data.
Adding a constraint \(g(\theta)\) to a causal problem (where \(\theta\) are the parameters of the causal problem) essentially imposes an additional constraint on the minimisation problem;
where \(g_{\text{data}}\) is the observed data value for the quantity \(g\), and \(\epsilon\) is some tolerance.
Source code in src/causalprog/causal_problem/components.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
__call__(samples)
Evaluate the constraint, given RV samples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
samples
|
dict[str, ArrayLike]
|
Mapping of RV (node) labels to drawn samples. |
required |
Returns:
| Type | Description |
|---|---|
ArrayLike
|
Value of the constraint. |
Source code in src/causalprog/causal_problem/components.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
__init__(*effect_handlers, model_quantity, outer_norm=None, data=0.0, tolerance=1e-06)
Create a new constraint.
Constraints have the form
where;
- \(\mathrm{norm}\) is the outer norm of the constraint (outer_norm),
- \(g(\theta)\) is the model quantity involved in the constraint
(model_quantity),
- \(g_{\mathrm{data}}\) is the observed data (data),
- \(\epsilon\) is the tolerance in the data (tolerance).
In a causal problem, each constraint appears as the condition \(c(\theta)\leq 0\) in the minimisation / maximisation (hence the inclusion of the \(-\epsilon\) term within \(c(\theta)\) itself).
\(g\) should be a (possibly vector-valued) function that acts on (a subset of) samples from the random variables of the causal problem. It must accept variable keyword-arguments only, and should access the samples for each random variable by indexing via the RV names (node labels). It should return the model quantity as computed from the samples, that \(g_{\mathrm{data}}\) observed.
\(g_{\mathrm{data}}\) should be a fixed value whose shape is broadcast-able with the return shape of \(g\). It defaults to \(0\) if not explicitly set.
\(\mathrm{norm}\) should be a suitable norm to take on the difference between the model quantity as predicted by the samples (\(g\)) and the observed data (\(g_{\mathrm{data}}\)). It must return a scalar value. The default is the 2-norm.
Source code in src/causalprog/causal_problem/components.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
HandlerToApply
dataclass
Specifies a handler that needs to be applied to a model at runtime.
Source code in src/causalprog/causal_problem/handlers.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
__eq__(other)
Equality operation.
HandlerToApplys are considered equal if they use the same handler function and
provide the same options to this function.
Comparison to other types returns False.
Source code in src/causalprog/causal_problem/handlers.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
__post_init__()
Validate set attributes.
- The handler is a callable object.
- The options have been passed as a dictionary of keyword-value pairs.
Source code in src/causalprog/causal_problem/handlers.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
from_pair(pair)
classmethod
Create an instance from an effect handler and its options.
The two objects should be passed in as the elements of a container of length
2. They can be passed in any order;
- One element must be a dictionary, which will be interpreted as the options
for the effect handler.
- The other element must be callable, and will be interpreted as the handler
itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pair
|
Sequence
|
Container of two elements, one being the effect handler callable and the other being the options to pass to it (as a dictionary). |
required |
Returns:
| Type | Description |
|---|---|
HandlerToApply
|
Class instance corresponding to the effect handler and options passed. |
Source code in src/causalprog/causal_problem/handlers.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
causal_problem
Classes for representing causal problems.
CausalProblem
Defines a causal problem.
Source code in src/causalprog/causal_problem/causal_problem.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
__init__(graph, *constraints, causal_estimand)
Create a new causal problem.
Source code in src/causalprog/causal_problem/causal_problem.py
52 53 54 55 56 57 58 59 60 61 | |
lagrangian(n_samples=1000, *, maximum_problem=False)
Return a function that evaluates the Lagrangian of this CausalProblem.
Following the KKT theorem, given the causal estimand and the constraints we can assemble a Lagrangian and seek its stationary points, to in turn identify minimisers of the constrained optimisation problem that we started with.
The Lagrangian returned is a mathematical function of its first two arguments.
The first argument is the same dictionary of parameters that is passed to models
like Graph.model, and is the values the parameters (represented by the
ParameterNodes) are taking. The second argument is a 1D vector of Lagrange
multipliers, whose length is equal to the number of constraints.
The remaining argument of the Lagrangian is the PRNG Key that should be used when drawing samples.
Note that our current implementation assumes there are no equality constraints being imposed (in which case, we would need a 3-argument Lagrangian function).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_samples
|
int
|
The number of random samples to be drawn when estimating the value of functions of the RVs. |
1000
|
maximum_problem
|
bool
|
If passed as |
False
|
Returns:
| Type | Description |
|---|---|
Callable[[dict[str, ArrayLike], ArrayLike, Array], ArrayLike]
|
The Lagrangian, as a function of the model parameters, Lagrange multipliers, and PRNG key. |
Source code in src/causalprog/causal_problem/causal_problem.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
sample_model(model, rng_key, parameter_values)
Draw samples from the predictive model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Predictive
|
Predictive model to draw samples from. |
required |
rng_key
|
Array
|
PRNG Key to use in pseudorandom number generation. |
required |
parameter_values
|
dict[str, ArrayLike]
|
Model parameter values to substitute. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, ArrayLike]
|
|
Source code in src/causalprog/causal_problem/causal_problem.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
components
Classes for defining causal estimands and constraints of causal problems.
CausalEstimand
Bases: _CPComponent
A Causal Estimand.
The causal estimand is the function that we want to minimise (and maximise) as part of a causal problem. It should be a scalar-valued function of the random variables appearing in a graph.
Source code in src/causalprog/causal_problem/components.py
16 17 18 19 20 21 22 23 | |
Constraint
Bases: _CPComponent
A Constraint that forms part of a causal problem.
Constraints of a causal problem are derived properties of RVs for which we have observed data. The causal estimand is minimised (or maximised) subject to the predicted values of the constraints being close to their observed values in the data.
Adding a constraint \(g(\theta)\) to a causal problem (where \(\theta\) are the parameters of the causal problem) essentially imposes an additional constraint on the minimisation problem;
where \(g_{\text{data}}\) is the observed data value for the quantity \(g\), and \(\epsilon\) is some tolerance.
Source code in src/causalprog/causal_problem/components.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
__call__(samples)
Evaluate the constraint, given RV samples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
samples
|
dict[str, ArrayLike]
|
Mapping of RV (node) labels to drawn samples. |
required |
Returns:
| Type | Description |
|---|---|
ArrayLike
|
Value of the constraint. |
Source code in src/causalprog/causal_problem/components.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
__init__(*effect_handlers, model_quantity, outer_norm=None, data=0.0, tolerance=1e-06)
Create a new constraint.
Constraints have the form
where;
- \(\mathrm{norm}\) is the outer norm of the constraint (outer_norm),
- \(g(\theta)\) is the model quantity involved in the constraint
(model_quantity),
- \(g_{\mathrm{data}}\) is the observed data (data),
- \(\epsilon\) is the tolerance in the data (tolerance).
In a causal problem, each constraint appears as the condition \(c(\theta)\leq 0\) in the minimisation / maximisation (hence the inclusion of the \(-\epsilon\) term within \(c(\theta)\) itself).
\(g\) should be a (possibly vector-valued) function that acts on (a subset of) samples from the random variables of the causal problem. It must accept variable keyword-arguments only, and should access the samples for each random variable by indexing via the RV names (node labels). It should return the model quantity as computed from the samples, that \(g_{\mathrm{data}}\) observed.
\(g_{\mathrm{data}}\) should be a fixed value whose shape is broadcast-able with the return shape of \(g\). It defaults to \(0\) if not explicitly set.
\(\mathrm{norm}\) should be a suitable norm to take on the difference between the model quantity as predicted by the samples (\(g\)) and the observed data (\(g_{\mathrm{data}}\)). It must return a scalar value. The default is the 2-norm.
Source code in src/causalprog/causal_problem/components.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
handlers
Container class for specifying effect handlers that need to be applied at runtime.
HandlerToApply
dataclass
Specifies a handler that needs to be applied to a model at runtime.
Source code in src/causalprog/causal_problem/handlers.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
__eq__(other)
Equality operation.
HandlerToApplys are considered equal if they use the same handler function and
provide the same options to this function.
Comparison to other types returns False.
Source code in src/causalprog/causal_problem/handlers.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
__post_init__()
Validate set attributes.
- The handler is a callable object.
- The options have been passed as a dictionary of keyword-value pairs.
Source code in src/causalprog/causal_problem/handlers.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
from_pair(pair)
classmethod
Create an instance from an effect handler and its options.
The two objects should be passed in as the elements of a container of length
2. They can be passed in any order;
- One element must be a dictionary, which will be interpreted as the options
for the effect handler.
- The other element must be callable, and will be interpreted as the handler
itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pair
|
Sequence
|
Container of two elements, one being the effect handler callable and the other being the options to pass to it (as a dictionary). |
required |
Returns:
| Type | Description |
|---|---|
HandlerToApply
|
Class instance corresponding to the effect handler and options passed. |
Source code in src/causalprog/causal_problem/handlers.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
graph
Creation and storage of graphs.
graph
Graph storage.
Graph
Bases: Labelled
A directed acyclic graph that represents a causality tree.
Source code in src/causalprog/graph/graph.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
edges
property
nodes
property
ordered_dist_nodes
property
DistributionNodes in dependency order.
Each DistributionNode in the returned list appears after all its
dependencies. Order is derived from self.ordered_nodes, selecting
only those nodes where is_distribution is True.
ordered_nodes
property
parameter_nodes
property
Returns all parameter nodes in the graph.
The returned tuple uses the ordered_nodes property to obtain the parameter
nodes so that a natural "fixed order" is given to the parameters. When parameter
values are given as inputs to the causal estimand and / or constraint functions,
they will ideally be given as a single vector of parameter values, in which case
a fixed ordering for the parameters is necessary to make an association to the
components of the given input vector.
Returns:
| Type | Description |
|---|---|
tuple[Node, ...]
|
Parameter nodes |
predecessors
property
successors
property
__init__(*, label, graph=None)
Create a graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
A label to identify the graph |
required |
graph
|
DiGraph | None
|
A networkx graph to base this graph on |
None
|
Source code in src/causalprog/graph/graph.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
add_edge(start_node, end_node)
Add a directed edge to the graph.
Adding an edge between nodes not currently in the graph, will cause said nodes to be added to the graph along with the edge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start_node
|
Node | str
|
The node that the edge points from |
required |
end_node
|
Node | str
|
The node that the edge points to |
required |
Source code in src/causalprog/graph/graph.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
add_node(node)
Add a node to the graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
Node
|
The node to add |
required |
Source code in src/causalprog/graph/graph.py
50 51 52 53 54 55 56 57 58 59 60 61 62 | |
get_node(label)
Get a node from its label.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label |
required |
Returns:
| Type | Description |
|---|---|
Node
|
The node |
Source code in src/causalprog/graph/graph.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
model(**parameter_values)
Model corresponding to the Graph's structure.
The model created takes values of the nodes that are parameter as keyword
arguments. Names of the keyword arguments should match the labels of the
ParameterNodes, and their values should be the values of those parameters.
The method returns a dictionary recording the mode sites that are created. This means that the model can be 'extended' further by defining additional sites in a wrapper around this method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parameter_values
|
ArrayLike
|
Names of the keyword arguments should match the labels
of the |
{}
|
Returns:
| Type | Description |
|---|---|
dict[str, ArrayLike]
|
Mapping of non- |
Source code in src/causalprog/graph/graph.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
roots_down_to_outcome(outcome_node_label)
Get ordered list of nodes that outcome depends on.
Nodes are ordered so that each node appears after its dependencies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outcome_node_label
|
str
|
The label of the outcome node |
required |
Returns:
| Type | Description |
|---|---|
tuple[Node, ...]
|
A list of the nodes, ordered from root nodes to the outcome Node. |
Source code in src/causalprog/graph/graph.py
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
node
Graph nodes.
base
Base graph node.
Node
Bases: Labelled
An abstract node in a graph.
Source code in src/causalprog/graph/node/base.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
constant_parameters
abstractmethod
property
is_distribution
property
Identify if the node is an distribution.
Returns:
| Type | Description |
|---|---|
bool
|
True if the node is an distribution |
is_parameter
property
Identify if the node is an parameter.
Returns:
| Type | Description |
|---|---|
bool
|
True if the node is an parameter |
parameters
abstractmethod
property
__init__(*, label, is_parameter=False, is_distribution=False)
Initialise.
Parameters (equivalently ParameterNodes) represent Nodes that do not have
random variables attached. Instead, these nodes represent values that are passed
to nodes that do have distributions attached, and the value of the "parameter"
node is used as a fixed value when constructing the dependent node's
distribution. The set of parameter nodes is the collection of "parameter"s over
which one should want to optimise the causal estimand (subject to any
constraints), and as such the value that a "parameter node" passes to its
dependent nodes will vary as the optimiser runs and explores the solution space.
Note that a "constant parameter" is distinct from a "parameter" in the sense that a constant parameter is not added to the collection of parameters over which we will want to optimise (it is a hard-coded, fixed value).
Distributions (equivalently DistributionNodes) are Nodes that represent
random variables described by probability distributions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
A unique label to identify the node |
required |
is_parameter
|
bool
|
Is the node a parameter? |
False
|
is_distribution
|
bool
|
Is the node a distribution? |
False
|
Source code in src/causalprog/graph/node/base.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
copy()
abstractmethod
Make a copy of a node.
Some inner objects stored inside the node may not be copied when this is called. Modifying some inner objects of a copy made using this may affect the original node.
Returns:
| Type | Description |
|---|---|
Node
|
A copy of the node |
Source code in src/causalprog/graph/node/base.py
77 78 79 80 81 82 83 84 85 86 87 88 89 | |
sample(parameter_values, sampled_dependencies, samples, *, rng_key)
abstractmethod
Sample a value from the node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parameter_values
|
dict[str, float]
|
Values to be taken by parameters |
required |
sampled_dependencies
|
dict[str, NDArray[float]]
|
Values taken by dependencies of this node |
required |
samples
|
int
|
Number of samples |
required |
rng_key
|
Array
|
Random key |
required |
Returns:
| Type | Description |
|---|---|
float
|
Sample value of this node |
Source code in src/causalprog/graph/node/base.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
distribution
Graph nodes representing distributions.
DistributionNode
Bases: Node
A node containing a distribution.
Source code in src/causalprog/graph/node/distribution.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | |
__init__(distribution, *, label, parameters=None, constant_parameters=None)
Initialise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
distribution
|
type
|
The distribution |
required |
label
|
str
|
A unique label to identify the node |
required |
parameters
|
dict[str, str] | None
|
A dictionary of parameters |
None
|
constant_parameters
|
dict[str, float] | None
|
A dictionary of constant parameters |
None
|
Source code in src/causalprog/graph/node/distribution.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
create_model_site(**dependent_nodes)
Create a model site for the (conditional) distribution attached to this node.
dependent_nodes should contain keyword arguments mapping dependent node names
to the values that those nodes are taking (ParameterNodes), or the sampling
object for those nodes (DistributionNodes). These are passed to
self._dist as keyword arguments to construct the sample-able object
representing this node.
Source code in src/causalprog/graph/node/distribution.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | |
parameter
Graph nodes representing parameters.
ParameterNode
Bases: Node
A node containing a parameter.
ParameterNodes differ from DistributionNodes in that they do not have an
attached distribution, but rather represent a parameter that contributes
to the shape of one (or more) DistributionNodes.
The collection of parameters described by ParameterNodes forms the set of
variables that will be optimised over in the corresponding CausalProblem.
ParameterNodes should not be used to encode constant values used by
DistributionNodes. Such constant values should be given to the necessary
DistributionNodes directly as constant_parameters.
Source code in src/causalprog/graph/node/parameter.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
__init__(*, label)
Initialise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
A unique label to identify the node |
required |
Source code in src/causalprog/graph/node/parameter.py
27 28 29 30 31 32 33 34 35 | |
solvers
Solvers for Causal Problems.
sgd
Minimisation via Stochastic Gradient Descent.
stochastic_gradient_descent(obj_fn, initial_guess, *, convergence_criteria=None, fn_args=None, fn_kwargs=None, learning_rate=0.1, maxiter=1000, optimiser=None, tolerance=1e-08)
Minimise a function of one argument using Stochastic Gradient Descent (SGD).
The obj_fn provided will be minimised over its first argument. If you wish to
minimise a function over a different argument, or multiple arguments, wrap it in a
suitable lambda expression that has the correct call signature. For example, to
minimise a function f(x, y, z) over y and z, use
g = lambda yz, x: f(x, yz[0], yz[1]), and pass g in as obj_fn. Note that
you will also need to provide a constant value for x via fn_args or fn_kwargs.
The fn_args and fn_kwargs keys can be used to supply additional parameters that
need to be passed to obj_fn, but which should be held constant.
SGD terminates when the convergence_criteria is found to be smaller than the
tolerance. That is, when
convergence_criteria(objective_value, gradient_value) <= tolerance is found to
be True, the algorithm considers a minimum to have been found. The default
condition under which the algorithm terminates is when the norm of the gradient
at the current argument value is smaller than the provided tolerance.
The optimiser to use can be selected by passing in a suitable optax optimiser
via the optimiser command. By default, optax.adams is used with the supplied
learning_rate. Providing an explicit value for optimiser will result in the
learning_rate argument being ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj_fn
|
Callable[[PyTree], ArrayLike]
|
Function to be minimised over its first argument. |
required |
initial_guess
|
PyTree
|
Initial guess for the minimising argument. |
required |
convergence_criteria
|
Callable[[PyTree, PyTree], ArrayLike] | None
|
The quantity that will be tested against |
None
|
fn_args
|
tuple | None
|
Positional arguments to be passed to |
None
|
fn_kwargs
|
dict | None
|
Keyword arguments to be passed to |
None
|
learning_rate
|
float
|
Default learning rate (or step size) to use when using the
default |
0.1
|
maxiter
|
int
|
Maximum number of iterations to perform. An error will be reported if this number of iterations is exceeded. |
1000
|
optimiser
|
GradientTransformationExtraArgs | None
|
The |
None
|
tolerance
|
float
|
|
1e-08
|
Returns:
| Type | Description |
|---|---|
SolverResult
|
Minimising argument of |
SolverResult
|
Value of |
SolverResult
|
Gradient of |
SolverResult
|
Number of iterations performed. |
Source code in src/causalprog/solvers/sgd.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | |
solver_result
Container class for outputs from solver methods.
SolverResult
dataclass
Container class for outputs from solver methods.
Instances of this class provide a container for useful information that comes out of running one of the solver methods on a causal problem.
Attributes:
| Name | Type | Description |
|---|---|---|
fn_args |
PyTree
|
Argument to the objective function at final iteration (the solution,
if |
grad_val |
PyTree
|
Value of the gradient of the objective function at the |
iters |
int
|
Number of iterations performed. |
maxiter |
int
|
Maximum number of iterations the solver was permitted to perform. |
obj_val |
ArrayLike
|
Value of the objective function at |
reason |
str
|
Human-readable string explaining success or reasons for solver failure. |
successful |
bool
|
|
Source code in src/causalprog/solvers/solver_result.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
utils
Utility classes and methods.
norms
Misc collection of norm-like functions for PyTree structures.
l2_normsq(x)
Square of the l2-norm of a PyTree.
This is effectively "sum(elements**2 in leaf for leaf in x)".
Source code in src/causalprog/utils/norms.py
11 12 13 14 15 16 17 18 | |
translator
Helper class to keep the codebase backend-agnostic.
Our frontend (or user-facing) classes each use a syntax that applies across the package codebase. By contrast, the various backends that we want to support will have different syntaxes and call signatures for the functions that we want to support. As such, we need a helper class that can store this "translation" information, allowing the user to interact with the package in a standard way but also allowing them to choose their own backend if desired.
Translator
Bases: ABC
Maps syntax of a backend function to our frontend syntax.
Different backends have different syntax for drawing samples from the distributions they support. In order to map these different syntaxes to our backend-agnostic framework, we need a container class to map the names we have chosen for our frontend methods to those used by their corresponding backend method.
A Translator allows us to identify whether a user-provided backend object is
compatible with one of our frontend wrapper classes (and thus, call signatures). It
also allows users to write their own translators for any custom backends that we do
not explicitly support.
The use case for a Translator is as follows. Suppose that we have a frontend
class C that needs to provide a method do_something. C stores a
reference to a backend object obj that can provide the functionality of
do_something via one of its methods, obj.backend_method. However, there is
no guarantee that the signature of do_something maps identically to that of
obj.backend_method. A Translator allows us to encode a mapping of
obj.backend_methods arguments to those of do_something.
Source code in src/causalprog/utils/translator.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | |
compulsory_backend_args
property
Arguments that are required to be taken by the backend function.
compulsory_frontend_args
abstractmethod
property
Arguments that are required by the frontend function.
__init__(backend_method=None, **front_args_to_back_args)
Create a new Translator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend_method
|
str
|
Name of the backend method that the instance translates. |
None
|
**front_args_to_back_args
|
str
|
Mapping of frontend argument names to the corresponding backend argument names. |
{}
|
Source code in src/causalprog/utils/translator.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
translate_args(**kwargs)
Translate frontend arguments (with values) to backend arguments.
Essentially transforms frontend keyword arguments into their backend keyword arguments, preserving the value assigned to each argument.
Source code in src/causalprog/utils/translator.py
87 88 89 90 91 92 93 94 95 96 97 | |
validate_compatible(obj)
Determine if obj provides a compatible backend method.
obj must provide a callable whose name matches self.backend_method,
and the callable referenced must take arguments matching the names specified in
self.compulsory_backend_args.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
Object to check possesses a method that can be translated into frontend syntax. |
required |
Source code in src/causalprog/utils/translator.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | |