此问题涉及使用Isabelle / HOL定理证明器生成代码。
当我导出列表上的distinct
函数的代码时
export_code distinct in Scala file -
我得到以下代码
def member[A : HOL.equal](x0: List[A], y: A): Boolean = (x0, y) match {
case (Nil, y) => false
case (x :: xs, y) => HOL.eq[A](x, y) || member[A](xs, y)
}
def distinct[A : HOL.equal](x0: List[A]): Boolean = x0 match {
case Nil => true
case x :: xs => ! (member[A](xs, x)) && distinct[A](xs)
}
此代码具有二次运行时。有更快的版本吗?我想到了在我的理论开头为字符串导入"~~/src/HOL/Library/Code_Char"
之类的东西,并建立了列表的高效代码生成。
distinct
的更好实现是在O(n log n)中对列表进行排序,并在列表上迭代一次。但我猜一个人可以做得更好吗?
无论如何,distinct
是否有更快的实施,可能还有来自Main
的其他功能?
答案 0 :(得分:7)
我不知道Isabelle2013库中的任何更快的实现,但您可以轻松地按照以下方式执行:
distinct_sorted
。distinct_sorted
确实在排序列表上实施distinct
distinct
实施distinct_list
并排序的引理,并将其声明为distinct
的新代码等式。总之,这看起来如下:
context linorder begin
fun distinct_sorted :: "'a list => bool" where
"distinct_sorted [] = True"
| "distinct_sorted [x] = True"
| "distinct_sorted (x#y#xs) = (x ~= y & distinct_sorted (y#xs))"
lemma distinct_sorted: "sorted xs ==> distinct_sorted xs = distinct xs"
by(induct xs rule: distinct_sorted.induct)(auto simp add: sorted_Cons)
end
lemma distinct_sort [code]: "distinct xs = distinct_sorted (sort xs)"
by(simp add: distinct_sorted)
接下来,您需要一种有效的排序算法。默认情况下,sort
使用插入排序。如果您从HOL / Library导入Multiset,sort
将由quicksort实现。如果您从Formal Proofs存档导入Efficient Mergesort,则会获得合并排序。
虽然这可以提高效率,但也有一个障碍:在上述声明之后,您只能在其元素是类型类distinct
的实例的列表上执行linorder
。由于这种改进仅在代码生成器内部发生,因此Isabelle中的定义和定理不受影响。
例如,要将distinct
应用于任何代码等式中的列表列表,首先必须在列表中定义线性顺序:List_lexord
中的HOL/Library
通过选择字典顺序,但这需要元素的线性顺序。如果您要使用缩写string
的{{1}},char list
定义Char_ord
上的常规顺序。如果使用char
将字符映射到目标语言的字符类型,则还需要适应理论Code_Char
以与Code_Char_ord
组合。