某些在 Dafny 类之外进行验证的代码在封装时无法验证。我想知道(1)为什么,以及(2)如何两全其美:封装/抽象和验证。该代码将“关系”建模为一对:一个域集和域集上的一组对。下面介绍两个版本。第一个验证,第二个没有。
该代码定义了一个有效性条件,该条件要求对集中的对实际上在域上。它定义了一个谓词 isFunction,如果如此建模的“关系”是单值的,则返回 true。这是在一种情况下验证但在另一种情况下不验证的谓词。然后,在 Main 例程中的代码验证 ( dom = {1,2,3,4}, pairs = { (1,1), (2,2), (3,3), (4,4 ) } ) 是单值的(一个函数)。但是,当我将域和对集合封装在一个类中,并将谓词制作成成员函数时,Main 中的相同代码不再验证。
未封装版本:
/*
Represent a finite binary relation on a set, S,
as a pair: the set S and a set of pairs (to be
drawn from S)
*/
type relationS<T> = (set<T>,set<(T,T)>)
/*
A de-facto Valid() predicate that checks that that each
value in each pair in pairs is a member ofthe domain set.
*/
function method relS<T(!new)>(dom: set<T>, pairs: set<(T,T)>):
relationS<T>
requires forall x, y :: (x, y) in pairs ==> x in dom && y in dom
{
(dom, pairs)
}
/*
Projection function: Given a relation on S, return its co/domain set.
*/
function method domS<T>(r: relationS<T>): set<T>
{
r.0
}
/*
Projection function: Given a relation on S, return its set of pairs.
*/
function method pairsS<T>(r: relationS<T>): set<(T,T)>
{
r.1
}
/*
Return true iff the relation is single-valued (a function)
*/
predicate isFunctionS<T>(r: relationS<T>)
{
forall x, y, z :: x in domS(r) && y in domS(r) && z in domS(r) &&
(x, y) in pairsS(r) &&
(x, z) in pairsS(r) ==>
y == z
}
method Main()
{
var d := {1, 2, 3, 4};
var h := { (1,1), (2,2), (3,3), (4,4) };
var r1 := relS(d,h);
assert isFunctionS(r1); // Verifies
}
封装版本(抱歉标识符略有不同)
/*
Abstraction of a finite binary relation on a
set, S. Underlying representation is a pair:
the domain set, S, and a set of pairs over S.
*/
class binRelationS<T(!new,==)>
{
var d: set<T>;
var p: set<(T,T)>;
predicate Valid()
reads this;
{
forall x, y :: (x, y) in p ==> x in d && y in d
}
/*
Constructor requires that all values appearing in
any of the pairs in p be in d. That is, the pairs
in p must represent a relation on domain, d.
*/
constructor(dom: set<T>, pairs: set<(T,T)>)
requires forall x, y ::
(x, y) in pairs ==> x in dom && y in dom;
ensures Valid();
{
d := dom;
p := pairs;
}
function method dom(): set<T>
requires Valid();
reads this;
ensures Valid();
{
d
}
function method rel(): set<(T,T)>
requires Valid();
reads this
ensures Valid();
{
p
}
/*
Return true iff the relation is single-valued (a function)
*/
predicate isFunction()
requires Valid();
reads this;
ensures Valid();
{
forall x, y, z ::
x in d && y in d && z in d &&
(x, y) in p && (x, z) in p ==>
y == z
}
}
method Main()
{
var d := {1, 2, 3, 4};
var h := { (1,1), (2,2), (3,3), (4,4) };
var r := new binRelationS(d,h);
assert r.isFunction(); // assertion violation
}