Dafny 中包含 属性 的最长序列
Longest sequence that holds a property in Dafny
在 Dafny 中,我正在尝试制作一个 Max
多态和高阶函数,给定一个序列和一个谓词,returns 包含它的最长子序列。比如最长的递增子序列,或者所有元素都为零的最长子序列。
为此,我设计了一个慢速算法(给定 P
谓词和 S
序列):
1. Start an i pivot in the left and a j pivot in the same place.
2. Start the max_sequence = [] and the max_sequence_length = 0.
3. While i<S.length:
counter = 0
j = i
While max_sequence[i..j] satisfies P and j<S.length:
If counter > max_sequence_length:
max_sequence_length = counter
max_sequence = max_sequence[i..j]
Increment j
Increment i
4. Return max_sequence
您可以看到它已实现:
method maxPropertySequence<T>(P: seq<T> -> bool, sequ: seq<T>) returns (max_seq: seq<T>)
{
var i := 0;
var j := 0;
var longest := 0;
var the_sgmt := sequ;
var fresh_segmnt := sequ;
var counter := longest;
while i<(|sequ|)
decreases |sequ|-i
{
j := i;
counter := 0;
fresh_segmnt := [sequ[i]];
if P(fresh_segmnt)
{
j := j+1;
counter:=counter+1;
if counter>longest {
longest:=counter;
the_sgmt := fresh_segmnt;
}
while P(fresh_segmnt) && j<|sequ|
decreases |sequ|-j
{
fresh_segmnt := fresh_segmnt + [sequ[j]];
j := j+1;
counter:=counter+1;
if counter>longest {
longest:=counter;
the_sgmt := fresh_segmnt;
}
}
}
i := i+1;
}
return the_sgmt;
}
我的问题是:如何验证 Max
函数的行为是否符合我的预期?更具体地说:我必须添加哪些 ensures
?
我的想法是这样的:对于原始序列的所有子序列,没有满足P
且比the_sgmt
长的子序列。但是不知道怎么表达才有效
谢谢!
我编写了从给定整数数组中查找(最左边)最长的零子序列的代码。由于您可以使用谓词映射 sequ
,因此这两个几乎是相同的问题。
// For a given integer array, let's find the longest subesquence of 0s.
// sz: size, pos: position. a[pos..(pos+sz)] will be all zeros
method longestZero(a: array<int>) returns (sz:int, pos:int)
requires 1 <= a.Length
ensures 0 <= sz <= a.Length
ensures 0 <= pos < a.Length
ensures pos + sz <= a.Length
ensures forall i:int :: pos <= i < pos + sz ==> a[i] == 0
ensures forall i,j :: (0 <= i < j < a.Length && getSize(i, j) > sz) ==> exists k :: i <= k <= j && a[k] != 0
{
var b := new int[a.Length]; // if b[i] == n, then a[i], a[i-1], ... a[i-n+1] will be all zeros and (i-n ==0 or a[i-n] !=0)
if a[0] == 0
{b[0] := 1;}
else
{b[0] := 0;}
var idx:int := 0;
while idx < a.Length - 1 // idx <- 0 to a.Length - 2
invariant 0 <= idx <= a.Length - 1
invariant forall i:int :: 0 <= i <= idx ==> 0 <= b[i] <= a.Length
invariant forall i:int :: 0 <= i <= idx ==> -1 <= i - b[i]
invariant forall i:int :: 0 <= i <= idx ==> (forall j:int :: i-b[i] < j <= i ==> a[j] == 0)
invariant forall i:int :: 0 <= i <= idx ==> ( 0 <= i - b[i] ==> a[i - b[i]] != 0 )
{
if a[idx + 1] == 0
{ b[idx + 1] := b[idx] + 1; }
else
{ b[idx + 1] := 0;}
idx := idx + 1;
}
idx := 1;
sz := b[0];
pos := 0;
// Let's find maximum of array b. That is the desired sz.
while idx < a.Length
invariant 1 <= idx <= b.Length
invariant 0 <= sz <= a.Length
invariant 0 <= pos < a.Length
invariant pos + sz <= a.Length
invariant forall i:int :: 0 <= i < idx ==> b[i] <= sz
invariant forall i:int :: pos <= i < pos + sz ==> a[i] == 0
invariant forall i, j:int :: (0 <= i < j < idx && getSize(i,j) > sz) ==> a[j-b[j]] != 0
{
// find max
if b[idx] > sz
{
sz := b[idx];
pos := idx - b[idx] + 1;
}
idx := idx + 1;
}
}
function getSize(i: int, j:int) : int
{
j - i + 1
}
由于我是 dafny 的新手,任何关于风格或任何方面的评论都将受到赞赏。
在 Dafny 中,我正在尝试制作一个 Max
多态和高阶函数,给定一个序列和一个谓词,returns 包含它的最长子序列。比如最长的递增子序列,或者所有元素都为零的最长子序列。
为此,我设计了一个慢速算法(给定 P
谓词和 S
序列):
1. Start an i pivot in the left and a j pivot in the same place.
2. Start the max_sequence = [] and the max_sequence_length = 0.
3. While i<S.length:
counter = 0
j = i
While max_sequence[i..j] satisfies P and j<S.length:
If counter > max_sequence_length:
max_sequence_length = counter
max_sequence = max_sequence[i..j]
Increment j
Increment i
4. Return max_sequence
您可以看到它已实现:
method maxPropertySequence<T>(P: seq<T> -> bool, sequ: seq<T>) returns (max_seq: seq<T>)
{
var i := 0;
var j := 0;
var longest := 0;
var the_sgmt := sequ;
var fresh_segmnt := sequ;
var counter := longest;
while i<(|sequ|)
decreases |sequ|-i
{
j := i;
counter := 0;
fresh_segmnt := [sequ[i]];
if P(fresh_segmnt)
{
j := j+1;
counter:=counter+1;
if counter>longest {
longest:=counter;
the_sgmt := fresh_segmnt;
}
while P(fresh_segmnt) && j<|sequ|
decreases |sequ|-j
{
fresh_segmnt := fresh_segmnt + [sequ[j]];
j := j+1;
counter:=counter+1;
if counter>longest {
longest:=counter;
the_sgmt := fresh_segmnt;
}
}
}
i := i+1;
}
return the_sgmt;
}
我的问题是:如何验证 Max
函数的行为是否符合我的预期?更具体地说:我必须添加哪些 ensures
?
我的想法是这样的:对于原始序列的所有子序列,没有满足P
且比the_sgmt
长的子序列。但是不知道怎么表达才有效
谢谢!
我编写了从给定整数数组中查找(最左边)最长的零子序列的代码。由于您可以使用谓词映射 sequ
,因此这两个几乎是相同的问题。
// For a given integer array, let's find the longest subesquence of 0s.
// sz: size, pos: position. a[pos..(pos+sz)] will be all zeros
method longestZero(a: array<int>) returns (sz:int, pos:int)
requires 1 <= a.Length
ensures 0 <= sz <= a.Length
ensures 0 <= pos < a.Length
ensures pos + sz <= a.Length
ensures forall i:int :: pos <= i < pos + sz ==> a[i] == 0
ensures forall i,j :: (0 <= i < j < a.Length && getSize(i, j) > sz) ==> exists k :: i <= k <= j && a[k] != 0
{
var b := new int[a.Length]; // if b[i] == n, then a[i], a[i-1], ... a[i-n+1] will be all zeros and (i-n ==0 or a[i-n] !=0)
if a[0] == 0
{b[0] := 1;}
else
{b[0] := 0;}
var idx:int := 0;
while idx < a.Length - 1 // idx <- 0 to a.Length - 2
invariant 0 <= idx <= a.Length - 1
invariant forall i:int :: 0 <= i <= idx ==> 0 <= b[i] <= a.Length
invariant forall i:int :: 0 <= i <= idx ==> -1 <= i - b[i]
invariant forall i:int :: 0 <= i <= idx ==> (forall j:int :: i-b[i] < j <= i ==> a[j] == 0)
invariant forall i:int :: 0 <= i <= idx ==> ( 0 <= i - b[i] ==> a[i - b[i]] != 0 )
{
if a[idx + 1] == 0
{ b[idx + 1] := b[idx] + 1; }
else
{ b[idx + 1] := 0;}
idx := idx + 1;
}
idx := 1;
sz := b[0];
pos := 0;
// Let's find maximum of array b. That is the desired sz.
while idx < a.Length
invariant 1 <= idx <= b.Length
invariant 0 <= sz <= a.Length
invariant 0 <= pos < a.Length
invariant pos + sz <= a.Length
invariant forall i:int :: 0 <= i < idx ==> b[i] <= sz
invariant forall i:int :: pos <= i < pos + sz ==> a[i] == 0
invariant forall i, j:int :: (0 <= i < j < idx && getSize(i,j) > sz) ==> a[j-b[j]] != 0
{
// find max
if b[idx] > sz
{
sz := b[idx];
pos := idx - b[idx] + 1;
}
idx := idx + 1;
}
}
function getSize(i: int, j:int) : int
{
j - i + 1
}
由于我是 dafny 的新手,任何关于风格或任何方面的评论都将受到赞赏。