Coq 证明列表的性质

Coq 证明列表的性质,coq,Coq,我的目的是证明生成列表的某些属性成立。 例如,一个生成器函数生成一个1的列表,列表的长度作为参数给出;我想证明列表的长度是参数指定的。这就是我到目前为止所做的: Require Import List. Fixpoint list_gen lng acc := match lng with 0 => acc | S lng_1 => list_gen (lng_1) (1::acc) end. Lemma lm0 : length(list_gen 0 nil) = 0. int

我的目的是证明生成列表的某些属性成立。 例如,一个生成器函数生成一个1的列表,列表的长度作为参数给出;我想证明列表的长度是参数指定的。这就是我到目前为止所做的:

Require Import List.

Fixpoint list_gen lng acc :=
match lng with
0 => acc
| S lng_1 => list_gen (lng_1) (1::acc)
end.

Lemma lm0 : length(list_gen 0 nil) = 0.
intuition.
Qed.

Lemma lm1 : forall lng:nat, length(list_gen lng nil) = lng.
induction lng.
apply lm0.
现在,在应用lm0后,剩下感应步骤:

1 subgoal
lng : nat
IHlng : length (list_gen lng nil) = lng
______________________________________(1/1)
length (list_gen (S lng) nil) = S lng

我希望这一步的证明可以从list_gen的代码中推断出来,但这很可能是一个错误的概念。如何证明这个子目标?

我同意Daniel的方法,但是更一般的方法是编写一个
列表\u gen
规范,例如使用非尾部递归
重复
函数:

Require Import List Arith.
Import ListNotations.

Lemma list_gen_spec : forall lng acc, list_gen lng acc = repeat 1 lng ++ acc.
Proof.
  induction lng as [| lng IH]; intros xs; simpl; trivial.
  rewrite IH.
  now rewrite app_cons_middle, repeat_singleton, repeat_app, Nat.add_comm.
Qed.
在这里,我不得不添加一些关于
重复
与一些标准列表函数的交互的引理

Lemma repeat_singleton {A} (x : A) :
  [x] = repeat x 1.
Admitted.

Lemma repeat_app {A} (x : A) n m :
  repeat x n ++ repeat x m = repeat x (n + m).
Admitted.

Lemma app_cons {A} (x : A) xs :
  x :: xs = [x] ++ xs.
Admitted.  (* this is a convenience lemma for the next one *)

Lemma app_cons_middle {A} (y : A) xs ys :
  xs ++ y :: ys = (xs ++ [y]) ++ ys.
Admitted.
我将把这些引理的证明留作练习

在证明了规范之后,你的引理可以通过一些重写来证明

Lemma lm1 lng : length(list_gen lng nil) = lng.
Proof.
  now rewrite list_gen_spec, app_nil_r, repeat_length.
Qed.

我同意Daniel的方法,但是更一般的方法是编写一个
list\u gen
规范,例如使用非尾部递归
repeat
函数:

Require Import List Arith.
Import ListNotations.

Lemma list_gen_spec : forall lng acc, list_gen lng acc = repeat 1 lng ++ acc.
Proof.
  induction lng as [| lng IH]; intros xs; simpl; trivial.
  rewrite IH.
  now rewrite app_cons_middle, repeat_singleton, repeat_app, Nat.add_comm.
Qed.
在这里,我不得不添加一些关于
重复
与一些标准列表函数的交互的引理

Lemma repeat_singleton {A} (x : A) :
  [x] = repeat x 1.
Admitted.

Lemma repeat_app {A} (x : A) n m :
  repeat x n ++ repeat x m = repeat x (n + m).
Admitted.

Lemma app_cons {A} (x : A) xs :
  x :: xs = [x] ++ xs.
Admitted.  (* this is a convenience lemma for the next one *)

Lemma app_cons_middle {A} (y : A) xs ys :
  xs ++ y :: ys = (xs ++ [y]) ++ ys.
Admitted.
我将把这些引理的证明留作练习

在证明了规范之后,你的引理可以通过一些重写来证明

Lemma lm1 lng : length(list_gen lng nil) = lng.
Proof.
  now rewrite list_gen_spec, app_nil_r, repeat_length.
Qed.

我猜你可能需要概括一下你正在证明的,以处理
acc
参数不是
nil
的情况:
forall(lng:nat)(acc:list nat),length(list_gen lng acc)=lng+length acc.
(然后
siml
应该对证明归纳步骤非常有帮助…)你可能想看看James WilcoxAnton的文章,这篇文章首先看起来很有希望,但最后它教授的唯一主题是,中间引理应该应用于更复杂的归纳证明中。如何构造这些引理是作者的未知数。@AttilaKaroly你可能需要一些经验来直接提出这些引理,但本文的结论是,当有累加器时,你几乎肯定需要证明对任何累加器都适用的更一般的结果(正如上面@Daniel在评论中所建议的)。实际上,你也可以通过尝试直接证明和理解你为什么被阻止来获得这个想法。这里,如果使用
siml
,显然需要一个归纳假设,其中
acc
不是
nil
,因此,你可以有广义版本的直觉。我猜你可能需要广义化你正在证明的,以处理
acc
参数不是
nil
对于所有(lng:nat)(acc:list nat),长度(list_gen lng acc)=lng+length acc.
(然后,
siml
应该非常有助于证明归纳步骤…)你可能想查看James WilcoxAnton的文章,这篇文章首先看起来很有希望,但最后它所教的唯一主题是,中间引理应该应用于更复杂的归纳证明中。如何构造这些引理是作者留给你的。@AttilaKaroly你可能需要一些经验来直接提出这些lemmas,但本文的结论是,当存在累加器时,几乎肯定需要证明对任何累加器都适用的更一般的结果(正如@Daniel在上面的评论中所建议的)事实上,你也可以通过尝试直接证明和理解你被阻止的原因来获得这个想法。在这里,如果你使用
siml
,很明显,你需要一个归纳假设,其中
acc
不是
nil
,因此你可以有广义版本的直觉。谢谢你,安东。这是一个非常有教育意义的答案Anton,list_gen_spec与list_gen之间的关系是什么?我注意到在规范中,函数的本质是表达的,即连接1;在这种情况下,list_gen的作用是什么?另一个问题是,在更复杂的模式生成器的情况下,这样的规范无法形成。(1)关于
list\u-gen\u-spec
,您似乎完全正确——它允许您将一个(可能)更快的尾部递归实现(
list\u-gen
)与另一个更明显(imho)和更容易推理的实现(基于
repeat
+
函数)连接起来我同意你的观点,给出一个干净简单的规范并不总是可能的,但我们应该努力做到这一点,并且在可能的情况下,我们应该利用它来为自己的利益服务。我不理解重复单态引理的含义。请你简要解释一下它的状态好吗?谢谢。这本质上是
r规范的一个特例epeat
当计数器为1时。我使用它将
repeat 1 lng++[1]
转换为
(repeat 1 lng++repeat 1)
,以便将后者转换为
repeat 1(lng+1)
使用
repeat\u app
。您可以更改
现在重写app\u cons\u middle,repeat\u singleton,repeat\u app,Nat。添加通信。
到一系列重写中:
重写app\u cons\u middle。重写repeat\u singleton。重写repeat\u app…
并以交互方式检查正在进行的操作。谢谢您,安东。一位受教育最多的人Anton,list_gen_spec与list_gen之间的关系是什么?我注意到在规范中,函数的本质是表达的,即连接1;在这种情况下,list_gen的作用是什么?另一个问题是,在更复杂的模式生成器的情况下,这样的规范无法形成。(1)关于
list\u gen\u spec
,您似乎做得很好——它允许您将一个(可能)更快的尾部递归实现(
list\u gen
)与另一个更明显(imho)和更容易推理的实现(基于
repeat
++