Multiset 仅使用一个元素数组进行验证
Multiset only verifying with one element array
我在验证多重集中的元素计数是否为特定数字时遇到问题。下面是两个程序,一个工作(验证正确),一个不工作。
验证正确:
method Main() {
var a: array<int> := new int[1];
a[0] := 2;
assert a[0] == 2;
var ms: multiset<int> := multiset(a[..]);
print ms;
assert ms[2] == 1;
}
未正确验证:
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
assert a[0] == 2;
assert a[1] == 3;
var ms: multiset<int> := multiset(a[..]);
print ms;
assert ms[2] == 1;
}
虽然,直接使用序列似乎工作得很好:
method Main() {
var s := [2, 3];
var ms: multiset<int> := multiset(s);
print ms;
assert ms[2] == 1;
}
我不确定为什么会这样。对于第一个程序 print ms;
打印出 multiset{2}
并且在第二个程序中 print ms;
打印出 multiset{2, 3}
这两个看起来都很好,但是 Dafny 在 assert ms[2] == 1;
。似乎当数组长度 > 1 时会发生这种情况。
我是不是误解了多重集的工作原理,还是有其他问题?
解决方案 1
第二个程序验证您是否在设置 a[0]
和 a[1]
后的某个时间添加 assert a[..] == [2, 3];
。例如以下作品:
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
assert a[0] == 2;
assert a[1] == 3;
var ms: multiset<int> := multiset(a[..]);
assert a[..] == [2, 3];
print ms;
assert ms[2] == 1;
}
我不知道为什么这个断言是必要的。
解决方案 2
还有另一种解决方案,它不需要声明 a[..]
的具体值。可以定义一个函数 to_seq(a, i)
,它显式计算 a[i..]
的值,然后 assert a[..] == to_seq(a, 0)
。更详细:
function to_seq<T>(a: array<T>, i: int) : (res: seq<T>)
requires 0 <= i <= a.Length
ensures res == a[i..]
reads a
decreases a.Length-i
{
if i == a.Length
then []
else [a[i]] + to_seq(a, i + 1)
}
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
var ms: multiset<int> := multiset(a[..]);
assert a[..] == to_seq(a, 0);
assert ms[2] == 1;
}
我又不确定为什么这个断言有帮助。
我在验证多重集中的元素计数是否为特定数字时遇到问题。下面是两个程序,一个工作(验证正确),一个不工作。
验证正确:
method Main() {
var a: array<int> := new int[1];
a[0] := 2;
assert a[0] == 2;
var ms: multiset<int> := multiset(a[..]);
print ms;
assert ms[2] == 1;
}
未正确验证:
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
assert a[0] == 2;
assert a[1] == 3;
var ms: multiset<int> := multiset(a[..]);
print ms;
assert ms[2] == 1;
}
虽然,直接使用序列似乎工作得很好:
method Main() {
var s := [2, 3];
var ms: multiset<int> := multiset(s);
print ms;
assert ms[2] == 1;
}
我不确定为什么会这样。对于第一个程序 print ms;
打印出 multiset{2}
并且在第二个程序中 print ms;
打印出 multiset{2, 3}
这两个看起来都很好,但是 Dafny 在 assert ms[2] == 1;
。似乎当数组长度 > 1 时会发生这种情况。
我是不是误解了多重集的工作原理,还是有其他问题?
解决方案 1
第二个程序验证您是否在设置 a[0]
和 a[1]
后的某个时间添加 assert a[..] == [2, 3];
。例如以下作品:
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
assert a[0] == 2;
assert a[1] == 3;
var ms: multiset<int> := multiset(a[..]);
assert a[..] == [2, 3];
print ms;
assert ms[2] == 1;
}
我不知道为什么这个断言是必要的。
解决方案 2
还有另一种解决方案,它不需要声明 a[..]
的具体值。可以定义一个函数 to_seq(a, i)
,它显式计算 a[i..]
的值,然后 assert a[..] == to_seq(a, 0)
。更详细:
function to_seq<T>(a: array<T>, i: int) : (res: seq<T>)
requires 0 <= i <= a.Length
ensures res == a[i..]
reads a
decreases a.Length-i
{
if i == a.Length
then []
else [a[i]] + to_seq(a, i + 1)
}
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
var ms: multiset<int> := multiset(a[..]);
assert a[..] == to_seq(a, 0);
assert ms[2] == 1;
}
我又不确定为什么这个断言有帮助。