Algorithm Dafny无法证明函数方法的等价性,即高阶多态递归与线性迭代
这个消息会有点长,但那是因为我想尽可能地解释它 在Dafny中,我遇到了下一个问题:给定一个数组,计算发生这种情况的长度为k的段数;段左半部分的正片数大于或等于右半部分 例如(假设片段只能是偶数,因此不讨论什么是半): 我以两种方式实现了这一点:一种是使用函数,使用高阶和多态性(但它不是线性的),另一种是使用迭代实现,它是线性的 该函数的工作方式如下:Algorithm Dafny无法证明函数方法的等价性,即高阶多态递归与线性迭代,algorithm,polymorphism,verification,dafny,formal-verification,Algorithm,Polymorphism,Verification,Dafny,Formal Verification,这个消息会有点长,但那是因为我想尽可能地解释它 在Dafny中,我遇到了下一个问题:给定一个数组,计算发生这种情况的长度为k的段数;段左半部分的正片数大于或等于右半部分 例如(假设片段只能是偶数,因此不讨论什么是半): 我以两种方式实现了这一点:一种是使用函数,使用高阶和多态性(但它不是线性的),另一种是使用迭代实现,它是线性的 该函数的工作方式如下: 我们定义了一个计数函数,它对数组中的属性进行计数 我们定义了一种方法,在给定数组的情况下,生成给定长度的所有段 我们使用Count定义一个谓词,
确保num_segmts==Count(segment_leftmore segmentright,product_segments(sequ,seg_length))代码>不进行验证。显然,我必须用引理证明一些关于Count
或Count\u linear
的性质,但不知道从哪里开始这个问题
有什么帮助吗?我希望我已经尽可能最好地解释了这个问题。我正在回答这个问题,只是为了得到好的代码格式
您的Count\u linear
有一个bug
var aseq := [1,2,3,4,5,6,7,8,9,10];
var slow := Count(segment_LeftMoreSegmentRight, produce_segments(aseq,4)); //high order and polymorphic
var fast := Count_linear(aseq, 4);
print slow, "\n";
print fast, "\n";
印刷品
7
5
我正在为您做一个完整的证明,但现在只需要一些简短的评论:(1)您的代码有错误:),您可以尝试运行添加一些打印语句,并在尝试证明之前先进行测试;(2) 确保在方法体中包含循环的子句始终需要循环不变量。首先,非常感谢。(1) 你完全正确,我用var bseq:=[1,2,3,4,5,6,7,8,9,10]证明了这一点
overvar seg\u leftRight:=Count(段\u Leftmore段右,bseq)
并且确实有效(即,将计数应用于一个具体段)。我知道我没有用你说的那个来证明,但我想我已经证明了。现在,更为合理的是,这一政策确实正在失败。(2) 我认为Dafny的当前版本并不总是需要不变量,至少对于简单的算法是如此,所以在再次提出此类问题之前,我将对此进行研究。抱歉耽误了时间,没问题!这不是浪费时间。我会在几个小时内回到一个完整的证明。要回答您关于循环不变量的问题,不,Dafny可以自动推断的唯一循环不变量是之类的东西,我非常感谢!我会接受你的建议,并记住不变量总是需要的。我在达夫尼呆了一段时间,但我几乎忘记了编程的迭代方式:(我一直在测试函数,没有发现任何问题。例如,我测试了var aseq:=[1,2,-1,4,5,6,7,-1,9,10];var bseq:=[1,2,3,4,5,6,7,8,9,10];var seg_leftRight:=Count(segment_LeftMoreSegmentRight,bseq)var seg2_leftRight:=Count(segment_leftmore segmentright,product_segments(aseq,5));
具有不同的aseq
和bseq
s,并且具有不同的段长度。我可能错了:哪些是失败的案例?我怎么没有看到这一个……我会看到的。非常感谢!(现在还不打算结束帖子)
//returns if the number of positives left is higher than the right or not
function method segmentL_isMore_right (pos_left:int,pos_right:int) : bool
{
if pos_left>=pos_right then true
else false
}
method initialize(sequ:seq<int>, seg_length:int) returns (sequ_new:seq<int>,pos_left: int,pos_right:int)
requires |sequ| >= seg_length >= 0
{
var length := |sequ|;
var pos_left_local := 0;
var pos_right_local :=0;
var i:=0;
while i<(length/2)
{
if sequ[i]>=1 {pos_left_local:=pos_left_local+1;}
i:=i+1;
}
while i<(length)
{
if sequ[i]>=1 {pos_right_local:=pos_right_local+1;}
i:=i+1;
}
return sequ[0..],pos_left_local,pos_right_local;
}
//Linear implementation
method Count_linear(sequ:seq<int>, seg_length:int) returns (num_segmts: int)
requires |sequ| >= seg_length >= 0
ensures num_segmts == Count(segment_LeftMoreSegmentRight, produce_segments(sequ,seg_length));
{
var num_segmts_local := 0;
var new_seq, pos_left_local, pos_right_local := initialize(sequ,seg_length);
var i:=seg_length+1;
while i<|sequ|
decreases |sequ|-i
{
if (sequ[i] >=0) {pos_right_local:=pos_right_local+1;}
if (sequ[i-seg_length]>=0) {pos_left_local:=pos_left_local+1;}
if (sequ[i-seg_length]/2>=0)
{
pos_right_local:=pos_right_local-1;
pos_left_local:=pos_left_local+1;
}
i:=i+1;
if segmentL_isMore_right (pos_left_local,pos_right_local)
{
num_segmts_local:=num_segmts_local+1;
}
}
return num_segmts_local;
}
\\if want to prove it:
method Main()
{
var aseq := [1,2,3,4,5,6,7,8,9,10];
var seg2_leftRight := Count(segment_LeftMoreSegmentRight, produce_segments(aseq,4)); //high order and polymorphic
}
var aseq := [1,2,3,4,5,6,7,8,9,10];
var slow := Count(segment_LeftMoreSegmentRight, produce_segments(aseq,4)); //high order and polymorphic
var fast := Count_linear(aseq, 4);
print slow, "\n";
print fast, "\n";
7
5