【问题标题】:Proving two dependent (AVL tree key-value) pairs equal证明两个依赖(AVL 树键值)对相等
【发布时间】:2020-06-29 17:21:11
【问题描述】:

标准库的 AVL 树实现使用依赖对来存储键值对。我有两个这样的对,它们的键(kk′)我已经证明是相等的(k≡k′)。它们还包含相同的值 (v)。我想证明这对是平等的。这是目标:

open import Agda.Primitive

open import Data.Nat
open import Data.Nat.Properties
open import Data.Product
open import Relation.Binary.PropositionalEquality

open import Data.AVL.Indexed <-strictTotalOrder

module Repro (ℓ : Level) (V : Value ℓ) where

Val = Value.family V
V≈ = Value.respects V

proof : (k k′ : ℕ) → (v : Val k) → (k≡k′ : k ≡ k′) → (k , v) ≡ (k′ , V≈ k≡k′ v)
proof k k′ v k≡k′ = {!!}

我尝试使用k≡k′ 重写,这会将LHS 上的k 变成k′ 和RHS 上的k≡k′ 变成refl。这就是我卡住的地方。我觉得我遗漏了一些明显的东西,因为这似乎是一件非常基本的事情。

(作为练习,我试图证明标准库的 AVL 树插入是正确的。因此我最近对它的 AVL 树代码很着迷。)

更新

嗯。也许这并不像我想象的那么微不足道,至少在不了解V 的情况下。毕竟,我目前所知道的是:

  • 有一种方法可以将 Val k 类型的值转换为 Val k′ 类型的值 - 通过 V≈

  • V≈ refl 接受 Val foo 并返回 Val foo

目前我不知道V≈ refl 是身份函数,这似乎是我需要做的证明。

更新二

例如,如果我知道 V≈ 实际上是 subst Val,那么我的证明将是:

proof′ : (k k′ : ℕ) → (v : Val k) → (k≡k′ : k ≡ k′) → (k , v) ≡ (k′ , subst Val k≡k′ v)
proof′ k k′ v k≡k′ rewrite k≡k′ = cong (k′ ,_) refl

所以,我想我的问题最终是:

  • 我可以用我现有的东西完成我的原始证明吗?

  • 如果不是,那么我需要什么属性 V≈ 才能完成我的原始证明(即“将其限制为类似于 subst 的函数”)?

更新 III

我正在提供更多背景信息来回应 MrO 的评论。我将提供更简单的东西,而不是剥离我的实际证明。让我们证明一个 AVL 树插入的特殊情况,这会导致我在一般情况下面临的相同问题。

让我们证明,将键 k 的值 v 插入到空树中,然后查找键 k 的值会产生我们插入的值 v

让我们开始吧:

open import Agda.Primitive using (Level)
open import Data.Maybe using (just)
open import Data.Nat using (ℕ)
open import Data.Nat.Properties using (<-strictTotalOrder ; <-cmp)
open import Data.Product using (proj₂)
open import Function using () renaming (const to constᶠ)
open import Relation.Binary using (tri< ; tri≈ ; tri>)
open import Relation.Binary.PropositionalEquality using (_≡_ ; refl )
open import Relation.Nullary.Negation using (contradiction)

open import Data.AVL.Indexed <-strictTotalOrder

module Simple {ℓ : Level} (V : Value ℓ) where

private
  Val = Value.family V
  V≈  = Value.respects V

现在,一个创建空树的函数:

make-empty : ∀ {l u} → l <⁺ u → Tree V l u 0
make-empty = leaf

还有证明:

proof : ∀ {l u} (k : ℕ) (v : Val k) (l<u : l <⁺ u) (l<k<u : l < k < u) →
  lookup k (proj₂ (insertWith k (constᶠ v) (make-empty l<u) l<k<u)) l<k<u ≡ just v

proof k v l<u l<k<u with <-cmp k k
... | tri< _ p _ = contradiction refl p
... | tri> _ p _ = contradiction refl p
... | tri≈ _ p _ rewrite p = {!!}

我要填写的目标是just (V≈ refl v) ≡ just v

【问题讨论】:

  • 关于您的第二次更新:您的证明可以简单地使用proof′ _ _ _ refl = refl,也可以不使用subst Val k≡k′ v,您不能简单地使用v 吗?我对您的问题真正需要证明的内容感到困惑。
  • 感谢您对此进行调查!让我试着改写一下。 V≈ : x ≡ y → Val x → Val y 是一个类似于subst 的函数,用于将Val x 类型的值转换为Val y 类型的值。它是 AVL 树模块的参数,所以我不知道它的定义,只知道它的类型。我想在从substV≈ 的第二次更新中概括证明。据我了解,我第二次更新中的证明使用了subst P refl 是恒等函数这一事实,因此subst Val k≡k′ v ≡ v。我似乎无法将这个事实用于V≈,因为我不知道V≈ refl 是身份函数。
  • 所有这些来自哪里:给定一个 AVL 树,其值 v′ : Val k′ 位于键 k′ : ℕ,使用键 k : ℕ 在树中查找 k ≡ k′。查找在树中找到值v′ : Val k′。 AVL 代码现在使用V≈v′Val k′ 转换为Val k 以返回。我们使用k 而不是k′ 进行了查找,所以我们得到了Val k - 即使k ≡ k′。在我关于 AVL 树插入的证明中,我被困在V≈ refl v′ ≡ v′。在我看来,如果不了解更多关于 V≈ 的信息,我将无法继续。所以我想知道我是否遗漏了什么。
  • 能否将您刚才描述的关于查找的完整证明添加到您的帖子中?
  • 谢谢!我还试图探索的另一件事(在我有限的理解范围内)是Val k 的某种唯一性或不相关属性,因此类型的相等意味着值的相等。如果我理解正确,那么我们不需要知道任何关于 V≈ refl 的信息,除了它需要一个 Val k 并产生一个 Val k

标签: agda


【解决方案1】:

您可以假设或将V≈ 保持值不变这一事实作为模块参数,如下所示:

postulate lemma : ∀ {k k′} {v : Val k} → (k≡k′ : k ≡ k′) → v ≡ subst _ (sym k≡k′) (V≈ k≡k′ v) 

之后,你的证明变成:

proof : (k k′ : ℕ) → (v : Val k) → (k≡k′ : k ≡ k′) → (k , v) ≡ (k′ , V≈ k≡k′ v) 
proof k ._ _ refl = cong (k ,_) (lemma refl)

【讨论】:

  • 太棒了!感谢您的解决方法,它非常适合我的用例。
猜你喜欢
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 2021-09-19
  • 2019-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
相关资源
最近更新 更多