此Q3
方法通过将m0添加到res | n0 |来传递n0 * m0倍。如果n0为负,我们将n0和m0反转为n0 * m0 = -n0 * -m0成立。
我遇到的问题是我不知道我的不变量应该是什么样子,因为不变量必须是boolean类型。任何人都能告诉我不变的布尔条件是什么样的吗?我想过Abs((n0)-n)*m == res
,但这不起作用。
method Q3(n0 : int, m0 : int) returns (res : int)
ensures n0*m0 == res
{
var n, m : int;
res := 0;
if (n0 >= 0)
{n,m := n0, m0;}
else
{n,m := -n0, -m0;}
while (0 < n)
invariant Abs((n0)-n)*m
{
res := res + m;
n := n - 1;
}
}
function Abs(x: int): int
{
if x < 0 then -x else x
}
答案 0 :(得分:1)
在尝试设计循环不变量时,首先向后工作会很有帮助。循环终止后你需要知道什么?
对于此方法,一旦循环终止,您将需要建立后置条件n0 * m0 == res
,因此这是循环不变量的起点。
由于循环更改res
,n0 * m0 == res
本身不是一个不变量。相反,我们必须考虑循环如何“朝着这个目标前进”。这个循环通过将m
添加到res
来取得进展,粗略地说这样做总共n
次。当n
为0时,循环终止。
一个常见的模式在这里很有用:不变量应该讨论“到目前为止”所做的事情以及“剩下要做什么”。在这种情况下,到目前为止所执行的操作是res
,剩下要做的是剩余的n
m
添加res + n * m == n0 * m0
。循环的每次迭代都需要做一件工作,并且保持不变量。
换句话说,这个循环的良好不变量是M <- matrix(NA, nrow = max(v), ncol = sum(v == 1))
M[cbind(v, cumsum(v == 1))] <- unlist(df, use.names = FALSE)
M
# [,1] [,2] [,3] [,4]
# [1,] -0.5604756 1.558708 0.07050839 0.1292877
# [2,] -0.2301775 NA NA 1.7150650
# [3,] NA NA NA 0.4609162
。
此外,Dafny Tutorial有一个关于循环不变量的部分,这可能会有所帮助。