A proof of Higman’s lemma about finite sequences.

module Higman where

import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; refl; _≢_; sym; trans; subst)
open Eq.≡-Reasoning
open import Data.Nat using (; zero; suc; _∸_; _≤_; s≤s; z≤n; _<_)
open import Data.Nat.Properties using (≤-refl; ≤-trans; <-trans; <-irrefl; m≤n⇒m≤1+n)
open import Data.Product using (Σ; _×_; _,_; proj₁; proj₂ ; ; Σ-syntax; ∃-syntax; ∃₂)
open import Data.Sum using (_⊎_; inj₁; inj₂) renaming ([_,_]′ to case-⊎)
open import Relation.Nullary using (¬_)
open import Data.Unit using (; tt)
open import Data.Empty using (; ⊥-elim)
open import Relation.Unary using (_∈_; _⊆_)
open import Function using (_∘_; id)
open import Data.List using (List; []; _∷_; _++_; length)

open import Miscellaneous

open import Classical

open import WQO

open import MinimalBadSeq

Suffix relation, etc.
private variable
  A B : Set

data _⊑_ : List A  List A  Set where
  ⊑-refl : {xs : List A}  xs  xs
  _∷ʳ_ : {xs ys : List A} (y : A)  xs  ys  xs  (y  ys)

⊑-reflexive : Reflexive (_⊑_ {A}) -- {xs : List A} → xs ⊑ xs
⊑-reflexive = ⊑-refl

⊑-transitive : {xs ys zs : List A}  xs  ys  ys  zs  xs  zs
⊑-transitive xs⊑ys ⊑-refl = xs⊑ys
⊑-transitive xs⊑ys (z ∷ʳ ys⊑zs) = z ∷ʳ (⊑-transitive xs⊑ys ys⊑zs)

⊑-length-≤ : {xs ys : List A}  xs  ys  length xs  length ys
⊑-length-≤ ⊑-refl = ≤-refl
⊑-length-≤ (y ∷ʳ xs⊑ys) = m≤n⇒m≤1+n (⊑-length-≤ xs⊑ys)

⊏-length-< : {xs ys : List A}  (xs  ys × xs  ys)  length xs < length ys
⊏-length-< (⊑-refl , xs≢xs) = ⊥-elim (xs≢xs refl)
⊏-length-< ((y ∷ʳ xs⊑ys) , xs≢ys) = s≤s (⊑-length-≤ xs⊑ys)

elem-⊑-elem : (x : A) (xs ys : List A)  x elem xs  xs  ys  x elem ys
elem-⊑-elem x xs .xs [x]elem[xs] ⊑-refl = [x]elem[xs]
elem-⊑-elem x xs (y  ys) [x]elem[xs] (y ∷ʳ xs⊑ys) = 
  there (elem-⊑-elem x xs ys [x]elem[xs] xs⊑ys)

Sub-⊑-Sub-elem : (f g :   List A) (k :   A)
   g  Sub _⊑_ f
   k  Sub _elem_ g
  ----------------
   k  Sub _elem_ f
Sub-⊑-Sub-elem f g k (r , r-increasing , h₁) (s , s-increasing , h₂) = 
  r  s , 
  (subseq-increasing _<_ r s r-increasing s-increasing) , 
  λ n  elem-⊑-elem (k n) (g (s n)) (f (r (s n))) (h₂ n) (h₁ (s n))

Subseq-mono : ((  B)  (  A)  Set)  Set
Subseq-mono P =  f (r :   ) (r-increasing : Increasing _<_ r)
   P (f  r)  P f

Sub-Sub-elem : Subseq-mono {B = List A} (Sub _elem_)
Sub-Sub-elem f r r-increasing (r₁ , r₁-increasing , h) = 
  r  r₁ , (subseq-increasing _<_ r r₁ r-increasing r₁-increasing) ,  n  h n)

The definition of the embedding relation.

The following definition from Data.List.Relation.Binary.Sublist.Heterogeneous.Core could be used instead.

data Sublist : REL (List A) (List B) (a ⊔ b ⊔ r) where
  []   : Sublist [] []
  _∷ʳ_ : ∀ {xs ys} → ∀ y → Sublist xs ys → Sublist xs (y ∷ ys)
  _∷_  : ∀ {x xs y ys} → R x y → Sublist xs ys → Sublist (x ∷ xs) (y ∷ ys)
module _ (_≼_ : A  A  Set) where
  infixr 5 _∷_ _∷ʳ_

  data Embedding : List A  List A  Set where
    []  : Embedding [] []
    _∷ʳ_ :  {xs ys}   y  Embedding xs ys  Embedding xs (y  ys)
    _∷_ :  {x xs y ys}  x  y  Embedding xs ys  Embedding (x  xs) (y  ys)

  embedding-reflexive : Reflexive _≼_  Reflexive Embedding
  embedding-reflexive h {[]} = []
  embedding-reflexive h {x  xs} = h  embedding-reflexive h

  embedding-transitive : Transitive _≼_  Transitive Embedding
  embedding-transitive h xsys [] with xsys
  ... | [] = []
  embedding-transitive h xsys (y ∷ʳ yszs) = y ∷ʳ embedding-transitive h xsys yszs
  embedding-transitive h (_ ∷ʳ xsys) (_  yszs) = _ ∷ʳ embedding-transitive h xsys yszs
  embedding-transitive h (x≼y  xsys) (y≼z  yszs) = h x≼y y≼z  embedding-transitive h xsys yszs
  
  []-Embedding :  xs  Embedding [] xs
  []-Embedding [] = []
  []-Embedding (x  xs) = x ∷ʳ []-Embedding xs

  embedding-⊑-embedding :  {xs ys zs}  Embedding xs ys  ys  zs  Embedding xs zs
  embedding-⊑-embedding h ⊑-refl = h
  embedding-⊑-embedding h (y ∷ʳ ys⊑zs) = y ∷ʳ embedding-⊑-embedding h ys⊑zs

  elem-embedding :  {x xs ys}  x elem xs  Embedding xs ys  ∃[ y ] y elem ys × x  y
  elem-embedding h (y ∷ʳ h₁) with elem-embedding h h₁
  ... | z , h₂ , x≼z = z , there h₂ , x≼z
  elem-embedding here (_∷_ {y = y} h₁ h₂) = y , here , h₁
  elem-embedding (there h) (h₁  h₂) with elem-embedding h h₂
  ... | z , h₃ , x≼z = z , there h₃ , x≼z

  tail-⊏ : {x : A} {xs : List A}  xs  (x  xs) × xs  x  xs
  tail-⊏ {x} {xs} = x ∷ʳ ⊑-refl , λ ()

  -- ++-Embedding : ∀ {xs ys us vs}
  --   → Embedding xs ys
  --   → Embedding us vs
  --   ---------------------------------
  --   → Embedding (xs ++ us) (ys ++ vs)
  -- ++-Embedding [] h₂ = h₂
  -- ++-Embedding (y ∷ʳ h₁) h₂ = y ∷ʳ ++-Embedding h₁ h₂
  -- ++-Embedding (xy ∷ h₁) h₂ = xy ∷ ++-Embedding h₁ h₂

  embedding-isQO : IsQO _≼_  IsQO Embedding
  embedding-isQO h = 
    record
    { reflexive = embedding-reflexive (IsQO.reflexive h)
    ; transitive = embedding-transitive (IsQO.transitive h)
    }

Higman’s lemma

  sub-elem-veryGood-good : (f :   List A)
     ((g :   A)  g  Sub _elem_ f  VeryGood _≼_ g)
     Good Embedding f
  sub-elem-veryGood-good f h = ¬¬-elim not-f-bad
    where
    not-f-bad : ¬ ¬ Good Embedding f
    not-f-bad f-bad = contra
      where
      open MBS {List A} length Embedding _⊑_ ⊑-reflexive {f} f-bad
      contra : 
      contra = case-⊎ h₁ h₂ (em {∃[ i ] mbs i  []})
        where
        h₁ : ∃[ i ] mbs i  []  
        h₁ (i , mbsi≡[]) = 
          mbs-bad (i , suc i , ≤-refl , 
                  subst  z  Embedding z (mbs (suc i))) 
                        (sym mbsi≡[])
                        ([]-Embedding (mbs (suc i))))
        h₂ : ¬ (∃[ i ] mbs i  [])  
        h₂ ¬∃i = mbs-bad (i , j , i<j , emb-mbsi-mbsj)
          where
          h₃ : (i : )  mbs i  []
          h₃ i mbsi≡[] = ¬∃i (i , mbsi≡[])
          h₄ : (i : )  ∃₂  x xs  mbs i  x  xs)
          h₄ i with mbs i in eq
          ... | [] = ⊥-elim (h₃ i eq)
          ... | x  xs = x , xs , refl
          g₁ :   A
          g₁ n = proj₁ (h₄ n)
          g₂ :   List A
          g₂ n = proj₁ (proj₂ (h₄ n))
          mbs≡g₁∷g₂ : (n : )  mbs n  g₁ n  g₂ n
          mbs≡g₁∷g₂ n = proj₂ (proj₂ (h₄ n))
          g₁∈Sub-elem-mbs : g₁  Sub _elem_ mbs
          g₁∈Sub-elem-mbs = id , id-increasing , h₅
            where
            h₅ : (n : )  g₁ n elem mbs n
            h₅ n = subst  z  (proj₁ (h₄ n)) elem z) (sym (mbs≡g₁∷g₂ n))
                          (here {x = proj₁ (h₄ n)} {xs = proj₁ (proj₂ (h₄ n))})
          g₁∈Sub-elem-f : g₁  Sub _elem_ f
          g₁∈Sub-elem-f = Sub-⊑-Sub-elem f mbs g₁ mbs-sub-⊑ g₁∈Sub-elem-mbs
          g₁-veryGood : VeryGood _≼_ g₁
          g₁-veryGood = h g₁ g₁∈Sub-elem-f
          open Sub-⊑-⊏ ⊏-length-< embedding-⊑-embedding ⊑-transitive
          g₂∈Sub-⊏-mbs : g₂  Sub _⊏_ mbs
          g₂∈Sub-⊏-mbs = 
            id , id-increasing , 
            λ n  subst (g₂ n ⊏_) (sym (mbs≡g₁∷g₂ n)) (tail-⊏ {x = g₁ n} {xs = g₂ n})
          g₂-veryGood : VeryGood Embedding g₂
          g₂-veryGood = Sub-⊏-mbs⇒VeryGood g₂ g₂∈Sub-⊏-mbs
          g₁g₂-veryGood : VeryGood (prodOrder _≼_ Embedding)  n  g₁ n , g₂ n)
          g₁g₂-veryGood = 
            prod-veryGood {A = A} {B = List A} {_≼₁_ = _≼_} {_≼₂_ = Embedding} {g₁} {g₂}
              g₁-veryGood g₂-veryGood
          g₁g₂-good : Good (prodOrder _≼_ Embedding) (prodSeq g₁ g₂)
          g₁g₂-good = veryGood⇒good (prodOrder _≼_ Embedding)  n  g₁ n , g₂ n) g₁g₂-veryGood
          i j : 
          i = proj₁ g₁g₂-good
          j = proj₁ (proj₂ g₁g₂-good)
          i<j : i < j
          i<j = proj₁ (proj₂ (proj₂ g₁g₂-good))
          g₁i≼g₁j : g₁ i  g₁ j
          g₁i≼g₁j = proj₁ (proj₂ (proj₂ (proj₂ g₁g₂-good)))
          emb-g₂i-g₂j : Embedding (g₂ i) (g₂ j)
          emb-g₂i-g₂j = proj₂ (proj₂ (proj₂ (proj₂ g₁g₂-good)))
          emb-g₁ig₂i-g₁jg₂j : Embedding (g₁ i  g₂ i) (g₁ j  g₂ j)
          emb-g₁ig₂i-g₁jg₂j = g₁i≼g₁j  emb-g₂i-g₂j
          emb-mbsi-mbsj : Embedding (mbs i) (mbs j)
          emb-mbsi-mbsj = 
            subst  z  Embedding z (mbs j)) (sym (mbs≡g₁∷g₂ i)) 
                    (subst (Embedding (g₁ i  g₂ i)) (sym (mbs≡g₁∷g₂ j)) emb-g₁ig₂i-g₁jg₂j)

  sub-elem-veryGood-veryGood : (f :   List A)
     ((g :   A)  g  Sub _elem_ f  VeryGood _≼_ g)
     VeryGood Embedding f
  sub-elem-veryGood-veryGood f h = 
    lemma-good-veryGood {A = List A} {_≼_ = Embedding} P P-closed sub-elem-veryGood-good f h
    where
    P : (  List A)  Set
    P z = (g :   A)  g  Sub _elem_ z  VeryGood _≼_ g
    P-closed : ClosedUnderSubseq P
    P-closed f r r-increasing Pf g g∈Sub-elem-f∘r = Pf g (Sub-Sub-elem f r r-increasing g∈Sub-elem-f∘r)

  embedding-isWQO : IsWQO _≼_  IsWQO Embedding
  embedding-isWQO ≼-isWQO = 
    record
    { isQO = embedding-isQO (IsWQO.isQO ≼-isWQO)
    ; almostFull = embedding-almostFull
    }
    where
    embedding-almostFull : (f :   List A)  Good Embedding f
    embedding-almostFull f = 
      sub-elem-veryGood-good f  g _  almostFull-veryGood _≼_ g (IsWQO.almostFull ≼-isWQO))