Earlier quoted context omitted.
That would be nice, then the run time predicate can be fast while the logical version remains elegant. What happens if you remove requires { forall i j. (i (pred i -> pred j)}? I think it should still check, actually. That property ensures that the answer will be unique, but the algorithm will find a point pred i = False /\ pred (i+1) = True even if the predicate does not satisfy that property. If you add the uniquen…
> What happens if you remove requires { forall i j. (i (pred i -> pred j)}? I think it should still check, actually. If I simply remove that 'requires', then Why3 cannot prove the postcondition of `binary_search` automatically anymore (using the Z3, CVC4 and Eprover automatic provers that I have installed). Specifically, Why3 tries to split the postcondition into the 2 parts: `pred result = False`, which gets verifie…
Ahh, right. I guess that's exactly the type of oversight that a checker is for :)
We could return the pair (!cur_low, !cur_high) and have the postcondition that pred (fst result) = False and pred (snd result) = True and abs (first result - snd result) = 1. Then it would work also if low > high, but I'm not sure this is useful in practice...
> The run-time version of `pred` is a partial function (it only works for valid array indices), so it needs a precondition. However, when I pass `pred` as an argument to `binary_search`, I can't / don't know how to specify that the argument needs the precondition.
If I'm understanding this correctly, you want to do something like this:
let binary_search (pred: (i:int) -> bool requires { low
But Why3 does not support this?If you add a precondition like that to pred, wouldn't that also prevent requires/ensures/invariant from calling pred on arguments that don't satisfy the precondition? In the precondition we do want pred low = False /\ pred high = True, but the run time predicate only allows pred k for low < k < high?