///|
/// Ordered, exhaustive, mutually exclusive hypotheses. Order is semantic.
pub struct Frame {
priv names : Array[String]
} derive(Debug, Eq)
///|
/// A finite powerset is deliberately bounded to at most sixteen hypotheses.
pub fn frame(names : Array[String]) -> Frame raise BeliefError {
if names.length() == 0 || names.length() > 16 {
raise Invalid("frame must contain 1..16 hypotheses")
}
for i = 0; i < names.length(); i = i + 1 {
if names[i].length() == 0 || names[i].length() > 256 {
raise Invalid("hypothesis label length must be 1..256")
}
for j = 0; j < i; j = j + 1 {
if names[i] == names[j] {
raise Invalid("duplicate hypothesis label")
}
}
}
{ names: names.copy(), }
}
///|
pub fn Frame::labels(self : Frame) -> Array[String] {
self.names.copy()
}
///|
pub fn Frame::size(self : Frame) -> Int32 {
self.names.length()
}
///|
pub fn Frame::universe(self : Frame) -> Int32 {
(1 << self.names.length()) - 1
}
///|
pub fn Frame::subset(
self : Frame,
labels : Array[String],
) -> Int32 raise BeliefError {
let mut mask = 0
for label in labels {
let mut found = false
for i = 0; i < self.names.length(); i = i + 1 {
if self.names[i] == label {
let bit = 1 << i
if (mask & bit) != 0 {
raise Invalid("duplicate subset label")
}
mask = mask | bit
found = true
break
}
}
if !found {
raise Invalid("unknown subset label")
}
}
mask
}
///|
pub fn Frame::members(
self : Frame,
mask : Int32,
) -> Array[String] raise BeliefError {
self.check_mask(mask)
let result : Array[String] = []
for i = 0; i < self.names.length(); i = i + 1 {
if (mask & (1 << i)) != 0 {
result.push(self.names[i])
}
}
result
}
///|
fn Frame::check_mask(self : Frame, mask : Int32) -> Unit raise BeliefError {
if mask < 0 || mask > self.universe() {
raise Invalid("subset outside frame")
}
}
///|
pub extend Frame with @debug.Debug::{to_repr}
///|
pub extend Frame with Eq::{equal, not_equal}