Library MetaCoq.PCUIC.PCUICReduction




Parallel reduction and confluence

For this notion of reductions, theses are the atoms that reduce to themselves:

Definition atom t :=
  match t with
  | tRel _
  | tVar _
  | tSort _
  | tConst _ _
  | tInd _ _
  | tConstruct _ _ _true
  | _false
  end.

Simple lemmas about reduction

Lemma red1_red (Σ : global_env) Γ t u : red1 Σ Γ t u red Σ Γ t u.

Lemma red_step Σ Γ t u v : red1 Σ Γ t u red Σ Γ u v red Σ Γ t v.

Lemma red_alt@{i j +} Σ Γ t u : red Σ Γ t u <~> clos_refl_trans@{i j} (red1 Σ Γ) t u.

Lemma red_trans Σ Γ t u v : red Σ Γ t u red Σ Γ u v red Σ Γ t v.

Instance red_Transitive Σ Γ : Transitive (red Σ Γ).

Generic method to show that a relation is closed by congruence using a notion of one-hole context.

Section ReductionCongruence.
  Context {Σ : global_env}.

  Inductive term_context : Set :=
  | tCtxHole : term_context
  | tCtxEvar : nat list_context term_context
  | tCtxProd_l : name term_context term term_context
  | tCtxProd_r : name term term_context term_context
  | tCtxLambda_l : name term_context term term_context
  | tCtxLambda_r : name term term_context term_context
  | tCtxLetIn_l : name term_context term
                    term term_context
  | tCtxLetIn_b : name term term_context
                    term term_context
  | tCtxLetIn_r : name term term
                    term_context term_context
  | tCtxApp_l : term_context term term_context
  | tCtxApp_r : term term_context term_context
  | tCtxCase_pred : (inductive × nat) term_context
                          term list (nat × term) term_context
  | tCtxCase_discr : (inductive × nat) term
                  term_context list (nat × term) term_context
  | tCtxCase_branch : (inductive × nat) term
                            term list_nat_context term_context
  | tCtxProj : projection term_context term_context
  
  

  with list_context : Set :=
   | tCtxHead : term_context list term list_context
   | tCtxTail : term list_context list_context

  with list_nat_context : Set :=
   | tCtxHead_nat : (nat × term_context) list (nat × term) list_nat_context
   | tCtxTail_nat : (nat × term) list_nat_context list_nat_context.



  Section FillContext.
    Context (t : term).

    Equations fill_context (ctx : term_context) : term by struct ctx := {
    | tCtxHolet;
    | tCtxEvar n ltEvar n (fill_list_context l);
    | tCtxProd_l na ctx btProd na (fill_context ctx) b;
    | tCtxProd_r na ty ctxtProd na ty (fill_context ctx);
    | tCtxLambda_l na ty btLambda na (fill_context ty) b;
    | tCtxLambda_r na ty btLambda na ty (fill_context b);
    | tCtxLetIn_l na b ty b'tLetIn na (fill_context b) ty b';
    | tCtxLetIn_b na b ty b'tLetIn na b (fill_context ty) b';
    | tCtxLetIn_r na b ty b'tLetIn na b ty (fill_context b');
    | tCtxApp_l f atApp (fill_context f) a;
    | tCtxApp_r f atApp f (fill_context a);
    | tCtxCase_pred par p c brstCase par (fill_context p) c brs;
    | tCtxCase_discr par p c brstCase par p (fill_context c) brs;
    | tCtxCase_branch par p c brstCase par p c (fill_list_nat_context brs);
    | tCtxProj p ctProj p (fill_context c) }
    
    

    with fill_list_context (l : list_context) : list term by struct l :=
    { fill_list_context (tCtxHead ctx l) ⇒ (fill_context ctx) :: l;
      fill_list_context (tCtxTail hd ctx) ⇒ hd :: fill_list_context ctx }

    with fill_list_nat_context (l : list_nat_context) : list (nat × term) by struct l :=
    { fill_list_nat_context (tCtxHead_nat (n, ctx) l) ⇒ (n, fill_context ctx) :: l;
      fill_list_nat_context (tCtxTail_nat hd ctx) ⇒ hd :: fill_list_nat_context ctx }.


    Equations hole_context (ctx : term_context) (Γ : context) : context by struct ctx := {
    | tCtxHole | ΓΓ;
    | tCtxEvar n l | Γhole_list_context l Γ;
    | tCtxProd_l na ctx b | Γhole_context ctx Γ;
    | tCtxProd_r na ty ctx | Γhole_context ctx (Γ ,, vass na ty);
    | tCtxLambda_l na ty b | Γhole_context ty Γ;
    | tCtxLambda_r na ty b | Γhole_context b (Γ ,, vass na ty);
    | tCtxLetIn_l na b ty b' | Γhole_context b Γ;
    | tCtxLetIn_b na b ty b' | Γhole_context ty Γ;
    | tCtxLetIn_r na b ty b' | Γhole_context b' (Γ ,, vdef na b ty);
    | tCtxApp_l f a | Γhole_context f Γ;
    | tCtxApp_r f a | Γhole_context a Γ;
    | tCtxCase_pred par p c brs | Γhole_context p Γ;
    | tCtxCase_discr par p c brs | Γhole_context c Γ;
    | tCtxCase_branch par p c brs | Γhole_list_nat_context brs Γ;
    | tCtxProj p c | Γhole_context c Γ }
    
    

    with hole_list_context (l : list_context) (Γ : context) : context by struct l :=
    { hole_list_context (tCtxHead ctx l) Γhole_context ctx Γ;
      hole_list_context (tCtxTail hd ctx) Γhole_list_context ctx Γ }

    with hole_list_nat_context (l : list_nat_context) (Γ : context) : context by struct l :=
    { hole_list_nat_context (tCtxHead_nat (n, ctx) l) Γhole_context ctx Γ;
      hole_list_nat_context (tCtxTail_nat hd ctx) Γhole_list_nat_context ctx Γ }.


  End FillContext.

  Inductive contextual_closure (red : Γ, term term Type) : context term term Type :=
  | ctxclos_atom Γ t : atom t contextual_closure red Γ t t
  | ctxclos_ctx Γ (ctx : term_context) (u u' : term) :
      red (hole_context ctx Γ) u u' contextual_closure red Γ (fill_context u ctx) (fill_context u' ctx).

  Lemma red_contextual_closure Γ t u : red Σ Γ t u contextual_closure (red Σ) Γ t u.


  Lemma contextual_closure_red Γ t u : contextual_closure (red Σ) Γ t u red Σ Γ t u.

  Theorem red_contextual_closure_equiv Γ t u : red Σ Γ t u <~> contextual_closure (red Σ) Γ t u.


  Lemma red_ctx {Γ} {M M'} ctx : red Σ (hole_context ctx Γ) M M'
                               red Σ Γ (fill_context M ctx) (fill_context M' ctx).

  Section Congruences.

    Inductive redl Γ {A} l : list (term × A) Type :=
    | refl_redl : redl Γ l l
    | trans_redl :
         l1 l2,
          redl Γ l l1
          OnOne2 (Trel_conj (on_Trel (red1 Σ Γ) fst) (on_Trel eq snd)) l1 l2
          redl Γ l l2.

    Lemma OnOne2_red_redl :
       Γ A (l l' : list (term × A)),
        OnOne2 (Trel_conj (on_Trel (red Σ Γ) fst) (on_Trel eq snd)) l l'
        redl Γ l l'.

    Lemma OnOne2_on_Trel_eq_red_redl :
       Γ A B (f : A term) (g : A B) l l',
        OnOne2 (on_Trel_eq (red Σ Γ) f g) l l'
        redl Γ (map (fun x(f x, g x)) l) (map (fun x(f x, g x)) l').

    Lemma OnOne2_prod_inv :
       A (P : A A Type) Q l l',
        OnOne2 (Trel_conj P Q) l l'
        OnOne2 P l l' × OnOne2 Q l l'.

    Lemma OnOne2_prod_inv_refl_r :
       A (P Q : A A Type) l l',
        ( x, Q x x)
        OnOne2 (Trel_conj P Q) l l'
        OnOne2 P l l' × All2 Q l l'.

    Lemma All2_eq :
       A (l l' : list A),
        All2 eq l l'
        l = l'.

    Lemma list_split_eq :
       A B (l l' : list (A × B)),
        map fst l = map fst l'
        map snd l = map snd l'
        l = l'.

    Notation swap := (fun x(snd x, fst x)).

    Lemma list_map_swap_eq :
       A B (l l' : list (A × B)),
        map swap l = map swap l'
        l = l'.

    Lemma map_swap_invol :
       A B (l : list (A × B)),
        l = map swap (map swap l).

    Lemma map_inj :
       A B (f : A B) l l',
        ( x y, f x = f y x = y)
        map f l = map f l'
        l = l'.

    Context {Γ : context}.

    Lemma red_abs na M M' N N' : red Σ Γ M M' red Σ (Γ ,, vass na M') N N'
                                               red Σ Γ (tLambda na M N) (tLambda na M' N').

    Lemma red_app M0 M1 N0 N1 :
      red Σ Γ M0 M1
      red Σ Γ N0 N1
      red Σ Γ (tApp M0 N0) (tApp M1 N1).

    Fixpoint mkApps_context l :=
      match l with
      | []tCtxHole
      | hd :: tltCtxApp_l (mkApps_context tl) hd
      end.

    Lemma mkApps_context_hole l Γ' : hole_context (mkApps_context (List.rev l)) Γ' = Γ'.

    Lemma fill_mkApps_context M l : fill_context M (mkApps_context (List.rev l)) = mkApps M l.

    Lemma red1_mkApps_f :
       t u l,
        red1 Σ Γ t u
        red1 Σ Γ (mkApps t l) (mkApps u l).

    Corollary red_mkApps_f :
       t u l,
        red Σ Γ t u
        red Σ Γ (mkApps t l) (mkApps u l).

    Lemma red_mkApps M0 M1 N0 N1 :
      red Σ Γ M0 M1
      All2 (red Σ Γ) N0 N1
      red Σ Γ (mkApps M0 N0) (mkApps M1 N1).

    Lemma red_letin na d0 d1 t0 t1 b0 b1 :
      red Σ Γ d0 d1 red Σ Γ t0 t1 red Σ (Γ ,, vdef na d1 t1) b0 b1
      red Σ Γ (tLetIn na d0 t0 b0) (tLetIn na d1 t1 b1).

    Lemma red_case_p :
       indn p c brs p',
        red Σ Γ p p'
        red Σ Γ (tCase indn p c brs) (tCase indn p' c brs).

    Lemma red_case_c :
       indn p c brs c',
        red Σ Γ c c'
        red Σ Γ (tCase indn p c brs) (tCase indn p c' brs).

    Lemma red_case_one_brs :
       indn p c brs brs',
        OnOne2 (on_Trel_eq (red Σ Γ) snd fst) brs brs'
        red Σ Γ (tCase indn p c brs) (tCase indn p c brs').

    Inductive rtrans_clos {A} (R : A A Type) (x : A) : A Type :=
    | rtrans_clos_refl : rtrans_clos R x x
    | rtrans_clos_trans :
         y z,
          rtrans_clos R x y
          R y z
          rtrans_clos R x z.

    Lemma All2_many_OnOne2 :
       A (R : A A Type) l l',
        All2 R l l'
        rtrans_clos (OnOne2 R) l l'.

    Lemma red_case_brs :
       indn p c brs brs',
        All2 (on_Trel_eq (red Σ Γ) snd fst) brs brs'
        red Σ Γ (tCase indn p c brs) (tCase indn p c brs').


    Lemma All2_ind_OnOne2 {A} P (l l' : list A) :
      All2 P l l'
       x a a', nth_error l x = Some a
                     nth_error l' x = Some a'
                     OnOne2 P (firstn x l ++ [a] ++ skipn (S x) l)%list
                            (firstn x l ++ [a'] ++ skipn (S x) l)%list.

    Lemma reds_case :
       indn p c brs p' c' brs',
        red Σ Γ p p'
        red Σ Γ c c'
        All2 (on_Trel_eq (red Σ Γ) snd fst) brs brs'
        red Σ Γ (tCase indn p c brs) (tCase indn p' c' brs').

    Lemma red1_it_mkLambda_or_LetIn :
       Δ u v,
        red1 Σ (Γ ,,, Δ) u v
        red1 Σ Γ (it_mkLambda_or_LetIn Δ u)
             (it_mkLambda_or_LetIn Δ v).

    Lemma red_it_mkLambda_or_LetIn :
       Δ u v,
        red Σ (Γ ,,, Δ) u v
        red Σ Γ (it_mkLambda_or_LetIn Δ u)
            (it_mkLambda_or_LetIn Δ v).

    Lemma red_proj_c :
       p c c',
        red Σ Γ c c'
        red Σ Γ (tProj p c) (tProj p c').

    Lemma red_fix_one_ty :
       mfix idx mfix',
        OnOne2 (on_Trel_eq (red Σ Γ) dtype (fun x(dname x, dbody x, rarg x))) mfix mfix'
        red Σ Γ (tFix mfix idx) (tFix mfix' idx).

    Lemma red_fix_ty :
       mfix idx mfix',
        All2 (on_Trel_eq (red Σ Γ) dtype (fun x(dname x, dbody x, rarg x))) mfix mfix'
        red Σ Γ (tFix mfix idx) (tFix mfix' idx).

    Lemma red_fix_one_body :
       mfix idx mfix',
        OnOne2
          (on_Trel_eq (red Σ (Γ ,,, fix_context mfix)) dbody (fun x(dname x, dtype x, rarg x)))
           mfix mfix'
        red Σ Γ (tFix mfix idx) (tFix mfix' idx).

    Lemma red_fix_body :
       mfix idx mfix',
        All2
          (on_Trel_eq (red Σ (Γ ,,, fix_context mfix)) dbody (fun x(dname x, dtype x, rarg x)))
           mfix mfix'
        red Σ Γ (tFix mfix idx) (tFix mfix' idx).

    Lemma red_fix_congr :
       mfix mfix' idx,
        All2 (fun d0 d1
                (red Σ Γ (dtype d0) (dtype d1)) ×
                (red Σ (Γ ,,, fix_context mfix) (dbody d0) (dbody d1) ×
                (dname d0, rarg d0) = (dname d1, rarg d1))
        ) mfix mfix'
      red Σ Γ (tFix mfix idx) (tFix mfix' idx).

    Lemma red_cofix_one_ty :
       mfix idx mfix',
        OnOne2 (on_Trel_eq (red Σ Γ) dtype (fun x(dname x, dbody x, rarg x))) mfix mfix'
        red Σ Γ (tCoFix mfix idx) (tCoFix mfix' idx).

    Lemma red_cofix_ty :
       mfix idx mfix',
        All2 (on_Trel_eq (red Σ Γ) dtype (fun x(dname x, dbody x, rarg x))) mfix mfix'
        red Σ Γ (tCoFix mfix idx) (tCoFix mfix' idx).

    Lemma red_cofix_one_body :
       mfix idx mfix',
        OnOne2
          (on_Trel_eq (red Σ (Γ ,,, fix_context mfix)) dbody (fun x(dname x, dtype x, rarg x)))
           mfix mfix'
        red Σ Γ (tCoFix mfix idx) (tCoFix mfix' idx).

    Lemma red_cofix_body :
       mfix idx mfix',
        All2
          (on_Trel_eq (red Σ (Γ ,,, fix_context mfix)) dbody (fun x(dname x, dtype x, rarg x)))
           mfix mfix'
        red Σ Γ (tCoFix mfix idx) (tCoFix mfix' idx).

    Lemma red_cofix_congr :
       mfix mfix' idx,
        All2 (fun d0 d1
                (red Σ Γ (dtype d0) (dtype d1)) ×
                (red Σ (Γ ,,, fix_context mfix) (dbody d0) (dbody d1) ×
                (dname d0, rarg d0) = (dname d1, rarg d1))
        ) mfix mfix'
      red Σ Γ (tCoFix mfix idx) (tCoFix mfix' idx).

    Lemma red_prod_l :
       na A B A',
        red Σ Γ A A'
        red Σ Γ (tProd na A B) (tProd na A' B).

    Lemma red_prod_r :
       na A B B',
        red Σ (Γ ,, vass na A) B B'
        red Σ Γ (tProd na A B) (tProd na A B').

    Lemma red_prod :
       na A B A' B',
        red Σ Γ A A'
        red Σ (Γ ,, vass na A) B B'
        red Σ Γ (tProd na A B) (tProd na A' B').

    Lemma OnOne2_on_Trel_eq_unit :
       A (R : A A Type) l l',
        OnOne2 R l l'
        OnOne2 (on_Trel_eq R (fun xx) (fun xtt)) l l'.

    Lemma red_one_evar :
       ev l l',
        OnOne2 (red Σ Γ) l l'
        red Σ Γ (tEvar ev l) (tEvar ev l').

    Lemma red_evar :
       ev l l',
        All2 (red Σ Γ) l l'
        red Σ Γ (tEvar ev l) (tEvar ev l').

    Lemma red_atom t : atom t red Σ Γ t t.

  End Congruences.
End ReductionCongruence.



Lemma OnOne2_All2 {A}:
   (ts ts' : list A) P Q,
    OnOne2 P ts ts'
    ( x y, P x y Q x y)%type
    ( x, Q x x)
    All2 Q ts ts'.