我可能不会以最好的方式解决这个问题,因为Agda,特别是Agda标准库对我来说还是一个新手。我试图实现二进制搜索树的一些概念。
我有一个二叉树的简单定义
data BTree (A : Set) : ℕ → Set where
Leaf : A → BTree A 1
Node : ∀ {n m} → A → BTree A n → BTree A m → BTree A (1 + n + m)
以及两个函数bt-⊔ : ∀ {n : ℕ} → BTree ℕ n → ℕ
和bt-⊓ : ∀ {n : ℕ} → BTree ℕ n → ℕ
,它们从二叉树中提取最大值和最小值。
我现在正在尝试定义一种数据类型,证明特定树是二叉搜索树。这是我到目前为止所拥有的。
data BST : {n : ℕ} → BTree ℕ n → Set where
sortL : {x : ℕ} → BST (Leaf x)
sortN : ∀ {n m} → {a : ℕ} → {l : BTree ℕ n} → {r : BTree ℕ m}
→ (sl : BST l) → (sr : BST r)
→ {cl : a ≥ (bt-⊔ l)} → {cr : a < (bt-⊓ r)}
→ BST (Node a l r)
我对节点BST构造函数的直觉是获取存储在节点(a
),两个子树(l
和r
)的值,证明这两个子树是BST(sl
和sr
)并证明当前值a
大于左子树中的所有内容并且小于右侧的所有内容(cl
和{{1 }})。
这似乎或多或少有效,我可以构建以下简单的树和BST证明。
cr
但是,我希望让Agda推断T₂ : BTree ℕ 3
T₂ = Node 5 (Leaf 3) (Leaf 7)
bst₂ : BST T₂
bst₂ = sortN sortL sortL {s≤s (s≤s (s≤s z≤n))} {s≤s (s≤s (s≤s (s≤s (s≤s (s≤s z≤n)))))}
和cl
的证明,因为它们非常乏味。如果我没有在cr
的定义中指定它们,那么Agda似乎认为我的代码中有漏洞,给出了与bst₂
和cl
相关的下划线变量。
我不清楚如何解决这个问题,也不清楚我是否正确地使用了标准库的这一部分。我愿意接受任何可以使这更容易的建议或解决方案。
答案 0 :(得分:3)
您可以将较小或相等的关系定义为函数:
open import Data.Empty
open import Data.Unit.Base using (⊤; tt)
open import Data.Nat.Base
_≤⊤_ : ℕ -> ℕ -> Set
0 ≤⊤ m = ⊤
suc n ≤⊤ 0 = ⊥
suc n ≤⊤ suc m = n ≤⊤ m
test : 10 ≤⊤ 20
test = tt
它也可以实现原始证明:
≤⊤→≤ : ∀ n m -> n ≤⊤ m -> n ≤ m
≤⊤→≤ 0 m _ = z≤n
≤⊤→≤ (suc n) 0 ()
≤⊤→≤ (suc n) (suc m) p = s≤s (≤⊤→≤ n m p)
test-test : 10 ≤ 20
test-test = ≤⊤→≤ _ _ test
test-test
评估为s≤s (s≤s (s≤s (s≤s (s≤s (s≤s (s≤s (s≤s (s≤s (s≤s z≤n)))))))))
。
以及提取最大值和最小值的两个函数
bt-⊔ : ∀ {n : ℕ} → BTree ℕ n → ℕ
和bt-⊓ : ∀ {n : ℕ} → BTree ℕ n → ℕ
来自二叉树。
存储它们而不是提取它们会更好。查看How to Keep Your Neighbours in Order文章,其中详细说明了如何定义有序数据类型(本文中的代码不会检查最新版本的Agda,请参阅一些提示here)。
但是,我希望让Agda推断
cl
和cr
的证明 非常乏味。
这些sortN
和sortL
也很乏味。应该可以定义
open import Relation.Nullary
ordered? : ∀ {n} -> (b : BTree ℕ n) -> Dec (BST b)
ordered? = ...
ordered?
决定树是否有序。然后,您可以在Dec
的帮助下删除此Relation.Nullary.Decidable.from-yes
。但请先阅读论文并选择更合适的BST
表示。