Hilbert epsilon运算符

时间:2018-07-06 09:57:41

标签: operator-keyword dafny epsilon

为什么可以在方法和函数中使用Hilbert epsilon运算符,但不能在“函数方法”中使用Hilbert epsilon运算符?

method choose<T>(s:set<T>) returns (x:T)
	requires s != {}
{
var z :| z in s;
return z;
}

function choose'<T>(s:set<T>):T
// function method choose'<T>(s:set<T>):T // Activate this line and comment the previous line to see the error
	requires s != {}
{
var z :| z in s;
z
}

2 个答案:

答案 0 :(得分:0)

为了Hilbert epsilon运算符(在Dafny中也称为let-such-that表达式),

var z :| P; E

要编译,约束P必须唯一地确定z。在您的情况下,约束Pz in s,除了单例集之外,它不能唯一地确定z

如果s的类型为set<int>,则可以通过将choose'函数更改为以下方式来(低效地)满足此要求:

function method choose'<T>(s:set<int>):int
  requires s != {}
{
  var z :| z in s && forall y :: y in s ==> z <= y;
  z
}

差不多。您需要说服Dafny有这样的z。您可以在引理中做到这一点。这是一个可能比需要的时间长的东西,但是我要做的第一个事情是。请注意,引理也使用Hilbert运算符,但是在语句上下文中,因此唯一性要求不适用。

function method choose'<T>(s:set<int>):int
  requires s != {}
{
  HasMinimum(s);
  var z :| z in s && forall y :: y in s ==> z <= y;
  z
}

lemma HasMinimum(s: set<int>)
  requires s != {}
  ensures exists z :: z in s && forall y :: y in s ==> z <= y
{
  var z :| z in s;
  if s == {z} {
    // the mimimum of a singleton set is its only element
  } else if forall y :: y in s ==> z <= y {
    // we happened to pick the minimum of s
  } else {
    // s-{z} is a smaller, nonempty set and it has a minimum
    var s' := s - {z};
    HasMinimum(s');
    var z' :| z' in s' && forall y :: y in s' ==> z' <= y;
    // the minimum of s' is the same as the miminum of s
    forall y | y in s
      ensures z' <= y
    {
      if
      case y in s' =>
        assert z' <= y;  // because z' in minimum in s'
      case y == z =>
        var k :| k in s && k < z;  // because z is not minimum in s
        assert k in s';  // because k != z
    }
  }
}

很遗憾,您的s的类型不是set<int>。我不知道如何从通用集合中获得唯一值。 :(

有关为何唯一性要求在编译表达式中如此重要的信息,请参见this paper

Rustan

答案 1 :(得分:0)

好的,谢谢,我理解非唯一确定值的编译问题。 但是,根据您的回答,我的第一个方法select应该引发与函数方法select'相同的错误,不是吗?

method choose<T>(s:set<T>) returns (x:T)
	requires s != {}
{
var z :| z in s;
return z;
}

function choose'<T>(s:set<T>):T
// function method choose'<T>(s:set<T>):T // Activate this line and comment the previous line to see the error
	requires s != {}
{
var z :| z in s;
z
}