In the "Draft Dafny Reference Manual" 4.0.2 it describes defining decreases clauses for mutually recursive functions but where the variables decreasing in both functions are of the type nat
. I have tried to do the same thing but it has not worked. One difference is that the variables are not of the same type.
datatype Trie = Trie(letters : map<char,Trie>, word : bool)
function size(t:Trie) :(r:nat)
decreases t
{
1 + sum_setT(t.letters.Values)
}
function sum_setT(xs: set<Trie>) : (z:nat)
decreases xs
{
var working := xs; //Needed!
if (|working| == 0) then 0
else (
var x:Trie :| x in working;
var sofar:nat := sum_setT(working-{x});
sofar + size(x)
)
}
Any idea how to define the decreases clause much appreciated.
If two functions (possibly the same function) call each other recursively, then each call needs to be shown to decrease the termination metric given by the
decreases
functions. More precisely, if on entry to a functionF
, thedecreases
clause ofF
evaluates toX
, and whenF
calls functionG
at a time whenG
'sdecreases
clause evaluates toY
, thenX
must be shown to exceedY
.The "exceeds" relation is a built-in well-founded order, but you have control over the
decreases
clauses that give rise to the valuesX
andY
. In your example, the easiest way to define these is to use lexicographic tuples. In the "outer" function,size
, uset
. In the "inner" function,sum_setT
, uset, xs
for the samet
. To get this to work out, you'll need to addt
as a parameter tosum_setT
as well.In the call from
size
tosum_setT
,X
andY
aret
andt, t.letters.Values
, which is smaller because the built-in well-founded order in Dafny considers shorterdecreases
tuples to be larger.In the recursive call of
sum_setT
,X
andY
have the same first component (t
) and the set is strictly smaller inY
.In the call from
sum_setT
back tosize
, the valuex
is structurally included int
, sot
exceedsx
as required. For the verifier to know this fact (that is, for it to know that parameterxs
has some relation tot
), you'll need to add a precondition tosum_setT
.So, the final program is