如何证明双重函数的回归等于Isabelle中回归函数的加倍?

时间:2014-10-19 20:23:43

标签: isabelle

我有一个函数,可以将表单元素加倍,格式为

double [x1, x2, ...] = [x1, x1, x2, x2, ...]

 fun double :: " 'a list ⇒ 'a list"
 where
   "double [] = []" |
   "double (x#xs) = x # x # double xs"

和一个函数,它在另一个函数snoc的帮助下反转列表的元素,该函数在列表的右侧添加了一个元素:

 fun snoc :: "'a list ⇒ 'a ⇒ 'a list"
 where
   "snoc [] x = [x]" |
   "snoc (y # ys) x = y # (snoc ys x)"


 fun reverse :: "'a list ⇒ 'a list"
 where
   "reverse [] = []" |
   "reverse (x # xs) = snoc (reverse xs) x"

现在我要证明

 lemma rev_double: "rev (double xs) = double (rev xs)"

是真的。

我尝试在xs

上应用归纳法
lemma rev_double: "rev (double xs) = double (rev xs)"
by (induction xs)

我编写了一个辅助引理double_snoc,确保加倍列表与加倍其第一个元素和列表的其余部分(使用函数snocleft相同,后者在列表的左端)

fun snocleft::"'a list ⇒ 'a  ⇒ 'a list "
where
  "snocleft [] x = [x]" |
  "snocleft (y # ys) x =  x # (y # ys)"


lemma double_snoc: "double (snocleft xs y) = y # y # double xs"
by (induction xs) auto

我在证明引理方面仍未取得任何进展。您对如何设置证明有一些解决方案或提示吗?

1 个答案:

答案 0 :(得分:0)

您将函数定义为reverse,但在所有引理中,您使用rev,指的是预定义列表反转函数rev

你的意思可能就是这样:

lemma reverse_double: "reverse (double xs) = double (reverse xs)"

如果你试图通过归纳来证明这一点(使用apply (induction xs)),你将陷入诱导案例,并达到以下目标:

snoc (snoc (double (reverse xs)) a) a =
   double (snoc (reverse xs) a)

这应该是直观明显的:如果你第一次snoc然后加倍,它就像第一次加倍然后再狙击两次一样。因此,让我们证明这是一个辅助引理:

lemma double_snoc: "double (snoc xs x) = snoc (snoc (double xs) x) x"
  by (induction xs) auto

现在reverse_double的证明会自动完成:

lemma reverse_double: "reverse (double xs) = double (reverse xs)"
  by (induction xs) (auto simp: double_snoc)