|
| 1 | +(* SPDX-License-Identifier: MPL-2.0 *) |
| 2 | +(* SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) *) |
| 3 | + |
| 4 | +(* |
| 5 | + QttSemiring.v |
| 6 | + ═════════════ |
| 7 | + Wave 2: the **QTT quantity semiring {0, 1, ω}** — the algebraic core of |
| 8 | + AffineScript's affine / quantitative type system (the `Quantity` module of |
| 9 | + the Solo calculus). Mechanizes the multiplicity semiring with its `+` |
| 10 | + (context addition) and `·` (scaling) operations, the usage order |
| 11 | + `0 ≤ 1 ≤ ω`, and the bridge to occurrence counts: |
| 12 | +
|
| 13 | + qof (m + n) = qplus (qof m) (qof n) |
| 14 | +
|
| 15 | + i.e. *occurrences add under QTT addition*. So using a **linear** (`1`) |
| 16 | + variable in BOTH the function and the argument of an application totals `ω` |
| 17 | + (`qplus One One = Omega`), exceeding the affine bound — the algebraic reason |
| 18 | + a linear value cannot be used twice. |
| 19 | +
|
| 20 | + Advances **P-4** (docs/PROOF-NEEDS.adoc) from prose to a mechanized core. |
| 21 | + All laws hold by exhaustive case analysis — axiom-free, no `Admitted`. |
| 22 | + A usage-counted linear *calculus* (the "1-var used exactly once" typing |
| 23 | + theorem) builds on this in AffineUsage.v. |
| 24 | +
|
| 25 | + `.v` is Coq, not V-lang — see formal/README.adoc and .hypatia-ignore. |
| 26 | +*) |
| 27 | + |
| 28 | +Require Import PeanoNat. |
| 29 | +Require Import Lia. |
| 30 | + |
| 31 | +Inductive quant := Zero | One | Omega. |
| 32 | + |
| 33 | +(* Context addition: how usages combine when a variable is used in two places. |
| 34 | + 1 + 1 = ω is the crux — two linear uses exceed the affine bound. *) |
| 35 | +Definition qplus (p q : quant) : quant := |
| 36 | + match p with |
| 37 | + | Zero => q |
| 38 | + | One => match q with Zero => One | _ => Omega end |
| 39 | + | Omega => Omega |
| 40 | + end. |
| 41 | + |
| 42 | +(* Scaling: how a usage is multiplied when passing through a binder of a given |
| 43 | + multiplicity. *) |
| 44 | +Definition qmult (p q : quant) : quant := |
| 45 | + match p with |
| 46 | + | Zero => Zero |
| 47 | + | One => q |
| 48 | + | Omega => match q with Zero => Zero | _ => Omega end |
| 49 | + end. |
| 50 | + |
| 51 | +(* ── semiring laws (exhaustive case analysis) ──────────────────────────── *) |
| 52 | + |
| 53 | +Lemma qplus_0_l : forall q, qplus Zero q = q. Proof. reflexivity. Qed. |
| 54 | +Lemma qplus_0_r : forall q, qplus q Zero = q. Proof. destruct q; reflexivity. Qed. |
| 55 | +Lemma qplus_comm : forall p q, qplus p q = qplus q p. |
| 56 | +Proof. destruct p, q; reflexivity. Qed. |
| 57 | +Lemma qplus_assoc : forall p q r, qplus p (qplus q r) = qplus (qplus p q) r. |
| 58 | +Proof. destruct p, q, r; reflexivity. Qed. |
| 59 | + |
| 60 | +Lemma qmult_0_l : forall q, qmult Zero q = Zero. Proof. reflexivity. Qed. |
| 61 | +Lemma qmult_0_r : forall q, qmult q Zero = Zero. Proof. destruct q; reflexivity. Qed. |
| 62 | +Lemma qmult_1_l : forall q, qmult One q = q. Proof. reflexivity. Qed. |
| 63 | +Lemma qmult_1_r : forall q, qmult q One = q. Proof. destruct q; reflexivity. Qed. |
| 64 | +Lemma qmult_comm : forall p q, qmult p q = qmult q p. |
| 65 | +Proof. destruct p, q; reflexivity. Qed. |
| 66 | +Lemma qmult_assoc : forall p q r, qmult p (qmult q r) = qmult (qmult p q) r. |
| 67 | +Proof. destruct p, q, r; reflexivity. Qed. |
| 68 | + |
| 69 | +Lemma qdistrib_l : forall p q r, qmult p (qplus q r) = qplus (qmult p q) (qmult p r). |
| 70 | +Proof. destruct p, q, r; reflexivity. Qed. |
| 71 | +Lemma qdistrib_r : forall p q r, qmult (qplus p q) r = qplus (qmult p r) (qmult q r). |
| 72 | +Proof. destruct p, q, r; reflexivity. Qed. |
| 73 | + |
| 74 | +(* ── the usage order 0 ≤ 1 ≤ ω ───────────────────────────────────────── *) |
| 75 | + |
| 76 | +Definition rank (q : quant) : nat := |
| 77 | + match q with Zero => 0 | One => 1 | Omega => 2 end. |
| 78 | +Definition qle (p q : quant) : Prop := rank p <= rank q. |
| 79 | + |
| 80 | +Lemma qle_refl : forall q, qle q q. Proof. intro; apply Nat.le_refl. Qed. |
| 81 | +Lemma qle_trans : forall p q r, qle p q -> qle q r -> qle p r. |
| 82 | +Proof. unfold qle; intros p q r H1 H2; eapply Nat.le_trans; eauto. Qed. |
| 83 | +Lemma qle_zero_min : forall q, qle Zero q. Proof. intro q; unfold qle; apply Nat.le_0_l. Qed. |
| 84 | +Lemma qle_omega_max : forall q, qle q Omega. Proof. destruct q; unfold qle; simpl; lia. Qed. |
| 85 | + |
| 86 | +(* ── the affine facts ──────────────────────────────────────────────────── *) |
| 87 | + |
| 88 | +(* Using a linear (1) value twice overflows to ω — i.e. exceeds the affine |
| 89 | + bound `≤ 1`. This is the algebraic heart of "a linear value is used once". *) |
| 90 | +Lemma linear_used_twice : qplus One One = Omega. Proof. reflexivity. Qed. |
| 91 | +Lemma affine_bound_exceeded : ~ qle (qplus One One) One. |
| 92 | +Proof. unfold qle; rewrite linear_used_twice; simpl; lia. Qed. |
| 93 | + |
| 94 | +(* Erased (0) variables contribute nothing and absorb under scaling. *) |
| 95 | +Lemma erased_scales_away : forall q, qmult Zero q = Zero. Proof. reflexivity. Qed. |
| 96 | + |
| 97 | +(* ── bridge: occurrence counts abstract to quantities ──────────────────── *) |
| 98 | + |
| 99 | +Definition qof (n : nat) : quant := |
| 100 | + match n with 0 => Zero | 1 => One | _ => Omega end. |
| 101 | + |
| 102 | +(* `qof` is a semiring homomorphism on addition: occurrences add under qplus. |
| 103 | + So a variable used m times in `f` and n times in `a` is used (m+n) times in |
| 104 | + `f a`, abstracting to qplus — and if both are 1, the total is ω. *) |
| 105 | +Theorem qof_plus : forall m n, qof (m + n) = qplus (qof m) (qof n). |
| 106 | +Proof. intros m n; destruct m as [| [| m]]; destruct n as [| [| n]]; reflexivity. Qed. |
| 107 | + |
| 108 | +Corollary qof_linear_twice : qof 1 = One /\ qof (1 + 1) = Omega. |
| 109 | +Proof. split; reflexivity. Qed. |
0 commit comments