///|
pub fn vacuous(
f : Frame,
budget~ : Limits = default_limits(),
) -> Mass raise BeliefError {
mass(f, [(f.universe(), 1.0)], budget~)
}
///|
/// Simple support does not silently create empty-set conflict.
pub fn simple_support(
f : Frame,
event : Int32,
support : Double,
budget~ : Limits = default_limits(),
) -> Mass raise BeliefError {
f.check_mask(event)
if event == 0 || !finite(support) || support < 0.0 || support > 1.0 {
raise Invalid(
"simple support requires a nonempty event and support in [0,1]",
)
}
mass(f, [(event, support), (f.universe(), 1.0 - support)], budget~)
}
///|
/// Bayesian mass: one explicit probability for each hypothesis in frame order.
pub fn bayesian(
f : Frame,
probabilities : Array[Double],
budget~ : Limits = default_limits(),
) -> Mass raise BeliefError {
if probabilities.length() != f.size() {
raise Invalid("probability vector must match frame size")
}
let entries : Array[(Int32, Double)] = []
for i = 0; i < probabilities.length(); i = i + 1 {
entries.push((1 << i, probabilities[i]))
}
mass(f, entries, budget~)
}
///|
fn same_frame(a : Mass, b : Mass) -> Unit raise BeliefError {
if a.domain != b.domain {
raise FrameMismatch
}
}
///|
/// Convex pooling is an alternative to independent-evidence fusion.
/// alpha is the weight of the first source, not a reliability estimate.
pub fn mixture(
a : Mass,
b : Mass,
alpha : Double,
budget~ : Limits = default_limits(),
) -> Mass raise BeliefError {
same_frame(a, b)
if !finite(alpha) || alpha < 0.0 || alpha > 1.0 {
raise Invalid("mixture weight must be finite and in [0,1]")
}
budget.check_dense(a.domain)
let bins = Array::make(a.domain.universe() + 1, 0.0)
for (mask, value) in a.focals {
bins[mask] = value * alpha
}
for (mask, value) in b.focals {
bins[mask] = bins[mask] + value * (1.0 - alpha)
}
from_bins(a.domain, bins, budget)
}