New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to Iterate set
in function
#4564
Comments
This bug still persists in the dafny 4.4.0+707b18acee078b3aa4d84c0590a980966bf22428 function f(s: set<int>) : (z:int)
requires s != {} {
has_minimum(s);
var z :| z in s && forall y :: y in s ==> z <= y;
z
}
lemma has_minimum(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};
has_minimum(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
}
}
} |
The current behavior is intentional. Functions must be deterministic, so when using the @DavePearce I'm closing this, but please reopen it if you have a remaining question or believe something is incorrect. |
Well, the behaviour definitely did change because I was using it and it broke!! In the end, this means that sets have a fairly limited utility. Still I can build my own using a
Well, in many cases, it is possible to select a unique element. For sets which contain ordered elements, you can select the least element, etc. Anyways, if that is the intended behaviour then that is fine. I can work around it, as discussed with |
Ah, sorry I failed to see how it broke. If you change your What to me is a bit magical, is that even if you don't prove that
Yes, if you use the |
The key point is that in a ghost context, it's sound to just assume that a deterministic interpretation of a particular
@henry-hz's comment above is a good example: #4564 (comment). You have to constrain the RHS of the
Yup, it's the fact that statements in a method (and methods in general) are allowed to be non-deterministic, so I cut a documentation enhancement request to cover this more explicitly in the reference manual, since it's a frequent point of confusion: #5372 :) |
I was confused by that until @RustanLeino made me realize that the same Dafny value could have different run-time representations. For example, |
This Dafny Power User Note provides some explanation and guidance on iterating over collections. |
More importantly https://dafny.org/dafny/DafnyRef/DafnyRef#555-iterating-over-collections has some of that content. I cut #5372 because the core documentation really needs to address this more directly. |
So, the comments above are helping! I wasn't aware that Dafny would actually try to establish that the selected element is unique. So, eventually, I managed to get this to compile / verify: lemma ThereIsAMinimum(s: set<int>)
requires s != {}
ensures exists x :: x in s && forall y :: y in s ==> x <= y
function g(items: set<nat>) : (r:nat)
requires |items| > 0 {
ThereIsAMinimum(items);
var item :| item in items && (forall k :: k in items ==> item <= k);
item
} That does actually solve the original problem we were having. |
I looked into your "trivial" lemma and after curating the proof, I came up with this solution as well: lemma ThereIsAMinimum(s: set<int>) returns (x: int)
requires s != {}
ensures x in s && forall y <- s :: x <= y
{
x :| x in s;
if forall y :: y in s ==> x <= y {
} else {
var notXButSmaller :| notXButSmaller in s && notXButSmaller < x;
assert notXButSmaller in s - {x};
var z := ThereIsAMinimum(s - {x});
forall y <- s ensures z <= y {
if y != x {
assert y in s - {x};
}
}
x := z;
}
} |
Haha, thanks @MikaelMayer !! I hadn't looked into that yet, but figured it could be done :) |
Dafny version
4.2.0
Code to produce this issue
Command to run and resulting output
What happened?
The term
var item :| item in items
compiles when in amethod
, but reports an error within afunction
. This seems inconsistent to me, and it previously worked in earlier versions of Dafny that supportedfunction method
syntax.Furthermore, I don't know any other way to iterate a
set<T>
--- which would imply you can't currently iterate sets from within afunction
? That seems unexpected to me.What type of operating system are you experiencing the problem on?
Linux
The text was updated successfully, but these errors were encountered: