Inference
Four query functions answer questions about a compiled network, each returning
an Answer:
| Query | Meaning |
|---|---|
marginal(network, "x") |
P(x) |
joint(network, {"x": True, "y": False}) |
P(x and not y) |
conditional(network, "x", {"y": True}) |
P(x | y) |
intervene(network, "x", set={"y": False}) |
P(x) after cutting the relations into y and fixing y false |
Conditioning on a node also updates what the node rests on; intervening does not. "What does the conclusion rest on?" is an interventional question.
Two exact engines are provided:
VariableElimination, the default, eliminates variables in a min-fill order. If an intermediate factor would exceedmax_factor_sizeentries (default 2²²), the query fails withProblemTooLargeError; it never falls back to an approximation on its own.Enumerationsums over every world. It is exponential in the number of free variables (limited to 20 by default) and serves as the independent reference in tests.
Parameter uncertainty¶
Every base and strength is treated as independent of the others. An Answer
carries:
point: the probability with every parameter at its credence mean. Because each parameter enters a joint probability with degree at most one, this is exactly the predictive probability E[P(A, E)] / E[P(E)] over the parameters' distributions, computed without sampling.band: the 5%, 50% and 95% quantiles (q05,q50,q95) of the exact answer over Monte Carlo draws of theBetaparameters. It shows how far the answer would move if the inputs were different.mean_over_draws: the average of those per-draw answers. The draws do not update the parameters on the evidence, so this generally differs frompointand is reported under its own name.draws: the number of draws behind the band.
The band is omitted (band and mean_over_draws are None) when every
parameter is a Point, or when draws=0 is passed. Queries make
DEFAULT_DRAWS (1000) draws by default; pass rng (a seed or a
numpy.random.Generator) for reproducible bands.
Overriding a Beta parameter with Network.with_parameters moves point but
not the band. The point answer uses the values the network holds, while every
Beta parameter is drawn from its stored credence, including one that has been
set to another value; a network whose Beta parameters have all been set still
gets a band. To hold a parameter fixed in the band, give it a Point credence
in the graph instead. Overriding a parameter whose credence is a Point moves
the band as well as point, because its overridden value is kept in every draw.
Parameters are independent by construction, so correlated inputs (two measurements sharing an unknown bias, say) cannot be expressed as correlated strengths. Model the shared cause as a proposition of its own, such as "the instrument is calibrated", with a relation into each.
Inference: exact engines, the marginal, joint, conditional and interventional queries, and their bands.
Answer
dataclass
¶
The answer to a query.
Attributes:
| Name | Type | Description |
|---|---|---|
point |
float
|
The point answer: the probability with every parameter at its credence mean. Because
the network is multilinear in its independent parameters, this equals the predictive
ratio |
band |
Band | None
|
The 5%, 50% and 95% quantiles of the answer over parameter draws, or |
mean_over_draws |
float | None
|
The average of the per-draw answers, reported separately from |
draws |
int
|
The number of parameter draws behind |
Source code in src/credencegraph/inference/queries.py
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 | |
__post_init__()
¶
Check that the band, its mean and the draw count come together or not at all.
Raises:
| Type | Description |
|---|---|
ValidationError
|
If some but not all of them are given. |
Source code in src/credencegraph/inference/queries.py
42 43 44 45 46 47 48 49 50 | |
to_dict()
¶
Return the answer as JSON-ready data.
Returns:
| Type | Description |
|---|---|
dict[str, object]
|
|
Source code in src/credencegraph/inference/queries.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
Band
dataclass
¶
Quantiles of a query's answer over parameter draws.
Attributes:
| Name | Type | Description |
|---|---|---|
q05 |
float
|
The 5% quantile. |
q50 |
float
|
The median. |
q95 |
float
|
The 95% quantile. |
Source code in src/credencegraph/inference/uncertainty.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
to_dict()
¶
Return the band as JSON-ready data.
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
|
Source code in src/credencegraph/inference/uncertainty.py
51 52 53 54 55 56 57 | |
Engine
¶
Bases: ABC
An inference engine.
An engine only has to compute the probability of a partial assignment. query turns that into
conditional and interventional answers, and observes every exclusive constraint as true.
Source code in src/credencegraph/inference/engine.py
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 | |
probability(network, assignment)
abstractmethod
¶
Compute the probability that the given variables take the given values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
assignment
|
Mapping[int, int]
|
Variable indices and values (0 or 1); every other variable is summed out. |
required |
Returns:
| Type | Description |
|---|---|
float
|
The probability. |
Source code in src/credencegraph/inference/engine.py
107 108 109 110 111 112 113 114 115 116 117 | |
query(network, query)
¶
Answer a query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network, at the parameter values the answer should use. |
required |
query
|
Query
|
The query. |
required |
Returns:
| Type | Description |
|---|---|
float
|
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the query names a node that is not an inference variable, or the interventions set merged nodes to different values. |
ZeroProbabilityError
|
If the evidence and constraints have probability zero. |
Source code in src/credencegraph/inference/engine.py
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 | |
Enumeration
¶
Bases: Engine
Exhaustive enumeration of every world consistent with the assignment.
Each world's probability is the product of one entry from every table, and the answer is the sum over worlds. It shares no code with variable elimination, which makes it the independent reference that engine is tested against. The cost doubles with every variable left free.
Source code in src/credencegraph/inference/enumeration.py
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 | |
__init__(max_free_variables=DEFAULT_MAX_FREE_VARIABLES)
¶
Configure the engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_free_variables
|
int
|
The largest number of summed-out variables allowed; a query needing
more raises |
DEFAULT_MAX_FREE_VARIABLES
|
Source code in src/credencegraph/inference/enumeration.py
24 25 26 27 28 29 30 31 | |
probability(network, assignment)
¶
Sum the joint probability of every world that agrees with assignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
assignment
|
Mapping[int, int]
|
Variable indices and values (0 or 1). |
required |
Returns:
| Type | Description |
|---|---|
float
|
The probability. |
Raises:
| Type | Description |
|---|---|
ProblemTooLargeError
|
If more than |
Source code in src/credencegraph/inference/enumeration.py
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 | |
query(network, query)
¶
Answer a query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network, at the parameter values the answer should use. |
required |
query
|
Query
|
The query. |
required |
Returns:
| Type | Description |
|---|---|
float
|
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the query names a node that is not an inference variable, or the interventions set merged nodes to different values. |
ZeroProbabilityError
|
If the evidence and constraints have probability zero. |
Source code in src/credencegraph/inference/engine.py
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 | |
InferenceError
¶
Bases: CredenceGraphError
Base class for errors raised while answering a query.
Source code in src/credencegraph/inference/errors.py
8 9 | |
ProblemTooLargeError
¶
Bases: InferenceError
An exact engine would need more memory than its configured limit allows.
Exact engines never fall back to an approximation on their own: they raise this error instead.
Attributes:
| Name | Type | Description |
|---|---|---|
required |
The size the query would need, in the unit |
|
limit |
The configured limit. |
Source code in src/credencegraph/inference/errors.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
__init__(message, required, limit)
¶
Store the sizes alongside the message.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Human-readable description naming the limit. |
required |
required
|
int
|
The size the query would need. |
required |
limit
|
int
|
The configured limit. |
required |
Source code in src/credencegraph/inference/errors.py
26 27 28 29 30 31 32 33 34 35 36 | |
Query
dataclass
¶
A probability query: P(target | evidence) after the interventions are applied.
Attributes:
| Name | Type | Description |
|---|---|---|
target |
Mapping[str, bool]
|
Node ids and the values whose joint probability is asked for. |
evidence |
Mapping[str, bool]
|
Node ids and the observed values conditioned on. |
interventions |
Mapping[str, bool]
|
Node ids and the values they are set to; relations into them are cut. |
Source code in src/credencegraph/inference/engine.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
__post_init__()
¶
Validate the three assignments and store read-only copies.
Source code in src/credencegraph/inference/engine.py
52 53 54 55 56 | |
VariableElimination
¶
Bases: Engine
Exact inference by variable elimination with a min-fill order.
The order depends only on the factor scopes once the assignment is applied, so it is computed once for each distinct set of scopes and reused by later queries, including those on networks that differ only in their parameter values.
Before any table is built, the engine works out the scope of every intermediate factor the
order produces. If the largest would hold more than max_factor_size entries, the query fails
with ProblemTooLargeError; the engine never falls back to an approximation.
Source code in src/credencegraph/inference/elimination.py
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 | |
__init__(max_factor_size=DEFAULT_MAX_FACTOR_SIZE)
¶
Configure the engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_factor_size
|
int
|
The largest intermediate factor allowed, in table entries. |
DEFAULT_MAX_FACTOR_SIZE
|
Source code in src/credencegraph/inference/elimination.py
122 123 124 125 126 127 128 | |
probability(network, assignment)
¶
Compute the probability of assignment by summing out every other variable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
assignment
|
Mapping[int, int]
|
Variable indices and values (0 or 1). |
required |
Returns:
| Type | Description |
|---|---|
float
|
The probability. |
Raises:
| Type | Description |
|---|---|
ProblemTooLargeError
|
If an intermediate factor would exceed |
Source code in src/credencegraph/inference/elimination.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
query(network, query)
¶
Answer a query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network, at the parameter values the answer should use. |
required |
query
|
Query
|
The query. |
required |
Returns:
| Type | Description |
|---|---|
float
|
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the query names a node that is not an inference variable, or the interventions set merged nodes to different values. |
ZeroProbabilityError
|
If the evidence and constraints have probability zero. |
Source code in src/credencegraph/inference/engine.py
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 | |
ZeroProbabilityError
¶
Bases: InferenceError, ValueError
The evidence of a query, together with the exclusive constraints, has probability zero.
Source code in src/credencegraph/inference/errors.py
12 13 | |
answers_over_draws(network, query, engine, samples)
¶
Answer a query exactly at every parameter draw.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
query
|
Query
|
The query. |
required |
engine
|
Engine
|
The exact engine used at each draw. |
required |
samples
|
Mapping[ParameterKey, ndarray]
|
Values by parameter, one array entry per draw, as from |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The answer at each draw. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the sample arrays differ in length, or a key or value is invalid. |
ZeroProbabilityError
|
If the evidence has probability zero at some draw. |
Source code in src/credencegraph/inference/uncertainty.py
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 | |
conditional(network, target, given, *, engine=None, draws=DEFAULT_DRAWS, rng=None)
¶
Compute P(target | given).
Conditioning on a node also updates the node's own premises: observing that a conclusion is false is evidence against what supports it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
target
|
str | Mapping[str, bool]
|
A node id, asked to be true, or an assignment. |
required |
given
|
Mapping[str, bool]
|
The observed values. |
required |
engine
|
Engine | None
|
The inference engine; variable elimination by default. |
None
|
draws
|
int
|
The number of parameter draws behind the band. Each draw answers the query exactly once
more, so the default band costs |
DEFAULT_DRAWS
|
rng
|
Seed
|
A random generator, or a seed for one, for the draws; |
None
|
Returns:
| Type | Description |
|---|---|
Answer
|
The answer. |
Source code in src/credencegraph/inference/queries.py
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 | |
has_spread(network)
¶
Tell whether any parameter of the network is uncertain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/credencegraph/inference/uncertainty.py
60 61 62 63 64 65 66 67 68 69 | |
intervene(network, target, set, *, given=None, engine=None, draws=DEFAULT_DRAWS, rng=None)
¶
Compute P(target | do(set), given): cut the relations into the set nodes and fix them.
This answers "suppose this premise is simply wrong": unlike conditioning, it does not update the set node's own premises.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
target
|
str | Mapping[str, bool]
|
A node id, asked to be true, or an assignment. |
required |
set
|
Mapping[str, bool]
|
The nodes to set and their values. |
required |
given
|
Mapping[str, bool] | None
|
Values observed after the intervention, if any. |
None
|
engine
|
Engine | None
|
The inference engine; variable elimination by default. |
None
|
draws
|
int
|
The number of parameter draws behind the band. Each draw answers the query exactly once
more, so the default band costs |
DEFAULT_DRAWS
|
rng
|
Seed
|
A random generator, or a seed for one, for the draws; |
None
|
Returns:
| Type | Description |
|---|---|
Answer
|
The answer. |
Source code in src/credencegraph/inference/queries.py
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 | |
joint(network, assignment, *, engine=None, draws=DEFAULT_DRAWS, rng=None)
¶
Compute the probability of a joint assignment, P(X = x and Y = y and ...).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
assignment
|
Mapping[str, bool] | Iterable[str]
|
Node ids and values, or an iterable of node ids that are all asked to be true. |
required |
engine
|
Engine | None
|
The inference engine; variable elimination by default. |
None
|
draws
|
int
|
The number of parameter draws behind the band. Each draw answers the query exactly once
more, so the default band costs |
DEFAULT_DRAWS
|
rng
|
Seed
|
A random generator, or a seed for one, for the draws; |
None
|
Returns:
| Type | Description |
|---|---|
Answer
|
The answer. |
Source code in src/credencegraph/inference/queries.py
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
marginal(network, node, value=True, *, engine=None, draws=DEFAULT_DRAWS, rng=None)
¶
Compute P(node = value).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
node
|
str
|
A node id. |
required |
value
|
bool
|
The value asked about. |
True
|
engine
|
Engine | None
|
The inference engine; variable elimination by default. |
None
|
draws
|
int
|
The number of parameter draws behind the band. Each draw answers the query exactly once
more, so the default band costs |
DEFAULT_DRAWS
|
rng
|
Seed
|
A random generator, or a seed for one, for the draws; |
None
|
Returns:
| Type | Description |
|---|---|
Answer
|
The answer. |
Source code in src/credencegraph/inference/queries.py
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 | |
min_fill_order(scopes)
¶
Choose an elimination order by the greedy min-fill heuristic.
At each step the variable whose elimination adds the fewest new edges to the interaction graph is eliminated next. Ties go to the variable with fewer neighbours, then to the lower index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scopes
|
Iterable[Iterable[int]]
|
The scopes of the factors; two variables interact when they share a scope. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
Every variable that appears in a scope, in elimination order. |
Source code in src/credencegraph/inference/elimination.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 | |
sample_parameters(network, draws, rng=None)
¶
Draw every Beta parameter of a network independently from its credence.
Parameters are drawn in the order network.parameters lists them, so a given seed always
yields the same draws for the same network. Point parameters are left out: they keep their
value in every draw. A Beta parameter is drawn from its credence even when
Network.with_parameters has set it to another value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
draws
|
int
|
The number of draws. |
required |
rng
|
Generator | int | None
|
A random generator, or a seed for one; |
None
|
Returns:
| Type | Description |
|---|---|
dict[ParameterKey, ndarray]
|
For each |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
Source code in src/credencegraph/inference/uncertainty.py
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 | |
spread(network, query, engine, draws=DEFAULT_DRAWS, rng=None)
¶
Estimate how a query's answer spreads over the parameters' credences.
Every Beta parameter is drawn from its credence, including one that Network.with_parameters
has set to another value: the band describes the Beta credences, not the values the network
holds for them, so overriding a Beta parameter moves the point answer but not the band. A
Point parameter keeps the value the network holds in every draw, so overriding one moves
both. The network does not record which values were overridden, so it cannot hold them fixed;
give a parameter a Point credence to keep it out of the draws.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
network
|
Network
|
The network. |
required |
query
|
Query
|
The query. |
required |
engine
|
Engine
|
The exact engine used at each draw. |
required |
draws
|
int
|
The number of Monte Carlo draws; 0 skips the estimate. |
DEFAULT_DRAWS
|
rng
|
Generator | int | None
|
A random generator, or a seed for one; |
None
|
Returns:
| Type | Description |
|---|---|
tuple[Band, float] | None
|
The band and the mean of the per-draw answers, or |
tuple[Band, float] | None
|
parameter is a |
tuple[Band, float] | None
|
a network whose every |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
ZeroProbabilityError
|
If the evidence has probability zero at some draw. |
Source code in src/credencegraph/inference/uncertainty.py
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 | |