2

My attempt to write an ACSL predicate to see if an integer is a power of 2 goes like this:

/*@
  predicate positive_power_of_2 (integer i) =
    i > 0 &&
    (i == 1 || ((i & 1) == 0 && positive_power_of_2 (i >> 1)));
 */

However when I added some assert lines into a random function, some Timeout (ie. fail). I don't understand why?

//@ assert positive_power_of_2 (1);  // Timeout
//@ assert positive_power_of_2 (2);  // Valid
//@ assert positive_power_of_2 (4);  // Valid
//@ assert !positive_power_of_2 (7); // Timeout
Rich
  • 926
  • 1
  • 9
  • 17

1 Answers1

2

As a side note, for such purely logic properties, you can use lemmas instead of assert, as in //@ lemma pow2_1: positive_power_of_2(1);. Since a lemma is a global annotation, it spares you from writing a function just for the sake of holding an assert.

Now back to the issue itself. Mixing bitwise operations with arithmetic ones (the less-than comparison) tends to confuse automated theorem provers. You did not specify which one(s) you use, but if you only used one, you might want to try installing others (nowadays, a mix of alt-ergo, z3 and cvc4 tends to provide good results). That said, a small interactive help to WP's internal simplifier QED is also sufficient: by using the GUI (see section 2.4 of WP manual), you can conclude by just unfolding the definition of positive_power_of_2 in each of the goals (as far as I know, there's no command-line option to do the equivalent).

Basically, once you are in the WP Proofs panel of the GUI, you have to double click in the Script column of the row corresponding to the proof obligation you want to work on, which will let you enter the interactive proof mode, as in the screenshot below:

WP interactive proof mode in Frama-C GUI

Now, the point is that the list of available tactics (on the right) is contextual: only the ones that are relevant for the term you have selected in the proof obligation (on the left) are shown. Some tactics are always relevant, such as Cut, which let you prove an auxiliary statement that can be used as an hypothesis in the rest of the proof, but unfolding a definition only makes sense if there's a definition to unfold in your selection. Hence you have to click on P_positive_power_of_2 to let the tactic appear. Afterwards, just click on the corresponding triangle to let WP unfold the definition and attempt to complete the proof afterwards.

Virgile
  • 9,724
  • 18
  • 42
  • alt-ergo 2.2.0, but I also have z3 and gappa installed (it seems to always prefer alt-ergo for reasons I can't understand). – Rich Oct 09 '20 at 11:36
  • Can you expand on what you mean by "you can conclude by just unfolding the definition of positive_power_of_2 in each of the goals"? Where in the GUI is this exactly? – Rich Oct 09 '20 at 11:52
  • Of course. WP's interactive proof interface is not the most ergonomic piece of software I have ever seen to say the least. I hope my explanations are sufficient, I'm afraid I'd need a full video instead of a single image to make things as clear as possible. – Virgile Oct 09 '20 at 12:28
  • Yes I was able to prove the simple is-power-of-2(N) for small constant N this way. I am doing this as part of trying to prove an actual C function, but I'm going to start a new question for that. – Rich Oct 09 '20 at 12:35