Some questions about weakest pre-condition notation in the F* tutorial - fstar

Chapter 9 in the F* tutorial has an example:
b ::= x | true | false
e ::= b | let x = e1 in e2 | assert b | if b then e1 else e2
WP b P = P b
WP (let x = e1 in e2) P = WP e1 (fun x -> WP e2 P)
WP (assert b) P = b /\ P b
WP (if b then e1 else e2) P = (b ==> WP e1 P) /\ ((not b) ==> WP e2 P)
Could someone please explain the notation here? I understand that WP is pre-condition and P post-condition, but what is P b? Post-condition that is applied to b?

Discussion from IRC channel #fstar:
20:33:49 - {AS}: let us say we have a program (let abs x = if x >= 0 then x else -x)
20:33:58 - ollehar1: ok
20:34:02 - {AS}: and we want to show that (fun res -> res >= 0)
20:34:15 - {AS}: so we do
20:34:26 - {AS}: WP (if x >= 0 then x else -x) (fun res -> res >= 0)
20:34:28 - {AS}: right?
20:34:32 - ollehar1: ok
20:34:36 - {AS}: then we follow the calculations in the example
20:34:42 - {AS}: so we apply the if-rule and get
20:35:39 - {AS}: ((x >= 0) ==> WP x (fun res -> res >= 0)) /\ ((not b) ==> WP (- x) (fun res -> res >= 0))
20:35:55 - {AS}: here ==> is implication and /\ is and
20:36:05 - ollehar1: yes
20:36:07 - {AS}: conjunction
20:36:17 - {AS}: so we carry on
20:36:17 - ollehar1: but "not b" should be "not x >= 0"
20:36:24 - {AS}: Yes, sorry :)
20:36:39 - ollehar1: np
20:36:43 - {AS}: not x is a basic value
20:36:46 - {AS}: now*
20:37:04 - {AS}: so WP x (fun res -> res >= 0) reduces to x >= 0 according to the rules
20:37:14 - {AS}: and similarly with - x in the other side
20:37:31 - {AS}: (they don't really have minus, so I just used the common intuition for that rule)
20:38:05 - {AS}: so we end up with having ((x >= 0) ==> (x >= 0)) /\ (not (x >= 0) ==> (- x >= 0))
20:38:35 - {AS}: of course, if we simplify a bit the first conjunct is trivially true
20:39:00 - {AS}: and if you have an integer arithmetic solver, you find out that the second is also true
20:39:13 - {AS}: so the weakest precondition ends up being true

Related

Write the function residue l n which calculates the residue of n by l by making an iterative calculation

I want to write the function residue l n which calculates the residue of n by l by making an iterative calculation starting with n and using the items in the list in order. The calculation is as follows:
-initially the residue is the value of n
-each element e of l (taken in the order of the list) changes the residue in the following way:
if e and the residue are of the same parity (both even or both odd) then the new residue is the sum of r and e, otherwise it is the difference between r and e (r-e).
-the last residue is the result of the game.
Example: residu [1;3] 7 returns 5 as a result of the following calculations:
7 + 1 (same parity +) = 8
8 - 3 (parité différente -) = 5
This is my code but it doesn't seem to be working:
let rec residue l n =
if l = [] then 0 else
if (((List.hd l) mod 2 <> 0) && (n mod 2 <> 0 )) || (((List.hd l) mod 2 == 0) && (n mod 2 == 0 ))
then
(List.hd l) + residue (List.tl l) ((List.hd l)+ n) else
n - (List.hd l) - residue (List.tl l) (n - (List.hd l));;
residu [1;3] 7;;
- : int = 6 (The correct result should be 5)
Thank you for your help.
Here is my stab at it.
let rec residue l n =
let parity a b =
if ((a mod 2 <> 0) && (b mod 2 <> 0)) ||
((a mod 2 == 0) && (b mod 2 == 0)) then true else false in
match l, n with
| [], n -> n
| (x::xs), n -> if parity x n then residue xs (n+x) else residue xs (n-x)
Hope it helps for figuring out the problem.

Hint on FStar proof dead end

Can I get a brief explanation why this proof effort fails?
In my studies I'm trying to recognize simple patterns in generated lists of integers.
The generator below produces a list of alternating 0s and 1s. I'd like to prove that items at even indexes are 0.
val evenb : nat -> bool
let rec evenb n =
match n with
| 0 -> true
| 1 -> false
| n -> evenb (n - 2)
val nth_item : ls: list nat {length ls > 0} -> n: nat {n < length ls} -> nat
let rec nth_item ls n =
match ls with
| [h] -> h
| h :: t -> if n = 0 then h else nth_item t (n - 1)
val gen_01 : lng: nat {lng >= 2 && evenb lng} -> ls: list nat {length ls = lng}
let rec gen_01 lng =
match lng with
| 2 -> [0; 1]
| _ -> [0; 1] # gen_01 (lng - 2)
let rec lemma_01 (lng: nat {lng >= 2 && evenb lng}) :
Lemma (forall (n: nat {n <= lng - 2 && evenb n}) . (nth_item (gen_01 lng) n) = 0) =
match lng with
| 2 -> ()
| _ -> lemma_01 (lng - 2)
FStar returns 'could not prove post-condition'.
I'd appreciate any help regarding the approach.
F* should also report a secondary error location pointing to the conjunct in the postcondition that was not provable---in this case, it's just the nth_item (gen_01 lng) n = 0 goal.
One way to diagnose this is to consider one branch of the proof at a time. E.g. if you add an admit(); in the second branch, then you'll see that the first branch is easily provable. So, what's going wrong is the inductive case. You don't have a strong enough induction hypothesis to prove the property you want.
Here's one proof of it ... there are probably many others.
First, I proved this:
let rec access_2n (l:nat{l >= 2 && evenb l}) (n:nat{2 * n < l})
: Lemma (ensures nth_item (gen_01 l) (2 * n) = 0)
= match n with
| 0 -> ()
| _ -> access_2n (l - 2) (n - 1)
Notice the induction on the pair l, n so that the length and the access index decrease together.
This is pretty much the property you wanted to prove, stated slightly differently. To massage it into the form you want, I did this:
First, a lemma to interpret evenb arithmetically:
[Edit: I added an open FStar.Mul to bring the * symbol into scope for multiplication]
open FStar.Mul
let rec evenb_is_even (n:nat{evenb n})
: Lemma (2 * (n / 2) = n)
= match n with
| 0 -> ()
| _ -> evenb_is_even (n - 2)
Then to prove something very like your lemma, but for an explicit n.
let lemma_01_aux (lng: nat {lng >= 2 && evenb lng}) (n:nat{n <= lng - 2 && evenb n})
: Lemma (nth_item (gen_01 lng) n = 0)
= access_2n lng (n / 2); evenb_is_even n
And finally to universally quantify over n using a library that turns lemmas into quantified postconditions.
let lemma_01 (lng: nat {lng >= 2 && evenb lng})
: Lemma (forall (n: nat {n <= lng - 2 && evenb n}) . (nth_item (gen_01 lng) n) = 0)
= FStar.Classical.forall_intro_2 lemma_01_aux

Proving primes in Coq

I have a Coq function that classifies prime numbers.
I exported it to Haskell and tested it; it works fine.
I want to rigorously prove it indeed classifies primes,
so I tried to prove the following theorem isPrimeCorrect:
(************)
(* helper'' *)
(************)
Fixpoint helper' (p m n : nat) : bool :=
match m with
| 0 => false
| 1 => false
| S m' => (orb ((mult m n) =? p) (helper' p m' n))
end.
(**********)
(* helper *)
(**********)
Fixpoint helper (p m : nat) : bool :=
match m with
| 0 => false
| S m' => (orb ((mult m m) =? p) (orb (helper' p m' m) (helper p m')))
end.
(***********)
(* isPrime *)
(***********)
Fixpoint isPrime (p : nat) : bool :=
match p with
| 0 => false
| 1 => false
| S p' => (negb (helper p p'))
end.
(***********)
(* divides *)
(***********)
Definition divides (n p : nat) : Prop :=
exists (m : nat), ((mult m n) = p).
(*********)
(* prime *)
(*********)
Definition prime (p : nat) : Prop :=
(p > 1) /\ (forall (n : nat), ((divides n p) -> ((n = 1) \/ (n = p)))).
(*****************************)
(* isPrime correctness proof *)
(*****************************)
Theorem isPrimeCorrect: forall (p : nat),
((isPrime p) = true) <-> (prime p).
I spent a good few hours on this theorem today with no actual progress.
Actually, I was a bit surprised how difficult it is since I previously
managed to prove pretty similar stuff. Any hints/clues how to proceed?
You must explicitely write lemmas for each of the helping functions, which state exactly what you think this function does for you. For instance, I tried to do this for your helper' function and I came up with the following lemma:
Require Import Arith Psatz.
(************)
(* helper'' *)
(************)
Fixpoint helper' (p m n : nat) : bool :=
match m with
| 0 => false
| 1 => false
| S m' => (orb ((mult m n) =? p) (helper' p m' n))
end.
Lemma helper'_correct :
forall p m n,
helper' p m n = true <-> exists k, (1 < k <= m /\ p = k * n).
Proof.
intros p; induction m as [ | m' IH]; intros n.
split;[discriminate | ].
intros [k [abs _]].
lia. (* Here the hypothesis abs has statement 1 <= k < 0
and lia recognizes that it is absurd. *)
destruct m' as [ | m''] eqn: E.
split;[discriminate | intros [k [abs _]]; lia].
change (helper' p (S (S m'')) n) with (orb ((mult (S (S m'')) n) =? p)
(helper' p (S m'') n)).
rewrite Bool.orb_true_iff.
split.
intros [it | later].
now exists (S (S m'')); split;[lia | symmetry; apply beq_nat_true ].
rewrite IH in later; destruct later as [k [k1 k2]].
exists k.
(* here hypothesis k1 states 1 < k <= S m''
k2 states p = k * n
and we need to prove 1 < k <= S (S m'') /\ p = k * n
lia can do that automatically. *)
lia.
intros [k [[k1 km] k2]].
apply le_lt_or_eq in km; rewrite or_comm in km; destruct km as [km | km].
now left; rewrite <- km; rewrite Nat.eqb_eq, k2.
right; apply lt_n_Sm_le in km.
change (helper' p (S m'') n = true); rewrite IH.
exists k.
lia.
Qed.
Obviously there should also be a way to link the helper function wih the divides predicate.

How to prove statements of the form forall x. phi x in F*?

I have just started learning F*, going through the tutorial. One of the exercises there is to prove that the reverse function on lists is injective.
Since this follows from the fact that involutions are injective I would like to express that fact as a lemma in F*. To do that I define
let is_involutive f = forall x. (f (f x) == x)
let is_injective f = forall x y. (f x == f y) ==> x == y
Is this the right way to define the notion of f being involutive or injective in F*?
Then I state the lemma
val inv_is_inj: #a:eqtype -> a -> f:(a->a) ->
Lemma (requires (is_involutive f)) (ensures(is_injective f))
Informally the proof can be written as
{ fix (x:a) (y:a)
assume (f x == f y)
then have (f (f x) == f (f y))
with (is_involutive f) have (x == y)
} hence (forall (x:a) (y:a). f x == f y ==> x == y)
then have (is_injective f)
How do I express such proof in F*?
In general, what F* language constructs can be used to prove statements of the form forall (x:a). phi x, where phi is a predicate on a type a?

Idris - Define a primes type

I am learning Idris and as a personal exercise, I would like to implement a Primes type, consisting of all the prime numbers.
Is there a way in idris to define a new type starting from a type and a property, which will select all the elements of the starting type for which the property holds true? In my case, is there a way to define Primes as the set of Nat such that n <= p and n|p => n=1 or n=p?
If this is not possible, should I define prime numbers constructing them inductively using some kind of sieve?
I like copumpkin's Agda definition of Prime, which looks like this in Idris:
data Divides : Nat -> Nat -> Type where
MkDivides : (q : Nat) ->
n = q * S m ->
Divides (S m) n
data Prime : Nat -> Type where
MkPrime : GT p 1 ->
((d : Nat) -> Divides d p -> Either (d = 1) (d = p))
-> Prime p
Read as "if p is divisible by d, then d must be 1 or p" - a common definition for primality.
Proving this by hand for a number can be pretty tedious:
p2' : (d : Nat) -> Divides d 2 -> Either (d = 1) (d = 2)
p2' Z (MkDivides _ _) impossible
p2' (S Z) (MkDivides Z Refl) impossible
p2' (S Z) (MkDivides (S Z) Refl) impossible
p2' (S Z) (MkDivides (S (S Z)) Refl) = Left Refl
p2' (S Z) (MkDivides (S (S (S _))) Refl) impossible
p2' (S (S Z)) (MkDivides Z Refl) impossible
p2' (S (S Z)) (MkDivides (S Z) Refl) = Right Refl
p2' (S (S Z)) (MkDivides (S (S _)) Refl) impossible
p2' (S (S (S _))) (MkDivides Z Refl) impossible
p2' (S (S (S _))) (MkDivides (S _) Refl) impossible
p2 : Prime 2
p2 = MkPrime (LTESucc (LTESucc LTEZero)) p2'
It's also very involved to write a decision procedure for this. That'll be a big exercise! You'll probably find the rest of the definitions useful for that:
https://gist.github.com/copumpkin/1286093