2

The experimental :fuel attribute of a function (which defaults to 1) should control how many times a function is unfolded during proof search. However, it seems to work in an unexpected way, as illustrated next with an example based on the tests (https://github.com/dafny-lang/dafny/blob/master/Test/dafny0/Fuel.dfy):

function {:fuel 1} pos(x:int) : int // :fuel 1 is the default
{
  if x < 0 then 0      // the function should return 0 for negative integers
  else 1 + pos(x - 1)  // and x + 1 for all other arguments, but recursively
}

method test()
{
    assert pos(32) == 33; // this assertion works with default fuel
}

The assertion pos(33) == 34 however requires fuel = 2. Here is the pattern that emerges:

pos(33) == 34: requires fuel = 2
pos(34) == 35: requires fuel = 4 <- skip 2
pos(35) == 36: requires fuel = 5
pos(36) == 37: requires fuel = 7 <- skip 2
pos(37) == 38: requires fuel = 8
pos(38) == 39: requires fuel = 10 <- skip 2
pos(39) == 40: requires fuel = 11
pos(40) == 41: requires fuel = 13 <- skip 2
pos(41) == 42: requires fuel = 14
pos(42) == 43: requires fuel = 16 <- skip 2
pos(43) == 44: requires fuel = 17
pos(44) == 45: requires fuel = 19 <- skip 2
... pattern continues ...
pos(95) == 96: requires fuel = 95
pos(96) == 97: requires fuel = 97 <- skip 2
pos(97) == 98: requires fuel = 98

Now here is what is truly surprising:

pos(98) == 99: does not work with any fuel whatsoever

Why does fuel behave this way:

  • why does it work up to 32 by default -- what is special about 32?
  • why does it require two additional units of fuel at every other step?
  • why does after 98 no amount of fuel works -- what is special about 98?

This is a follow-up to a previous question I had on unfolding recursive functions (Is there a bound in Dafny on the number of recursive calls?) where the Computing with an SMT Solver (https://www.microsoft.com/en-us/research/wp-content/uploads/2016/12/krml237.pdf) paper is mentioned. However, the encoding presented there (compile-time constants, ite barriers, triggering on non-zero fuel, SMT priorities) does not explain the three bullet points above.

What is the mental model I should use to understand :fuel?

0 Answers0