列表上“不同”的代码更快

时间:2013-03-21 10:31:41

标签: scala optimization code-generation isabelle

此问题涉及使用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的其他功能?

1 个答案:

答案 0 :(得分:7)

我不知道Isabelle2013库中的任何更快的实现,但您可以轻松地按照以下方式执行:

  1. 实现一个确定排序列表清晰度的函数distinct_sorted
  2. 证明distinct_sorted确实在排序列表上实施distinct
  3. 证明通过distinct实施distinct_list并排序的引理,并将其声明为distinct的新代码等式。
  4. 总之,这看起来如下:

    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组合。