我是初学者,我坚持使用Coq证明nat的列表。
我有一个list
reg nat
和一个函数clear_regs,它将每个值都更改为0并保持第三个值(索引2)不变。
我想展示forall regs, clear_regs regs = clear_regs (clear_regs regs)
。
我目前有两个功能,但我不知道一个是否比另一个好。
(1)第一个用辅助递归函数定义,取一个(递减)索引并检查它是否是第三个值。如果是这种情况,它会保留其值,否则会生成0.
(2)第二个映射(fun x => 0)
以使用(nth 2 reg 0)
注册并更新第三个值。我正在使用let
指令来保持其值。
我尝试过感应之类的东西,但似乎并没有把证据引向正确的道路。我真的不知道应该如何处理这个问题。 有人能帮助我吗?
答案 0 :(得分:3)
我有两条评论,第一条是关于"注册号码2"似乎有点特别。为什么2?如果数字或寄存器是1,会发生什么?
试图证明这种过于特殊的引理通常会使Coq中的证据复杂化。您可以更好地尝试证明更一般的引理,例如对于n寄存器机器,设置k< n次登记是幂等的。"该结果的证明在库中为set_set_nth
。您可以将设置与"设置为零"注册操作。我做了证据,你说它可以比较任意2如何使大小推理复杂化:
From mathcomp
Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Implicit Type (reg : seq nat).
(* You could also use take/drop to perform surgery *)
Definition clear_regs reg :=
set_nth 0 (nseq (size reg) 0) 2 (nth 0 reg 2).
Definition idem A (f : A -> A) := forall x, f (f x) = f x.
Lemma clear_regs_idem : idem clear_regs.
Proof.
(* We reduce equality of lists to equality of their elements, `eq_from_nth` *)
move=> reg; apply: (@eq_from_nth _ 0).
by rewrite !size_set_nth !size_nseq maxnA maxnn.
(* Now we need to use the fact that nth (set s x) = x, plus a bit of case reasoning *)
move=> i i_sz; rewrite !nth_set_nth /=; case: eqP => [//|].
by rewrite !nth_nseq; case: ifP; case: ifP.
Qed.
请注意,证明是无感应的,因为所有需要的归纳都封装在更高级别的seq引理中!我猜你可能很难做一次归纳来证明这个引理,因为你可能需要设置一个非常复杂的归纳假设。因此,最好组成几个较小的。
另一种可能更好的方法是为寄存器使用更强的表示形式。特别是,我选择使用一个很好的数据类型mathcomp,它被称为"有限支持的函数",即来自有限数据类型的映射。我们用地图'I_n.+1 -> nat
表示n个寄存器,其中'I_n
是小于n的自然数的类型。即使在您的特殊情况下,您也可以看到它运作良好:
From mathcomp
Require Import choice fintype finfun.
Section Regs.
Variable k : nat.
Definition reg := {ffun 'I_k.+1 -> nat}.
Implicit Type (r : reg).
Definition clearr r : reg :=
[ffun idx => if idx == (inord 2) then r (inord 2) else 0].
Lemma clearr_idem : idem clearr.
Proof. by move=> x; apply/ffunP=> j; rewrite !ffunE eqxx. Qed.
ffunP
引理是地图扩展性:两个地图相等,如果它们映射到相同的元素,其余的是常规的(eqxx会将x == x
重写为true
。
这里有可运行的代码:https://x80.org/collacoq/omemesamoy.coq让我知道任何问题。
问候,E。
答案 1 :(得分:2)
这里我已经定义了clear_reg
带有辅助函数的计数器来查找 k 元素。我证明了辅助函数是幂等的,并在clear_reg
的简单证明中使用它。
Require Import Arith. (* for eq_nat_dec *)
Fixpoint clear_reg_aux (l:list nat) k (i:nat) :=
match l with
| nil => nil
| cons x l' =>
let x' := if eq_nat_dec i k then x else 0 in
cons x' (clear_reg_aux l' k (i+1))
end.
Definition clear_reg l := clear_reg_aux l 2 0.
Lemma cra_idem:
forall l k n, clear_reg_aux l k n = clear_reg_aux (clear_reg_aux l k n) k n.
Proof.
induction l.
- auto.
- intros k n. simpl. rewrite <- IHl. destruct (eq_nat_dec n k). auto. auto.
Qed.
Lemma clear_reg_idem: forall l, clear_reg l = clear_reg (clear_reg l).
intros. unfold clear_reg. rewrite <- cra_idem. auto.
Qed.