Dafny类之外的代码验证了什么,但是在封装时没有?

时间:2018-02-28 15:58:12

标签: dafny

在Dafny类之外验证的某些代码无法验证何时封装。我想知道(1)为什么,以及(2)如何充分利用两个世界:封装/抽象和验证。代码将“关系”建模为一对:域集和域集上的一组对。下面介绍两个版本。第一个验证,第二个验证。

代码定义了一个有效性条件,要求对集合中的对实际上在域上。它定义了一个谓词isFunction,如果这样建模的“关系”是单值的,则返回true。这是在一种情况下验证但不在另一种情况下验证的谓词。然后,在Main例程中的代码验证(dom = {1,2,3,4},pair = {(1,1),(2,2),(3,3),(4,4) })是单值(函数)。但是,当我在一个类中封装域和对集合,并将谓词转换为成员函数时,Main中的相同代码不再进行验证。

UNENCAPSULATED VERSION:

/*
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
}

1 个答案:

答案 0 :(得分:1)

你只是缺少构造函数的后置条件。

ensures d == dom && p == pairs

这是必要的,因为与方法一样,构造函数的主体不会向调用者显示。所以Main不知道构造函数除了规范中的内容之外做了什么。