如何根据Coq中的规范构建字节列表
我正试图根据我在上下文中的规范构建一个字节列表(该规范是基于如何根据Coq中的规范构建字节列表,coq,proof,coq-tactic,formal-verification,Coq,Proof,Coq Tactic,Formal Verification,我正试图根据我在上下文中的规范构建一个字节列表(该规范是基于nth\u error函数的联合定义的,这些函数确定索引中的字节值(或一系列索引中的字节值)。例如,请参见下面的目标和上下文 a_len, b_len : nat a : seq.seq byte b : seq.seq byte H : Datatypes.length a = a_len /\ (* the length of list I'd like to build *) Datatypes.len
nth\u error
函数的联合定义的,这些函数确定索引中的字节值(或一系列索引中的字节值)。例如,请参见下面的目标和上下文
a_len, b_len : nat
a : seq.seq byte
b : seq.seq byte
H : Datatypes.length a = a_len /\ (* the length of list I'd like to build *)
Datatypes.length b = b_len /\ (* the length of another list concatenated at the end *)
is_true (b_len + 4 <= a_len) /\ (* added after edit *)
is_true (1 < b_len) /\ (* added after edit *)
nth_error a 0 = x00 /\ (* the value of first byte is zero *)
(forall i : nat, (* then we have a bunch of x01's *)
is_true (0 < i) /\ is_true (i < a_len - b_len - 1) ->
nth_error a i = Some x01) /\
nth_error a (a_len - b_len - 1) = Some x00 /\ (* next byte is zero *)
(forall j : nat, (* which ends with a list that is equal to b *)
is_true (0 <= j) /\ is_true (j < b_len) ->
nth_error a (a_len - b_len + j) = nth_error b j)
______________________________________(1/1)
a = [x00] ++ repeat x01 (a_len - b_len - 2) ++ [x00] ++ b
定义一些引理如下:
Lemma two_concats_equality1:
forall (lb1 lb1' lb2 lb2': list byte),
(lb1 ++ lb2) = (lb1' ++ lb2') /\ length lb1 = length lb1' -> lb1 = lb1' /\ lb2 = lb2'.
为了建立字节列表,a
,从零开始使用n次错误分割
,使用two-concats\u equality1
携带信息,并多次执行此操作直到结束。但还没有成功。我甚至无法证明two-concats\u equality1
引理(目前假设为真)。
我在字节重复的开头卡住了,n\u错误a I=Some x01
我想知道这是否是证明这个目标的正确方法。如果不是,请告诉我你会怎么做
如有任何意见,将不胜感激
编辑:
正如@Yves指出的,我正在进行以下编辑:
n
,它应该是a_len
a_len
和b_len
的关系,避免了前面提到的错误陈述来自mathcomp的
要求导入所有\u ssreflect ssrnat。
从Coq需要导入Lia。
需要导入Init.Byte Coq.Lists.List。
导入列表符号。
引理根据规范构建:
forall(a_len b_len:nat)(a b:list字节),
Datatypes.length a=a_len/\
Datatypes.length b=b_len/\
a_len>=b_len+4/\
b_len>=2/\
n_错误a 0=某些x00/\
(对于所有i:nat,(0
n_错误a i=某些x01)/\
n次误差a(a_len-b_len-1)=一些x00/\
(对于所有j:nat,(0
第n个错误a(a_len-b_len+j)=第n个错误bj)
->
a=[x00]++重复x01(a_len-b_len-2)++[x00]++b。
证明。
承认。
问题由原始海报编辑,更改了声明。此消息的底部是原始问题的答案
为了解决这个问题,你需要一个在库中还不存在的定理,我在这里包括:
Lemma eq_from_nth_error {A : Type} (l1 l2 : list A) :
(forall i, nth_error l1 i = nth_error l2 i) -> l1 = l2.
Proof.
elim: l1 l2 => [ | a l1 IH] [ | a' l2] //.
by move=> abs; have := (abs 0).
by move=> abs; have := (abs 0).
move=> cmp; congr (_ :: _).
by have := (cmp 0) => /= [[]].
apply: IH=> i; exact (cmp i.+1).
Qed.
有了这个定理,你可以通过研究所有可能的指数i
来证明等式,这些指数是你作为n次误差
的参数给出的。所以,你介绍你的假设,然后你应用这个定理,你介绍i
,然后你看i
的5种可能的情况:
i=0
0
i=a_len-b_len-1
a_len-b_len-1
a\u len
List.nth_错误[::x00]i=Some x01)。
按移动=>i[igt0 ilt0]。
断言(cnd2:forall j:nat,
0
List.nth_错误[::x00](1-0+j)=List.nth_错误[::]j)。
按移动=>j[jge0 glt0]。
推广(abs10(x00::nil)nil(conj-erefl)
(conj erefl(conj erefl(conj cnd1)(conj erefl cnd2())))。
通过重写/=。
Qed。
此脚本混合了数学组件样式和香草coq样式,这很糟糕。请提供一个最小的可复制示例,特别是指出您加载的库。您的目标包含一个变量
n
,如果是i
?谢谢,@Yves。我将用以下内容编辑我的问题:1)最小可重复性示例;2) 修复应为a_len
的n
的打字错误;3)通过添加a_len
和b_len
的缺失关系,修复您在下面的回答中指出的错误陈述问题。谢谢!我解决了这个问题。但是关于使用nth*
,我必须使用nth\u error
。你认为它是否仍然可以用第n个错误来证明吗?我刚刚读了编辑过的问题。这使得答案过时了。我将尝试编辑,以便新读者不会太困惑。请注意,unfold在HRep中是正确的。
是无用的,我建议删除这一行。另外,我认为作为第一个命令的rewrite-?(minusE,plusE)
是笨拙的,它可能不会删除您想要删除的所有实例。因此,我们同意第二种情况是0
。您几乎完成了,并且出现了HPrem:n\u错误a i=Some“001”%byte
。用这个假设重写,然后使用引理nth\u error\u app2
,它的算术条件应该用siml来求解;lia
。然后使用引理n\u error\u app1
。对于它的算术条件,你需要一个关于重复长度的引理,这个引理被称为repeat\u length
。对于nth\u error\u app1
的算术条件,在用repeat\u length
重写之后,您仍然需要修改假设i_lt_border
,以便它使用算术运算符lia
knows,而不是ssreflect变量。这可以通过move/ltP:i_lt_border=>i_lt_border.
然后siml;lia
完成此算术条件。
From mathcomp Require Import all_ssreflect ssrnat.
From Coq Require Import Lia.
Require Import Init.Byte Coq.Lists.List.
Import ListNotations.
Lemma build_from_spec :
forall (a_len b_len : nat) (a b : list byte),
Datatypes.length a = a_len /\
Datatypes.length b = b_len /\
a_len >= b_len + 4 /\
b_len >= 2 /\
nth_error a 0 = Some x00 /\
(forall i : nat, (0 < i) /\ (i < a_len - b_len - 1) ->
nth_error a i = Some x01) /\
nth_error a (a_len - b_len - 1) = Some x00 /\
(forall j : nat, (0 <= j) /\ (j < b_len) ->
nth_error a (a_len - b_len + j) = nth_error b j)
->
a = [x00] ++ repeat x01 (a_len - b_len - 2) ++ [x00] ++ b.
Proof.
Admitted.
Lemma eq_from_nth_error {A : Type} (l1 l2 : list A) :
(forall i, nth_error l1 i = nth_error l2 i) -> l1 = l2.
Proof.
elim: l1 l2 => [ | a l1 IH] [ | a' l2] //.
by move=> abs; have := (abs 0).
by move=> abs; have := (abs 0).
move=> cmp; congr (_ :: _).
by have := (cmp 0) => /= [[]].
apply: IH=> i; exact (cmp i.+1).
Qed.
have [/eqP i_is_0 | i_is_not_0] := boolP(i == 0).
have [i_lt_border | is_larger] := boolP(i < a_len - b_len - 1).
Lemma arithmetic_difficulty i j : i + 3 < j - 2 -> i <= j.
Proof.
Fail lia.
rewrite -?(minusE, plusE).
move/ltP => i3j2.
apply/leP.
lia.
Qed.
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Section some_context.
Definition byte := nat.
Variables x00 x01 : byte.
Lemma Dan_problem : (forall (a_len b_len : nat)
(a b : seq byte)
(H : Datatypes.length a = a_len /\
Datatypes.length b = b_len /\
List.nth_error a 0 = Some x00 /\
(forall i : nat,
is_true (0 < i) /\ is_true (i < a_len - b_len - 1) ->
List.nth_error a i = Some x01) /\
List.nth_error a (a_len - b_len - 1) = Some x00 /\
(forall j : nat,
is_true (0 <= j) /\ is_true (j < b_len) ->
List.nth_error a (a_len - b_len + j) = List.nth_error b j)),
a = [:: x00] ++ List.repeat x01 (a_len - b_len - 2) ++ [:: x00] ++ b) ->
False.
Proof.
intros abs.
assert (cnd1 : forall i, 0 < i /\ i < 1 - 0 -1 ->
List.nth_error [:: x00] i = Some x01).
by move=> i [igt0 ilt0].
assert (cnd2 : forall j : nat,
0 <= j /\ j < 0 ->
List.nth_error [:: x00] (1 - 0 + j) = List.nth_error [::] j).
by move=> j [jge0 glt0].
generalize (abs 1 0 (x00::nil) nil (conj erefl
(conj erefl (conj erefl (conj cnd1 (conj erefl cnd2)))))).
by rewrite /=.
Qed.