2088 lines
80 KiB
Coq
2088 lines
80 KiB
Coq
Require Import Autosubst2.core Autosubst2.unscoped Autosubst2.syntax
|
||
common typing preservation admissible fp_red structural soundness.
|
||
From Hammer Require Import Tactics.
|
||
Require Import ssreflect ssrbool.
|
||
Require Import Psatz.
|
||
From stdpp Require Import relations (rtc(..), nsteps(..)).
|
||
Require Import Coq.Logic.FunctionalExtensionality.
|
||
Require Import Cdcl.Itauto.
|
||
|
||
Module HRed.
|
||
Lemma ToRRed (a b : PTm) : HRed.R a b -> RRed.R a b.
|
||
Proof. induction 1; hauto lq:on ctrs:RRed.R. Qed.
|
||
|
||
Lemma preservation Γ (a b A : PTm) : Γ ⊢ a ∈ A -> HRed.R a b -> Γ ⊢ b ∈ A.
|
||
Proof.
|
||
sfirstorder use:subject_reduction, ToRRed.
|
||
Qed.
|
||
|
||
Lemma ToEq Γ (a b : PTm ) A : Γ ⊢ a ∈ A -> HRed.R a b -> Γ ⊢ a ≡ b ∈ A.
|
||
Proof. sfirstorder use:ToRRed, RRed_Eq. Qed.
|
||
|
||
End HRed.
|
||
|
||
Module HReds.
|
||
Lemma preservation Γ (a b A : PTm) : Γ ⊢ a ∈ A -> rtc HRed.R a b -> Γ ⊢ b ∈ A.
|
||
Proof. induction 2; sfirstorder use:HRed.preservation. Qed.
|
||
|
||
Lemma ToEq Γ (a b : PTm) A : Γ ⊢ a ∈ A -> rtc HRed.R a b -> Γ ⊢ a ≡ b ∈ A.
|
||
Proof.
|
||
induction 2; sauto lq:on use:HRed.ToEq, E_Transitive, HRed.preservation.
|
||
Qed.
|
||
End HReds.
|
||
|
||
Lemma T_Conv_E Γ (a : PTm) A B i :
|
||
Γ ⊢ a ∈ A ->
|
||
Γ ⊢ A ≡ B ∈ PUniv i \/ Γ ⊢ B ≡ A ∈ PUniv i ->
|
||
Γ ⊢ a ∈ B.
|
||
Proof. qauto use:T_Conv, Su_Eq, E_Symmetric. Qed.
|
||
|
||
Lemma E_Conv_E Γ (a b : PTm) A B i :
|
||
Γ ⊢ a ≡ b ∈ A ->
|
||
Γ ⊢ A ≡ B ∈ PUniv i \/ Γ ⊢ B ≡ A ∈ PUniv i ->
|
||
Γ ⊢ a ≡ b ∈ B.
|
||
Proof. qauto use:E_Conv, Su_Eq, E_Symmetric. Qed.
|
||
|
||
Lemma lored_embed Γ (a b : PTm) A :
|
||
Γ ⊢ a ∈ A -> LoRed.R a b -> Γ ⊢ a ≡ b ∈ A.
|
||
Proof. sfirstorder use:LoRed.ToRRed, RRed_Eq. Qed.
|
||
|
||
Lemma loreds_embed Γ (a b : PTm ) A :
|
||
Γ ⊢ a ∈ A -> rtc LoRed.R a b -> Γ ⊢ a ≡ b ∈ A.
|
||
Proof.
|
||
move => + h. move : Γ A.
|
||
elim : a b /h.
|
||
- sfirstorder use:E_Refl.
|
||
- move => a b c ha hb ih Γ A hA.
|
||
have ? : Γ ⊢ a ≡ b ∈ A by sfirstorder use:lored_embed.
|
||
have ? : Γ ⊢ b ∈ A by hauto l:on use:regularity.
|
||
hauto lq:on ctrs:Eq.
|
||
Qed.
|
||
|
||
Lemma Zero_Inv Γ U :
|
||
Γ ⊢ PZero ∈ U ->
|
||
Γ ⊢ PNat ≲ U.
|
||
Proof.
|
||
move E : PZero => u hu.
|
||
move : E.
|
||
elim : Γ u U /hu=>//=.
|
||
by eauto using Su_Eq, E_Refl, T_Nat'.
|
||
hauto lq:on rew:off ctrs:LEq.
|
||
Qed.
|
||
|
||
Lemma Sub_Bind_InvR Γ p (A : PTm ) B C :
|
||
Γ ⊢ PBind p A B ≲ C ->
|
||
exists i A0 B0, Γ ⊢ C ≡ PBind p A0 B0 ∈ PUniv i.
|
||
Proof.
|
||
move => /[dup] h.
|
||
move /synsub_to_usub.
|
||
move => [h0 [h1 h2]].
|
||
move /LoReds.FromSN : h1.
|
||
move => [C' [hC0 hC1]].
|
||
have [i hC] : exists i, Γ ⊢ C ∈ PUniv i by qauto l:on use:regularity.
|
||
have hE : Γ ⊢ C ≡ C' ∈ PUniv i by sfirstorder use:loreds_embed.
|
||
have : Γ ⊢ PBind p A B ≲ C' by eauto using Su_Transitive, Su_Eq.
|
||
move : hE hC1. clear.
|
||
case : C' => //=.
|
||
- move => k _ _ /synsub_to_usub.
|
||
clear. move => [_ [_ h]]. exfalso.
|
||
rewrite /Sub.R in h.
|
||
move : h => [c][d][+ []].
|
||
move /REReds.bind_inv => ?.
|
||
move /REReds.var_inv => ?.
|
||
sauto lq:on.
|
||
- move => p0 h. exfalso.
|
||
have {h} : Γ ⊢ PAbs p0 ∈ PUniv i by hauto l:on use:regularity.
|
||
move /Abs_Inv => [A0][B0][_]/synsub_to_usub.
|
||
hauto l:on use:Sub.bind_univ_noconf.
|
||
- move => u v hC /andP [h0 h1] /synsub_to_usub ?.
|
||
exfalso.
|
||
suff : SNe (PApp u v) by hauto l:on use:Sub.bind_sne_noconf.
|
||
eapply ne_nf_embed => //=. itauto.
|
||
- move => p0 p1 hC h ?. exfalso.
|
||
have {hC} : Γ ⊢ PPair p0 p1 ∈ PUniv i by hauto l:on use:regularity.
|
||
hauto lq:on use:Sub.bind_univ_noconf, synsub_to_usub, Pair_Inv.
|
||
- move => p0 p1 _ + /synsub_to_usub.
|
||
hauto lq:on use:Sub.bind_sne_noconf, ne_nf_embed.
|
||
- move => b p0 p1 h0 h1 /[dup] h2 /synsub_to_usub *.
|
||
have ? : b = p by hauto l:on use:Sub.bind_inj. subst.
|
||
eauto.
|
||
- hauto lq:on use:synsub_to_usub, Sub.bind_univ_noconf.
|
||
- move => _ _ /synsub_to_usub [_ [_ h]]. exfalso.
|
||
apply Sub.nat_bind_noconf in h => //=.
|
||
- move => h.
|
||
have {}h : Γ ⊢ PZero ∈ PUniv i by hauto l:on use:regularity.
|
||
exfalso. move : h. clear.
|
||
move /Zero_Inv /synsub_to_usub.
|
||
hauto l:on use:Sub.univ_nat_noconf.
|
||
- move => a h.
|
||
have {}h : Γ ⊢ PSuc a ∈ PUniv i by hauto l:on use:regularity.
|
||
exfalso. move /Suc_Inv : h => [_ /synsub_to_usub].
|
||
hauto lq:on use:Sub.univ_nat_noconf.
|
||
- move => P0 a0 b0 c0 h0 h1 /synsub_to_usub [_ [_ h2]].
|
||
set u := PInd _ _ _ _ in h0.
|
||
have hne : SNe u by sfirstorder use:ne_nf_embed.
|
||
exfalso. move : h2 hne. hauto l:on use:Sub.bind_sne_noconf.
|
||
Qed.
|
||
|
||
Lemma Sub_Univ_InvR Γ i C :
|
||
Γ ⊢ PUniv i ≲ C ->
|
||
exists j k, Γ ⊢ C ≡ PUniv j ∈ PUniv k.
|
||
Proof.
|
||
move => /[dup] h.
|
||
move /synsub_to_usub.
|
||
move => [h0 [h1 h2]].
|
||
move /LoReds.FromSN : h1.
|
||
move => [C' [hC0 hC1]].
|
||
have [j hC] : exists i, Γ ⊢ C ∈ PUniv i by qauto l:on use:regularity.
|
||
have hE : Γ ⊢ C ≡ C' ∈ PUniv j by sfirstorder use:loreds_embed.
|
||
have : Γ ⊢ PUniv i ≲ C' by eauto using Su_Transitive, Su_Eq.
|
||
move : hE hC1. clear.
|
||
case : C' => //=.
|
||
- move => f => _ _ /synsub_to_usub.
|
||
move => [_ [_]].
|
||
move => [v0][v1][/REReds.univ_inv + [/REReds.var_inv ]].
|
||
hauto lq:on inv:Sub1.R.
|
||
- move => p hC.
|
||
have {hC} : Γ ⊢ PAbs p ∈ PUniv j by hauto l:on use:regularity.
|
||
hauto lq:on rew:off use:Abs_Inv, synsub_to_usub,
|
||
Sub.bind_univ_noconf.
|
||
- hauto q:on use:synsub_to_usub, Sub.univ_sne_noconf, ne_nf_embed.
|
||
- move => a b hC.
|
||
have {hC} : Γ ⊢ PPair a b ∈ PUniv j by hauto l:on use:regularity.
|
||
hauto lq:on rew:off use:Pair_Inv, synsub_to_usub,
|
||
Sub.bind_univ_noconf.
|
||
- hauto q:on use:synsub_to_usub, Sub.univ_sne_noconf, ne_nf_embed.
|
||
- hauto lq:on use:synsub_to_usub, Sub.univ_bind_noconf.
|
||
- sfirstorder.
|
||
- hauto q:on use:synsub_to_usub, Sub.nat_univ_noconf.
|
||
- move => h.
|
||
have {}h : Γ ⊢ PZero ∈ PUniv j by hauto l:on use:regularity.
|
||
exfalso. move : h. clear.
|
||
move /Zero_Inv /synsub_to_usub.
|
||
hauto l:on use:Sub.univ_nat_noconf.
|
||
- move => a h.
|
||
have {}h : Γ ⊢ PSuc a ∈ PUniv j by hauto l:on use:regularity.
|
||
exfalso. move /Suc_Inv : h => [_ /synsub_to_usub].
|
||
hauto lq:on use:Sub.univ_nat_noconf.
|
||
- move => P0 a0 b0 c0 h0 h1 /synsub_to_usub [_ [_ h2]].
|
||
set u := PInd _ _ _ _ in h0.
|
||
have hne : SNe u by sfirstorder use:ne_nf_embed.
|
||
exfalso. move : h2 hne. hauto l:on use:Sub.univ_sne_noconf.
|
||
Qed.
|
||
|
||
Lemma Sub_Bind_InvL Γ p (A : PTm) B C :
|
||
Γ ⊢ C ≲ PBind p A B ->
|
||
exists i A0 B0, Γ ⊢ PBind p A0 B0 ≡ C ∈ PUniv i.
|
||
Proof.
|
||
move => /[dup] h.
|
||
move /synsub_to_usub.
|
||
move => [h0 [h1 h2]].
|
||
move /LoReds.FromSN : h0.
|
||
move => [C' [hC0 hC1]].
|
||
have [i hC] : exists i, Γ ⊢ C ∈ PUniv i by qauto l:on use:regularity.
|
||
have hE : Γ ⊢ C ≡ C' ∈ PUniv i by sfirstorder use:loreds_embed.
|
||
have : Γ ⊢ C' ≲ PBind p A B by eauto using Su_Transitive, Su_Eq, E_Symmetric.
|
||
move : hE hC1. clear.
|
||
case : C' => //=.
|
||
- move => k _ _ /synsub_to_usub.
|
||
clear. move => [_ [_ h]]. exfalso.
|
||
rewrite /Sub.R in h.
|
||
move : h => [c][d][+ []].
|
||
move /REReds.var_inv => ?.
|
||
move /REReds.bind_inv => ?.
|
||
hauto lq:on inv:Sub1.R.
|
||
- move => p0 h. exfalso.
|
||
have {h} : Γ ⊢ PAbs p0 ∈ PUniv i by hauto l:on use:regularity.
|
||
move /Abs_Inv => [A0][B0][_]/synsub_to_usub.
|
||
hauto l:on use:Sub.bind_univ_noconf.
|
||
- move => u v hC /andP [h0 h1] /synsub_to_usub ?.
|
||
exfalso.
|
||
suff : SNe (PApp u v) by hauto l:on use:Sub.sne_bind_noconf.
|
||
eapply ne_nf_embed => //=. itauto.
|
||
- move => p0 p1 hC h ?. exfalso.
|
||
have {hC} : Γ ⊢ PPair p0 p1 ∈ PUniv i by hauto l:on use:regularity.
|
||
hauto lq:on use:Sub.bind_univ_noconf, synsub_to_usub, Pair_Inv.
|
||
- move => p0 p1 _ + /synsub_to_usub.
|
||
hauto lq:on use:Sub.sne_bind_noconf, ne_nf_embed.
|
||
- move => b p0 p1 h0 h1 /[dup] h2 /synsub_to_usub *.
|
||
have ? : b = p by hauto l:on use:Sub.bind_inj. subst.
|
||
eauto using E_Symmetric.
|
||
- hauto lq:on use:synsub_to_usub, Sub.univ_bind_noconf.
|
||
- move => _ _ /synsub_to_usub [_ [_ h]]. exfalso.
|
||
apply Sub.bind_nat_noconf in h => //=.
|
||
- move => h.
|
||
have {}h : Γ ⊢ PZero ∈ PUniv i by hauto l:on use:regularity.
|
||
exfalso. move : h. clear.
|
||
move /Zero_Inv /synsub_to_usub.
|
||
hauto l:on use:Sub.univ_nat_noconf.
|
||
- move => a h.
|
||
have {}h : Γ ⊢ PSuc a ∈ PUniv i by hauto l:on use:regularity.
|
||
exfalso. move /Suc_Inv : h => [_ /synsub_to_usub].
|
||
hauto lq:on use:Sub.univ_nat_noconf.
|
||
- move => P0 a0 b0 c0 h0 h1 /synsub_to_usub [_ [_ h2]].
|
||
set u := PInd _ _ _ _ in h0.
|
||
have hne : SNe u by sfirstorder use:ne_nf_embed.
|
||
exfalso. move : h2 hne. subst u.
|
||
hauto l:on use:Sub.sne_bind_noconf.
|
||
Qed.
|
||
|
||
Lemma T_Abs_Inv Γ (a0 a1 : PTm) U :
|
||
Γ ⊢ PAbs a0 ∈ U ->
|
||
Γ ⊢ PAbs a1 ∈ U ->
|
||
exists Δ V, Δ ⊢ a0 ∈ V /\ Δ ⊢ a1 ∈ V.
|
||
Proof.
|
||
move /Abs_Inv => [A0][B0][wt0]hU0.
|
||
move /Abs_Inv => [A1][B1][wt1]hU1.
|
||
move /Sub_Bind_InvR : (hU0) => [i][A2][B2]hE.
|
||
have hSu : Γ ⊢ PBind PPi A1 B1 ≲ PBind PPi A2 B2 by eauto using Su_Eq, Su_Transitive.
|
||
have hSu' : Γ ⊢ PBind PPi A0 B0 ≲ PBind PPi A2 B2 by eauto using Su_Eq, Su_Transitive.
|
||
exists ((cons A2 Γ)), B2.
|
||
have [k ?] : exists k, Γ ⊢ A2 ∈ PUniv k by hauto lq:on use:regularity, Bind_Inv.
|
||
split.
|
||
- have /Su_Pi_Proj2_Var ? := hSu'.
|
||
have /Su_Pi_Proj1 ? := hSu'.
|
||
move /regularity_sub0 : hSu' => [j] /Bind_Inv [k0 [? ?]].
|
||
apply T_Conv with (A := B0); eauto.
|
||
apply : ctx_eq_subst_one; eauto.
|
||
- have /Su_Pi_Proj2_Var ? := hSu.
|
||
have /Su_Pi_Proj1 ? := hSu.
|
||
move /regularity_sub0 : hSu => [j] /Bind_Inv [k0 [? ?]].
|
||
apply T_Conv with (A := B1); eauto.
|
||
apply : ctx_eq_subst_one; eauto.
|
||
Qed.
|
||
|
||
Lemma T_Univ_Raise Γ (a : PTm) i j :
|
||
Γ ⊢ a ∈ PUniv i ->
|
||
i <= j ->
|
||
Γ ⊢ a ∈ PUniv j.
|
||
Proof. hauto lq:on rew:off use:T_Conv, Su_Univ, wff_mutual. Qed.
|
||
|
||
Lemma Bind_Univ_Inv Γ p (A : PTm) B i :
|
||
Γ ⊢ PBind p A B ∈ PUniv i ->
|
||
Γ ⊢ A ∈ PUniv i /\ (cons A Γ) ⊢ B ∈ PUniv i.
|
||
Proof.
|
||
move /Bind_Inv.
|
||
move => [i0][hA][hB]h.
|
||
move /synsub_to_usub : h => [_ [_ /Sub.univ_inj ? ]].
|
||
sfirstorder use:T_Univ_Raise.
|
||
Qed.
|
||
|
||
Lemma Abs_Pi_Inv Γ (a : PTm) A B :
|
||
Γ ⊢ PAbs a ∈ PBind PPi A B ->
|
||
(cons A Γ) ⊢ a ∈ B.
|
||
Proof.
|
||
move => h.
|
||
have [i hi] : exists i, Γ ⊢ PBind PPi A B ∈ PUniv i by hauto use:regularity.
|
||
have [{}i {}hi] : exists i, Γ ⊢ A ∈ PUniv i by hauto use:Bind_Inv.
|
||
apply : subject_reduction; last apply RRed.AppAbs'.
|
||
apply : T_App'; cycle 1.
|
||
apply : weakening_wt'; cycle 2. apply hi.
|
||
apply h. reflexivity. reflexivity. rewrite -/ren_PTm.
|
||
apply T_Var with (i := var_zero).
|
||
by eauto using Wff_Cons'.
|
||
apply here.
|
||
rewrite -/ren_PTm.
|
||
by asimpl; rewrite subst_scons_id.
|
||
rewrite -/ren_PTm.
|
||
by asimpl; rewrite subst_scons_id.
|
||
Qed.
|
||
|
||
Lemma Pair_Sig_Inv Γ (a b : PTm) A B :
|
||
Γ ⊢ PPair a b ∈ PBind PSig A B ->
|
||
Γ ⊢ a ∈ A /\ Γ ⊢ b ∈ subst_PTm (scons a VarPTm) B.
|
||
Proof.
|
||
move => /[dup] h0 h1.
|
||
have [i hr] : exists i, Γ ⊢ PBind PSig A B ∈ PUniv i by sfirstorder use:regularity.
|
||
move /T_Proj1 in h0.
|
||
move /T_Proj2 in h1.
|
||
split.
|
||
hauto lq:on use:subject_reduction ctrs:RRed.R.
|
||
have hE : Γ ⊢ PProj PL (PPair a b) ≡ a ∈ A by
|
||
hauto lq:on use:RRed_Eq ctrs:RRed.R.
|
||
apply : T_Conv.
|
||
move /subject_reduction : h1. apply.
|
||
apply RRed.ProjPair.
|
||
apply : bind_inst; eauto.
|
||
Qed.
|
||
|
||
|
||
(* Coquand's algorithm with subtyping *)
|
||
Reserved Notation "a ∼ b" (at level 70).
|
||
Reserved Notation "a ↔ b" (at level 70).
|
||
Reserved Notation "a ⇔ b" (at level 70).
|
||
Inductive CoqEq : PTm -> PTm -> Prop :=
|
||
| CE_ZeroZero :
|
||
PZero ↔ PZero
|
||
|
||
| CE_SucSuc a b :
|
||
a ⇔ b ->
|
||
(* ------------- *)
|
||
PSuc a ↔ PSuc b
|
||
|
||
| CE_AbsAbs a b :
|
||
a ⇔ b ->
|
||
(* --------------------- *)
|
||
PAbs a ↔ PAbs b
|
||
|
||
| CE_AbsNeu a u :
|
||
ishne u ->
|
||
a ⇔ PApp (ren_PTm shift u) (VarPTm var_zero) ->
|
||
(* --------------------- *)
|
||
PAbs a ↔ u
|
||
|
||
| CE_NeuAbs a u :
|
||
ishne u ->
|
||
PApp (ren_PTm shift u) (VarPTm var_zero) ⇔ a ->
|
||
(* --------------------- *)
|
||
u ↔ PAbs a
|
||
|
||
| CE_PairPair a0 a1 b0 b1 :
|
||
a0 ⇔ a1 ->
|
||
b0 ⇔ b1 ->
|
||
(* ---------------------------- *)
|
||
PPair a0 b0 ↔ PPair a1 b1
|
||
|
||
| CE_PairNeu a0 a1 u :
|
||
ishne u ->
|
||
a0 ⇔ PProj PL u ->
|
||
a1 ⇔ PProj PR u ->
|
||
(* ----------------------- *)
|
||
PPair a0 a1 ↔ u
|
||
|
||
| CE_NeuPair a0 a1 u :
|
||
ishne u ->
|
||
PProj PL u ⇔ a0 ->
|
||
PProj PR u ⇔ a1 ->
|
||
(* ----------------------- *)
|
||
u ↔ PPair a0 a1
|
||
|
||
| CE_UnivCong i :
|
||
(* -------------------------- *)
|
||
PUniv i ↔ PUniv i
|
||
|
||
| CE_BindCong p A0 A1 B0 B1 :
|
||
A0 ⇔ A1 ->
|
||
B0 ⇔ B1 ->
|
||
(* ---------------------------- *)
|
||
PBind p A0 B0 ↔ PBind p A1 B1
|
||
|
||
| CE_NatCong :
|
||
(* ------------------ *)
|
||
PNat ↔ PNat
|
||
|
||
| CE_NeuNeu a0 a1 :
|
||
a0 ∼ a1 ->
|
||
a0 ↔ a1
|
||
|
||
with CoqEq_Neu : PTm -> PTm -> Prop :=
|
||
| CE_VarCong i :
|
||
(* -------------------------- *)
|
||
VarPTm i ∼ VarPTm i
|
||
|
||
| CE_ProjCong p u0 u1 :
|
||
ishne u0 ->
|
||
ishne u1 ->
|
||
u0 ∼ u1 ->
|
||
(* --------------------- *)
|
||
PProj p u0 ∼ PProj p u1
|
||
|
||
| CE_AppCong u0 u1 a0 a1 :
|
||
ishne u0 ->
|
||
ishne u1 ->
|
||
u0 ∼ u1 ->
|
||
a0 ⇔ a1 ->
|
||
(* ------------------------- *)
|
||
PApp u0 a0 ∼ PApp u1 a1
|
||
|
||
| CE_IndCong P0 P1 u0 u1 b0 b1 c0 c1 :
|
||
ishne u0 ->
|
||
ishne u1 ->
|
||
P0 ⇔ P1 ->
|
||
u0 ∼ u1 ->
|
||
b0 ⇔ b1 ->
|
||
c0 ⇔ c1 ->
|
||
(* ----------------------------------- *)
|
||
PInd P0 u0 b0 c0 ∼ PInd P1 u1 b1 c1
|
||
|
||
with CoqEq_R : PTm -> PTm -> Prop :=
|
||
| CE_HRed a a' b b' :
|
||
rtc HRed.R a a' ->
|
||
rtc HRed.R b b' ->
|
||
a' ↔ b' ->
|
||
(* ----------------------- *)
|
||
a ⇔ b
|
||
where "a ↔ b" := (CoqEq a b) and "a ⇔ b" := (CoqEq_R a b) and "a ∼ b" := (CoqEq_Neu a b).
|
||
|
||
Lemma CE_HRedL (a a' b : PTm) :
|
||
HRed.R a a' ->
|
||
a' ⇔ b ->
|
||
a ⇔ b.
|
||
Proof.
|
||
hauto lq:on ctrs:rtc, CoqEq_R inv:CoqEq_R.
|
||
Qed.
|
||
|
||
Scheme
|
||
coqeq_neu_ind := Induction for CoqEq_Neu Sort Prop
|
||
with coqeq_ind := Induction for CoqEq Sort Prop
|
||
with coqeq_r_ind := Induction for CoqEq_R Sort Prop.
|
||
|
||
Combined Scheme coqeq_mutual from coqeq_neu_ind, coqeq_ind, coqeq_r_ind.
|
||
|
||
Lemma coqeq_symmetric_mutual :
|
||
(forall (a b : PTm), a ∼ b -> b ∼ a) /\
|
||
(forall (a b : PTm), a ↔ b -> b ↔ a) /\
|
||
(forall (a b : PTm), a ⇔ b -> b ⇔ a).
|
||
Proof. apply coqeq_mutual; qauto l:on ctrs:CoqEq,CoqEq_R, CoqEq_Neu. Qed.
|
||
|
||
Lemma coqeq_sound_mutual :
|
||
(forall (a b : PTm ), a ∼ b -> forall Γ A B, Γ ⊢ a ∈ A -> Γ ⊢ b ∈ B -> exists C,
|
||
Γ ⊢ C ≲ A /\ Γ ⊢ C ≲ B /\ Γ ⊢ a ≡ b ∈ C) /\
|
||
(forall (a b : PTm ), a ↔ b -> forall Γ A, Γ ⊢ a ∈ A -> Γ ⊢ b ∈ A -> Γ ⊢ a ≡ b ∈ A) /\
|
||
(forall (a b : PTm ), a ⇔ b -> forall Γ A, Γ ⊢ a ∈ A -> Γ ⊢ b ∈ A -> Γ ⊢ a ≡ b ∈ A).
|
||
Proof.
|
||
move => [:hAppL hPairL].
|
||
apply coqeq_mutual.
|
||
- move => i Γ A B hi0 hi1.
|
||
move /Var_Inv : hi0 => [hΓ [C [h00 h01]]].
|
||
move /Var_Inv : hi1 => [_ [C0 [h10 h11]]].
|
||
have ? : C0 = C by eauto using lookup_deter. subst.
|
||
exists C.
|
||
repeat split => //=.
|
||
apply E_Refl. eauto using T_Var.
|
||
- move => [] u0 u1 hu0 hu1 hu ihu Γ A B hu0' hu1'.
|
||
+ move /Proj1_Inv : hu0'.
|
||
move => [A0][B0][hu0']hu0''.
|
||
move /Proj1_Inv : hu1'.
|
||
move => [A1][B1][hu1']hu1''.
|
||
specialize ihu with (1 := hu0') (2 := hu1').
|
||
move : ihu.
|
||
move => [C][ih0][ih1]ih.
|
||
have [i[A2[B2 h2]]] : exists i A2 B2, Γ ⊢ PBind PSig A2 B2 ≡ C ∈ PUniv i by sfirstorder use:Sub_Bind_InvL.
|
||
exists A2.
|
||
have [h3 h4] : Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A0 B0 /\ Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A1 B1 by qauto l:on use:Su_Eq, Su_Transitive.
|
||
repeat split;
|
||
eauto using Su_Sig_Proj1, Su_Transitive;[idtac].
|
||
apply E_Proj1 with (B := B2); eauto using E_Conv_E.
|
||
+ move /Proj2_Inv : hu0'.
|
||
move => [A0][B0][hu0']hu0''.
|
||
move /Proj2_Inv : hu1'.
|
||
move => [A1][B1][hu1']hu1''.
|
||
specialize ihu with (1 := hu0') (2 := hu1').
|
||
move : ihu.
|
||
move => [C][ih0][ih1]ih.
|
||
have [A2 [B2 [i hi]]] : exists A2 B2 i, Γ ⊢ PBind PSig A2 B2 ≡ C ∈ PUniv i by hauto q:on use:Sub_Bind_InvL.
|
||
have [h3 h4] : Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A0 B0 /\ Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A1 B1 by qauto l:on use:Su_Eq, Su_Transitive.
|
||
have h5 : Γ ⊢ u0 ≡ u1 ∈ PBind PSig A2 B2 by eauto using E_Conv_E.
|
||
exists (subst_PTm (scons (PProj PL u0) VarPTm) B2).
|
||
have [? ?] : Γ ⊢ u0 ∈ PBind PSig A2 B2 /\ Γ ⊢ u1 ∈ PBind PSig A2 B2 by hauto l:on use:regularity.
|
||
repeat split => //=.
|
||
apply : Su_Transitive ;eauto.
|
||
apply : Su_Sig_Proj2; eauto.
|
||
apply E_Refl. eauto using T_Proj1.
|
||
apply : Su_Transitive ;eauto.
|
||
apply : Su_Sig_Proj2; eauto.
|
||
apply : E_Proj1; eauto.
|
||
apply : E_Proj2; eauto.
|
||
- move => u0 u1 a0 a1 neu0 neu1 hu ihu ha iha Γ A B wta0 wta1.
|
||
move /App_Inv : wta0 => [A0][B0][hu0][ha0]hU.
|
||
move /App_Inv : wta1 => [A1][B1][hu1][ha1]hU1.
|
||
move : ihu hu0 hu1. repeat move/[apply].
|
||
move => [C][hC0][hC1]hu01.
|
||
have [i [A2 [B2 hPi]]] : exists i A2 B2, Γ ⊢ PBind PPi A2 B2 ≡ C ∈ PUniv i by sfirstorder use:Sub_Bind_InvL.
|
||
have ? : Γ ⊢ PBind PPi A2 B2 ≲ PBind PPi A0 B0 by eauto using Su_Eq, Su_Transitive.
|
||
have h : Γ ⊢ PBind PPi A2 B2 ≲ PBind PPi A1 B1 by eauto using Su_Eq, Su_Transitive.
|
||
have ha' : Γ ⊢ a0 ≡ a1 ∈ A2 by
|
||
sauto lq:on use:Su_Transitive, Su_Pi_Proj1.
|
||
have hwf : Γ ⊢ PBind PPi A2 B2 ∈ PUniv i by hauto l:on use:regularity.
|
||
have [j hj'] : exists j,Γ ⊢ A2 ∈ PUniv j by hauto l:on use:regularity.
|
||
have ? : ⊢ Γ by sfirstorder use:wff_mutual.
|
||
exists (subst_PTm (scons a0 VarPTm) B2).
|
||
repeat split. apply : Su_Transitive; eauto.
|
||
apply : Su_Pi_Proj2'; eauto using E_Refl.
|
||
apply : Su_Transitive; eauto.
|
||
have ? : Γ ⊢ A1 ≲ A2 by eauto using Su_Pi_Proj1.
|
||
apply Su_Transitive with (B := subst_PTm (scons a1 VarPTm) B2);
|
||
first by sfirstorder use:bind_inst.
|
||
apply : Su_Pi_Proj2'; eauto using E_Refl.
|
||
apply E_App with (A := A2); eauto using E_Conv_E.
|
||
- move {hAppL hPairL} => P0 P1 u0 u1 b0 b1 c0 c1 neu0 neu1 hP ihP hu ihu hb ihb hc ihc Γ A B.
|
||
move /Ind_Inv => [i0][hP0][hu0][hb0][hc0]hSu0.
|
||
move /Ind_Inv => [i1][hP1][hu1][hb1][hc1]hSu1.
|
||
move : ihu hu0 hu1; do!move/[apply]. move => ihu.
|
||
have {}ihu : Γ ⊢ u0 ≡ u1 ∈ PNat by hauto l:on use:E_Conv.
|
||
have wfΓ : ⊢ Γ by hauto use:wff_mutual.
|
||
have wfΓ' : ⊢ (cons PNat Γ) by hauto lq:on use:Wff_Cons', T_Nat'.
|
||
move => [:sigeq].
|
||
have sigeq' : Γ ⊢ PBind PSig PNat P0 ≡ PBind PSig PNat P1 ∈ PUniv (max i0 i1).
|
||
apply E_Bind. by eauto using T_Nat, E_Refl.
|
||
abstract : sigeq. hauto lq:on use:T_Univ_Raise solve+:lia.
|
||
have sigleq : Γ ⊢ PBind PSig PNat P0 ≲ PBind PSig PNat P1.
|
||
apply Su_Sig with (i := 0)=>//. by apply T_Nat'. by eauto using Su_Eq, T_Nat', E_Refl.
|
||
apply Su_Eq with (i := max i0 i1). apply sigeq.
|
||
exists (subst_PTm (scons u0 VarPTm) P0). repeat split => //.
|
||
suff : Γ ⊢ subst_PTm (scons u0 VarPTm) P0 ≲ subst_PTm (scons u1 VarPTm) P1 by eauto using Su_Transitive.
|
||
by eauto using Su_Sig_Proj2.
|
||
apply E_IndCong with (i := max i0 i1); eauto. move :sigeq; clear; hauto q:on use:regularity.
|
||
apply ihb; eauto. apply : T_Conv; eauto. eapply morphing. apply : Su_Eq. apply E_Symmetric. apply sigeq.
|
||
done. apply morphing_ext. apply morphing_id. done. by apply T_Zero.
|
||
apply ihc; eauto.
|
||
eapply T_Conv; eauto.
|
||
eapply ctx_eq_subst_one; eauto. apply : Su_Eq; apply sigeq.
|
||
eapply weakening_su; eauto.
|
||
eapply morphing; eauto. apply : Su_Eq. apply E_Symmetric. apply sigeq.
|
||
apply morphing_ext. set x := {1}(funcomp _ shift).
|
||
have -> : x = funcomp (ren_PTm shift) VarPTm by asimpl.
|
||
apply : morphing_ren; eauto. apply : renaming_shift; eauto. by apply morphing_id.
|
||
apply T_Suc. apply T_Var; eauto using here.
|
||
- hauto lq:on use:Zero_Inv db:wt.
|
||
- hauto lq:on use:Suc_Inv db:wt.
|
||
- move => a b ha iha Γ A h0 h1.
|
||
move /Abs_Inv : h0 => [A0][B0][h0]h0'.
|
||
move /Abs_Inv : h1 => [A1][B1][h1]h1'.
|
||
have [i [A2 [B2 h]]] : exists i A2 B2, Γ ⊢ A ≡ PBind PPi A2 B2 ∈ PUniv i by hauto l:on use:Sub_Bind_InvR.
|
||
have hp0 : Γ ⊢ PBind PPi A0 B0 ≲ PBind PPi A2 B2 by eauto using Su_Transitive, Su_Eq.
|
||
have hp1 : Γ ⊢ PBind PPi A1 B1 ≲ PBind PPi A2 B2 by eauto using Su_Transitive, Su_Eq.
|
||
have [j ?] : exists j, Γ ⊢ A0 ∈ PUniv j by eapply wff_mutual in h0; inversion h0; subst; eauto.
|
||
have [k ?] : exists j, Γ ⊢ A1 ∈ PUniv j by eapply wff_mutual in h1; inversion h1; subst; eauto.
|
||
have [l ?] : exists j, Γ ⊢ A2 ∈ PUniv j by hauto lq:on rew:off use:regularity, Bind_Inv.
|
||
have [h2 h3] : Γ ⊢ A2 ≲ A0 /\ Γ ⊢ A2 ≲ A1 by hauto l:on use:Su_Pi_Proj1.
|
||
apply E_Conv with (A := PBind PPi A2 B2); cycle 1.
|
||
eauto using E_Symmetric, Su_Eq.
|
||
apply : E_Abs; eauto. hauto l:on use:regularity.
|
||
apply iha.
|
||
move /Su_Pi_Proj2_Var in hp0.
|
||
apply : T_Conv; eauto.
|
||
eapply ctx_eq_subst_one with (A0 := A0); eauto.
|
||
move /Su_Pi_Proj2_Var in hp1.
|
||
apply : T_Conv; eauto.
|
||
eapply ctx_eq_subst_one with (A0 := A1); eauto.
|
||
- abstract : hAppL.
|
||
move => a u hneu ha iha Γ A wta wtu.
|
||
move /Abs_Inv : wta => [A0][B0][wta]hPi.
|
||
have [i [A2 [B2 h]]] : exists i A2 B2, Γ ⊢ A ≡ PBind PPi A2 B2 ∈ PUniv i by hauto l:on use:Sub_Bind_InvR.
|
||
have hPi'' : Γ ⊢ PBind PPi A2 B2 ≲ A by eauto using Su_Eq, Su_Transitive, E_Symmetric.
|
||
have [j0 ?] : exists j0, Γ ⊢ A0 ∈ PUniv j0 by move /regularity_sub0 in hPi; hauto lq:on use:Bind_Inv.
|
||
have [j2 ?] : exists j0, Γ ⊢ A2 ∈ PUniv j0 by move /regularity_sub0 in hPi''; hauto lq:on use:Bind_Inv.
|
||
have hPi' : Γ ⊢ PBind PPi A0 B0 ≲ PBind PPi A2 B2 by eauto using Su_Eq, Su_Transitive.
|
||
have hPidup := hPi'.
|
||
apply E_Conv with (A := PBind PPi A2 B2); eauto.
|
||
have /regularity_sub0 [i' hPi0] := hPi.
|
||
have : Γ ⊢ PAbs (PApp (ren_PTm shift u) (VarPTm var_zero)) ≡ u ∈ PBind PPi A2 B2.
|
||
apply : E_AppEta; eauto.
|
||
hauto l:on use:regularity.
|
||
apply T_Conv with (A := A);eauto.
|
||
eauto using Su_Eq.
|
||
move => ?.
|
||
suff : Γ ⊢ PAbs a ≡ PAbs (PApp (ren_PTm shift u) (VarPTm var_zero)) ∈ PBind PPi A2 B2
|
||
by eauto using E_Transitive.
|
||
apply : E_Abs; eauto. hauto l:on use:regularity.
|
||
apply iha.
|
||
move /Su_Pi_Proj2_Var in hPi'.
|
||
apply : T_Conv; eauto.
|
||
eapply ctx_eq_subst_one with (A0 := A0); eauto.
|
||
sfirstorder use:Su_Pi_Proj1.
|
||
eapply T_App' with (A := ren_PTm shift A2) (B := ren_PTm (upRen_PTm_PTm shift) B2).
|
||
by asimpl; rewrite subst_scons_id.
|
||
eapply weakening_wt' with (a := u) (A := PBind PPi A2 B2);eauto.
|
||
by eauto using T_Conv_E. apply T_Var. apply : Wff_Cons'; eauto.
|
||
apply here.
|
||
(* Mirrors the last case *)
|
||
- move => a u hu ha iha Γ A hu0 ha0.
|
||
apply E_Symmetric.
|
||
apply : hAppL; eauto.
|
||
sfirstorder use:coqeq_symmetric_mutual.
|
||
sfirstorder use:E_Symmetric.
|
||
- move => {hAppL hPairL} a0 a1 b0 b1 ha iha hb ihb Γ A.
|
||
move /Pair_Inv => [A0][B0][h00][h01]h02.
|
||
move /Pair_Inv => [A1][B1][h10][h11]h12.
|
||
have [i[A2[B2 h2]]] : exists i A2 B2, Γ ⊢ A ≡ PBind PSig A2 B2 ∈ PUniv i by hauto l:on use:Sub_Bind_InvR.
|
||
apply E_Conv with (A := PBind PSig A2 B2); last by eauto using E_Symmetric, Su_Eq.
|
||
have h0 : Γ ⊢ PBind PSig A0 B0 ≲ PBind PSig A2 B2 by eauto using Su_Transitive, Su_Eq, E_Symmetric.
|
||
have h1 : Γ ⊢ PBind PSig A1 B1 ≲ PBind PSig A2 B2 by eauto using Su_Transitive, Su_Eq, E_Symmetric.
|
||
have /Su_Sig_Proj1 h0' := h0.
|
||
have /Su_Sig_Proj1 h1' := h1.
|
||
move => [:eqa].
|
||
apply : E_Pair; eauto. hauto l:on use:regularity.
|
||
abstract : eqa. apply iha; eauto using T_Conv.
|
||
apply ihb.
|
||
+ apply T_Conv with (A := subst_PTm (scons a0 VarPTm) B0); eauto.
|
||
have : Γ ⊢ a0 ≡ a0 ∈A0 by eauto using E_Refl.
|
||
hauto l:on use:Su_Sig_Proj2.
|
||
+ apply T_Conv with (A := subst_PTm (scons a1 VarPTm) B2); eauto; cycle 1.
|
||
move /E_Symmetric in eqa.
|
||
have ? : Γ ⊢ PBind PSig A2 B2 ∈ PUniv i by hauto use:regularity.
|
||
apply:bind_inst; eauto.
|
||
apply : T_Conv; eauto.
|
||
have : Γ ⊢ a1 ≡ a1 ∈ A1 by eauto using E_Refl.
|
||
hauto l:on use:Su_Sig_Proj2.
|
||
- move => {hAppL}.
|
||
abstract : hPairL.
|
||
move => {hAppL}.
|
||
move => a0 a1 u neu h0 ih0 h1 ih1 Γ A ha hu.
|
||
move /Pair_Inv : ha => [A0][B0][ha0][ha1]ha.
|
||
have [i [A2 [B2 hA]]] : exists i A2 B2, Γ ⊢ A ≡ PBind PSig A2 B2 ∈ PUniv i by hauto l:on use:Sub_Bind_InvR.
|
||
have hA' : Γ ⊢ PBind PSig A2 B2 ≲ A by eauto using E_Symmetric, Su_Eq.
|
||
move /E_Conv : (hA'). apply.
|
||
have hSig : Γ ⊢ PBind PSig A0 B0 ≲ PBind PSig A2 B2 by eauto using E_Symmetric, Su_Eq, Su_Transitive.
|
||
have hA02 : Γ ⊢ A0 ≲ A2 by sfirstorder use:Su_Sig_Proj1.
|
||
have hu' : Γ ⊢ u ∈ PBind PSig A2 B2 by eauto using T_Conv_E.
|
||
move => [:ih0'].
|
||
apply : E_Transitive; last (apply E_Symmetric; apply : E_PairEta).
|
||
apply : E_Pair; eauto. hauto l:on use:regularity.
|
||
abstract : ih0'.
|
||
apply ih0. apply : T_Conv; eauto.
|
||
by eauto using T_Proj1.
|
||
apply ih1. apply : T_Conv; eauto.
|
||
move /E_Refl in ha0.
|
||
hauto l:on use:Su_Sig_Proj2.
|
||
move /T_Proj2 in hu'.
|
||
apply : T_Conv; eauto.
|
||
move /E_Symmetric in ih0'.
|
||
move /regularity_sub0 in hA'.
|
||
hauto l:on use:bind_inst.
|
||
hauto l:on use:regularity.
|
||
eassumption.
|
||
(* Same as before *)
|
||
- move {hAppL}.
|
||
move => *. apply E_Symmetric. apply : hPairL;
|
||
sfirstorder use:coqeq_symmetric_mutual, E_Symmetric.
|
||
- sfirstorder use:E_Refl.
|
||
- move => {hAppL hPairL} p A0 A1 B0 B1 hA ihA hB ihB Γ A hA0 hA1.
|
||
move /Bind_Inv : hA0 => [i][hA0][hB0]hU.
|
||
move /Bind_Inv : hA1 => [j][hA1][hB1]hU1.
|
||
have [l [k hk]] : exists l k, Γ ⊢ A ≡ PUniv k ∈ PUniv l
|
||
by hauto lq:on use:Sub_Univ_InvR.
|
||
have hjk : Γ ⊢ PUniv j ≲ PUniv k by eauto using Su_Eq, Su_Transitive.
|
||
have hik : Γ ⊢ PUniv i ≲ PUniv k by eauto using Su_Eq, Su_Transitive.
|
||
apply E_Conv with (A := PUniv k); last by eauto using Su_Eq, E_Symmetric.
|
||
move => [:eqA].
|
||
apply E_Bind. abstract : eqA. apply ihA.
|
||
apply T_Conv with (A := PUniv i); eauto.
|
||
apply T_Conv with (A := PUniv j); eauto.
|
||
apply ihB.
|
||
apply T_Conv with (A := PUniv i); eauto.
|
||
move : weakening_su hik hA0. by repeat move/[apply].
|
||
apply T_Conv with (A := PUniv j); eauto.
|
||
apply : ctx_eq_subst_one; eauto. apply : Su_Eq; apply eqA.
|
||
move : weakening_su hjk hA0. by repeat move/[apply].
|
||
- hauto lq:on ctrs:Eq,LEq,Wt.
|
||
- hauto lq:on ctrs:Eq,LEq,Wt.
|
||
- move => a a' b b' ha hb hab ihab Γ A ha0 hb0.
|
||
have [*] : Γ ⊢ a' ∈ A /\ Γ ⊢ b' ∈ A by eauto using HReds.preservation.
|
||
hauto lq:on use:HReds.ToEq, E_Symmetric, E_Transitive.
|
||
Qed.
|
||
|
||
Definition algo_metric k (a b : PTm) :=
|
||
exists i j va vb, nsteps LoRed.R i a va /\ nsteps LoRed.R j b vb /\ nf va /\ nf vb /\ EJoin.R va vb /\ size_PTm va + size_PTm vb + i + j <= k.
|
||
|
||
Lemma ne_hne (a : PTm) : ne a -> ishne a.
|
||
Proof. elim : a => //=; sfirstorder b:on. Qed.
|
||
|
||
Lemma hf_hred_lored (a b : PTm) :
|
||
~~ ishf a ->
|
||
LoRed.R a b ->
|
||
HRed.R a b \/ ishne a.
|
||
Proof.
|
||
move => + h. elim : a b/ h=>//=.
|
||
- hauto l:on use:HRed.AppAbs.
|
||
- hauto l:on use:HRed.ProjPair.
|
||
- hauto lq:on ctrs:HRed.R.
|
||
- hauto lq:on ctrs:HRed.R.
|
||
- hauto lq:on ctrs:HRed.R.
|
||
- sfirstorder use:ne_hne.
|
||
- hauto lq:on ctrs:HRed.R.
|
||
- sfirstorder use:ne_hne.
|
||
- hauto q:on ctrs:HRed.R.
|
||
- hauto lq:on use:ne_hne.
|
||
- hauto lq:on use:ne_hne.
|
||
Qed.
|
||
|
||
Lemma algo_metric_case k (a b : PTm) :
|
||
algo_metric k a b ->
|
||
(ishf a \/ ishne a) \/ exists k' a', HRed.R a a' /\ algo_metric k' a' b /\ k' < k.
|
||
Proof.
|
||
move=>[i][j][va][vb][h0] [h1][h2][h3][[v [h4 h5]]] h6.
|
||
case : a h0 => //=; try firstorder.
|
||
- inversion h0 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.AppAbs unfold:algo_metric solve+:lia.
|
||
+ hauto q:on ctrs:HRed.R use: hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder qb:on use:ne_hne.
|
||
- inversion h0 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.ProjPair unfold:algo_metric solve+:lia.
|
||
+ hauto q:on ctrs:HRed.R use: hf_hred_lored unfold:algo_metric solve+:lia.
|
||
- inversion h0 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.IndZero unfold:algo_metric solve+:lia.
|
||
+ hauto lq:on ctrs:HRed.R use:hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder use:ne_hne.
|
||
+ hauto lq:on ctrs:HRed.R use:hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder use:ne_hne.
|
||
+ sfirstorder use:ne_hne.
|
||
Qed.
|
||
|
||
Lemma algo_metric_sym k (a b : PTm) :
|
||
algo_metric k a b -> algo_metric k b a.
|
||
Proof. hauto lq:on unfold:algo_metric solve+:lia. Qed.
|
||
|
||
Lemma hred_hne (a b : PTm) :
|
||
HRed.R a b ->
|
||
ishne a ->
|
||
False.
|
||
Proof. induction 1; sfirstorder. Qed.
|
||
|
||
Lemma hf_not_hne (a : PTm) :
|
||
ishf a -> ishne a -> False.
|
||
Proof. case : a => //=. Qed.
|
||
|
||
Lemma T_AbsPair_Imp Γ a (b0 b1 : PTm) A :
|
||
Γ ⊢ PAbs a ∈ A ->
|
||
Γ ⊢ PPair b0 b1 ∈ A ->
|
||
False.
|
||
Proof.
|
||
move /Abs_Inv => [A0][B0][_]haU.
|
||
move /Pair_Inv => [A1][B1][_][_]hbU.
|
||
move /Sub_Bind_InvR : haU => [i][A2][B2]h2.
|
||
have : Γ ⊢ PBind PSig A1 B1 ≲ PBind PPi A2 B2 by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub. hauto l:on use:Sub.bind_inj.
|
||
Qed.
|
||
|
||
Lemma T_AbsZero_Imp Γ a (A : PTm) :
|
||
Γ ⊢ PAbs a ∈ A ->
|
||
Γ ⊢ PZero ∈ A ->
|
||
False.
|
||
Proof.
|
||
move /Abs_Inv => [A0][B0][_]haU.
|
||
move /Zero_Inv => hbU.
|
||
move /Sub_Bind_InvR : haU => [i][A2][B2]h2.
|
||
have : Γ ⊢ PNat ≲ PBind PPi A2 B2 by eauto using Su_Transitive, Su_Eq.
|
||
clear. hauto lq:on use:synsub_to_usub, Sub.bind_nat_noconf.
|
||
Qed.
|
||
|
||
Lemma T_AbsSuc_Imp Γ a b (A : PTm) :
|
||
Γ ⊢ PAbs a ∈ A ->
|
||
Γ ⊢ PSuc b ∈ A ->
|
||
False.
|
||
Proof.
|
||
move /Abs_Inv => [A0][B0][_]haU.
|
||
move /Suc_Inv => [_ hbU].
|
||
move /Sub_Bind_InvR : haU => [i][A2][B2]h2.
|
||
have {hbU h2} : Γ ⊢ PNat ≲ PBind PPi A2 B2 by eauto using Su_Transitive, Su_Eq.
|
||
hauto lq:on use:Sub.bind_nat_noconf, synsub_to_usub.
|
||
Qed.
|
||
|
||
Lemma Nat_Inv Γ A:
|
||
Γ ⊢ PNat ∈ A ->
|
||
exists i, Γ ⊢ PUniv i ≲ A.
|
||
Proof.
|
||
move E : PNat => u hu.
|
||
move : E.
|
||
elim : Γ u A / hu=>//=.
|
||
- hauto lq:on use:E_Refl, T_Univ, Su_Eq.
|
||
- hauto lq:on ctrs:LEq.
|
||
Qed.
|
||
|
||
Lemma T_AbsNat_Imp Γ a (A : PTm ) :
|
||
Γ ⊢ PAbs a ∈ A ->
|
||
Γ ⊢ PNat ∈ A ->
|
||
False.
|
||
Proof.
|
||
move /Abs_Inv => [A0][B0][_]haU.
|
||
move /Nat_Inv => [i hA].
|
||
move /Sub_Univ_InvR : hA => [j][k]hA.
|
||
have : Γ ⊢ PBind PPi A0 B0 ≲ PUniv j by eauto using Su_Transitive, Su_Eq.
|
||
hauto lq:on use:Sub.bind_univ_noconf, synsub_to_usub.
|
||
Qed.
|
||
|
||
Lemma T_PairBind_Imp Γ (a0 a1 : PTm ) p A0 B0 U :
|
||
Γ ⊢ PPair a0 a1 ∈ U ->
|
||
Γ ⊢ PBind p A0 B0 ∈ U ->
|
||
False.
|
||
Proof.
|
||
move /Pair_Inv => [A1][B1][_][_]hbU.
|
||
move /Bind_Inv => [i][_ [_ haU]].
|
||
move /Sub_Univ_InvR : haU => [j][k]hU.
|
||
have : Γ ⊢ PBind PSig A1 B1 ≲ PUniv j by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub. hauto l:on use:Sub.bind_univ_noconf.
|
||
Qed.
|
||
|
||
Lemma T_PairNat_Imp Γ (a0 a1 : PTm) U :
|
||
Γ ⊢ PPair a0 a1 ∈ U ->
|
||
Γ ⊢ PNat ∈ U ->
|
||
False.
|
||
Proof.
|
||
move/Pair_Inv => [A1][B1][_][_]hbU.
|
||
move /Nat_Inv => [i]/Sub_Univ_InvR[j][k]hU.
|
||
have : Γ ⊢ PBind PSig A1 B1 ≲ PUniv j by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub. hauto l:on use:Sub.bind_univ_noconf.
|
||
Qed.
|
||
|
||
Lemma T_PairZero_Imp Γ (a0 a1 : PTm ) U :
|
||
Γ ⊢ PPair a0 a1 ∈ U ->
|
||
Γ ⊢ PZero ∈ U ->
|
||
False.
|
||
Proof.
|
||
move/Pair_Inv=>[A1][B1][_][_]hbU.
|
||
move/Zero_Inv. move/Sub_Bind_InvR : hbU=>[i][A0][B0]*.
|
||
have : Γ ⊢ PNat ≲ PBind PSig A0 B0 by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub. hauto l:on use:Sub.bind_nat_noconf.
|
||
Qed.
|
||
|
||
Lemma T_PairSuc_Imp Γ (a0 a1 : PTm ) b U :
|
||
Γ ⊢ PPair a0 a1 ∈ U ->
|
||
Γ ⊢ PSuc b ∈ U ->
|
||
False.
|
||
Proof.
|
||
move/Pair_Inv=>[A1][B1][_][_]hbU.
|
||
move/Suc_Inv=>[_ hU]. move/Sub_Bind_InvR : hbU=>[i][A0][B0]*.
|
||
have : Γ ⊢ PNat ≲ PBind PSig A0 B0 by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub. hauto l:on use:Sub.bind_nat_noconf.
|
||
Qed.
|
||
|
||
Lemma Univ_Inv Γ i U :
|
||
Γ ⊢ PUniv i ∈ U ->
|
||
Γ ⊢ PUniv i ∈ PUniv (S i) /\ Γ ⊢ PUniv (S i) ≲ U.
|
||
Proof.
|
||
move E : (PUniv i) => u hu.
|
||
move : i E. elim : Γ u U / hu => n //=.
|
||
- hauto l:on use:E_Refl, Su_Eq, T_Univ.
|
||
- hauto lq:on rew:off ctrs:LEq.
|
||
Qed.
|
||
|
||
Lemma T_PairUniv_Imp Γ (a0 a1 : PTm) i U :
|
||
Γ ⊢ PPair a0 a1 ∈ U ->
|
||
Γ ⊢ PUniv i ∈ U ->
|
||
False.
|
||
Proof.
|
||
move /Pair_Inv => [A1][B1][_][_]hbU.
|
||
move /Univ_Inv => [h0 h1].
|
||
move /Sub_Univ_InvR : h1 => [j [k hU]].
|
||
have : Γ ⊢ PBind PSig A1 B1 ≲ PUniv j by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub.
|
||
hauto lq:on use:Sub.bind_univ_noconf.
|
||
Qed.
|
||
|
||
Lemma T_AbsUniv_Imp Γ a i (A : PTm) :
|
||
Γ ⊢ PAbs a ∈ A ->
|
||
Γ ⊢ PUniv i ∈ A ->
|
||
False.
|
||
Proof.
|
||
move /Abs_Inv => [A0][B0][_]haU.
|
||
move /Univ_Inv => [h0 h1].
|
||
move /Sub_Univ_InvR : h1 => [j [k hU]].
|
||
have : Γ ⊢ PBind PPi A0 B0 ≲ PUniv j by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub.
|
||
hauto lq:on use:Sub.bind_univ_noconf.
|
||
Qed.
|
||
|
||
Lemma T_AbsUniv_Imp' Γ (a : PTm) i :
|
||
Γ ⊢ PAbs a ∈ PUniv i -> False.
|
||
Proof.
|
||
hauto lq:on use:synsub_to_usub, Sub.bind_univ_noconf, Abs_Inv.
|
||
Qed.
|
||
|
||
Lemma T_PairUniv_Imp' Γ (a b : PTm) i :
|
||
Γ ⊢ PPair a b ∈ PUniv i -> False.
|
||
Proof.
|
||
hauto lq:on use:synsub_to_usub, Sub.bind_univ_noconf, Pair_Inv.
|
||
Qed.
|
||
|
||
Lemma T_AbsBind_Imp Γ a p A0 B0 (U : PTm ) :
|
||
Γ ⊢ PAbs a ∈ U ->
|
||
Γ ⊢ PBind p A0 B0 ∈ U ->
|
||
False.
|
||
Proof.
|
||
move /Abs_Inv => [A1][B1][_ ha].
|
||
move /Bind_Inv => [i [_ [_ h]]].
|
||
move /Sub_Univ_InvR : h => [j [k hU]].
|
||
have : Γ ⊢ PBind PPi A1 B1 ≲ PUniv j by eauto using Su_Transitive, Su_Eq.
|
||
clear. move /synsub_to_usub.
|
||
hauto lq:on use:Sub.bind_univ_noconf.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_suc_inv k (a : PTm ) b :
|
||
nsteps LoRed.R k (PSuc a) b -> exists b', nsteps LoRed.R k a b' /\ b = PSuc b'.
|
||
Proof.
|
||
move E : (PSuc a) => u hu.
|
||
move : a E.
|
||
elim : u b /hu.
|
||
- hauto l:on.
|
||
- scrush ctrs:nsteps inv:LoRed.R.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_abs_inv k (a : PTm) b :
|
||
nsteps LoRed.R k (PAbs a) b -> exists b', nsteps LoRed.R k a b' /\ b = PAbs b'.
|
||
Proof.
|
||
move E : (PAbs a) => u hu.
|
||
move : a E.
|
||
elim : u b /hu.
|
||
- hauto l:on.
|
||
- scrush ctrs:nsteps inv:LoRed.R.
|
||
Qed.
|
||
|
||
Lemma lored_hne_preservation (a b : PTm) :
|
||
LoRed.R a b -> ishne a -> ishne b.
|
||
Proof. induction 1; sfirstorder. Qed.
|
||
|
||
Lemma loreds_hne_preservation (a b : PTm ) :
|
||
rtc LoRed.R a b -> ishne a -> ishne b.
|
||
Proof. induction 1; hauto lq:on ctrs:rtc use:lored_hne_preservation. Qed.
|
||
|
||
Lemma lored_nsteps_bind_inv k p (a0 : PTm ) b0 C :
|
||
nsteps LoRed.R k (PBind p a0 b0) C ->
|
||
exists i j a1 b1,
|
||
i <= k /\ j <= k /\
|
||
C = PBind p a1 b1 /\
|
||
nsteps LoRed.R i a0 a1 /\
|
||
nsteps LoRed.R j b0 b1.
|
||
Proof.
|
||
move E : (PBind p a0 b0) => u hu. move : p a0 b0 E.
|
||
elim : k u C / hu.
|
||
- sauto lq:on.
|
||
- move => k a0 a1 a2 ha ha' ih p a3 b0 ?. subst.
|
||
inversion ha; subst => //=;
|
||
spec_refl.
|
||
move : ih => [i][j][a1][b1][?][?][?][h0]h1. subst.
|
||
exists (S i),j,a1,b1. sauto lq:on solve+:lia.
|
||
move : ih => [i][j][a1][b1][?][?][?][h0]h1. subst.
|
||
exists i,(S j),a1,b1. sauto lq:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_ind_inv k P0 (a0 : PTm) b0 c0 U :
|
||
nsteps LoRed.R k (PInd P0 a0 b0 c0) U ->
|
||
ishne a0 ->
|
||
exists iP ia ib ic P1 a1 b1 c1,
|
||
iP <= k /\ ia <= k /\ ib <= k /\ ic <= k /\
|
||
U = PInd P1 a1 b1 c1 /\
|
||
nsteps LoRed.R iP P0 P1 /\
|
||
nsteps LoRed.R ia a0 a1 /\
|
||
nsteps LoRed.R ib b0 b1 /\
|
||
nsteps LoRed.R ic c0 c1.
|
||
Proof.
|
||
move E : (PInd P0 a0 b0 c0) => u hu.
|
||
move : P0 a0 b0 c0 E.
|
||
elim : k u U / hu.
|
||
- sauto lq:on.
|
||
- move => k t0 t1 t2 ht01 ht12 ih P0 a0 b0 c0 ? nea0. subst.
|
||
inversion ht01; subst => //=; spec_refl.
|
||
* move /(_ ltac:(done)) : ih.
|
||
move => [iP][ia][ib][ic].
|
||
exists (S iP), ia, ib, ic. sauto lq:on solve+:lia.
|
||
* move /(_ ltac:(sfirstorder use:lored_hne_preservation)) : ih.
|
||
move => [iP][ia][ib][ic].
|
||
exists iP, (S ia), ib, ic. sauto lq:on solve+:lia.
|
||
* move /(_ ltac:(done)) : ih.
|
||
move => [iP][ia][ib][ic].
|
||
exists iP, ia, (S ib), ic. sauto lq:on solve+:lia.
|
||
* move /(_ ltac:(done)) : ih.
|
||
move => [iP][ia][ib][ic].
|
||
exists iP, ia, ib, (S ic). sauto lq:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_app_inv k (a0 b0 C : PTm) :
|
||
nsteps LoRed.R k (PApp a0 b0) C ->
|
||
ishne a0 ->
|
||
exists i j a1 b1,
|
||
i <= k /\ j <= k /\
|
||
C = PApp a1 b1 /\
|
||
nsteps LoRed.R i a0 a1 /\
|
||
nsteps LoRed.R j b0 b1.
|
||
Proof.
|
||
move E : (PApp a0 b0) => u hu. move : a0 b0 E.
|
||
elim : k u C / hu.
|
||
- sauto lq:on.
|
||
- move => k a0 a1 a2 ha01 ha12 ih a3 b0 ?. subst.
|
||
inversion ha01; subst => //=.
|
||
spec_refl.
|
||
move => h.
|
||
have : ishne a4 by sfirstorder use:lored_hne_preservation.
|
||
move : ih => /[apply]. move => [i][j][a1][b1][?][?][?][h0]h1.
|
||
subst. exists (S i),j,a1,b1. sauto lq:on solve+:lia.
|
||
spec_refl. move : ih => /[apply].
|
||
move => [i][j][a1][b1][?][?][?][h0]h1. subst.
|
||
exists i, (S j), a1, b1. sauto lq:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_proj_inv k p (a0 C : PTm) :
|
||
nsteps LoRed.R k (PProj p a0) C ->
|
||
ishne a0 ->
|
||
exists i a1,
|
||
i <= k /\
|
||
C = PProj p a1 /\
|
||
nsteps LoRed.R i a0 a1.
|
||
Proof.
|
||
move E : (PProj p a0) => u hu. move : a0 E.
|
||
elim : k u C / hu.
|
||
- sauto lq:on.
|
||
- move => k a0 a1 a2 ha01 ha12 ih a3 ?. subst.
|
||
inversion ha01; subst => //=.
|
||
spec_refl.
|
||
move => h.
|
||
have : ishne a4 by sfirstorder use:lored_hne_preservation.
|
||
move : ih => /[apply]. move => [i][a1][?][?]h0. subst.
|
||
exists (S i), a1. hauto lq:on ctrs:nsteps solve+:lia.
|
||
Qed.
|
||
|
||
Lemma algo_metric_proj k p0 p1 (a0 a1 : PTm) :
|
||
algo_metric k (PProj p0 a0) (PProj p1 a1) ->
|
||
ishne a0 ->
|
||
ishne a1 ->
|
||
p0 = p1 /\ exists j, j < k /\ algo_metric j a0 a1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5 hne0 hne1.
|
||
move : lored_nsteps_proj_inv h0 (hne0);repeat move/[apply].
|
||
move => [i0][a2][hi][?]ha02. subst.
|
||
move : lored_nsteps_proj_inv h1 (hne1);repeat move/[apply].
|
||
move => [i1][a3][hj][?]ha13. subst.
|
||
simpl in *.
|
||
move /EJoin.hne_proj_inj : h4 => [h40 h41]. subst.
|
||
split => //.
|
||
exists (k - 1). split. simpl in *; lia.
|
||
rewrite/algo_metric.
|
||
do 4 eexists. repeat split; eauto. sfirstorder use:ne_nf.
|
||
sfirstorder use:ne_nf.
|
||
lia.
|
||
Qed.
|
||
|
||
|
||
Lemma hreds_nf_refl a b :
|
||
HRed.nf a ->
|
||
rtc HRed.R a b ->
|
||
a = b.
|
||
Proof. inversion 2; sfirstorder. Qed.
|
||
|
||
Lemma lored_nsteps_app_cong k (a0 a1 b : PTm) :
|
||
nsteps LoRed.R k a0 a1 ->
|
||
ishne a0 ->
|
||
nsteps LoRed.R k (PApp a0 b) (PApp a1 b).
|
||
move => h. move : b.
|
||
elim : k a0 a1 / h.
|
||
- sauto.
|
||
- move => m a0 a1 a2 h0 h1 ih.
|
||
move => b hneu.
|
||
apply : nsteps_l; eauto using LoRed.AppCong0.
|
||
apply LoRed.AppCong0;eauto. move : hneu. clear. case : a0 => //=.
|
||
apply ih. sfirstorder use:lored_hne_preservation.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_proj_cong k p (a0 a1 : PTm) :
|
||
nsteps LoRed.R k a0 a1 ->
|
||
ishne a0 ->
|
||
nsteps LoRed.R k (PProj p a0) (PProj p a1).
|
||
move => h. move : p.
|
||
elim : k a0 a1 / h.
|
||
- sauto.
|
||
- move => m a0 a1 a2 h0 h1 ih p hneu.
|
||
apply : nsteps_l; eauto using LoRed.ProjCong.
|
||
apply LoRed.ProjCong;eauto. move : hneu. clear. case : a0 => //=.
|
||
apply ih. sfirstorder use:lored_hne_preservation.
|
||
Qed.
|
||
|
||
Lemma lored_nsteps_pair_inv k (a0 b0 C : PTm ) :
|
||
nsteps LoRed.R k (PPair a0 b0) C ->
|
||
exists i j a1 b1,
|
||
i <= k /\ j <= k /\
|
||
C = PPair a1 b1 /\
|
||
nsteps LoRed.R i a0 a1 /\
|
||
nsteps LoRed.R j b0 b1.
|
||
move E : (PPair a0 b0) => u hu. move : a0 b0 E.
|
||
elim : k u C / hu.
|
||
- sauto lq:on.
|
||
- move => k a0 a1 a2 ha01 ha12 ih a3 b0 ?. subst.
|
||
inversion ha01; subst => //=.
|
||
spec_refl.
|
||
move : ih => [i][j][a1][b1][?][?][?][h0]h1.
|
||
subst. exists (S i),j,a1,b1. sauto lq:on solve+:lia.
|
||
spec_refl.
|
||
move : ih => [i][j][a1][b1][?][?][?][h0]h1. subst.
|
||
exists i, (S j), a1, b1. sauto lq:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma algo_metric_join k (a b : PTm ) :
|
||
algo_metric k a b ->
|
||
DJoin.R a b.
|
||
rewrite /algo_metric.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][[v [h40 h41]]]h5.
|
||
have {}h0 : rtc LoRed.R a va by hauto lq:on use:@relations.rtc_nsteps.
|
||
have {}h1 : rtc LoRed.R b vb by hauto lq:on use:@relations.rtc_nsteps.
|
||
apply REReds.FromEReds in h40,h41.
|
||
apply LoReds.ToRReds in h0,h1.
|
||
apply REReds.FromRReds in h0,h1.
|
||
rewrite /DJoin.R. exists v. sfirstorder use:@relations.rtc_transitive.
|
||
Qed.
|
||
|
||
Lemma algo_metric_pair k (a0 b0 a1 b1 : PTm) :
|
||
SN (PPair a0 b0) ->
|
||
SN (PPair a1 b1) ->
|
||
algo_metric k (PPair a0 b0) (PPair a1 b1) ->
|
||
exists j, j < k /\ algo_metric j a0 a1 /\ algo_metric j b0 b1.
|
||
move => sn0 sn1 /[dup] /algo_metric_join hj.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5.
|
||
move : lored_nsteps_pair_inv h0;repeat move/[apply].
|
||
move => [i0][i1][a2][b2][?][?][?][ha02]hb02. subst.
|
||
move : lored_nsteps_pair_inv h1;repeat move/[apply].
|
||
move => [j0][j1][a3][b3][?][?][?][ha13]hb13. subst.
|
||
simpl in *. exists (k - 1).
|
||
move /andP : h2 => [h20 h21].
|
||
move /andP : h3 => [h30 h31].
|
||
suff : EJoin.R a2 a3 /\ EJoin.R b2 b3 by hauto lq:on solve+:lia.
|
||
hauto l:on use:DJoin.ejoin_pair_inj.
|
||
Qed.
|
||
|
||
Lemma hne_nf_ne (a : PTm ) :
|
||
ishne a -> nf a -> ne a.
|
||
Proof. case : a => //=. Qed.
|
||
|
||
Lemma lored_nsteps_renaming k (a b : PTm) (ξ : nat -> nat) :
|
||
nsteps LoRed.R k a b ->
|
||
nsteps LoRed.R k (ren_PTm ξ a) (ren_PTm ξ b).
|
||
Proof.
|
||
induction 1; hauto lq:on ctrs:nsteps use:LoRed.renaming.
|
||
Qed.
|
||
|
||
Lemma algo_metric_neu_abs k (a0 : PTm) u :
|
||
algo_metric k u (PAbs a0) ->
|
||
ishne u ->
|
||
exists j, j < k /\ algo_metric j (PApp (ren_PTm shift u) (VarPTm var_zero)) a0.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5 neu.
|
||
have neva : ne va by hauto lq:on use:hne_nf_ne, loreds_hne_preservation, @relations.rtc_nsteps.
|
||
move /lored_nsteps_abs_inv : h1 => [a1][h01]?. subst.
|
||
exists (k - 1). simpl in *. split. lia.
|
||
have {}h0 : nsteps LoRed.R i (ren_PTm shift u) (ren_PTm shift va)
|
||
by eauto using lored_nsteps_renaming.
|
||
have {}h0 : nsteps LoRed.R i (PApp (ren_PTm shift u) (VarPTm var_zero)) (PApp (ren_PTm shift va) (VarPTm var_zero)).
|
||
apply lored_nsteps_app_cong => //=.
|
||
scongruence use:ishne_ren.
|
||
do 4 eexists. repeat split; eauto.
|
||
hauto b:on use:ne_nf_ren.
|
||
have h : EJoin.R (PAbs (PApp (ren_PTm shift va) (VarPTm var_zero))) (PAbs a1) by hauto q:on ctrs:rtc,ERed.R.
|
||
apply DJoin.ejoin_abs_inj; eauto.
|
||
hauto b:on drew:off use:ne_nf_ren.
|
||
simpl in *. rewrite size_PTm_ren. lia.
|
||
Qed.
|
||
|
||
Lemma algo_metric_neu_pair k (a0 b0 : PTm) u :
|
||
algo_metric k u (PPair a0 b0) ->
|
||
ishne u ->
|
||
exists j, j < k /\ algo_metric j (PProj PL u) a0 /\ algo_metric j (PProj PR u) b0.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5 neu.
|
||
move /lored_nsteps_pair_inv : h1.
|
||
move => [i0][j0][a1][b1][hi][hj][?][ha01]hb01. subst.
|
||
simpl in *.
|
||
have ? : ishne va by
|
||
hauto lq:on use:loreds_hne_preservation, @relations.rtc_nsteps.
|
||
have ? : ne va by sfirstorder use:hne_nf_ne.
|
||
exists (k - 1). split. lia.
|
||
move :lored_nsteps_proj_cong (neu) h0; repeat move/[apply].
|
||
move => h. have hL := h PL. have {h} hR := h PR.
|
||
suff [? ?] : EJoin.R (PProj PL va) a1 /\ EJoin.R (PProj PR va) b1.
|
||
rewrite /algo_metric.
|
||
split; do 4 eexists; repeat split;eauto; sfirstorder b:on solve+:lia.
|
||
eapply DJoin.ejoin_pair_inj; hauto qb:on ctrs:rtc, ERed.R.
|
||
Qed.
|
||
|
||
Lemma algo_metric_ind k P0 (a0 : PTm ) b0 c0 P1 a1 b1 c1 :
|
||
algo_metric k (PInd P0 a0 b0 c0) (PInd P1 a1 b1 c1) ->
|
||
ishne a0 ->
|
||
ishne a1 ->
|
||
exists j, j < k /\ algo_metric j P0 P1 /\ algo_metric j a0 a1 /\
|
||
algo_metric j b0 b1 /\ algo_metric j c0 c1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5 hne0 hne1.
|
||
move /lored_nsteps_ind_inv /(_ hne0) : h0.
|
||
move =>[iP][ia][ib][ic][P2][a2][b2][c2][?][?][?][?][?][?][?][?]?. subst.
|
||
move /lored_nsteps_ind_inv /(_ hne1) : h1.
|
||
move =>[iP0][ia0][ib0][ic0][P3][a3][b3][c3][?][?][?][?][?][?][?][?]?. subst.
|
||
move /EJoin.ind_inj : h4.
|
||
move => [?][?][?]?.
|
||
exists (k -1). simpl in *.
|
||
hauto lq:on rew:off use:ne_nf b:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma algo_metric_app k (a0 b0 a1 b1 : PTm) :
|
||
algo_metric k (PApp a0 b0) (PApp a1 b1) ->
|
||
ishne a0 ->
|
||
ishne a1 ->
|
||
exists j, j < k /\ algo_metric j a0 a1 /\ algo_metric j b0 b1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5.
|
||
move => hne0 hne1.
|
||
move : lored_nsteps_app_inv h0 (hne0);repeat move/[apply].
|
||
move => [i0][i1][a2][b2][?][?][?][ha02]hb02. subst.
|
||
move : lored_nsteps_app_inv h1 (hne1);repeat move/[apply].
|
||
move => [j0][j1][a3][b3][?][?][?][ha13]hb13. subst.
|
||
simpl in *. exists (k - 1).
|
||
move /andP : h2 => [h20 h21].
|
||
move /andP : h3 => [h30 h31].
|
||
move /EJoin.hne_app_inj : h4 => [h40 h41].
|
||
split. lia.
|
||
split.
|
||
+ rewrite /algo_metric.
|
||
exists i0,j0,a2,a3.
|
||
repeat split => //=.
|
||
sfirstorder b:on use:ne_nf.
|
||
sfirstorder b:on use:ne_nf.
|
||
lia.
|
||
+ rewrite /algo_metric.
|
||
exists i1,j1,b2,b3.
|
||
repeat split => //=; sfirstorder b:on use:ne_nf.
|
||
Qed.
|
||
|
||
Lemma algo_metric_suc k (a0 a1 : PTm) :
|
||
algo_metric k (PSuc a0) (PSuc a1) ->
|
||
exists j, j < k /\ algo_metric j a0 a1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5.
|
||
exists (k - 1).
|
||
move /lored_nsteps_suc_inv : h0.
|
||
move => [a0'][ha0]?. subst.
|
||
move /lored_nsteps_suc_inv : h1.
|
||
move => [b0'][hb0]?. subst. simpl in *.
|
||
split; first by lia.
|
||
rewrite /algo_metric.
|
||
hauto lq:on rew:off use:EJoin.suc_inj solve+:lia.
|
||
Qed.
|
||
|
||
Lemma algo_metric_bind k p0 (A0 : PTm ) B0 p1 A1 B1 :
|
||
algo_metric k (PBind p0 A0 B0) (PBind p1 A1 B1) ->
|
||
p0 = p1 /\ exists j, j < k /\ algo_metric j A0 A1 /\ algo_metric j B0 B1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5.
|
||
move : lored_nsteps_bind_inv h0 => /[apply].
|
||
move => [i0][i1][a2][b2][?][?][?][ha02]hb02. subst.
|
||
move : lored_nsteps_bind_inv h1 => /[apply].
|
||
move => [j0][j1][a3][b3][?][?][?][ha13]hb13. subst.
|
||
move /EJoin.bind_inj : h4 => [?][hEa]hEb. subst.
|
||
split => //.
|
||
exists (k - 1). split. simpl in *; lia.
|
||
simpl in *.
|
||
split.
|
||
- exists i0,j0,a2,a3.
|
||
repeat split => //=; sfirstorder b:on solve+:lia.
|
||
- exists i1,j1,b2,b3. sfirstorder b:on solve+:lia.
|
||
Qed.
|
||
|
||
|
||
Lemma coqeq_complete' k (a b : PTm ) :
|
||
algo_metric k a b ->
|
||
(forall Γ A, Γ ⊢ a ∈ A -> Γ ⊢ b ∈ A -> a ⇔ b) /\
|
||
(forall Γ A B, ishne a -> ishne b -> Γ ⊢ a ∈ A -> Γ ⊢ b ∈ B -> a ∼ b /\ exists C, Γ ⊢ C ≲ A /\ Γ ⊢ C ≲ B /\ Γ ⊢ a ∈ C /\ Γ ⊢ b ∈ C).
|
||
Proof.
|
||
move : k a b.
|
||
elim /Wf_nat.lt_wf_ind.
|
||
move => n ih.
|
||
move => a b /[dup] h /algo_metric_case. move : a b h => [:hstepL].
|
||
move => a b h.
|
||
(* Cases where a and b can take steps *)
|
||
case; cycle 1.
|
||
move : ih a b h.
|
||
abstract : hstepL. qauto l:on use:HRed.preservation, CE_HRedL, hred_hne.
|
||
move /algo_metric_sym /algo_metric_case : (h).
|
||
case; cycle 1.
|
||
move /algo_metric_sym : h.
|
||
move : hstepL ih => /[apply]/[apply].
|
||
repeat move /[apply].
|
||
move => hstepL.
|
||
hauto lq:on use:coqeq_symmetric_mutual, algo_metric_sym.
|
||
(* Cases where a and b can't take wh steps *)
|
||
move {hstepL}.
|
||
move : a b h. move => [:hnfneu].
|
||
move => a b h.
|
||
case => fb; case => fa.
|
||
- split; last by sfirstorder use:hf_not_hne.
|
||
move {hnfneu}.
|
||
case : a h fb fa => //=.
|
||
+ case : b => //=; try qauto depth:1 use:T_AbsPair_Imp, T_AbsBind_Imp, T_AbsUniv_Imp, T_AbsZero_Imp, T_AbsSuc_Imp, T_AbsNat_Imp.
|
||
move => a0 a1 ha0 _ _ Γ A wt0 wt1.
|
||
move : T_Abs_Inv wt0 wt1; repeat move/[apply]. move => [Δ [V [wt1 wt0]]].
|
||
apply : CE_HRed; eauto using rtc_refl.
|
||
apply CE_AbsAbs.
|
||
suff [l [h0 h1]] : exists l, l < n /\ algo_metric l a1 a0 by eapply ih; eauto.
|
||
have ? : n > 0 by sauto solve+:lia.
|
||
exists (n - 1). split; first by lia.
|
||
move : (ha0). rewrite /algo_metric.
|
||
move => [i][j][va][vb][hr0][hr1][nfva][nfvb][[v [hr0' hr1']]] har.
|
||
apply lored_nsteps_abs_inv in hr0, hr1.
|
||
move : hr0 => [va' [hr00 hr01]].
|
||
move : hr1 => [vb' [hr10 hr11]]. move {ih}.
|
||
exists i,j,va',vb'. subst.
|
||
suff [v0 [hv00 hv01]] : exists v0, rtc ERed.R va' v0 /\ rtc ERed.R vb' v0.
|
||
repeat split =>//=. sfirstorder.
|
||
simpl in *; by lia.
|
||
move /algo_metric_join /DJoin.symmetric : ha0.
|
||
have : SN a0 /\ SN a1 by qauto l:on use:fundamental_theorem, logrel.SemWt_SN.
|
||
move => /[dup] [[ha00 ha10]] [].
|
||
move : DJoin.abs_inj; repeat move/[apply].
|
||
move : DJoin.standardization ha00 ha10; repeat move/[apply].
|
||
(* this is awful *)
|
||
move => [vb][va][h' [h'' [h''' [h'''' h'''''']]]].
|
||
have /LoReds.ToRReds {}hr00 : rtc LoRed.R a1 va'
|
||
by hauto lq:on use:@relations.rtc_nsteps.
|
||
have /LoReds.ToRReds {}hr10 : rtc LoRed.R a0 vb'
|
||
by hauto lq:on use:@relations.rtc_nsteps.
|
||
simpl in *.
|
||
have [*] : va' = va /\ vb' = vb by eauto using red_uniquenf. subst.
|
||
sfirstorder.
|
||
+ case : b => //=; try qauto depth:1 use:T_AbsPair_Imp, T_PairBind_Imp, T_PairUniv_Imp, T_PairNat_Imp, T_PairSuc_Imp, T_PairZero_Imp.
|
||
move => a1 b1 a0 b0 h _ _ Γ A hu0 hu1.
|
||
have [sn0 sn1] : SN (PPair a0 b0) /\ SN (PPair a1 b1)
|
||
by qauto l:on use:fundamental_theorem, logrel.SemWt_SN.
|
||
apply : CE_HRed; eauto using rtc_refl.
|
||
move /Pair_Inv : hu0 => [A0][B0][ha0][hb0]hSu0.
|
||
move /Pair_Inv : hu1 => [A1][B1][ha1][hb1]hSu1.
|
||
move /Sub_Bind_InvR : (hSu0).
|
||
move => [i][A2][B2]hE.
|
||
have hSu12 : Γ ⊢ PBind PSig A1 B1 ≲ PBind PSig A2 B2
|
||
by eauto using Su_Transitive, Su_Eq.
|
||
have hSu02 : Γ ⊢ PBind PSig A0 B0 ≲ PBind PSig A2 B2
|
||
by eauto using Su_Transitive, Su_Eq.
|
||
have hA02 : Γ ⊢ A0 ≲ A2 by eauto using Su_Sig_Proj1.
|
||
have hA12 : Γ ⊢ A1 ≲ A2 by eauto using Su_Sig_Proj1.
|
||
have ha0A2 : Γ ⊢ a0 ∈ A2 by eauto using T_Conv.
|
||
have ha1A2 : Γ ⊢ a1 ∈ A2 by eauto using T_Conv.
|
||
move /algo_metric_pair : h sn0 sn1; repeat move/[apply].
|
||
move => [j][hj][ih0 ih1].
|
||
have haE : a0 ⇔ a1 by hauto l:on.
|
||
apply CE_PairPair => //.
|
||
have {}haE : Γ ⊢ a0 ≡ a1 ∈ A2
|
||
by hauto l:on use:coqeq_sound_mutual.
|
||
have {}hb1 : Γ ⊢ b1 ∈ subst_PTm (scons a1 VarPTm) B2.
|
||
apply : T_Conv; eauto.
|
||
move /E_Refl in ha1. hauto l:on use:Su_Sig_Proj2.
|
||
eapply ih; cycle -1; eauto.
|
||
apply : T_Conv; eauto.
|
||
apply Su_Transitive with (B := subst_PTm (scons a0 VarPTm) B2).
|
||
move /E_Refl in ha0. hauto l:on use:Su_Sig_Proj2.
|
||
move : hE haE. clear.
|
||
move => h.
|
||
eapply regularity in h.
|
||
move : h => [_ [hB _]].
|
||
eauto using bind_inst.
|
||
+ case : b => //=.
|
||
* hauto lq:on use:T_AbsBind_Imp.
|
||
* hauto lq:on rew:off use:T_PairBind_Imp.
|
||
* move => p1 A1 B1 p0 A0 B0.
|
||
move /algo_metric_bind.
|
||
move => [?][j [ih0 [ih1 ih2]]]_ _. subst.
|
||
move => Γ A hU0 hU1.
|
||
move /Bind_Inv : hU0 => [i0 [hA0 [hB0 hS0]]].
|
||
move /Bind_Inv : hU1 => [i1 [hA1 [hB1 hS1]]].
|
||
have ? : Γ ⊢ PUniv i0 ≲ PUniv (max i0 i1)
|
||
by hauto lq:on rew:off use:Su_Univ, wff_mutual solve+:lia.
|
||
have ? : Γ ⊢ PUniv i1 ≲ PUniv (max i0 i1)
|
||
by hauto lq:on rew:off use:Su_Univ, wff_mutual solve+:lia.
|
||
have {}hA0 : Γ ⊢ A0 ∈ PUniv (max i0 i1) by eauto using T_Conv.
|
||
have {}hA1 : Γ ⊢ A1 ∈ PUniv (max i0 i1) by eauto using T_Conv.
|
||
have {}hB0 : (cons A0 Γ) ⊢ B0 ∈ PUniv (max i0 i1)
|
||
by hauto lq:on use:T_Univ_Raise solve+:lia.
|
||
have {}hB1 : (cons A1 Γ) ⊢ B1 ∈ PUniv (max i0 i1)
|
||
by hauto lq:on use:T_Univ_Raise solve+:lia.
|
||
|
||
have ihA : A0 ⇔ A1 by hauto l:on.
|
||
have hAE : Γ ⊢ A0 ≡ A1 ∈ PUniv (Nat.max i0 i1)
|
||
by hauto l:on use:coqeq_sound_mutual.
|
||
apply : CE_HRed; eauto using rtc_refl.
|
||
constructor => //.
|
||
|
||
eapply ih; eauto.
|
||
apply : ctx_eq_subst_one; eauto.
|
||
eauto using Su_Eq.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on use:DJoin.bind_univ_noconf.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on use:Sub.nat_bind_noconf, Sub.FromJoin.
|
||
* move => > /algo_metric_join.
|
||
clear. hauto lq:on rew:off use:REReds.bind_inv, REReds.zero_inv.
|
||
* move => > /algo_metric_join. clear.
|
||
hauto lq:on rew:off use:REReds.bind_inv, REReds.suc_inv.
|
||
+ case : b => //=.
|
||
* hauto lq:on use:T_AbsUniv_Imp.
|
||
* hauto lq:on use:T_PairUniv_Imp.
|
||
* qauto l:on use:algo_metric_join, DJoin.bind_univ_noconf, DJoin.symmetric.
|
||
* move => i j /algo_metric_join /DJoin.univ_inj ? _ _ Γ A hi hj.
|
||
subst.
|
||
hauto l:on.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on use:Sub.nat_univ_noconf, Sub.FromJoin.
|
||
* move => > /algo_metric_join.
|
||
clear. hauto lq:on rew:off use:REReds.univ_inv, REReds.zero_inv.
|
||
* move => > /algo_metric_join.
|
||
clear. hauto lq:on rew:off use:REReds.univ_inv, REReds.suc_inv.
|
||
+ case : b => //=.
|
||
* qauto l:on use:T_AbsNat_Imp.
|
||
* qauto l:on use:T_PairNat_Imp.
|
||
* move => > /algo_metric_join /Sub.FromJoin. hauto l:on use:Sub.bind_nat_noconf.
|
||
* move => > /algo_metric_join /Sub.FromJoin. hauto lq:on use:Sub.univ_nat_noconf.
|
||
* hauto l:on.
|
||
* move /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.nat_inv, REReds.zero_inv.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.nat_inv, REReds.suc_inv.
|
||
(* Zero *)
|
||
+ case : b => //=.
|
||
* hauto lq:on rew:off use:T_AbsZero_Imp.
|
||
* hauto lq: on use: T_PairZero_Imp.
|
||
* move =>> /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.zero_inv, REReds.bind_inv.
|
||
* move =>> /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.zero_inv, REReds.univ_inv.
|
||
* move =>> /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.zero_inv, REReds.nat_inv.
|
||
* hauto l:on.
|
||
* move =>> /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.zero_inv, REReds.suc_inv.
|
||
(* Suc *)
|
||
+ case : b => //=.
|
||
* hauto lq:on rew:off use:T_AbsSuc_Imp.
|
||
* hauto lq:on use:T_PairSuc_Imp.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.suc_inv, REReds.bind_inv.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.suc_inv, REReds.univ_inv.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.suc_inv, REReds.nat_inv.
|
||
* move => > /algo_metric_join.
|
||
hauto lq:on rew:off use:REReds.suc_inv, REReds.zero_inv.
|
||
* move => a0 a1 h _ _.
|
||
move /algo_metric_suc : h => [j [h4 h5]].
|
||
move => Γ A /Suc_Inv [h0 h1] /Suc_Inv [h2 h3].
|
||
move : ih h4 h5;do!move/[apply].
|
||
move => [ih _].
|
||
move : ih h0 h2;do!move/[apply].
|
||
move => h. apply : CE_HRed; eauto using rtc_refl.
|
||
by constructor.
|
||
- move : a b h fb fa. abstract : hnfneu.
|
||
move => + b.
|
||
case : b => //=.
|
||
(* NeuAbs *)
|
||
+ move => a u halg _ nea. split => // Γ A hu /[dup] ha.
|
||
move /Abs_Inv => [A0][B0][_]hSu.
|
||
move /Sub_Bind_InvR : (hSu) => [i][A2][B2]hE.
|
||
have {}hu : Γ ⊢ u ∈ PBind PPi A2 B2 by eauto using T_Conv_E.
|
||
have {}ha : Γ ⊢ PAbs a ∈ PBind PPi A2 B2 by eauto using T_Conv_E.
|
||
have {}hE : Γ ⊢ PBind PPi A2 B2 ∈ PUniv i
|
||
by hauto l:on use:regularity.
|
||
have {i} [j {}hE] : exists j, Γ ⊢ A2 ∈ PUniv j
|
||
by qauto l:on use:Bind_Inv.
|
||
have hΓ : ⊢ cons A2 Γ by eauto using Wff_Cons'.
|
||
set Δ := cons _ _ in hΓ.
|
||
have {}hu : Δ ⊢ PApp (ren_PTm shift u) (VarPTm var_zero) ∈ B2.
|
||
apply : T_App'; cycle 1. apply : weakening_wt' => //=; eauto.
|
||
reflexivity.
|
||
rewrite -/ren_PTm.
|
||
apply T_Var; eauto using here.
|
||
rewrite -/ren_PTm. by asimpl; rewrite subst_scons_id.
|
||
move /Abs_Pi_Inv in ha.
|
||
move /algo_metric_neu_abs /(_ nea) : halg.
|
||
move => [j0][hj0]halg.
|
||
apply : CE_HRed; eauto using rtc_refl.
|
||
eapply CE_NeuAbs => //=.
|
||
eapply ih; eauto.
|
||
(* NeuPair *)
|
||
+ move => a0 b0 u halg _ neu.
|
||
split => // Γ A hu /[dup] wt.
|
||
move /Pair_Inv => [A0][B0][ha0][hb0]hU.
|
||
move /Sub_Bind_InvR : (hU) => [i][A2][B2]hE.
|
||
have {}wt : Γ ⊢ PPair a0 b0 ∈ PBind PSig A2 B2 by sauto lq:on.
|
||
have {}hu : Γ ⊢ u ∈ PBind PSig A2 B2 by eauto using T_Conv_E.
|
||
move /Pair_Sig_Inv : wt => [{}ha0 {}hb0].
|
||
have /T_Proj1 huL := hu.
|
||
have /T_Proj2 {hu} huR := hu.
|
||
move /algo_metric_neu_pair /(_ neu) : halg => [j [hj [hL hR]]].
|
||
have heL : PProj PL u ⇔ a0 by hauto l:on.
|
||
eapply CE_HRed; eauto using rtc_refl.
|
||
apply CE_NeuPair; eauto.
|
||
eapply ih; eauto.
|
||
apply : T_Conv; eauto.
|
||
have {}hE : Γ ⊢ PBind PSig A2 B2 ∈ PUniv i
|
||
by hauto l:on use:regularity.
|
||
have /E_Symmetric : Γ ⊢ PProj PL u ≡ a0 ∈ A2 by
|
||
hauto l:on use:coqeq_sound_mutual.
|
||
hauto l:on use:bind_inst.
|
||
(* NeuBind: Impossible *)
|
||
+ move => b p p0 a /algo_metric_join h _ h0. exfalso.
|
||
move : h h0. clear.
|
||
move /Sub.FromJoin.
|
||
hauto l:on use:Sub.hne_bind_noconf.
|
||
(* NeuUniv: Impossible *)
|
||
+ hauto lq:on rew:off use:DJoin.hne_univ_noconf, algo_metric_join.
|
||
+ hauto lq:on rew:off use:DJoin.hne_nat_noconf, algo_metric_join.
|
||
(* Zero *)
|
||
+ case => //=.
|
||
* move => i /algo_metric_join. clear.
|
||
hauto lq:on rew:off use:REReds.var_inv, REReds.zero_inv.
|
||
* move => >/algo_metric_join. clear.
|
||
hauto lq:on rew:off use:REReds.hne_app_inv, REReds.zero_inv.
|
||
* move => >/algo_metric_join. clear.
|
||
hauto lq:on rew:off use:REReds.hne_proj_inv, REReds.zero_inv.
|
||
* move => >/algo_metric_join. clear.
|
||
move => h _ h2. exfalso.
|
||
hauto q:on use:REReds.hne_ind_inv, REReds.zero_inv.
|
||
(* Suc *)
|
||
+ move => a0.
|
||
case => //=; move => >/algo_metric_join; clear.
|
||
* hauto lq:on rew:off use:REReds.var_inv, REReds.suc_inv.
|
||
* hauto lq:on rew:off use:REReds.hne_app_inv, REReds.suc_inv.
|
||
* hauto lq:on rew:off use:REReds.hne_proj_inv, REReds.suc_inv.
|
||
* hauto q:on use:REReds.hne_ind_inv, REReds.suc_inv.
|
||
- move {ih}.
|
||
move /algo_metric_sym in h.
|
||
qauto l:on use:coqeq_symmetric_mutual.
|
||
- move {hnfneu}.
|
||
(* Clear out some trivial cases *)
|
||
suff : (forall Γ A B, Γ ⊢ a ∈ A -> Γ ⊢ b ∈ B -> a ∼ b /\ (exists C, Γ ⊢ C ≲ A /\ Γ ⊢ C ≲ B /\ Γ ⊢ a ∈ C /\ Γ ⊢ b ∈ C)).
|
||
move => h0.
|
||
split. move => *. apply : CE_HRed; eauto using rtc_refl. apply CE_NeuNeu. by firstorder.
|
||
by firstorder.
|
||
|
||
case : a h fb fa => //=.
|
||
+ case : b => //=; move => > /algo_metric_join.
|
||
* move /DJoin.var_inj => i _ _. subst.
|
||
move => Γ A B /Var_Inv [? [B0 [h0 h1]]].
|
||
move /Var_Inv => [_ [C0 [h2 h3]]].
|
||
have ? : B0 = C0 by eauto using lookup_deter. subst.
|
||
sfirstorder use:T_Var.
|
||
* clear => ? ? _. exfalso.
|
||
hauto l:on use:REReds.var_inv, REReds.hne_app_inv.
|
||
* clear => ? ? _. exfalso.
|
||
hauto l:on use:REReds.var_inv, REReds.hne_proj_inv.
|
||
* clear => ? ? _. exfalso.
|
||
hauto q:on use:REReds.var_inv, REReds.hne_ind_inv.
|
||
+ case : b => //=;
|
||
lazymatch goal with
|
||
| [|- context[algo_metric _ (PApp _ _) (PApp _ _)]] => idtac
|
||
| _ => move => > /algo_metric_join
|
||
end.
|
||
* clear => *. exfalso.
|
||
hauto lq:on rew:off use:REReds.hne_app_inv, REReds.var_inv.
|
||
(* real case *)
|
||
* move => b1 a1 b0 a0 halg hne1 hne0 Γ A B wtA wtB.
|
||
move /App_Inv : wtA => [A0][B0][hb0][ha0]hS0.
|
||
move /App_Inv : wtB => [A1][B1][hb1][ha1]hS1.
|
||
move : algo_metric_app (hne0) (hne1) halg. repeat move/[apply].
|
||
move => [j [hj [hal0 hal1]]].
|
||
have /ih := hal0.
|
||
move /(_ hj).
|
||
move => [_ ihb].
|
||
move : ihb (hne0) (hne1) hb0 hb1. repeat move/[apply].
|
||
move => [hb01][C][hT0][hT1][hT2]hT3.
|
||
move /Sub_Bind_InvL : (hT0).
|
||
move => [i][A2][B2]hE.
|
||
have hSu20 : Γ ⊢ PBind PPi A2 B2 ≲ PBind PPi A0 B0 by
|
||
eauto using Su_Eq, Su_Transitive.
|
||
have hSu10 : Γ ⊢ PBind PPi A2 B2 ≲ PBind PPi A1 B1 by
|
||
eauto using Su_Eq, Su_Transitive.
|
||
have hSuA0 : Γ ⊢ A0 ≲ A2 by sfirstorder use:Su_Pi_Proj1.
|
||
have hSuA1 : Γ ⊢ A1 ≲ A2 by sfirstorder use:Su_Pi_Proj1.
|
||
have ha1' : Γ ⊢ a1 ∈ A2 by eauto using T_Conv.
|
||
have ha0' : Γ ⊢ a0 ∈ A2 by eauto using T_Conv.
|
||
move : ih (hj) hal1. repeat move/[apply].
|
||
move => [ih _].
|
||
move : ih (ha0') (ha1'); repeat move/[apply].
|
||
move => iha.
|
||
split. qblast.
|
||
exists (subst_PTm (scons a0 VarPTm) B2).
|
||
split.
|
||
apply : Su_Transitive; eauto.
|
||
move /E_Refl in ha0.
|
||
hauto l:on use:Su_Pi_Proj2.
|
||
have h01 : Γ ⊢ a0 ≡ a1 ∈ A2 by sfirstorder use:coqeq_sound_mutual.
|
||
split.
|
||
apply Su_Transitive with (B := subst_PTm (scons a1 VarPTm) B2).
|
||
move /regularity_sub0 : hSu10 => [i0].
|
||
hauto l:on use:bind_inst.
|
||
hauto lq:on rew:off use:Su_Pi_Proj2, Su_Transitive, E_Refl.
|
||
split.
|
||
by apply : T_App; eauto using T_Conv_E.
|
||
apply : T_Conv; eauto.
|
||
apply T_App with (A := A2) (B := B2); eauto.
|
||
apply : T_Conv_E; eauto.
|
||
move /E_Symmetric in h01.
|
||
move /regularity_sub0 : hSu20 => [i0].
|
||
sfirstorder use:bind_inst.
|
||
* clear => ? ? ?. exfalso.
|
||
hauto q:on use:REReds.hne_app_inv, REReds.hne_proj_inv.
|
||
* clear => ? ? ?. exfalso.
|
||
hauto q:on use:REReds.hne_app_inv, REReds.hne_ind_inv.
|
||
+ case : b => //=.
|
||
* move => i p h /algo_metric_join. clear => ? _ ?. exfalso.
|
||
hauto l:on use:REReds.hne_proj_inv, REReds.var_inv.
|
||
* move => > /algo_metric_join. clear => ? ? ?. exfalso.
|
||
hauto l:on use:REReds.hne_proj_inv, REReds.hne_app_inv.
|
||
(* real case *)
|
||
* move => p1 a1 p0 a0 /algo_metric_proj ha hne1 hne0.
|
||
move : ha (hne0) (hne1); repeat move/[apply].
|
||
move => [? [j []]]. subst.
|
||
move : ih; repeat move/[apply].
|
||
move => [_ ih].
|
||
case : p1.
|
||
** move => Γ A B ha0 ha1.
|
||
move /Proj1_Inv : ha0. move => [A0][B0][ha0]hSu0.
|
||
move /Proj1_Inv : ha1. move => [A1][B1][ha1]hSu1.
|
||
move : ih ha0 ha1 (hne0) (hne1); repeat move/[apply].
|
||
move => [ha [C [hS0 [hS1 [wta0 wta1]]]]].
|
||
split. sauto lq:on.
|
||
move /Sub_Bind_InvL : (hS0) => [i][A2][B2]hS2.
|
||
have hSu20 : Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A0 B0
|
||
by eauto using Su_Transitive, Su_Eq.
|
||
have hSu21 : Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A1 B1
|
||
by eauto using Su_Transitive, Su_Eq.
|
||
exists A2. split; eauto using Su_Sig_Proj1, Su_Transitive.
|
||
repeat split => //=.
|
||
hauto l:on use:Su_Sig_Proj1, Su_Transitive.
|
||
apply T_Proj1 with (B := B2); eauto using T_Conv_E.
|
||
apply T_Proj1 with (B := B2); eauto using T_Conv_E.
|
||
** move => Γ A B ha0 ha1.
|
||
move /Proj2_Inv : ha0. move => [A0][B0][ha0]hSu0.
|
||
move /Proj2_Inv : ha1. move => [A1][B1][ha1]hSu1.
|
||
move : ih (ha0) (ha1) (hne0) (hne1); repeat move/[apply].
|
||
move => [ha [C [hS0 [hS1 [wta0 wta1]]]]].
|
||
split. sauto lq:on.
|
||
move /Sub_Bind_InvL : (hS0) => [i][A2][B2]hS2.
|
||
have hSu20 : Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A0 B0
|
||
by eauto using Su_Transitive, Su_Eq.
|
||
have hSu21 : Γ ⊢ PBind PSig A2 B2 ≲ PBind PSig A1 B1
|
||
by eauto using Su_Transitive, Su_Eq.
|
||
have hA20 : Γ ⊢ A2 ≲ A0 by eauto using Su_Sig_Proj1.
|
||
have hA21 : Γ ⊢ A2 ≲ A1 by eauto using Su_Sig_Proj1.
|
||
have {}wta0 : Γ ⊢ a0 ∈ PBind PSig A2 B2 by eauto using T_Conv_E.
|
||
have {}wta1 : Γ ⊢ a1 ∈ PBind PSig A2 B2 by eauto using T_Conv_E.
|
||
have haE : Γ ⊢ PProj PL a0 ≡ PProj PL a1 ∈ A2
|
||
by sauto lq:on use:coqeq_sound_mutual.
|
||
exists (subst_PTm (scons (PProj PL a0) VarPTm) B2).
|
||
repeat split.
|
||
*** apply : Su_Transitive; eauto.
|
||
have : Γ ⊢ PProj PL a0 ≡ PProj PL a0 ∈ A2
|
||
by qauto use:regularity, E_Refl.
|
||
sfirstorder use:Su_Sig_Proj2.
|
||
*** apply : Su_Transitive; eauto.
|
||
sfirstorder use:Su_Sig_Proj2.
|
||
*** eauto using T_Proj2.
|
||
*** apply : T_Conv.
|
||
apply : T_Proj2; eauto.
|
||
move /E_Symmetric in haE.
|
||
move /regularity_sub0 in hSu21.
|
||
sfirstorder use:bind_inst.
|
||
* move => > /algo_metric_join; clear => ? ? ?. exfalso.
|
||
hauto q:on use:REReds.hne_proj_inv, REReds.hne_ind_inv.
|
||
(* ind ind case *)
|
||
+ move => P a0 b0 c0.
|
||
case : b => //=;
|
||
lazymatch goal with
|
||
| [|- context[algo_metric _ (PInd _ _ _ _) (PInd _ _ _ _)]] => idtac
|
||
| _ => move => > /algo_metric_join; clear => *; exfalso
|
||
end.
|
||
* hauto q:on use:REReds.hne_ind_inv, REReds.var_inv.
|
||
* hauto q:on use:REReds.hne_ind_inv, REReds.hne_app_inv.
|
||
* hauto q:on use:REReds.hne_ind_inv, REReds.hne_proj_inv.
|
||
* move => P1 a1 b1 c1 /[dup] halg /algo_metric_ind + h0 h1.
|
||
move /(_ h1 h0).
|
||
move => [j][hj][hP][ha][hb]hc Γ A B hL hR.
|
||
move /Ind_Inv : hL => [iP0][wtP0][wta0][wtb0][wtc0]hSu0.
|
||
move /Ind_Inv : hR => [iP1][wtP1][wta1][wtb1][wtc1]hSu1.
|
||
have {}iha : a0 ∼ a1 by qauto l:on.
|
||
have [] : iP0 <= max iP0 iP1 /\ iP1 <= max iP0 iP1 by lia.
|
||
move : T_Univ_Raise wtP0; do!move/[apply]. move => wtP0.
|
||
move : T_Univ_Raise wtP1; do!move/[apply]. move => wtP1.
|
||
have {}ihP : P ⇔ P1 by qauto l:on.
|
||
set Δ := cons _ _ in wtP0, wtP1, wtc0, wtc1.
|
||
have wfΔ :⊢ Δ by hauto l:on use:wff_mutual.
|
||
have hPE : Δ ⊢ P ≡ P1 ∈ PUniv (max iP0 iP1)
|
||
by hauto l:on use:coqeq_sound_mutual.
|
||
have haE : Γ ⊢ a0 ≡ a1 ∈ PNat
|
||
by hauto l:on use:coqeq_sound_mutual.
|
||
have wtΓ : ⊢ Γ by hauto l:on use:wff_mutual.
|
||
have hE : Γ ⊢ subst_PTm (scons PZero VarPTm) P ≡ subst_PTm (scons PZero VarPTm) P1 ∈ subst_PTm (scons PZero VarPTm) (PUniv (Nat.max iP0 iP1)).
|
||
eapply morphing; eauto. apply morphing_ext. by apply morphing_id. by apply T_Zero.
|
||
have {}wtb1 : Γ ⊢ b1 ∈ subst_PTm (scons PZero VarPTm) P
|
||
by eauto using T_Conv_E.
|
||
have {}ihb : b0 ⇔ b1 by hauto l:on.
|
||
have hPSig : Γ ⊢ PBind PSig PNat P ≡ PBind PSig PNat P1 ∈ PUniv (Nat.max iP0 iP1) by eauto with wt.
|
||
set T := ren_PTm shift _ in wtc0.
|
||
have : (cons P Δ) ⊢ c1 ∈ T.
|
||
apply : T_Conv; eauto. apply : ctx_eq_subst_one; eauto with wt.
|
||
apply : Su_Eq; eauto.
|
||
subst T. apply : weakening_su; eauto.
|
||
eapply morphing. apply : Su_Eq. apply E_Symmetric. by eauto.
|
||
hauto l:on use:wff_mutual.
|
||
apply morphing_ext. set x := funcomp _ _.
|
||
have -> : x = funcomp (ren_PTm shift) VarPTm by asimpl.
|
||
apply : morphing_ren; eauto using renaming_shift. by apply morphing_id.
|
||
apply T_Suc. apply T_Var => //=. apply here. subst T => {}wtc1.
|
||
have {}ihc : c0 ⇔ c1 by qauto l:on.
|
||
move => [:ih].
|
||
split. abstract : ih. move : h0 h1 ihP iha ihb ihc. clear. sauto lq:on.
|
||
have hEInd : Γ ⊢ PInd P a0 b0 c0 ≡ PInd P1 a1 b1 c1 ∈ subst_PTm (scons a0 VarPTm) P by hfcrush use:coqeq_sound_mutual.
|
||
exists (subst_PTm (scons a0 VarPTm) P).
|
||
repeat split => //=; eauto with wt.
|
||
apply : Su_Transitive.
|
||
apply : Su_Sig_Proj2; eauto. apply : Su_Sig; eauto using T_Nat' with wt.
|
||
apply : Su_Eq. apply E_Refl. by apply T_Nat'.
|
||
apply : Su_Eq. apply hPE. by eauto.
|
||
move : hEInd. clear. hauto l:on use:regularity.
|
||
Qed.
|
||
|
||
Lemma coqeq_sound : forall Γ (a b : PTm) A,
|
||
Γ ⊢ a ∈ A -> Γ ⊢ b ∈ A -> a ⇔ b -> Γ ⊢ a ≡ b ∈ A.
|
||
Proof. sfirstorder use:coqeq_sound_mutual. Qed.
|
||
|
||
Lemma coqeq_complete Γ (a b A : PTm) :
|
||
Γ ⊢ a ≡ b ∈ A -> a ⇔ b.
|
||
Proof.
|
||
move => h.
|
||
suff : exists k, algo_metric k a b by hauto lq:on use:coqeq_complete', regularity.
|
||
eapply fundamental_theorem in h.
|
||
move /logrel.SemEq_SN_Join : h.
|
||
move => h.
|
||
have : exists va vb : PTm,
|
||
rtc LoRed.R a va /\
|
||
rtc LoRed.R b vb /\ nf va /\ nf vb /\ EJoin.R va vb
|
||
by hauto l:on use:DJoin.standardization_lo.
|
||
move => [va][vb][hva][hvb][nva][nvb]hj.
|
||
move /relations.rtc_nsteps : hva => [i hva].
|
||
move /relations.rtc_nsteps : hvb => [j hvb].
|
||
exists (i + j + size_PTm va + size_PTm vb).
|
||
hauto lq:on solve+:lia.
|
||
Qed.
|
||
|
||
|
||
Reserved Notation "a ≪ b" (at level 70).
|
||
Reserved Notation "a ⋖ b" (at level 70).
|
||
Inductive CoqLEq : PTm -> PTm -> Prop :=
|
||
| CLE_UnivCong i j :
|
||
i <= j ->
|
||
(* -------------------------- *)
|
||
PUniv i ⋖ PUniv j
|
||
|
||
| CLE_PiCong A0 A1 B0 B1 :
|
||
A1 ≪ A0 ->
|
||
B0 ≪ B1 ->
|
||
(* ---------------------------- *)
|
||
PBind PPi A0 B0 ⋖ PBind PPi A1 B1
|
||
|
||
| CLE_SigCong A0 A1 B0 B1 :
|
||
A0 ≪ A1 ->
|
||
B0 ≪ B1 ->
|
||
(* ---------------------------- *)
|
||
PBind PSig A0 B0 ⋖ PBind PSig A1 B1
|
||
|
||
| CLE_NatCong :
|
||
PNat ⋖ PNat
|
||
|
||
| CLE_NeuNeu a0 a1 :
|
||
a0 ∼ a1 ->
|
||
a0 ⋖ a1
|
||
|
||
with CoqLEq_R : PTm -> PTm -> Prop :=
|
||
| CLE_HRed a a' b b' :
|
||
rtc HRed.R a a' ->
|
||
rtc HRed.R b b' ->
|
||
a' ⋖ b' ->
|
||
(* ----------------------- *)
|
||
a ≪ b
|
||
where "a ≪ b" := (CoqLEq_R a b) and "a ⋖ b" := (CoqLEq a b).
|
||
|
||
Scheme coqleq_ind := Induction for CoqLEq Sort Prop
|
||
with coqleq_r_ind := Induction for CoqLEq_R Sort Prop.
|
||
|
||
Combined Scheme coqleq_mutual from coqleq_ind, coqleq_r_ind.
|
||
|
||
Definition salgo_metric k (a b : PTm ) :=
|
||
exists i j va vb, nsteps LoRed.R i a va /\ nsteps LoRed.R j b vb /\ nf va /\ nf vb /\ ESub.R va vb /\ size_PTm va + size_PTm vb + i + j <= k.
|
||
|
||
Lemma salgo_metric_algo_metric k (a b : PTm) :
|
||
ishne a \/ ishne b ->
|
||
salgo_metric k a b ->
|
||
algo_metric k a b.
|
||
Proof.
|
||
move => h.
|
||
move => [i][j][va][vb][hva][hvb][nva][nvb][hS]sz.
|
||
rewrite/ESub.R in hS.
|
||
move : hS => [va'][vb'][h0][h1]h2.
|
||
suff : va' = vb' by sauto lq:on.
|
||
have {}hva : rtc RERed.R a va by hauto lq:on use:@relations.rtc_nsteps, REReds.FromRReds, LoReds.ToRReds.
|
||
have {}hvb : rtc RERed.R b vb by hauto lq:on use:@relations.rtc_nsteps, REReds.FromRReds, LoReds.ToRReds.
|
||
apply REReds.FromEReds in h0, h1.
|
||
have : ishne va' \/ ishne vb' by
|
||
hauto lq:on rew:off use:@relations.rtc_transitive, REReds.hne_preservation.
|
||
hauto lq:on use:Sub1.hne_refl.
|
||
Qed.
|
||
|
||
Lemma coqleq_sound_mutual :
|
||
(forall (a b : PTm), a ⋖ b -> forall Γ i, Γ ⊢ a ∈ PUniv i -> Γ ⊢ b ∈ PUniv i -> Γ ⊢ a ≲ b ) /\
|
||
(forall (a b : PTm), a ≪ b -> forall Γ i, Γ ⊢ a ∈ PUniv i -> Γ ⊢ b ∈ PUniv i -> Γ ⊢ a ≲ b ).
|
||
Proof.
|
||
apply coqleq_mutual.
|
||
- hauto lq:on use:wff_mutual ctrs:LEq.
|
||
- move => A0 A1 B0 B1 hA ihA hB ihB Γ i.
|
||
move /Bind_Univ_Inv => [hA0]hB0 /Bind_Univ_Inv [hA1]hB1.
|
||
have hlA : Γ ⊢ A1 ≲ A0 by sfirstorder.
|
||
have hΓ : ⊢ Γ by sfirstorder use:wff_mutual.
|
||
apply Su_Transitive with (B := PBind PPi A1 B0).
|
||
by apply : Su_Pi; eauto using E_Refl, Su_Eq.
|
||
apply : Su_Pi; eauto using E_Refl, Su_Eq.
|
||
apply : ihB; eauto using ctx_eq_subst_one.
|
||
- move => A0 A1 B0 B1 hA ihA hB ihB Γ i.
|
||
move /Bind_Univ_Inv => [hA0]hB0 /Bind_Univ_Inv [hA1]hB1.
|
||
have hlA : Γ ⊢ A0 ≲ A1 by sfirstorder.
|
||
have hΓ : ⊢ Γ by sfirstorder use:wff_mutual.
|
||
apply Su_Transitive with (B := PBind PSig A0 B1).
|
||
apply : Su_Sig; eauto using E_Refl, Su_Eq.
|
||
apply : ihB; by eauto using ctx_eq_subst_one.
|
||
apply : Su_Sig; eauto using E_Refl, Su_Eq.
|
||
- sauto lq:on use:coqeq_sound_mutual, Su_Eq.
|
||
- sauto lq:on use:coqeq_sound_mutual, Su_Eq.
|
||
- move => a a' b b' ? ? ? ih Γ i ha hb.
|
||
have /Su_Eq ? : Γ ⊢ a ≡ a' ∈ PUniv i by sfirstorder use:HReds.ToEq.
|
||
have /E_Symmetric /Su_Eq ? : Γ ⊢ b ≡ b' ∈ PUniv i by sfirstorder use:HReds.ToEq.
|
||
suff : Γ ⊢ a' ≲ b' by eauto using Su_Transitive.
|
||
eauto using HReds.preservation.
|
||
Qed.
|
||
|
||
Lemma salgo_metric_case k (a b : PTm ) :
|
||
salgo_metric k a b ->
|
||
(ishf a \/ ishne a) \/ exists k' a', HRed.R a a' /\ salgo_metric k' a' b /\ k' < k.
|
||
Proof.
|
||
move=>[i][j][va][vb][h0] [h1][h2][h3][[v [h4 h5]]] h6.
|
||
case : a h0 => //=; try firstorder.
|
||
- inversion h0 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.AppAbs unfold:algo_metric solve+:lia.
|
||
+ hauto q:on ctrs:HRed.R use: hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder qb:on use:ne_hne.
|
||
- inversion h0 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.ProjPair unfold:algo_metric solve+:lia.
|
||
+ hauto q:on ctrs:HRed.R use: hf_hred_lored unfold:algo_metric solve+:lia.
|
||
- inversion h0 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.IndZero unfold:algo_metric solve+:lia.
|
||
+ hauto lq:on ctrs:HRed.R use:hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder use:ne_hne.
|
||
+ hauto lq:on ctrs:HRed.R use:hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder use:ne_hne.
|
||
+ sfirstorder use:ne_hne.
|
||
Qed.
|
||
|
||
Lemma CLE_HRedL (a a' b : PTm ) :
|
||
HRed.R a a' ->
|
||
a' ≪ b ->
|
||
a ≪ b.
|
||
Proof.
|
||
hauto lq:on ctrs:rtc, CoqLEq_R inv:CoqLEq_R.
|
||
Qed.
|
||
|
||
Lemma CLE_HRedR (a a' b : PTm) :
|
||
HRed.R a a' ->
|
||
b ≪ a' ->
|
||
b ≪ a.
|
||
Proof.
|
||
hauto lq:on ctrs:rtc, CoqLEq_R inv:CoqLEq_R.
|
||
Qed.
|
||
|
||
|
||
Lemma algo_metric_caseR k (a b : PTm) :
|
||
salgo_metric k a b ->
|
||
(ishf b \/ ishne b) \/ exists k' b', HRed.R b b' /\ salgo_metric k' a b' /\ k' < k.
|
||
Proof.
|
||
move=>[i][j][va][vb][h0] [h1][h2][h3][[v [h4 h5]]] h6.
|
||
case : b h1 => //=; try by firstorder.
|
||
- inversion 1 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto q:on use:HRed.AppAbs unfold:salgo_metric solve+:lia.
|
||
+ hauto q:on ctrs:HRed.R use: hf_hred_lored unfold:salgo_metric solve+:lia.
|
||
+ sfirstorder qb:on use:ne_hne.
|
||
- inversion 1 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.ProjPair unfold:algo_metric solve+:lia.
|
||
+ hauto q:on ctrs:HRed.R use: hf_hred_lored unfold:algo_metric solve+:lia.
|
||
- inversion 1 as [|A B C D E F]; subst.
|
||
hauto qb:on use:ne_hne.
|
||
inversion E; subst => /=.
|
||
+ hauto lq:on use:HRed.IndZero unfold:algo_metric solve+:lia.
|
||
+ hauto lq:on ctrs:HRed.R use:hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder use:ne_hne.
|
||
+ hauto lq:on ctrs:HRed.R use:hf_hred_lored unfold:algo_metric solve+:lia.
|
||
+ sfirstorder use:ne_hne.
|
||
+ sfirstorder use:ne_hne.
|
||
Qed.
|
||
|
||
Lemma salgo_metric_sub k (a b : PTm) :
|
||
salgo_metric k a b ->
|
||
Sub.R a b.
|
||
Proof.
|
||
rewrite /algo_metric.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][[va' [vb' [hva [hvb hS]]]]]h5.
|
||
have {}h0 : rtc LoRed.R a va by hauto lq:on use:@relations.rtc_nsteps.
|
||
have {}h1 : rtc LoRed.R b vb by hauto lq:on use:@relations.rtc_nsteps.
|
||
apply REReds.FromEReds in hva,hvb.
|
||
apply LoReds.ToRReds in h0,h1.
|
||
apply REReds.FromRReds in h0,h1.
|
||
rewrite /Sub.R. exists va', vb'. sfirstorder use:@relations.rtc_transitive.
|
||
Qed.
|
||
|
||
Lemma salgo_metric_pi k (A0 : PTm) B0 A1 B1 :
|
||
salgo_metric k (PBind PPi A0 B0) (PBind PPi A1 B1) ->
|
||
exists j, j < k /\ salgo_metric j A1 A0 /\ salgo_metric j B0 B1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5.
|
||
move : lored_nsteps_bind_inv h0 => /[apply].
|
||
move => [i0][i1][a2][b2][?][?][?][ha02]hb02. subst.
|
||
move : lored_nsteps_bind_inv h1 => /[apply].
|
||
move => [j0][j1][a3][b3][?][?][?][ha13]hb13. subst.
|
||
move /ESub.pi_inj : h4 => [? ?].
|
||
hauto qb:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma salgo_metric_sig k (A0 : PTm) B0 A1 B1 :
|
||
salgo_metric k (PBind PSig A0 B0) (PBind PSig A1 B1) ->
|
||
exists j, j < k /\ salgo_metric j A0 A1 /\ salgo_metric j B0 B1.
|
||
Proof.
|
||
move => [i][j][va][vb][h0][h1][h2][h3][h4]h5.
|
||
move : lored_nsteps_bind_inv h0 => /[apply].
|
||
move => [i0][i1][a2][b2][?][?][?][ha02]hb02. subst.
|
||
move : lored_nsteps_bind_inv h1 => /[apply].
|
||
move => [j0][j1][a3][b3][?][?][?][ha13]hb13. subst.
|
||
move /ESub.sig_inj : h4 => [? ?].
|
||
hauto qb:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma coqleq_complete' k (a b : PTm ) :
|
||
salgo_metric k a b -> (forall Γ i, Γ ⊢ a ∈ PUniv i -> Γ ⊢ b ∈ PUniv i -> a ≪ b).
|
||
Proof.
|
||
move : k a b.
|
||
elim /Wf_nat.lt_wf_ind.
|
||
move => n ih.
|
||
move => a b /[dup] h /salgo_metric_case.
|
||
(* Cases where a and b can take steps *)
|
||
case; cycle 1.
|
||
move : a b h.
|
||
qauto l:on use:HRed.preservation, CLE_HRedL, hred_hne.
|
||
case /algo_metric_caseR : (h); cycle 1.
|
||
qauto l:on use:HRed.preservation, CLE_HRedR, hred_hne.
|
||
(* Cases where neither a nor b can take steps *)
|
||
case => fb; case => fa.
|
||
- case : a fa h => //=; try hauto depth:1 lq:on use:T_AbsUniv_Imp', T_PairUniv_Imp'.
|
||
+ case : b fb => //=; try hauto depth:1 lq:on use:T_AbsUniv_Imp', T_PairUniv_Imp'.
|
||
* move => p0 A0 B0 _ p1 A1 B1 _.
|
||
move => h.
|
||
have ? : p1 = p0 by
|
||
hauto lq:on rew:off use:salgo_metric_sub, Sub.bind_inj.
|
||
subst.
|
||
case : p0 h => //=.
|
||
** move /salgo_metric_pi.
|
||
move => [j [hj [hA hB]]] Γ i.
|
||
move /Bind_Univ_Inv => [hA1 hB1] /Bind_Univ_Inv [hA0 hB0].
|
||
have ihA : A0 ≪ A1 by hauto l:on.
|
||
econstructor; eauto using E_Refl; constructor=> //.
|
||
have ihA' : Γ ⊢ A0 ≲ A1 by hauto l:on use:coqleq_sound_mutual.
|
||
suff : (cons A0 Γ) ⊢ B1 ∈ PUniv i
|
||
by hauto l:on.
|
||
eauto using ctx_eq_subst_one.
|
||
** move /salgo_metric_sig.
|
||
move => [j [hj [hA hB]]] Γ i.
|
||
move /Bind_Univ_Inv => [hA1 hB1] /Bind_Univ_Inv [hA0 hB0].
|
||
have ihA : A1 ≪ A0 by hauto l:on.
|
||
econstructor; eauto using E_Refl; constructor=> //.
|
||
have ihA' : Γ ⊢ A1 ≲ A0 by hauto l:on use:coqleq_sound_mutual.
|
||
suff : (cons A1 Γ) ⊢ B0 ∈ PUniv i
|
||
by hauto l:on.
|
||
eauto using ctx_eq_subst_one.
|
||
* hauto lq:on use:salgo_metric_sub, Sub.bind_univ_noconf.
|
||
* hauto lq:on use:salgo_metric_sub, Sub.nat_bind_noconf.
|
||
* move => _ > _ /salgo_metric_sub.
|
||
hauto lq:on rew:off use:REReds.bind_inv, REReds.zero_inv inv:Sub1.R.
|
||
* hauto lq:on rew:off use:REReds.bind_inv, REReds.suc_inv, salgo_metric_sub inv:Sub1.R.
|
||
+ case : b fb => //=; try hauto depth:1 lq:on use:T_AbsUniv_Imp', T_PairUniv_Imp'.
|
||
* hauto lq:on use:salgo_metric_sub, Sub.univ_bind_noconf.
|
||
* move => *. econstructor; eauto using rtc_refl.
|
||
hauto lq:on use:salgo_metric_sub, Sub.univ_inj, CLE_UnivCong.
|
||
* hauto lq:on rew:off use:REReds.univ_inv, REReds.nat_inv, salgo_metric_sub inv:Sub1.R.
|
||
* hauto lq:on rew:off use:REReds.univ_inv, REReds.zero_inv, salgo_metric_sub inv:Sub1.R.
|
||
* hauto lq:on rew:off use:REReds.suc_inv, REReds.univ_inv, salgo_metric_sub inv:Sub1.R.
|
||
(* Both cases are impossible *)
|
||
+ case : b fb => //=.
|
||
* hauto lq:on use:T_AbsNat_Imp.
|
||
* hauto lq:on use:T_PairNat_Imp.
|
||
* hauto lq:on rew:off use:REReds.nat_inv, REReds.bind_inv, salgo_metric_sub inv:Sub1.R.
|
||
* hauto lq:on rew:off use:REReds.nat_inv, REReds.univ_inv, salgo_metric_sub inv:Sub1.R.
|
||
* hauto l:on.
|
||
* hauto lq:on rew:off use:REReds.nat_inv, REReds.zero_inv, salgo_metric_sub inv:Sub1.R.
|
||
* hauto lq:on rew:off use:REReds.nat_inv, REReds.suc_inv, salgo_metric_sub inv:Sub1.R.
|
||
+ move => ? ? Γ i /Zero_Inv.
|
||
clear.
|
||
move /synsub_to_usub => [_ [_ ]].
|
||
hauto lq:on rew:off use:REReds.nat_inv, REReds.univ_inv inv:Sub1.R.
|
||
+ move => ? _ _ Γ i /Suc_Inv => [[_]].
|
||
move /synsub_to_usub.
|
||
hauto lq:on rew:off use:REReds.nat_inv, REReds.univ_inv inv:Sub1.R.
|
||
- have {}h : DJoin.R a b by
|
||
hauto lq:on use:salgo_metric_algo_metric, algo_metric_join.
|
||
case : b fb h => //=; try hauto depth:1 lq:on use:T_AbsUniv_Imp', T_PairUniv_Imp'.
|
||
+ hauto lq:on use:DJoin.hne_bind_noconf.
|
||
+ hauto lq:on use:DJoin.hne_univ_noconf.
|
||
+ hauto lq:on use:DJoin.hne_nat_noconf.
|
||
+ move => _ _ Γ i _.
|
||
move /Zero_Inv.
|
||
hauto q:on use:REReds.nat_inv, REReds.univ_inv, synsub_to_usub inv:Sub1.R.
|
||
+ move => p _ _ Γ i _ /Suc_Inv.
|
||
hauto q:on use:REReds.nat_inv, REReds.univ_inv, synsub_to_usub inv:Sub1.R.
|
||
- have {}h : DJoin.R b a by
|
||
hauto lq:on use:salgo_metric_algo_metric, algo_metric_join, DJoin.symmetric.
|
||
case : a fa h => //=; try hauto depth:1 lq:on use:T_AbsUniv_Imp', T_PairUniv_Imp'.
|
||
+ hauto lq:on use:DJoin.hne_bind_noconf.
|
||
+ hauto lq:on use:DJoin.hne_univ_noconf.
|
||
+ hauto lq:on use:DJoin.hne_nat_noconf.
|
||
+ move => _ _ Γ i.
|
||
move /Zero_Inv.
|
||
hauto q:on use:REReds.nat_inv, REReds.univ_inv, synsub_to_usub inv:Sub1.R.
|
||
+ move => p _ _ Γ i /Suc_Inv.
|
||
hauto q:on use:REReds.nat_inv, REReds.univ_inv, synsub_to_usub inv:Sub1.R.
|
||
- move => Γ i ha hb.
|
||
econstructor; eauto using rtc_refl.
|
||
apply CLE_NeuNeu. move {ih}.
|
||
have {}h : algo_metric n a b by
|
||
hauto lq:on use:salgo_metric_algo_metric.
|
||
eapply coqeq_complete'; eauto.
|
||
Qed.
|
||
|
||
Lemma coqleq_complete Γ (a b : PTm) :
|
||
Γ ⊢ a ≲ b -> a ≪ b.
|
||
Proof.
|
||
move => h.
|
||
suff : exists k, salgo_metric k a b by hauto lq:on use:coqleq_complete', regularity.
|
||
eapply fundamental_theorem in h.
|
||
move /logrel.SemLEq_SN_Sub : h.
|
||
move => h.
|
||
have : exists va vb : PTm ,
|
||
rtc LoRed.R a va /\
|
||
rtc LoRed.R b vb /\ nf va /\ nf vb /\ ESub.R va vb
|
||
by hauto l:on use:Sub.standardization_lo.
|
||
move => [va][vb][hva][hvb][nva][nvb]hj.
|
||
move /relations.rtc_nsteps : hva => [i hva].
|
||
move /relations.rtc_nsteps : hvb => [j hvb].
|
||
exists (i + j + size_PTm va + size_PTm vb).
|
||
hauto lq:on solve+:lia.
|
||
Qed.
|
||
|
||
Lemma coqleq_sound : forall Γ (a b : PTm) i j,
|
||
Γ ⊢ a ∈ PUniv i -> Γ ⊢ b ∈ PUniv j -> a ≪ b -> Γ ⊢ a ≲ b.
|
||
Proof.
|
||
move => Γ a b i j.
|
||
have [*] : i <= i + j /\ j <= i + j by lia.
|
||
have : Γ ⊢ a ∈ PUniv (i + j) /\ Γ ⊢ b ∈ PUniv (i + j)
|
||
by sfirstorder use:T_Univ_Raise.
|
||
sfirstorder use:coqleq_sound_mutual.
|
||
Qed.
|