Skip to content

Commit afa0e29

Browse files
claudehyperpolymath
authored andcommitted
proof(solo-core): multiplicative product (X) (TTensor + let-pair) — F1.4 phase 3b
Completes the product redesign: adds the genuine multiplicative product `TTensor` (a (X) b) alongside the additive `TWith` (a & b) from phase 3a. Where `&` shares usage and projects one component, `(X)` SPLITS usage at introduction (both halves paid for separately) and its eliminator `LetPair` (let (x,y) = e1 in e2) delivers BOTH components: the body binds two variables (x:a at de Bruijn index 1, y:b at index 0), each used linearly. * Syntax.v TTensor type; Tensor / LetPair terms; shift & subst_at cases (LetPair body cutoff/index += 2); new `subst2` two-variable substitution (subst0 . subst0, correct for the closed values the reduction rule plugs in). * Typing.v T_Tensor (uadd D1 D2, split); T_LetPair (body in TSnoc (TSnoc G a) b under USnoc (USnoc D2 One) One). * Soundness.v VTensor value; S_Tensor1/2 congruence; S_LetPair computation (-> subst2 v1 v2 body); S_LetPair1 congruence; canon_tensor; the four existing canonical forms extended to the new 7th value constructor; progress Tensor + LetPair cases. Verification: full chain compiles under Coq 8.18; `progress` over the full 15-constructor term language remains "Closed under the global context" (zero axioms, zero admits). NOTE: Idris twin + Rust checker still to gain the &/(X) split (phases 5 / future). `subst2`'s general (open-term) form is a phase-4 concern; the operational rule only ever substitutes closed values.
1 parent d7036ae commit afa0e29

3 files changed

Lines changed: 97 additions & 9 deletions

File tree

proofs/verification/coq/solo-core/Soundness.v

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ Inductive value : tm -> Prop :=
4040
| VInr : forall a t, value t -> value (Inr a t)
4141
(* an echo with a fully-evaluated residue is a value; [Weaken] is
4242
not (it is the elimination that drives the linear->affine step) *)
43-
| VEcho : forall m a b t, value t -> value (MkEcho m a b t).
43+
| VEcho : forall m a b t, value t -> value (MkEcho m a b t)
44+
(* a multiplicative pair is a value once both components are *)
45+
| VTensor : forall t1 t2, value t1 -> value t2 -> value (Tensor t1 t2).
4446

4547
(** * Small-step reduction — call-by-value, left-to-right (F1.1).
4648
@@ -63,6 +65,9 @@ Inductive step : tm -> tm -> Prop :=
6365
value v -> step (Case (Inr a v) tL tR) (subst0 v tR)
6466
| S_Let : forall q v t2,
6567
value v -> step (Let q v t2) (subst0 v t2)
68+
| S_LetPair : forall v1 v2 body,
69+
value v1 -> value v2 ->
70+
step (LetPair (Tensor v1 v2) body) (subst2 v1 v2 body)
6671
(* --- congruence (left-to-right, CBV) --- *)
6772
| S_App1 : forall t1 t1' t2,
6873
step t1 t1' -> step (App t1 t2) (App t1' t2)
@@ -84,6 +89,12 @@ Inductive step : tm -> tm -> Prop :=
8489
step t t' -> step (Case t tL tR) (Case t' tL tR)
8590
| S_Let1 : forall q t1 t1' t2,
8691
step t1 t1' -> step (Let q t1 t2) (Let q t1' t2)
92+
| S_Tensor1 : forall t1 t1' t2,
93+
step t1 t1' -> step (Tensor t1 t2) (Tensor t1' t2)
94+
| S_Tensor2 : forall v1 t2 t2',
95+
value v1 -> step t2 t2' -> step (Tensor v1 t2) (Tensor v1 t2')
96+
| S_LetPair1 : forall t1 t1' t2,
97+
step t1 t1' -> step (LetPair t1 t2) (LetPair t1' t2)
8798
(* echo residue: evaluate inside, and the one-way linear->affine
8899
weakening fires once the residue is a value (EchoLinear.weaken). *)
89100
| S_Echo1 : forall m a b t t',
@@ -155,13 +166,14 @@ Lemma canon_arr : forall q a b v,
155166
Proof.
156167
intros q a b v Hv Ht.
157168
destruct Hv as [ | q0 a0 tb | u1 u2 Hu1 Hu2 | b0 u0 Hu0 | a0 u0 Hu0
158-
| m0 ae be ue Hue ].
169+
| m0 ae be ue Hue | w1 w2 Hw1 Hw2 ].
159170
- inversion Ht.
160171
- exists q0, a0, tb. reflexivity.
161172
- inversion Ht.
162173
- inversion Ht.
163174
- inversion Ht.
164175
- inversion Ht.
176+
- inversion Ht.
165177
Qed.
166178

167179
Lemma canon_with : forall a b v,
@@ -170,13 +182,14 @@ Lemma canon_with : forall a b v,
170182
Proof.
171183
intros a b v Hv Ht.
172184
destruct Hv as [ | q0 a0 tb | u1 u2 Hu1 Hu2 | b0 u0 Hu0 | a0 u0 Hu0
173-
| m0 ae be ue Hue ].
185+
| m0 ae be ue Hue | w1 w2 Hw1 Hw2 ].
174186
- inversion Ht.
175187
- inversion Ht.
176188
- exists u1, u2. split; [reflexivity | split; assumption].
177189
- inversion Ht.
178190
- inversion Ht.
179191
- inversion Ht.
192+
- inversion Ht.
180193
Qed.
181194

182195
Lemma canon_sum : forall a b v,
@@ -186,13 +199,14 @@ Lemma canon_sum : forall a b v,
186199
Proof.
187200
intros a b v Hv Ht.
188201
destruct Hv as [ | q0 a0 tb | u1 u2 Hu1 Hu2 | b0 u0 Hu0 | a0 u0 Hu0
189-
| m0 ae be ue Hue ].
202+
| m0 ae be ue Hue | w1 w2 Hw1 Hw2 ].
190203
- inversion Ht.
191204
- inversion Ht.
192205
- inversion Ht.
193206
- left. exists b0, u0. split; [reflexivity | assumption].
194207
- right. exists a0, u0. split; [reflexivity | assumption].
195208
- inversion Ht.
209+
- inversion Ht.
196210
Qed.
197211

198212
(** Canonical form for echoes: a closed value of echo type is an
@@ -204,13 +218,33 @@ Lemma canon_echo : forall m a b v,
204218
Proof.
205219
intros m a b v Hv Ht.
206220
destruct Hv as [ | q0 a0 tb | u1 u2 Hu1 Hu2 | b0 u0 Hu0 | a0 u0 Hu0
207-
| m0 ae be ue Hue ].
221+
| m0 ae be ue Hue | w1 w2 Hw1 Hw2 ].
208222
- inversion Ht.
209223
- inversion Ht.
210224
- inversion Ht.
211225
- inversion Ht.
212226
- inversion Ht.
213227
- inversion Ht; subst. exists ue. split; [reflexivity | assumption].
228+
- inversion Ht.
229+
Qed.
230+
231+
(** Canonical form for tensors: a closed value of multiplicative-product
232+
type is a [Tensor] of two values. Drives the [LetPair] case of
233+
progress. *)
234+
Lemma canon_tensor : forall a b v,
235+
value v -> has_type TEmpty UEmpty v (TTensor a b) ->
236+
exists v1 v2, v = Tensor v1 v2 /\ value v1 /\ value v2.
237+
Proof.
238+
intros a b v Hv Ht.
239+
destruct Hv as [ | q0 a0 tb | u1 u2 Hu1 Hu2 | b0 u0 Hu0 | a0 u0 Hu0
240+
| m0 ae be ue Hue | w1 w2 Hw1 Hw2 ].
241+
- inversion Ht.
242+
- inversion Ht.
243+
- inversion Ht.
244+
- inversion Ht.
245+
- inversion Ht.
246+
- inversion Ht.
247+
- exists w1, w2. split; [reflexivity | split; assumption].
214248
Qed.
215249

216250
(** ** Progress. *)
@@ -226,6 +260,8 @@ Proof.
226260
| t1 IHt1 t2 IHt2 (* With *)
227261
| t1 IHt1 (* Fst *)
228262
| t1 IHt1 (* Snd *)
263+
| t1 IHt1 t2 IHt2 (* Tensor *)
264+
| t1 IHt1 t2 IHt2 (* LetPair *)
229265
| bAnn t1 IHt1 (* Inl *)
230266
| aAnn t1 IHt1 (* Inr *)
231267
| t1 IHt1 tL IHtL tR IHtR (* Case *)
@@ -288,6 +324,27 @@ Proof.
288324
| right; exists (Snd t1'); apply S_Snd1; exact Hs ]
289325
end.
290326

327+
- (* Tensor t1 t2 : multiplicative pair — a value once both components are *)
328+
inversion Ht; subst; empty_uvec.
329+
match goal with HT1 : has_type TEmpty UEmpty t1 _ |- _ =>
330+
match goal with HT2 : has_type TEmpty UEmpty t2 _ |- _ =>
331+
destruct (IHt1 _ HT1) as [Hv1 | [t1' Hs1]];
332+
[ destruct (IHt2 _ HT2) as [Hv2 | [t2' Hs2]];
333+
[ left; apply VTensor; assumption
334+
| right; exists (Tensor t1 t2'); apply S_Tensor2; [exact Hv1 | exact Hs2] ]
335+
| right; exists (Tensor t1' t2); apply S_Tensor1; exact Hs1 ]
336+
end
337+
end.
338+
339+
- (* LetPair t1 t2 : steps once the scrutinee is a Tensor value *)
340+
inversion Ht; subst; empty_uvec.
341+
match goal with HT : has_type TEmpty UEmpty t1 (TTensor _ _) |- _ =>
342+
destruct (IHt1 _ HT) as [Hv | [t1' Hs]];
343+
[ destruct (canon_tensor _ _ _ Hv HT) as [v1 [v2 [Heqv [Hv1 Hv2]]]]; subst t1;
344+
right; exists (subst2 v1 v2 t2); apply S_LetPair; [exact Hv1 | exact Hv2]
345+
| right; exists (LetPair t1' t2); apply S_LetPair1; exact Hs ]
346+
end.
347+
291348
- (* Inl bAnn t1 *)
292349
inversion Ht; subst; empty_uvec.
293350
match goal with HT : has_type TEmpty UEmpty t1 _ |- _ =>

proofs/verification/coq/solo-core/Syntax.v

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ Require Import EchoMode.
1717

1818
Inductive ty : Type :=
1919
| TUnit : ty
20-
| TWith : ty -> ty -> ty (* additive product a & b (shared usage,
21-
projected by Fst/Snd). The multiplicative
22-
product a (X) b is deferred to a
23-
follow-up (TTensor + let-pair). *)
20+
| TWith : ty -> ty -> ty (* additive product a & b
21+
(shared usage, projected by Fst/Snd) *)
22+
| TTensor : ty -> ty -> ty (* multiplicative product a (X) b
23+
(split usage, eliminated by let-pair) *)
2424
| TSum : ty -> ty -> ty
2525
| TArr : Q -> ty -> ty -> ty (* (q x : a) -> b *)
2626
| TEcho : Mode -> ty -> ty -> ty. (* echo residue: [m] Echo<a => b> *)
@@ -35,6 +35,8 @@ Inductive tm : Type :=
3535
| With : tm -> tm -> tm (* additive pair <t1, t2> : a & b *)
3636
| Fst : tm -> tm
3737
| Snd : tm -> tm
38+
| Tensor : tm -> tm -> tm (* multiplicative pair (t1, t2) : a (X) b *)
39+
| LetPair : tm -> tm -> tm (* let (x, y) = e1 in e2 (e2 binds 2 vars) *)
3840
| Inl : ty -> tm -> tm (* annotation = the other summand *)
3941
| Inr : ty -> tm -> tm
4042
| Case : tm -> tm -> tm -> tm (* scrutinee, left (binds 1), right (binds 1) *)
@@ -71,6 +73,8 @@ Fixpoint shift (c : nat) (t : tm) : tm :=
7173
| With t1 t2 => With (shift c t1) (shift c t2)
7274
| Fst t1 => Fst (shift c t1)
7375
| Snd t1 => Snd (shift c t1)
76+
| Tensor t1 t2 => Tensor (shift c t1) (shift c t2)
77+
| LetPair t1 t2 => LetPair (shift c t1) (shift (S (S c)) t2)
7478
| Inl b t1 => Inl b (shift c t1)
7579
| Inr a t1 => Inr a (shift c t1)
7680
| Case t1 tL tR => Case (shift c t1) (shift (S c) tL) (shift (S c) tR)
@@ -97,6 +101,9 @@ Fixpoint subst_at (j : nat) (u : tm) (t : tm) : tm :=
97101
| With t1 t2 => With (subst_at j u t1) (subst_at j u t2)
98102
| Fst t1 => Fst (subst_at j u t1)
99103
| Snd t1 => Snd (subst_at j u t1)
104+
| Tensor t1 t2 => Tensor (subst_at j u t1) (subst_at j u t2)
105+
| LetPair t1 t2 =>
106+
LetPair (subst_at j u t1) (subst_at (S (S j)) (shift 0 (shift 0 u)) t2)
100107
| Inl b t1 => Inl b (subst_at j u t1)
101108
| Inr a t1 => Inr a (subst_at j u t1)
102109
| Case t1 tL tR =>
@@ -111,3 +118,10 @@ Fixpoint subst_at (j : nat) (u : tm) (t : tm) : tm :=
111118
(** Single-variable substitution for index 0 — the [(\x.t) v -> t[v/x]]
112119
workhorse of the reduction rules. *)
113120
Definition subst0 (u : tm) (t : tm) : tm := subst_at 0 u t.
121+
122+
(** Two-variable substitution for the let-pair eliminator: replace de
123+
Bruijn index 1 by [u1] and index 0 by [u2]. For CLOSED [u1] [u2]
124+
(the operational use — both are values), the two sequential single
125+
substitutions suffice: substituting index 0 first collapses the
126+
former index 1 down to index 0 for the second pass. *)
127+
Definition subst2 (u1 u2 : tm) (t : tm) : tm := subst0 u1 (subst0 u2 t).

proofs/verification/coq/solo-core/Typing.v

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,23 @@ Inductive has_type : tctx -> uvec -> tm -> ty -> Prop :=
8383
has_type G D t (TWith a b) ->
8484
has_type G D (Snd t) b
8585

86+
(* Multiplicative product a (X) b (the genuine tensor). Introduction
87+
SPLITS usage (uadd D1 D2): both halves are paid for separately,
88+
because elimination delivers BOTH components. Eliminated by LetPair
89+
(let (x,y) = e1 in e2): the body e2 binds two variables — x:a at de
90+
Bruijn index 1, y:b at index 0 — each used linearly (One). *)
91+
| T_Tensor : forall G D D1 D2 a b t1 t2,
92+
has_type G D1 t1 a ->
93+
has_type G D2 t2 b ->
94+
uadd D1 D2 = Some D ->
95+
has_type G D (Tensor t1 t2) (TTensor a b)
96+
97+
| T_LetPair : forall G D D1 D2 a b c t1 t2,
98+
has_type G D1 t1 (TTensor a b) ->
99+
has_type (TSnoc (TSnoc G a) b) (USnoc (USnoc D2 One) One) t2 c ->
100+
uadd D1 D2 = Some D ->
101+
has_type G D (LetPair t1 t2) c
102+
86103
| T_Inl : forall G D a b t,
87104
has_type G D t a ->
88105
has_type G D (Inl b t) (TSum a b)

0 commit comments

Comments
 (0)