minerva 0.2.0

Causal ordering for distributed systems
use super::super::super::support::arb_vv;
use super::arb_roster;
use crate::metis::VersionVector;
use proptest::prelude::*;

proptest! {
    /// The difference is the co-Heyting residual, specified by its universal
    /// property: `a.difference(&b) <= x` exactly when `a <= b.merge(&x)` (the
    /// Galois connection), hence bottom exactly when the creditor already
    /// dominates, and repaying the debt reaches exactly the join, no more.
    /// The adjoint ledger predicted all three laws before the read existed.
    #[test]
    fn prop_difference_is_the_co_heyting_residual(
        a in arb_vv(), b in arb_vv(), x in arb_vv(),
    ) {
        let owed = a.difference(&b);
        prop_assert_eq!(owed <= x, a <= b.merge(&x));
        let repaid = b.merge(&owed);
        prop_assert_eq!(repaid, a.merge(&b));
        let cleared = owed == VersionVector::new();
        prop_assert_eq!(cleared, a <= b);
    }

    /// The residual carries the claim to be reached, never a subtracted
    /// counter: each owed entry is the debtor's own count at a station where
    /// it strictly leads, and no other entry appears (the ledger's shape
    /// warning made law; canonical form follows, since every carried count is
    /// positive).
    #[test]
    fn prop_difference_carries_claims_never_subtractions(
        a in arb_vv(), b in arb_vv(),
    ) {
        let owed = a.difference(&b);
        for station in 0u32..8 {
            let expected = if a.get(station) > b.get(station) {
                a.get(station)
            } else {
                0
            };
            prop_assert_eq!(owed.get(station), expected);
        }
    }

    /// Owed against two creditors folds their knowledge (currying), the
    /// residual preserves joins in the debtor (a left adjoint's law), and it
    /// exchanges the creditor's meet for a join of debts (the co-Heyting
    /// exchange over the distributive lattice).
    #[test]
    fn prop_difference_curries_and_preserves_debtor_joins(
        a in arb_vv(), b in arb_vv(), c in arb_vv(),
    ) {
        prop_assert_eq!(
            a.difference(&b).difference(&c),
            a.difference(&b.merge(&c))
        );
        prop_assert_eq!(
            a.merge(&b).difference(&c),
            a.difference(&c).merge(&b.difference(&c))
        );
        prop_assert_eq!(
            a.difference(&b.meet(&c)),
            a.difference(&b).merge(&a.difference(&c))
        );
    }

    /// The difference commutes exactly with restriction: the residual is
    /// computed per station from that station's coordinates alone, so its
    /// base-change law is free (PRD 0013 R2; this test is the witness, the
    /// first shipped composition of the difference and relative families).
    #[test]
    fn prop_difference_commutes_with_restriction(
        a in arb_vv(), b in arb_vv(), r in arb_roster(),
    ) {
        prop_assert_eq!(
            a.difference(&b).restrict(r.iter().copied()),
            a.restrict(r.iter().copied())
                .difference(&b.restrict(r.iter().copied()))
        );
    }
}