\begin{code}
{-# OPTIONS --safe #-}
open import Prelude
module Data.Set.Noetherian {a} {A : Type a} (disc : Discrete A) where
private
infix 4 _≟_
_≟_ = disc
open import Data.Set
open import Data.Set.Discrete disc
open import Data.Nat.Properties
open import Data.Nat
infixr 5 _#_
_#_ : A → 𝒦 A → ℕ
x # xs = if does (x ∈? xs) then 0 else 1
size : 𝒦 A → ℕ
size = ⟦ size-alg ⟧
where
opaque
unfolding _∈?_
lemma₁ : ∀ x y xs → (x # y ∷ xs) + (y # xs) ≡ (y # x ∷ xs) + (x # xs)
lemma₁ x y xs with x ≟ y
... | yes x≡y = cong (_# xs) (sym x≡y) ; cong (_+ bool 1 0 (does (x ∈? xs))) (cong (bool 1 0 ∘ bool _ _) (sym (it-does (y ≟ x) (sym x≡y) )))
... | no x≢y with x ∈? xs | y ∈? xs
... | no x∉xs | y∈?xs = sym (+-comm (bool 1 0 (does y∈?xs)) 1) ; cong (_+ 1) (cong (bool 1 0 ∘ bool _ _) (sym (it-doesn't (y ≟ x) (x≢y ∘ sym))))
... | x∈?xs | no y∉xs = +-comm (bool 1 0 (does x∈?xs)) 1 ; cong (_+ bool 1 0 (does x∈?xs)) (cong (bool 1 0 ∘ bool false true) (sym (it-doesn't (y ≟ x) (x≢y ∘ sym))))
... | yes x∈xs | yes y∈xs = cong (_+ 0) (cong (bool 1 0 ∘ bool true true) (sym (it-doesn't (y ≟ x) (x≢y ∘ sym))))
lemma₂ : ∀ x xs → x # x ∷ xs ≡ 0
lemma₂ x xs with x ≟ x
... | no x≢x = absurd (x≢x refl)
... | yes _ = refl
size-alg : Ψ[ xs ⦂ 𝒦 A ] ↦ ℕ
size-alg .fst ∅ = zero
size-alg .fst (x ∷ xs ⟨ P⟨xs⟩ ⟩) = (x # xs) + P⟨xs⟩
size-alg .snd .c-trunc _ = Discrete→isSet discreteℕ
size-alg .snd .c-com x y xs P⟨xs⟩ = sym (+-assoc (x # y ∷ xs) (y # xs) P⟨xs⟩) ; cong (_+ P⟨xs⟩) (lemma₁ x y xs) ; +-assoc (y # x ∷ xs) (x # xs) P⟨xs⟩
size-alg .snd .c-dup x xs P⟨xs⟩ = cong (_+ ((x # xs) + P⟨xs⟩)) (lemma₂ x xs)
_-_ : 𝒦 A → 𝒦 A → 𝒦 A
xs - ys = ⟦ alg xs ⟧ ys
where
alg : ∀ xs → Ψ[ ys ⦂ 𝒦 A ] ↦ 𝒦 A
alg xs .fst ∅ = xs
alg _ .fst (y ∷ _ ⟨ xs-ys ⟩) = xs-ys \\ y
alg xs .snd .c-trunc _ = trunc
alg xs .snd .c-com x y _ P⟨xs⟩ = \\-com y x P⟨xs⟩
alg xs .snd .c-dup x _ ys = \\-idem x ys
open import Data.Nat.Properties
open import HITs.PropositionalTruncation
∷-size : ∀ x xs → size xs ≤′ size (x ∷ xs)
∷-size x xs with x ∈? xs
... | yes x∈xs = zero , refl
... | no x∉xs = 1 , refl
\\-size : ∀ x xs → size (xs \\ x) ≤′ size xs
\\-size x = ⟦ alg x ⟧
where
alg : ∀ x → Ψ[ xs ⦂ 𝒦 A ] ↦ size (xs \\ x) ≤′ size xs
alg x .snd = prop-coh λ _ → isProp-≤′ _ _
alg x .fst ∅ = zero , refl
alg x .fst (y ∷ xs ⟨ P⟨xs⟩ ⟩) with x ≟ y | y ∈? xs
... | yes x≡y | yes y∈xs = P⟨xs⟩
... | no x≢y | yes y∈xs = subst (_≤′ size xs) (cong (_+ size (xs \\ x)) (sym (cong (bool 1 0) (it-does (y ∈? (xs \\ x)) (≢-rem y x (x≢y ∘ sym) xs y∈xs))))) P⟨xs⟩
... | yes x≡y | no y∉xs = ≤′-trans (size (xs \\ x)) _ _ P⟨xs⟩ (1 , refl)
... | no x≢y | no y∉xs = subst (_≤′ 1 + size xs) (sym (cong (_+ size (xs \\ x)) (cong (bool 1 0) (it-doesn't (y ∈? (xs \\ x)) (y∉xs ∘ rem-∈ y x xs))))) (p≤′p _ _ P⟨xs⟩ )
\\-∈-size : ∀ x xs → x ∈ xs → size (xs \\ x) <′ size xs
\\-∈-size x = ⟦ alg x ⟧
where
alg : ∀ x → Ψ[ xs ⦂ 𝒦 A ] ↦ (x ∈ xs → size (xs \\ x) <′ size xs)
alg x .snd = prop-coh λ xs → isProp→ (isProp-<′ _ _)
alg x .fst (y ∷ xs ⟨ P⟨xs⟩ ⟩) x∈xs with x ≟ y | y ∈? xs
... | yes x≡y | no y∉xs = ≤⇒s< _ _ (\\-size x xs)
... | yes x≡y | yes y∈xs = P⟨xs⟩ (subst (_∈ xs) (sym x≡y) y∈xs)
... | no x≢y | yes y∈xs = subst (_<′ size xs) (sym (cong (_+ size (xs \\ x)) (cong (bool 1 0) (it-does (y ∈? (xs \\ x)) ((≢-rem y x (x≢y ∘ sym) xs y∈xs)))))) (P⟨xs⟩ (∥rec∥ (isProp-∈ x xs) (absurd ∘ ∥rec∥ isProp⊥ x≢y ▿ id) x∈xs))
... | no x≢y | no y∉xs = subst (_<′ suc (size xs)) (sym (cong (_+ size (xs \\ x)) (cong (bool 1 0) (it-doesn't (y ∈? (xs \\ x)) (y∉xs ∘ rem-∈ y x xs)))) ) (p<′p _ _ (P⟨xs⟩ ((∥rec∥ (isProp-∈ x xs) (absurd ∘ ∥rec∥ isProp⊥ x≢y ▿ id) x∈xs))))
-‿∈ : ∀ x xs ys → x ∈ xs → x ∉ ys → x ∈ xs - ys
-‿∈ x xs = ⟦ alg x xs ⟧
where
alg : ∀ x xs → Ψ[ ys ⦂ 𝒦 A ] ↦ (x ∈ xs → x ∉ ys → x ∈ xs - ys)
alg x xs .snd = prop-coh (λ ys → isProp→ (isProp→ (isProp-∈ x (xs - ys))))
alg x xs .fst ∅ x∈xs x∉ys = x∈xs
alg x xs .fst (y ∷ ys ⟨ P⟨ys⟩ ⟩) x∈xs x∉ys =
≢-rem x y (x∉ys ∘ ∣_∣ ∘ inl ∘ ∣_∣) (xs - ys) (P⟨ys⟩ x∈xs (x∉ys ∘ ∣_∣ ∘ inr))
open import WellFounded
module _ (Dom : 𝒦 A) where
\end{code}
%<*noeth-acc>
\begin{code}
data NoethAcc (seen : 𝒦 A) : Type a where
nacc : (∀ x → x ∈ Dom → x ∉ seen → NoethAcc (x ∷ seen)) → NoethAcc seen
\end{code}
%</noeth-acc>
\begin{code}
infix 4 _≺′_
_≺′_ : 𝒦 A → 𝒦 A → Type
xs ≺′ ys = size xs <′ size ys
noeth′ : ∀ seen → Acc _≺′_ (Dom - seen) → NoethAcc seen
noeth′ seen (acc wf) =
nacc λ x x∈d x∉s →
noeth′
(x ∷ seen)
(wf (Dom - (x ∷ seen)) (\\-∈-size x (Dom - seen) (-‿∈ x Dom seen x∈d x∉s)))
opaque
noeth : NoethAcc ∅
noeth = noeth′ ∅ (fun-wellFounded size <-wellFounded Dom)
\end{code}