Internal DSL
An internal domain-specific language for probability expressions.
Expression |
Description |
---|---|
\(P(A)\) |
The probability of A occurring |
\(P(A^*)\) |
The probability of A not occurring |
\(P(A, B)\) |
The joint probability of A and B occurring |
\(P(A \mid B)\) |
The conditional probability of A given B occurring |
\(P(A \mid B^*)\) |
The conditional probability of A occurring given B not occurring |
\(P(A^* \mid B)\) |
The conditional probability of A not occurring given B occurring |
\(P(A^* \mid B^*)\) |
The conditional probability of A not occurring given B not occurring |
\(\sum_A P(A, B)\) |
The marginal probability of B |
Level 3 of Pearl’s Causal Hierarchy.
Expression |
Description |
---|---|
\(P(Y_X \mid X^*, Y^*)\) |
Probability of sufficient causation |
\(P(Y^*_{X^*} \mid X, Y)\) |
Probability of necessary causation |
\(P(Y_X, Y^*_{X^*})\) |
Probability of necessary and sufficient causation |
- class Element[source]
An element in the y0 internal domain-speific language that can be converted to text, LaTeX, and code.
- class Variable(name: str, star: bool | None = None)[source]
A variable, typically with a single letter.
- star: bool | None = None
The star status of the variable. None means it’s a variable, False means it’s the same as the value for the variable, and True means it’s a different value from the variable.
- classmethod norm(name: str | Variable) Variable [source]
Automatically upgrade a string to a variable.
- to_latex() str [source]
Output this variable in the LaTeX string format.
- Returns:
The LaTeX representaton of this variable.
>>> Variable('X').to_latex() 'X' >>> Variable('X1').to_latex() 'X_1' >>> Variable('X12').to_latex() 'X_{12}'
- intervene(variables: str | Variable | Iterable[str | Variable]) CounterfactualVariable [source]
Intervene on this variable with the given variable(s).
- Parameters:
variables – The variable(s) used to extend this variable as it is changed to a counterfactual variable
- Returns:
A new counterfactual variable over this variable with the given intervention(s).
Note
This function can be accessed with the matmult @ operator.
- given(parents: str | Variable | Iterable[str | Variable] | Distribution) Distribution [source]
Create a distribution in which this variable is conditioned on the given variable(s).
The new distribution is a Markov Kernel.
- Parameters:
parents – A variable or list of variables to include as conditions in the new conditional distribution
- Returns:
A new conditional probability distribution
- Raises:
TypeError – If a distribution is given as the parents that contains conditionals
Note
This function can be accessed with the or | operator.
- joint(children: str | Variable | Iterable[str | Variable]) Distribution [source]
Create a joint distribution between this variable and the given variable(s).
- Parameters:
children – The variable(s) for use with this variable in a joint distribution
- Returns:
A new joint distribution over this variable and the given variables.
Note
This function can be accessed with the and & operator.
- invert() Variable [source]
Create an
Intervention
variable that is different from what was observed (with a star).
- class Intervention(name: str, star: bool | None = None)[source]
An intervention variable.
An intervention variable is usually used as a subscript in a
CounterfactualVariable
.
- class CounterfactualVariable(name: str, star: bool | None = None, interventions: frozenset[~y0.dsl.Intervention] = <factory>)[source]
A counterfactual variable.
Counterfactual variables are like normal variables, but can have a list of interventions. Each intervention is either the same as what was observed (no star) or different from what was observed (star).
- interventions: frozenset[Intervention]
The interventions on the variable. Should be non-empty
- to_latex() str [source]
Output this counterfactual variable in the LaTeX string format.
- Returns:
A latex representation of this counterfactual variable
>>> (Variable('X') @ Variable('Y')).to_latex() '{X}_{Y}' >>> (Variable('X1') @ Variable('Y')).to_latex() '{X_1}_{Y}' >>> (Variable('X12') @ Variable('Y')).to_latex() '{X_{12}}_{Y}'
- has_tautology() bool [source]
Return if the counterfactual variable contain its own value in the subscript.
- Returns:
True if we force a variable X to have a value x and the resulting value of X is x.
- Raises:
ValueError – if the counterfactual value doesn’t have a value assigned
- is_inconsistent() bool [source]
Return if the counterfactual variable violates the Axiom of Effectiveness.
- Returns:
True if we force a variable X to have a value x and the resulting value of X is not x
- Raises:
ValueError – if the counterfactual value doesn’t have a value assigned
- intervene(variables: str | Variable | Iterable[str | Variable]) CounterfactualVariable [source]
Intervene on this counterfactual variable with the given variable(s).
- Parameters:
variables – The variable(s) used to extend this counterfactual variable’s current interventions. Automatically converts variables to interventions.
- Returns:
A new counterfactual variable with both this counterfactual variable’s interventions and the given intervention(s).
Warning
Will raise a value error ff the value of a new intervention conflicts with the value of intervention already listed in this counterfactual.
Note
This function can be accessed with the matmult @ operator.
- invert() CounterfactualVariable [source]
Invert the value of the counterfactual variable.
- class Distribution(children: ~typing.Tuple[~y0.dsl.Variable, ...], parents: ~typing.Tuple[~y0.dsl.Variable, ...] = <factory>)[source]
A general distribution over several child variables, conditioned by several parents.
P(X | Y) means that X is a child and Y is a parent.
- classmethod safe(distribution: str | Variable | Iterable[str | Variable] | Distribution, *args: str | Variable | Distribution) Distribution [source]
Create a distribution the given variable(s) or distribution.
- Parameters:
distribution – If given a
Distribution
, creates a probability expression directly over the distribution. If given variable or list of variables, conveniently creates aDistribution
with the variable(s) as children.args – If the first argument (
distribution
) was given as a single variable, theargs
variadic argument can be used to specify a list of additional variables.
- Returns:
A Distribution object
- Raises:
ValueError – If invalid combination of arguments are given.
- is_markov_kernel() bool [source]
Return if this distribution a markov kernel -> one child variable and one or more conditionals.
- intervene(variables: str | Variable | Iterable[str | Variable]) Distribution [source]
Return a new distribution that has the given intervention(s) on all variables.
- uncondition() Distribution [source]
Return a new distribution that is not conditioned on the parents.
- joint(children: str | Variable | Iterable[str | Variable]) Distribution [source]
Create a new distribution including the given child variables.
- Parameters:
children – The variable(s) with which this distribution’s children are extended
- Returns:
A new distribution.
Note
This function can be accessed with the and & operator.
- given(parents: str | Variable | Iterable[str | Variable] | Distribution) Distribution [source]
Create a new mixed distribution additionally conditioned on the given parent variables.
- Parameters:
parents – The variable(s) with which this distribution’s parents are extended
- Returns:
A new distribution
- Raises:
TypeError – If a distribution is given as the parents that contains conditionals
Note
This function can be accessed with the or | operator.
- Event
A conjunction of factual and counterfactual events
alias of
Dict
[Variable
,Intervention
]
- P = <y0.dsl.ProbabilityBuilderType object>
P
is a magical object of mystery and wonder that can be used to createProbability
instances.It itself is a singleton instance of
ProbabilityBuilderType
and can be used wither via theProbabilityBuilderType.__call__()
, as if it were a function likeP(Y)
or it can be used as a combination with theProbabilityBuilderType.__getitem__()
and a call, likeP[X](Y)
to denote interventions using the do-Calculus \(L_2\) notation. Here are some examples:A univariate distribution can be created either with a string or a
Variable
:>>> from y0.dsl import P, A >>> P('A') == P(A)
Multivariate Distributions
A joint distribution can be created with several strings or
Variable
instances with variadic arguments:>>> from y0.dsl import P, A, B >>> P(A, B) == P('A', 'B')
A joint distribution can also be created with a single argument that is either an iterable of either strings or
Variable
instances>>> from y0.dsl import P, A, B >>> P((A, B)) == P([A, B]) == P(('A', 'B')) == P(['A', 'B'])
This even extends to fancy generators, for which you can omit the parentheses:
Creation with a fancy generator of variables:
>>> from y0.dsl import P, A, B >>> P(Variable(name) for name in 'AB') == P(name for name in 'AB') == P(A, B)
Conditional Distributions
Creation with a conditional distribution:
>>> from y0.dsl import P, A, B >>> P(A | B)
Creation with a mixed joint/conditional distribution:
>>> from y0.dsl import P, A, B, C >>> P(A & B | C)
Specifying an Intervention with L2 do-Calculus Notation
Intervene on a single variable:
>>> from y0.dsl import P, X, Y >>> P[X](Y) == P(Y @ X)
Intervene on multiple children:
>>> from y0.dsl import P, X, Y, Z >>> P[X](Y, Z) == P(Y @ X & Z @ X)
Intervene on multiple parents:
>>> from y0.dsl import P, W, X, Y, Z >>> P[X](Y | (W, Z)) == P(Y @ X | (W @ X, Z @ X)):
Intervene on both children and parents:
>>> from y0.dsl import P, X, Y, Z >>> P[X](Y | Z) == P(Y @ X | Z @ X)
Intervene on X on top of previous interventions:
>>> from y0.dsl import P, X, Y, Z >>> P[X](Y @ Z) == P(Y @ X @ Z)
Allow mixing with L3, where each variable can have different interventions:
>>> from y0.dsl import P, W, X, Y, Z >>> P[X](Y @ Z | W) == P(Y @ X @ Z | W @ X)
Specifying Multiple Interventions with L2 do-Calculus Notation
Multiple interventions on a single variable:
>>> from y0.dsl import P, X1, X2, Y >>> P[X1, X2](Y) == P(Y @ X)
Multiple interventions on multiple children:
>>> from y0.dsl import P, X1, X2, Y, Z >>> P[X1, X2](Y, Z) == P(Y @ X1 @ X2 & Z @ X1 @ X2)
… and so on
- class Probability(distribution: Distribution)[source]
The probability over a distribution.
- distribution: Distribution
The distribution over which the probability is expressed
- classmethod safe(distribution: str | Variable | Iterable[str | Variable] | Distribution, *args: str | Variable, interventions: str | Variable | Iterable[str | Variable] | None = None) Probability [source]
Create a distribution the given variable(s) or distribution.
- Parameters:
distribution – If given a
Distribution
, creates a probability expression directly over the distribution. If given variable or list of variables, conveniently creates aDistribution
with the variable(s) as children.args – If the first argument (
distribution
) was given as a single variable, theargs
variadic argument can be used to specify a list of additional variables.interventions – An optional variable or variables to use as interventions.
- Returns:
A probability object
- is_markov_kernel() bool [source]
Return if this distribution a markov kernel -> one child variable and one or more conditionals.
- intervene(variables: str | Variable | Iterable[str | Variable]) Probability [source]
Return a new probability where the underlying distribution has been intervened by the given variables.
- uncondition() Probability [source]
Return a new probability where the underlying distribution is no longer conditioned by the parents.
- Returns:
A new probability over a distribution over the children and parents of the previous distribution
>>> from y0.dsl import P, A, B >>> P(A | B).uncondition() == P(A, B)
- conditional(ranges: str | Variable | Iterable[str | Variable]) Expression [source]
Return this expression, conditioned by the given variables.
- Parameters:
ranges – A variable or list of variables over which to marginalize this expression
- Returns:
A fraction in which the denominator is represents the sum over the given ranges
>>> from y0.dsl import P, A, B >>> assert P(A, B).conditional(A) == P(A, B) / Sum[B](P(A, B)) >>> assert P(A, B, C).conditional([A, B]) == P(A, B, C) / Sum[C](P(A, B, C))
- class Sum(expression: Expression, ranges: frozenset[Variable])[source]
Represent the sum over an expression over an optional set of variables.
- expression: Expression
The expression over which the sum is done
- ranges: frozenset[Variable]
The variables over which the sum is done. Defaults to an empty list, meaning no variables.
- classmethod safe(expression: Expression, ranges: str | Variable | Iterable[str | Variable], *, simplify: bool = False) Expression [source]
Construct a sum from an expression and a permissive set of things in the ranges.
- Parameters:
expression – The expression over which the sum is done
ranges – The variable or list of variables over which the sum is done
simplify – Should the sum be simplified using
Sum.simplify()
?
- Returns:
A
Sum
object
Standard usage, same as the normal
__init__
:>>> from y0.dsl import Sum, X, Y, A, P >>> Sum.safe(P(X, Y), (X,))
Use a list or other iterable:
>>> Sum.safe(P(X, Y), [X])
Use a single variable:
>>> Sum.safe(P(X, Y), X)
- simplify() Expression [source]
Simplify this sum.
- class Product(expressions: Tuple[Expression, ...])[source]
Represent the product of several probability expressions.
- classmethod safe(expressions: Expression | Iterable[Expression]) Expression [source]
Construct a product from any iterable of expressions.
- Parameters:
expressions – An expression or iterable of expressions which should be multiplied
- Returns:
A
Product
object
Standard usage, same as the normal
__init__
:>>> from y0.dsl import Product, X, Y, A, P >>> Product.safe((P(X, Y), ))
Use a list or other iterable:
>>> Product.safe([P(X), P(Y | X)])
Use an inline generator:
>>> Product.safe(P(v) for v in [X, Y])
Use a single expression:
>>> Product.safe(P(X, Y))
- class Fraction(numerator: Expression, denominator: Expression)[source]
Represents a fraction of two expressions.
- numerator: Expression
The expression in the numerator of the fraction
- denominator: Expression
The expression in the denominator of the fraction
- simplify() Expression [source]
Simplify this fraction.
- class Expression[source]
The abstract class representing all expressions.
- conditional(ranges: str | Variable | Iterable[str | Variable]) Expression [source]
Return this expression, conditioned by the given variables.
- Parameters:
ranges – A variable or list of variables over which to marginalize this expression
- Returns:
A fraction in which the denominator is represents the sum over the given ranges
>>> from y0.dsl import P, A, B >>> assert P(A, B).conditional(A) == P(A, B) / Sum[B](P(A, B)) >>> assert P(A, B, C).conditional([A, B]) == P(A, B, C) / Sum[C](P(A, B, C))
- normalize_marginalize(ranges: str | Variable | Iterable[str | Variable]) Expression [source]
Return this expression, normalized by this expression marginalized by the given variables.
- marginalize(ranges: str | Variable | Iterable[str | Variable]) Expression [source]
Return this expression, marginalizing out the given variables.
- Parameters:
ranges – A variable or list of variables over which to marginalize this expression
- Returns:
The expression but summed over the given variables
>>> from y0.dsl import P, A, B, C >>> assert P(A, B).marginalize(A) == Sum[A](P(A, B)) >>> assert P(A, B, C).marginalize([A, B]) == Sum[A, B](P(A, B, C))
- class QFactor(domain: frozenset[Variable], codomain: frozenset[Variable])[source]
A function from the variables in the domain to a probability function over variables in the codomain.
- ensure_ordering(expression: Expression, *, ordering: Iterable[str | Variable] | None = None) Sequence[Variable] [source]
Get a canonical ordering of the variables in the expression, or pass one through.
The canonical ordering of the variables in a given expression is based on the alphabetical sort order of the variables based on their names.
- Parameters:
expression – The expression to get a canonical ordering from.
ordering – A given ordering to pass through if not none, otherwise calculate it.
- Returns:
The ordering
- vmap_pairs(edges: Iterable[Tuple[str, str]]) List[Tuple[Variable, Variable]] [source]
Map pair of strings to pairs of variables.
- class PopulationProbability(distribution: Distribution, population: Variable)[source]
A probability that is annotated with a population.
>>> from y0.dsl import PP, Pi1, Y, X >>> # Make a population-annotated probability of Y >>> PP[Pi1](Y) >>> # Make a conditioned population of Y @ X >>> PP[Pi1][X](Y)
Related publications: - Surrogate Outcomes and Transportability (Tikka and Karvanen, 2018)
- PP
alias of
PopulationProbabilityBuilderType