Mutation
Functions that mutate probability expressions.
- canonicalize(expression: Expression, ordering: Sequence[str | Variable] | None = None) Expression [source]
Canonicalize an expression that meets the markov condition with respect to the given ordering.
- Parameters:
expression – An expression to canonicalize
ordering – A toplogical ordering. If none is given, it is assigned by sort order of the variable names.
- Returns:
A canonical expression
- canonical_expr_equal(left: Expression, right: Expression) bool [source]
Return True if two expressions are equal after canonicalization.
- chain_expand(p: Probability, *, reorder: bool = True, ordering: Iterable[str | Variable] | None = None) Expression [source]
Expand a probability distribution to a product of conditional probabilities on single variables.
- Parameters:
p – The given probability expression
reorder – Should the variables be reordered with respect to the ordering before expanding? This is important because there are a variety of equivalent expressions that can’t be directly matched.
ordering – An ordering to be used if
reorder
is true. If none, automatically generates a canonical ordering usingy0.dsl.ensure_ordering()
.
- Returns:
A product representing the expanded distribution, in which each probability term is a markov kernel
- Raises:
ValueError – if the ordering is passed explicitly and it does not cover all variables
Two variables:
\[P(X,Y)=P(X|Y)*P(Y)\]>>> from y0.dsl import P, X, Y >>> assert chain_expand(P(X, Y)) == P(X | Y) * P(Y)
The recurrence relation for many variables is defined as:
\[P(X_n,\dots,X_1) = P(X_n|X_{n-1},\dots,X_1) \times P(X_{n-1},\dots,X_1)\]>>> from y0.dsl import P, A, X, Y, Z >>> assert chain_expand(P(X, Y, Z)) == P(X | Y, Z) * P(Y | Z) * P(Z)
Extra conditions come along for the ride.
>>> assert chain_expand(P(X, Y, Z | A)) == P(X | Y, Z, A) * P(Y | Z, A) * P(Z | A)
- fraction_expand(p: Probability) Expression [source]
Expand a probability distribution with fractions.
- Parameters:
p – The given probability expression
- Returns:
A fraction representing the joint distribution
The simple case has one child variable (\(A\)) and one parent variable (\(B\)):
\[P(A | B) = \frac{P(A,B)}{P(B)}\]>>> from y0.dsl import P, A, B, Sum >>> from y0.mutate.chain import fraction_expand >>> assert fraction_expand(P(A | B)) == P(A, B) / P(B)
If there are no conditions (i.e., parents), then the probability is returned without modification.
>>> assert fraction_expand(P(A, B)) == P(A, B)
In general, with many children \(Y_i\) and many parents \(X_i\):
\[P(Y_1,\dots,Y_n | X_1, \dots, X_m) = \frac{P(Y_1,\dots,Y_n,X_1,\dots,X_m)}{P(X_1,\dots,X_m)}\]
- bayes_expand(p: Probability) Expression [source]
Expand a probability distribution using Bayes’ theorem.
- Parameters:
p – The given probability expression, with arbitrary number of children and parents
- Returns:
A fraction representing the joint distribution
\[P(Y_1,\dots,Y_n|X_1,\dots,X_m) = \frac{P(Y_1,\dots,Y_n,X_1,\dots,X_m)}{\sum_{Y_1,\dots,Y_n} P(Y_1,\dots,Y_n,X_1,\dots,X_m)}\]>>> from y0.dsl import P, A, B, C, Sum >>> from y0.mutate.chain import bayes_expand >>> assert bayes_expand(P(A | B)) == P(A, B) / Sum[A](P(A, B)
If there are no conditions (i.e., parents), then the probability is returned without modification.
>>> assert bayes_expand(P(A, B)) == P(A, B)
Note
This expansion will create a different but equal expression to
fraction_expand()
.