Let's play Agda
{-# OPTIONS --cubical-compatible #-}
module Padova2025-zh-TW.ProvingBasics.Termination.Ordering where

自然數上的標準序#

open import Padova2025-zh-TW.ProgrammingBasics.Naturals.Base
open import Padova2025-zh-TW.ProgrammingBasics.Naturals.Arithmetic
open import Padova2025-zh-TW.ProgrammingBasics.Lists
open import Padova2025-zh-TW.ProvingBasics.Negation
open import Padova2025-zh-TW.ProvingBasics.Connectives.Disjunction
open import Padova2025-zh-TW.ProvingBasics.Connectives.More
open import Padova2025-zh-TW.ProvingBasics.Equality.Base
open import Padova2025-zh-TW.ProvingBasics.Equality.General
open import Padova2025-zh-TW.ProvingBasics.Equality.NaturalNumbers

在這個模組中,我們引進自然數上的標準序 _≤_,以及它的變體 _<_、_≥_ 與 _>_,並驗證它們的基本性質。

infix 4 _≤_ _<_ _≥_ _>_
data _≤_ : ℕ → ℕ → Set where
  z≤n : {n : ℕ}   → zero ≤ n
  s≤s : {n m : ℕ} → (n≤m : n ≤ m) → succ n ≤ succ m

_<_ : ℕ → ℕ → Set
n < m = succ n ≤ m

_>_ : ℕ → ℕ → Set
n > m = m < n

_≥_ : ℕ → ℕ → Set
n ≥ m = m ≤ n

習題:自反性、遞移性與反對稱性#

習題 1≤-refl
≤-refl : {a : ℕ} → a ≤ a
≤-refl = {!!}
參考解答用到: zero z≤n succ s≤s
參考解答
≤-refl : {a : ℕ} → a ≤ a
≤-refl {zero}   = z≤n
≤-refl {succ a} = s≤s ≤-refl
習題 2≤-trans
≤-trans : {a b c : ℕ} → a ≤ b → b ≤ c → a ≤ c
≤-trans = {!!}
參考解答用到: z≤n s≤s
參考解答
≤-trans : {a b c : ℕ} → a ≤ b → b ≤ c → a ≤ c
≤-trans z≤n     q       = z≤n
≤-trans (s≤s p) (s≤s q) = s≤s (≤-trans p q)
習題 3≤-antisymm
≤-antisymm : {a b : ℕ} → a ≤ b → b ≤ a → a ≡ b
≤-antisymm = {!!}
參考解答用到: z≤n refl s≤s cong succ
參考解答
≤-antisymm : {a b : ℕ} → a ≤ b → b ≤ a → a ≡ b
≤-antisymm z≤n     z≤n     = refl
≤-antisymm (s≤s p) (s≤s q) = cong succ (≤-antisymm p q)
習題 4<-irreflexive
<-irreflexive : {a : ℕ} → a < a → ⊥
<-irreflexive = {!!}
參考解答用到: s≤s
參考解答
<-irreflexive : {a : ℕ} → a < a → ⊥
<-irreflexive (s≤s p) = <-irreflexive p
習題 5<-irreflexive'
<-irreflexive' : {a b : ℕ} → a ≤ b → b < a → ⊥
<-irreflexive' = {!!}
參考解答用到: s≤s
參考解答
<-irreflexive' : {a b : ℕ} → a ≤ b → b < a → ⊥
<-irreflexive' (s≤s p) (s≤s q) = <-irreflexive' p q
習題 6<-irreflexive''
<-irreflexive'' : {a b : ℕ} → a < b → b < a → ⊥
<-irreflexive'' = {!!}
參考解答用到: s≤s
參考解答
<-irreflexive'' : {a b : ℕ} → a < b → b < a → ⊥
<-irreflexive'' (s≤s p) (s≤s q) = <-irreflexive'' p q
習題 7≡⇒≤
≡⇒≤ : {a b : ℕ} → a ≡ b → a ≤ b
≡⇒≤ = {!!}
參考解答用到: refl ≤-refl
參考解答
≡⇒≤ : {a b : ℕ} → a ≡ b → a ≤ b
≡⇒≤ refl = ≤-refl

習題:決策程序#

習題 8≤-<-connex
≤-<-connex : (a b : ℕ) → a ≤ b ⊎ b < a
≤-<-connex = {!!}
參考解答用到: zero left z≤n succ right s≤s
參考解答
≤-<-connex : (a b : ℕ) → a ≤ b ⊎ b < a
≤-<-connex zero     b        = left z≤n
≤-<-connex (succ a) zero     = right (s≤s z≤n)
≤-<-connex (succ a) (succ b) with ≤-<-connex a b
... | left  a≤b = left  (s≤s a≤b)
... | right b<a = right (s≤s b<a)

也許令人驚訝的是,這個習題與下一個習題都可以靠自動駕駛解決。適當地使用 C-c C-c、C-c C-a 與 with 關鍵字, 對適當的遞迴呼叫的結果做 pattern matching。

習題 9<-cmp
<-cmp : (a b : ℕ) → a ≡ b ⊎ (a < b ⊎ a > b)
<-cmp = {!!}
參考解答用到: zero left refl succ right s≤s z≤n cong
參考解答
<-cmp : (a b : ℕ) → a ≡ b ⊎ (a < b ⊎ a > b)
<-cmp zero     zero     = left refl
<-cmp zero     (succ b) = right (left (s≤s z≤n))
<-cmp (succ a) zero     = right (right (s≤s z≤n))
<-cmp (succ a) (succ b) with <-cmp a b
... | left  a≡b         = left (cong succ a≡b)
... | right (left a<b)  = right (left (s≤s a<b))
... | right (right a>b) = right (right (s≤s a>b))
習題 10dec-≤
dec-≤ : (a b : ℕ) → Dec (a ≤ b)
dec-≤ = {!!}
參考解答用到: zero yes z≤n succ no s≤s
參考解答
dec-≤ : (a b : ℕ) → Dec (a ≤ b)
dec-≤ zero     b = yes z≤n
dec-≤ (succ a) zero = no λ ()
dec-≤ (succ a) (succ b) with dec-≤ a b
... | yes a≤b  = yes (s≤s a≤b)
... | no  ¬a≤b = no λ { (s≤s a≤b) → ¬a≤b a≤b }
習題 11dec-<
dec-< : (a b : ℕ) → Dec (a < b)
dec-< = {!!}
參考解答用到: dec-≤ succ
參考解答
dec-< : (a b : ℕ) → Dec (a < b)
dec-< a b = dec-≤ (succ a) b

習題:幾個函數的序性質#

succ-monotone : {a b : ℕ} → a ≤ b → succ a ≤ succ b
succ-monotone = s≤s
習題 12pred-monotone
pred-monotone : {a b : ℕ} → a ≤ b → pred a ≤ pred b
pred-monotone = {!!}
參考解答用到: z≤n s≤s
參考解答
pred-monotone : {a b : ℕ} → a ≤ b → pred a ≤ pred b
pred-monotone z≤n     = z≤n
pred-monotone (s≤s p) = p
習題 13succ-inflationary
succ-inflationary : (a : ℕ) → a ≤ succ a
succ-inflationary = {!!}
參考解答用到: zero z≤n s≤s
參考解答
succ-inflationary : (a : ℕ) → a ≤ succ a
succ-inflationary zero     = z≤n
succ-inflationary (succ a) = s≤s (succ-inflationary a)
習題 14twice-inflationary
twice-inflationary : (a : ℕ) → a ≤ twice a
twice-inflationary = {!!}
參考解答
twice-inflationary : (a : ℕ) → a ≤ twice a
twice-inflationary zero     = z≤n
twice-inflationary (succ a) = ≤-trans (succ-inflationary (succ a)) (succ-monotone (succ-monotone (twice-inflationary a)))
習題 15max-inflationaryₗ
max-inflationaryₗ : (a b : ℕ) → a ≤ max a b
max-inflationaryₗ = {!!}
參考解答用到: zero z≤n succ ≤-refl s≤s
參考解答
max-inflationaryₗ : (a b : ℕ) → a ≤ max a b
max-inflationaryₗ zero     b        = z≤n
max-inflationaryₗ (succ a) zero     = ≤-refl
max-inflationaryₗ (succ a) (succ b) = s≤s (max-inflationaryₗ a b)
習題 16max-inflationaryᵣ
max-inflationaryᵣ : (a b : ℕ) → b ≤ max a b
max-inflationaryᵣ = {!!}
參考解答用到: zero ≤-refl succ z≤n s≤s
參考解答
max-inflationaryᵣ : (a b : ℕ) → b ≤ max a b
max-inflationaryᵣ zero     b        = ≤-refl
max-inflationaryᵣ (succ a) zero     = z≤n
max-inflationaryᵣ (succ a) (succ b) = s≤s (max-inflationaryᵣ a b)
習題 17+-monotone
+-monotone : {a a' b b' : ℕ} → a ≤ b → a' ≤ b' → a + a' ≤ b + b'
+-monotone = {!!}
參考解答
+-monotone : {a a' b b' : ℕ} → a ≤ b → a' ≤ b' → a + a' ≤ b + b'
+-monotone z≤n     z≤n     = z≤n
+-monotone z≤n     (s≤s q) = ≤-trans (succ-monotone (+-monotone z≤n q)) (≡⇒≤ (sym (+-succ _ _)))
+-monotone (s≤s p) q       = succ-monotone (+-monotone p q)
習題 18+-inflationaryₗ
+-inflationaryₗ : (a b : ℕ) → a ≤ a + b
+-inflationaryₗ = {!!}
參考解答用到: zero z≤n succ s≤s
參考解答
+-inflationaryₗ : (a b : ℕ) → a ≤ a + b
+-inflationaryₗ zero     b = z≤n
+-inflationaryₗ (succ a) b = s≤s (+-inflationaryₗ a b)
習題 19+-inflationaryᵣ
+-inflationaryᵣ : (a b : ℕ) → b ≤ a + b
+-inflationaryᵣ = {!!}
參考解答用到: +-monotone zero z≤n ≤-refl
參考解答
+-inflationaryᵣ : (a b : ℕ) → b ≤ a + b
+-inflationaryᵣ a b = +-monotone {zero} {b} {a} {b} z≤n ≤-refl

習題:串列的最大值#

maximum : List ℕ → ℕ
maximum []       = zero
maximum (x ∷ xs) = max x (maximum xs)

maximum-≥ : (k : ℕ) (xs : List ℕ) → k ∈ xs → k ≤ maximum xs
maximum-≥ k (x ∷ xs) (here  refl) = max-inflationaryₗ x (maximum xs)
maximum-≥ k (x ∷ xs) (there p)    = ≤-trans (maximum-≥ k xs p) (max-inflationaryᵣ x (maximum xs))

習題:減半#

習題 20half-≤
half-≤ : (x : ℕ) → half x ≤ x
half-≤ = {!!}
參考解答
half-≤ : (x : ℕ) → half x ≤ x
half-≤ zero            = z≤n
half-≤ (succ zero)     = z≤n
half-≤ (succ (succ x)) = succ-monotone (≤-trans (half-≤ x) (succ-inflationary x))
習題 21half-<
half-< : (x : ℕ) → half (succ x) < succ x
half-< = {!!}
參考解答用到: zero s≤s z≤n succ-monotone half-≤
參考解答
half-< : (x : ℕ) → half (succ x) < succ x
half-< zero     = s≤s z≤n
half-< (succ x) = succ-monotone (succ-monotone (half-≤ x))

習題:減法會變小#

open import Padova2025-zh-TW.ProvingBasics.EvenOdd
習題 22monus-≤
monus-≤ : (a b : ℕ) → a ≥ b → a ∸ b ≤ a
monus-≤ = {!!}
參考解答
monus-≤ : (a b : ℕ) → a ≥ b → a ∸ b ≤ a
monus-≤ a        zero     z≤n       = ≤-refl
monus-≤ (succ a) (succ b) (s≤s a≥b) = ≤-trans (monus-≤ a b a≥b) (succ-inflationary a)
習題 23monus-<
monus-< : (a b : ℕ) → IsPositive b → a ≥ b → a ∸ b < a
monus-< = {!!}
參考解答
monus-< : (a b : ℕ) → IsPositive b → a ≥ b → a ∸ b < a
monus-< (succ a) (succ zero)     b≥0  (s≤s a≥b) = ≤-refl
monus-< (succ a) (succ (succ b)) b≥-1 (s≤s a>b) =
  ≤-trans (monus-< a (succ b) (case-succ b) a>b) (succ-inflationary a)

偶數有無限多個#

open import Padova2025-zh-TW.ProvingBasics.Connectives.Existential
open import Padova2025-zh-TW.ProvingBasics.Connectives.Conjunction
open import Padova2025-zh-TW.ProvingBasics.EvenOdd
open import Padova2025-zh-TW.ProvingBasics.Equality.NaturalNumbers

要表達偶數有無限多個,一個特別正面的方式是:在每個自然數之後,都還有一個偶數。讓我們在 Agda 中陳述並證明這個事實。

習題 24Even-infinite
Even-infinite : (x : ℕ) → ∃[ y ] (y ≥ x × Even y)
Even-infinite = {!!}
參考解答用到: twice _,_ twice-inflationary twice-even
參考解答
Even-infinite : (x : ℕ) → ∃[ y ] (y ≥ x × Even y)
Even-infinite x = twice x , twice-inflationary x , twice-even x
-- 或者,更經濟地,改以 `x` 或 `succ x` 作為見證,
-- 而不是 `twice x`:
-- Even-infinite x with even-or-odd x
-- ... | left  xeven = x      , ≤-refl              , xeven
-- ... | right xodd  = succ x , succ-inflationary x , succ-odd xodd

自然數有無限多個#

open import Padova2025-zh-TW.ProvingBasics.Connectives.Existential

要表達自然數有無限多個,有幾種方式,其中一種是:對每個有限的自然數串列,都有一個不在該串列中的自然數。 我們可以這樣形式化並證明這個斷言。

習題 25ℕ-infinite
ℕ-infinite : (xs : List ℕ) → ∃[ x ] x ∉ xs
ℕ-infinite xs = succ (sum xs) , λ p → <-irreflexive (go p)
  where
  go : {xs : List ℕ} {y : ℕ} → y ∈ xs → y < succ (sum xs)
  go (here  refl) = {!!}
  go (there p)    = {!!}
參考解答
ℕ-infinite : (xs : List ℕ) → ∃[ x ] x ∉ xs
ℕ-infinite xs = succ (sum xs) , λ p → <-irreflexive (go p)
  where
  go : {xs : List ℕ} {y : ℕ} → y ∈ xs → y < succ (sum xs)
  go (here  refl) = succ-monotone (≤-trans (≡⇒≤ (sym (+-zero _))) (+-monotone ≤-refl z≤n))
  go (there p)    = ≤-trans (go p) (succ-monotone (+-monotone z≤n ≤-refl))

習題:嚴格序關係的另一種定義#

有時候,嚴格小於關係的下列另一種定義會很有用。

data _<'_ : ℕ → ℕ → Set where
  base' : {n : ℕ}     → n <' succ n
  step' : {a b : ℕ}   → a <' b → a <' succ b
習題 26z<'s
z<'s : {x : ℕ} → zero <' succ x
z<'s = {!!}
參考解答用到: base' step'
參考解答
z<'s : {x : ℕ} → zero <' succ x
z<'s {zero}   = base'
z<'s {succ x} = step' z<'s
習題 27s<'s
s<'s : {x y : ℕ} → x <' y → succ x <' succ y
s<'s = {!!}
參考解答用到: base' step'
參考解答
s<'s : {x y : ℕ} → x <' y → succ x <' succ y
s<'s base'     = base'
s<'s (step' p) = step' (s<'s p)
習題 28<⇒<'
<⇒<' : {x y : ℕ} → x < y → x <' y
<⇒<' = {!!}
參考解答用到: s≤s _≤_ succ z≤n z<'s s<'s
參考解答
<⇒<' : {x y : ℕ} → x < y → x <' y
<⇒<' (s≤s p) = lemma p
  where
  lemma : {x y : ℕ} → x ≤ y → x <' succ y
  lemma z≤n     = z<'s
  lemma (s≤s p) = s<'s (lemma p)
習題 29<'⇒<
<'⇒< : {x y : ℕ} → x <' y → x < y
<'⇒< = {!!}
參考解答
<'⇒< : {x y : ℕ} → x <' y → x < y
<'⇒< base'     = ≤-refl
<'⇒< (step' p) = ≤-trans (<'⇒< p) (succ-inflationary _)

習題:索引#

習題 30lookup
lookup : {P : ℕ → Set} {n m : ℕ} → All P (downFrom n) → m < n → P m
lookup = {!!}
參考解答
lookup : {P : ℕ → Set} {n m : ℕ} → All P (downFrom n) → m < n → P m
lookup {P} {succ n} {m} (p ∷ ps) m<n with ≤-<-connex n m
... | left  n≤m = subst P (≤-antisymm n≤m (pred-monotone m<n)) p
... | right m<n = lookup ps m<n