Library hydras.rpo.term

by Evelyne Contejean, LRI

Term algebra defined as functor from a Module Signature and a Module Variable.


From Coq Require Import List Arith.
From hydras Require Import more_list list_permut list_set.

Set Implicit Arguments.

Module Type Signature.

There are almost no assumptions, except a decidable equality and an arity function.
Module Type Signature.

  Parameter symb : Set.
  Axiom eq_symbol_dec : f1 f2 : symb, {f1 = f2} + {f1 f2}.

The arity of a symbol contains also the information about built-in theories as in CiME
  Inductive arity_type : Set :=
  | AC : arity_type
  | C : arity_type
  | Free : nat arity_type.

  Parameter arity : symb arity_type.
End Signature.

Module Type Variables.

There are almost no assumptions, except a decidable equality.
Module Type Variables.

  Parameter var : Set.
  Axiom eq_variable_dec : v1 v2 : var, {v1 = v2} + {v1 v2}.

End Variables.

Module Type Term built from a signature and a set of variables.

Module Type Term.

  Declare Module F : Signature.
  Declare Module X : Variables.

  Definition symbol := F.symb.
  Definition variable := X.var.

  Import F.
  Import X.


  Ltac destruct_arity f n Af :=
    generalize (refl_equal (arity f)); pattern f at 1; destruct (arity f) as [ | | n]; intro Af.

Definition of terms. Arity is not taken into account, and terms may be hill-formed.
  Inductive term : Set :=
  | Var : variable term
  | Term : symbol list term term.

  Definition direct_subterm t1 t2 : Prop :=
    match t2 with
    | Var _False
    | Term _ lIn t1 l
    end.

Definition and a few properties of the size of a term.
  Fixpoint size (t:term) : nat :=
    match t with
    | Var v ⇒ 1
    | Term f l ⇒ 1 + fold_left (fun size_acc esize_acc + size e) l 0
    end.

  Axiom size_unfold :
     t, size t = match t with
                       | Var _ ⇒ 1
                       | Term f l ⇒ 1 + list_size size l
                       end.

  Axiom size_ge_one : t, 1 size t.

  Axiom size_direct_subterm :
     t1 t2, direct_subterm t1 t2 size t1 < size t2.

Recursion on terms.

  Section Recursion.
    Variable P : term Type.
    Variable Pl : list term Type.

    Axiom term_rec2 : ( n t, size t n P t) t, P t.
    Axiom term_rec3 :
      ( v, P (Var v)) ( f l, ( t, In t l P t) P (Term f l)) t, P t.
    Axiom term_rec4 :
      ( v, P (Var v)) ( f l, Pl l P (Term f l))
      ( l, ( t, In t l P t) Pl l) t, P t.
  End Recursion.

Double recursion on terms.

  Section DoubleRecursion.
    Variable P2 : term term Type.
    Variable Pl2 : list term list term Type.

    Axiom term_rec7 :
      ( v1 t2, P2 (Var v1) t2)
      ( t1 v2, P2 t1 (Var v2))
      ( f1 f2 l1 l2, Pl2 l1 l2 P2 (Term f1 l1) (Term f2 l2))
      ( l1 l2, ( t1 t2, In t1 l1 In t2 l2 P2 t1 t2) Pl2 l1 l2)
       t1 t2, P2 t1 t2.

    Axiom term_rec8 :
      ( v1 t2, P2 (Var v1) t2)
      ( t1 v2, P2 t1 (Var v2))
      ( f1 f2 l1 l2, Pl2 l1 l2 P2 (Term f1 l1) (Term f2 l2))
      ( l1 l2, ( t1 t2, In t1 l1 In t2 l2 P2 t1 t2) Pl2 l1 l2)
       l1 l2, Pl2 l1 l2.
  End DoubleRecursion.

Equality on terms is decidable.

  Axiom eq_term_dec : t1 t2:term, {t1 = t2} + {t1 t2}.
  Declare Module Term_eq_dec : decidable_set.S with Definition A:= term
    with Definition eq_A_dec := eq_term_dec.

Well-formedness of terms, according to the arity.

  Fixpoint well_formed (t:term) : Prop :=
    match t with
    | Var _True
    | Term f l
      let well_formed_list :=
          (fix well_formed_list (l:list term) : Prop :=
             match l with
             | nilTrue
             | h :: tlwell_formed h well_formed_list tl
             end) in
      well_formed_list l
      (match arity f with
       | Free nlength l = n
       | _length l = 2
       end)
    end.

  Axiom well_formed_unfold :
     t, well_formed t
              match t with
              | Var _True
              | Term f l
                ( u, In u l well_formed u)
                (match arity f with
                 | Free nlength l = n
                 | _length l = 2
                 end)
              end.

  Axiom well_formed_fold :
     t,
      match t with
      | Var _True
      | Term f l
        ( u, In u l well_formed u)
        (match arity f with
         | Free nlength l = n
         | _length l = 2
         end)
      end well_formed t.

  Fixpoint well_formed_list (l : list term) : Prop :=
    match l with
    | nilTrue
    | h :: tlwell_formed h well_formed_list tl
    end.

Substitutions.

  Definition substitution := list (variable × term).

  Fixpoint apply_subst (sigma : substitution) (t : term) {struct t} : term :=
    match t with
    | Var v
      match find eq_variable_dec v sigma with
      | Nonet
      | Some v_sigmav_sigma
      end
    | Term f lTerm f (map (apply_subst sigma) l)
    end.

  Axiom empty_subst_is_id : t, apply_subst nil t = t.
  Axiom empty_subst_is_id_list : l, map (apply_subst nil) l = l.

Composition of substitutions.
  Definition map_subst (f : variable term term) sigma :=
    map (fun x
           match (x : variable × term) with
           | (v, v_sigma)(v, f v v_sigma)
           end)
        sigma.

  Definition subst_comp sigma1 sigma2 :=
    (map_subst (fun _ tapply_subst sigma1 t) sigma2)
      ++
      (map_subst (fun v t
                    match find eq_variable_dec v sigma2 with
                    | Nonet
                    | Some v_sigma2apply_subst sigma1 v_sigma2
                    end)
                 sigma1).

  Axiom subst_comp_is_subst_comp_aux1 :
     v sigma f,
      find eq_variable_dec v (map_subst f sigma) =
      match find eq_variable_dec v sigma with
      | NoneNone
      | Some tSome (f v t)
      end.

  Axiom subst_comp_is_subst_comp :
     sigma1 sigma2 t,
      apply_subst (subst_comp sigma1 sigma2) t =
      apply_subst sigma1 (apply_subst sigma2 t).

Well-formed substitutions.
  Definition well_formed_subst sigma :=
     v, match find eq_variable_dec v sigma with
              | NoneTrue
              | Some twell_formed t
              end.

  Axiom well_formed_apply_subst :
     sigma, well_formed_subst sigma
                   t, well_formed t well_formed (apply_subst sigma t).

Positions in a term.

  Fixpoint is_a_pos (t : term) (p : list nat) {struct p}: bool :=
    match p with
    | niltrue
    | i :: q
      match t with
      | Var _false
      | Term _ l
        match nth_error l i with
        | Some tiis_a_pos ti q
        | Nonefalse
        end
      end
    end.

  Fixpoint subterm_at_pos (t : term) (p : list nat) {struct p}: option term :=
    match p with
    | nilSome t
    | i :: q
      match t with
      | Var _None
      | Term _ l
        match nth_error l i with
        | Some tisubterm_at_pos ti q
        | NoneNone
        end
      end
    end.

  Axiom size_subterm_at_pos :
     t i p, match subterm_at_pos t (i :: p) with
                  | Some usize u < size t
                  | NoneTrue
                  end.

  Axiom is_a_pos_exists_subtem :
     t p, is_a_pos t p = true u, subterm_at_pos t p = Some u.

  Fixpoint replace_at_pos (t u : term) (p : list nat) {struct p} : term :=
    match p with
    | nilu
    | i :: q
      match t with
      | Var _t
      | Term f l
        let replace_at_pos_list :=
            (fix replace_at_pos_list j (l : list term) {struct l}: list term :=
               match l with
               | nilnil
               | h :: tl
                 match j with
                 | O(replace_at_pos h u q) :: tl
                 | S kh :: (replace_at_pos_list k tl)
                 end
               end) in
        Term f (replace_at_pos_list i l)
      end
    end.

  Fixpoint replace_at_pos_list (l : list term) (u : term) (i : nat) (p : list nat)
           {struct l}: list term :=
    match l with
    | nilnil
    | h :: tl
      match i with
      | O(replace_at_pos h u p) :: tl
      | S jh :: (replace_at_pos_list tl u j p)
      end
    end.

  Axiom replace_at_pos_unfold :
     f l u i q,
      replace_at_pos (Term f l) u (i :: q) = Term f (replace_at_pos_list l u i q).

  Axiom replace_at_pos_is_replace_at_pos1 :
     t u p, is_a_pos t p = true
                  subterm_at_pos (replace_at_pos t u p) p = Some u.

  Axiom replace_at_pos_is_replace_at_pos2 :
     t p u, subterm_at_pos t p = Some u replace_at_pos t u p = t.

  Axiom subterm_at_pos_apply_subst_apply_subst_subterm_at_pos :
     t p sigma,
      match subterm_at_pos t p with
      | Some u
        subterm_at_pos (apply_subst sigma t) p = Some (apply_subst sigma u)
      | NoneTrue
      end.

  Axiom replace_at_pos_list_replace_at_pos_in_subterm :
     l1 ui l2 u i p, length l1 = i
                           replace_at_pos_list (l1 ++ ui :: l2) u i p =
                           l1 ++ (replace_at_pos ui u p) :: l2.

End Term.

A functor building a Term Module from a Signature and a set of Variables.


Module Make (F1 : Signature) (X1 : Variables) <:
  Term with Module F := F1 with Module X := X1.

  Module F := F1.
  Module X := X1.

  Definition symbol := F.symb.
  Definition variable := X.var.

  Import F.
  Import X.

  Module DecVar <: decidable_set.S.
    Definition A := variable.

    Lemma eq_A_dec : x y : A, { x = y } + { x y }.

  End DecVar.

  Module VSet <: list_set.S with Definition DS.A := variable :=
    list_set.Make (DecVar).

Definition of terms. Arity is not taken into account, and terms may be ill-formed.
  Inductive term : Set :=
  | Var : variable term
  | Term : symbol list term term.

  Definition direct_subterm t1 t2 : Prop :=
    match t2 with
    | Var _False
    | Term _ lIn t1 l
    end.

Definition and a few properties of the size of a term.
  Fixpoint size (t:term) : nat :=
    match t with
    | Var v ⇒ 1
    | Term f l ⇒ 1 + fold_left (fun size_acc esize_acc + size e) l 0
    end.

  Lemma size_unfold :
     t,
      size t = match t with
               | Var _ ⇒ 1
               | Term f l ⇒ 1 + list_size size l
               end.

  Lemma size_ge_one : t, 1 size t.

  Lemma size_direct_subterm :
     t1 t2, direct_subterm t1 t2 size t1 < size t2.

Recursion on terms.

  Section Recursion.
    Variable P : term Type.
    Variable Pl : list term Type.

    Definition term_rec2 : ( n t, size t n P t) t, P t.

    Definition term_rec3 :
      ( v, P (Var v)) ( f l, ( t, In t l P t) P (Term f l)) t, P t.

    Definition term_rec4 :
      ( v, P (Var v)) ( f l, Pl l P (Term f l))
      ( l, ( t, In t l P t) Pl l) t, P t.
  End Recursion.

Double recursion on terms.

  Section DoubleRecursion.
    Variable P2 : term term Type.
    Variable Pl2 : list term list term Type.

    Definition term_rec7 :
      ( v1 t2, P2 (Var v1) t2)
      ( t1 v2, P2 t1 (Var v2))
      ( f1 f2 l1 l2, Pl2 l1 l2 P2 (Term f1 l1) (Term f2 l2))
      ( l1 l2, ( t1 t2, In t1 l1 In t2 l2 P2 t1 t2) Pl2 l1 l2)
       t1 t2, P2 t1 t2.

    Definition term_rec8 :
      ( v1 t2, P2 (Var v1) t2)
      ( t1 v2, P2 t1 (Var v2))
      ( f1 f2 l1 l2, Pl2 l1 l2 P2 (Term f1 l1) (Term f2 l2))
      ( l1 l2, ( t1 t2, In t1 l1 In t2 l2 P2 t1 t2) Pl2 l1 l2)
       l1 l2, Pl2 l1 l2.
  End DoubleRecursion.

Equality on terms is decidable.

  Theorem eq_term_dec :
     t1 t2:term, {t1 = t2} + {t1 t2}.

  Module Term_eq_dec : decidable_set.S with Definition A:= term
    with Definition eq_A_dec := eq_term_dec.
    Definition A := term.
    Definition eq_A_dec := eq_term_dec.
  End Term_eq_dec.

Well-formedness of terms, according to the arity.

  Fixpoint well_formed (t:term) : Prop :=
    match t with
    | Var _True
    | Term f l
      let well_formed_list :=
          (fix well_formed_list (l:list term) : Prop :=
             match l with
             | nilTrue
             | h :: tlwell_formed h well_formed_list tl
             end) in
      well_formed_list l
      (match arity f with
       | Free nlength l = n
       | _length l = 2
       end)
    end.

  Lemma well_formed_unfold :
     t, well_formed t
              match t with
              | Var _True
              | Term f l
                ( u, In u l well_formed u)
                (match arity f with
                 | Free nlength l = n
                 | _length l = 2
                 end)
              end.

  Lemma well_formed_fold :
     t,
      match t with
      | Var _True
      | Term f l
        ( u, In u l well_formed u)
        (match arity f with
         | Free nlength l = n
         | _length l = 2
         end)
      end well_formed t.

  Fixpoint well_formed_list (l : list term) : Prop :=
    match l with
    | nilTrue
    | h :: tlwell_formed h well_formed_list tl
    end.

Substitutions.

  Definition substitution := list (variable × term).

  Fixpoint apply_subst (sigma : substitution) (t : term) {struct t} : term :=
    match t with
    | Var v
      match find eq_variable_dec v sigma with
      | Nonet
      | Some v_sigmav_sigma
      end
    | Term f lTerm f (map (apply_subst sigma) l)
    end.

  Lemma empty_subst_is_id : t, apply_subst nil t = t.

  Lemma empty_subst_is_id_list : l, map (apply_subst nil) l = l.

Composition of substitutions.
  Definition map_subst (f : variable term term) sigma :=
    map (fun x
           match (x : variable × term) with
           | (v, v_sigma)(v, f v v_sigma)
           end)
        sigma.

  Definition subst_comp sigma1 sigma2 :=
    (map_subst (fun _ tapply_subst sigma1 t) sigma2)
      ++
      (map_subst (fun v t
                    match find eq_variable_dec v sigma2 with
                    | Nonet
                    | Some v_sigma2apply_subst sigma1 v_sigma2
                    end)
                 sigma1).

  Lemma subst_comp_is_subst_comp_aux1 :
     v sigma f,
      find eq_variable_dec v (map_subst f sigma) =
      match find eq_variable_dec v sigma with
      | NoneNone
      | Some tSome (f v t)
      end.

  Lemma subst_comp_is_subst_comp_aux2 :
     v sigma1 sigma2,
      find (B:= term) eq_variable_dec v (sigma1 ++ sigma2) =
      match find eq_variable_dec v sigma1 with
      | Some _find eq_variable_dec v sigma1
      | Nonefind eq_variable_dec v sigma2
      end.

  Theorem subst_comp_is_subst_comp :
     sigma1 sigma2 t,
      apply_subst (subst_comp sigma1 sigma2) t =
      apply_subst sigma1 (apply_subst sigma2 t).

Well-formed substitutions.
  Definition well_formed_subst sigma :=
     v, match find eq_variable_dec v sigma with
              | NoneTrue
              | Some twell_formed t
              end.

  Theorem well_formed_apply_subst :
     sigma, well_formed_subst sigma
                   t, well_formed t well_formed (apply_subst sigma t).

Positions in a term.

  Fixpoint is_a_pos (t : term) (p : list nat) {struct p}: bool :=
    match p with
    | niltrue
    | i :: q
      match t with
      | Var _false
      | Term _ l
        match nth_error l i with
        | Some tiis_a_pos ti q
        | Nonefalse
        end
      end
    end.

  Fixpoint subterm_at_pos (t : term) (p : list nat) {struct p}: option term :=
    match p with
    | nilSome t
    | i :: q
      match t with
      | Var _None
      | Term _ l
        match nth_error l i with
        | Some tisubterm_at_pos ti q
        | NoneNone
        end
      end
    end.

  Lemma size_subterm_at_pos :
     t i p, match subterm_at_pos t (i :: p) with
                  | Some usize u < size t
                  | NoneTrue
                  end.

  Lemma is_a_pos_exists_subtem :
     t p, is_a_pos t p = true u, subterm_at_pos t p = Some u.

  Fixpoint replace_at_pos (t u : term) (p : list nat) {struct p} : term :=
    match p with
    | nilu
    | i :: q
      match t with
      | Var _t
      | Term f l
        let replace_at_pos_list :=
            (fix replace_at_pos_list j (l : list term) {struct l}: list term :=
               match l with
               | nilnil
               | h :: tl
                 match j with
                 | O(replace_at_pos h u q) :: tl
                 | S kh :: (replace_at_pos_list k tl)
                 end
               end) in
        Term f (replace_at_pos_list i l)
      end
    end.

  Fixpoint replace_at_pos_list (l : list term) (u : term) (i : nat) (p : list nat)
           {struct l}: list term :=
    match l with
    | nilnil
    | h :: tl
      match i with
      | O(replace_at_pos h u p) :: tl
      | S jh :: (replace_at_pos_list tl u j p)
      end
    end.

  Lemma replace_at_pos_unfold :
     f l u i q,
      replace_at_pos (Term f l) u (i :: q) = Term f (replace_at_pos_list l u i q).

  Lemma replace_at_pos_is_replace_at_pos1 :
     t u p, is_a_pos t p = true
                  subterm_at_pos (replace_at_pos t u p) p = Some u.

  Lemma replace_at_pos_is_replace_at_pos2 :
     t p u, subterm_at_pos t p = Some u replace_at_pos t u p = t.

  Lemma subterm_at_pos_apply_subst_apply_subst_subterm_at_pos :
     t p sigma,
      match subterm_at_pos t p with
      | Some u
        subterm_at_pos (apply_subst sigma t) p = Some (apply_subst sigma u)
      | NoneTrue
      end.

  Lemma replace_at_pos_list_replace_at_pos_in_subterm :
     l1 ui l2 u i p, length l1 = i
                           replace_at_pos_list (l1 ++ ui :: l2) u i p =
                           l1 ++ (replace_at_pos ui u p) :: l2.

End Make.