我在Dafny写了一个类
的课程class Question{
var a: int;
var b: seq<int>;
predicate isValid(something: Type) { .... }
method X(something : Type) returns (b : int)
{
//utilises b to calculate a value for a
.....
}
predicate Second(something: Type) { a == X(something) }
//"something" is the same for all predicates and functions
}
我知道我不能在Second()谓词中调用该方法,但我想断言整数&#34; a&#34;当给定变量&#34;某些&#34;时,应该等于某个整数,用类中定义的方法计算。有没有办法做到这一点?
提前致谢。
答案 0 :(得分:1)
正如我在评论中提到的,没有直接的方法来影响任何逻辑实体(例如谓词)。相反,您需要在函数中描述您关心的内容,然后您可以使用它来讨论该值。
让我用您在评论中提到的示例代码进行说明。考虑w
类中的方法Graph
。此方法没有副作用,其返回值将在进一步的规范中有用。我们可以用函数Weight
替换它,如下所示。
function Weight(u: int, v: int): int
reads this, this.edges, this.vertices
requires this.isValid() && this.hasEdge(u,v)
requires u < d.Length && v< d.Length
{
var f : Edge? :| f in edges && f !=null && f.source == u && f.dest == v;
f.weight
}
在这种情况下,它相对简单:身体基本相同。
这是另一个更复杂的例子。考虑getL
类中的Path
方法。同样,这种方法是无副作用的,所以让我们用一个函数替换它。
function Length(G: Graph?): int
reads ...
requires ...
{
Sum(0, |pv| - 1, i /* ... */ => G.Weight(pv[i].id, pv[i+1].id))
}
我们使用G.Weight
和函数Sum
,其类型看起来(大致)像这样
function Sum(lo: int, hi: int, f: int -> int): int
decreases hi - lo
{
if lo >= hi then 0
else f(lo) + Sum(lo + 1, hi, f)
}
它将f
的值加到[lo, hi)
范围内。
实际上,我们需要一个更强大的Sum
版本,它允许f
具有前提条件并且还可以读取堆。这是它的类型(相同的身体工作)。
function Sum(lo: int, hi: int, f: int ~> int): int
requires forall i | lo <= i < hi :: f.requires(i)
decreases hi - lo
reads set i, o | lo <= i < hi && o in f.reads(i) :: o
请注意->
成为~>
,我们添加了requires
和reads
条款。
回到Length
,我们还需要填写一些缺少的reads
和requires
注释。这是完整的定义。
function Length(G: Graph): int
reads G, G.vertices, G.d , G.edges
reads this, this.pv
requires G != null && G.isValid() && this.isValid(G)
{
Sum(0, |pv| - 1, i reads this, this.pv, G, G.edges, G.vertices, G.d
requires 0 <= i < |pv| - 1 && G.isValid() && this.isValid(G) =>
G.Weight(pv[i].id, pv[i+1].id))
}
这会计算与getL
相同的值,并且可以在规范中使用。
希望这有帮助!