【问题标题】:Termination checking failed to prove ∃-even′ : ∀ {n : ℕ} → ∃[ m ] ( 2 * m ≡ n) → even n终止检查未能证明 ∃-even′ : ∀ {n : ℕ} → ∃[ m ] ( 2 * m ≡ n) → even n
【发布时间】:2021-04-17 06:35:22
【问题描述】:

PLFA 练习:如果我们在量词章节 (https://plfa.github.io/Quantifiers/) 中更“自然”地编写算术会怎样?

∃-even′ : ∀ {n : ℕ} → ∃[ m ] (    2 * m ≡ n) → even n
∃-odd′  : ∀ {n : ℕ} → ∃[ m ] (2 * m + 1 ≡ n) →  odd n

我已经把类型写对了。但是以下功能的终止检查失败:

dbl≡2* : ∀ n → n + n ≡ 2 * n
dbl≡2* n = cong (n +_) (sym (+-identityʳ n))

+-suc1 : ∀ (m : ℕ) → m + 1 ≡ suc m
+-suc1 m =
  begin
    m + 1
    ≡⟨⟩
    m + (suc zero)
    ≡⟨ +-suc m zero ⟩
    suc (m + zero)
    ≡⟨ cong suc (+-identityʳ m) ⟩
    suc m
    ∎ 

help1 : ∀ m → 2 * m + 1 ≡ suc (m + m)
help1 m =
  begin
    2 * m + 1
    ≡⟨  sym ( cong (_+ 1) (dbl≡2* m) ) ⟩
    m + m + 1  -- must use every rule
    ≡⟨ +-assoc m m 1 ⟩
    m + (m + 1)
    ≡⟨ cong (m +_) (+-suc1 m) ⟩
    m + suc m
    ≡⟨ +-suc m m ⟩
    suc (m + m)
    ∎

∃-even′ ⟨ zero , refl ⟩ = even-zero
∃-even′ ⟨ suc m , refl ⟩ rewrite +-identityʳ m
                | +-suc m m
                = even-suc (∃-odd′ ⟨ (m) ,  help1 m ⟩)

∃-odd′ ⟨ m , refl ⟩ rewrite +-suc (2 * m) 0
                | +-identityʳ m
                | +-identityʳ (m + m)
                | dbl≡2* m
                = odd-suc (∃-even′ ⟨ m , refl ⟩)

对于普通版本,相同的相互递归定义可以正常工作。

∃-even : ∀ {n : ℕ} → ∃[ m ] (    m * 2 ≡ n) → even n
∃-odd  : ∀ {n : ℕ} → ∃[ m ] (1 + m * 2 ≡ n) →  odd n

∃-even ⟨ zero , refl ⟩ = even-zero
∃-even ⟨ suc x , refl ⟩ = even-suc (∃-odd ⟨ x , refl ⟩)
∃-odd ⟨ x , refl ⟩ = odd-suc (∃-even ⟨ x , refl ⟩)

【问题讨论】:

    标签: agda termination plfa


    【解决方案1】:
    ∃-even′ ⟨ zero , refl ⟩ = even-zero
    ∃-even′ ⟨ suc m , refl ⟩ rewrite +-identityʳ m
                    | +-suc m m
                    = even-suc (∃-odd′ ⟨ m ,  help1 m ⟩)
    
    ∃-odd′ ⟨ m , refl ⟩ rewrite +-suc (2 * m) 0
                    | +-identityʳ m
                    | +-identityʳ (m + m)
                    | dbl≡2* m
                    = odd-suc (∃-even′ ⟨ m , refl ⟩)
    

    您的递归调用是:

    • ∃-even′ ⟨ suc m , refl ⟩ -> ∃-odd′ ⟨ m , help1 m ⟩
    • ∃-odd′ ⟨ m , refl ⟩ -> ∃-even′ ⟨ m , refl ⟩

    在第一个中,suc m -> m 减少,但 refl -> help1 m(在其表面上)增加。如果您将refl 作为第二个参数传递给∃-odd′,那么终止检查器会接受它,因为这意味着第二个参数保持不变,而第一个参数在两个调用的完整链上严格单调递减。

    那么我们如何将第一个递归调用更改为∃-odd′ ⟨ m , refl ⟩?通过sym (help1 m)重写:

    ∃-even′ ( suc m , refl ) rewrite +-identityʳ m
                    | +-suc m m
                    | sym (help1 m)
                    = even-suc (∃-odd′ (m ,  refl))
    

    这个代码然后被终止检查器接受。

    【讨论】:

    • 更改您的建议,但终止检查仍然失败。我的agda版本是2.6.1.2
    • 这是包含所有导入的完整代码(不使用任何特定于 PLFA 的内容):gist.github.com/gergoerdi/ffc02d72b0fd6ac06a1050c255998a45 在 Agda 版本 2.6.2-d713902-dirty 上测试
    • 你是对的。我将继续检查为什么我的 PLFA 版本仍然失败。似乎 PLFA 重新定义了一些想法,例如:同构和量词
    • 现在无法检查,只是一个疯狂的猜测,但可能是他们的 Sigma 类型定义没有 eta,这会导致这种情况吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    相关资源
    最近更新 更多