Skip to main content

qualia_core_db/modalities/likeliness/
algebra.rs

1//! The Kleene / De Morgan lattice on the likeliness scale. These are the logical
2//! connectives of the calculus; the non-probabilistic character lives here (no excluded
3//! middle, no contradiction collapse).
4
5use super::Likeliness;
6
7/// Negation — the order-reversing involution `Impossible ↔ Certain`, `Even` fixed.
8/// Note `not(not(l)) == l`, but `or(l, not l)` need not be `Certain`.
9pub fn not(l: Likeliness) -> Likeliness {
10    Likeliness::from_level(-l.level())
11}
12
13/// Conjunction — the **meet** (weakest link): a claim resting on both `a` and `b` is no
14/// more expected than its least-expected part.
15pub fn and(a: Likeliness, b: Likeliness) -> Likeliness {
16    a.min(b)
17}
18
19/// Disjunction — the **join** (best alternative): a claim reachable via `a` or `b` is at
20/// least as expected as its most-expected route.
21pub fn or(a: Likeliness, b: Likeliness) -> Likeliness {
22    a.max(b)
23}
24
25/// Likeliness of a conjunction of premises = the weakest (meet over all). The vacuous
26/// conjunction (no premises) is `Certain` (the top).
27pub fn combine_premises(premises: &[Likeliness]) -> Likeliness {
28    premises.iter().copied().fold(Likeliness::Certain, and)
29}
30
31/// Likeliness of a conclusion reachable by alternative routes = the strongest (join over
32/// all). The vacuous disjunction (no routes) is `Impossible` (the bottom).
33pub fn combine_routes(routes: &[Likeliness]) -> Likeliness {
34    routes.iter().copied().fold(Likeliness::Impossible, or)
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use Likeliness::*;
41
42    #[test]
43    fn negation_is_an_involution_reflecting_the_scale() {
44        assert_eq!(not(Impossible), Certain);
45        assert_eq!(not(Unlikely), Likely);
46        assert_eq!(not(Even), Even);
47        for l in [Impossible, Unlikely, Even, VeryLikely, Certain] {
48            assert_eq!(not(not(l)), l);
49        }
50    }
51
52    #[test]
53    fn meet_and_join_are_min_and_max() {
54        assert_eq!(and(Likely, Unlikely), Unlikely);
55        assert_eq!(or(Likely, Unlikely), Likely);
56        assert_eq!(and(Certain, Even), Even);
57        assert_eq!(or(Impossible, Even), Even);
58    }
59
60    #[test]
61    fn de_morgan_laws_hold() {
62        for a in [Impossible, Unlikely, Even, Likely, Certain] {
63            for b in [Impossible, Unlikely, Even, Likely, Certain] {
64                assert_eq!(not(and(a, b)), or(not(a), not(b)));
65                assert_eq!(not(or(a, b)), and(not(a), not(b)));
66            }
67        }
68    }
69
70    #[test]
71    fn kleene_no_excluded_middle_no_contradiction() {
72        // The defining non-probabilistic property: a merely-Likely proposition and its
73        // negation neither exhaust certainty nor collapse to impossibility.
74        assert_eq!(or(Likely, not(Likely)), Likely); // ≠ Certain
75        assert_eq!(and(Likely, not(Likely)), Unlikely); // ≠ Impossible
76                                                        // Only at the extremes do they behave classically.
77        assert_eq!(or(Certain, not(Certain)), Certain);
78        assert_eq!(and(Certain, not(Certain)), Impossible);
79    }
80
81    #[test]
82    fn vacuous_folds_are_top_and_bottom() {
83        assert_eq!(combine_premises(&[]), Certain);
84        assert_eq!(combine_routes(&[]), Impossible);
85        assert_eq!(combine_premises(&[Likely, Even, Certain]), Even);
86        assert_eq!(combine_routes(&[Unlikely, Even, VeryUnlikely]), Even);
87    }
88}