-
Notifications
You must be signed in to change notification settings - Fork 67
fix(phl): emit the non-negativity of the bound as a separate goal in rnd (on #1105)
#1135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,15 @@ If the conclusion is a probabilistic Hoare logic statement judgement whose progr | |
| which can be provided explicitly. When `E`` is not | ||
| specified, it is inferred from the current postcondition. | ||
|
|
||
| The upper bound is checked in the (partial-correctness) postcondition, | ||
| which only constrains the terminating runs of the program preceding the | ||
| sampling. The non-terminating runs contribute probability 0, so the | ||
| tactic additionally requires the bound to be non-negative, as a separate | ||
| goal quantified over all memories (a probabilistic Hoare logic judgement | ||
| whose bound is negative in some memory is false, whether or not that | ||
| memory satisfies the precondition). That goal is closed automatically | ||
| when it is trivial. | ||
|
|
||
| .. ecproof:: | ||
| :title: Probabilistic Hoare logic example (upper bound) | ||
|
|
||
|
|
@@ -145,9 +154,11 @@ If the conclusion is a probabilistic Hoare logic statement judgement whose progr | |
| (* The post now has two clauses, the first is to prove the | ||
| probability upper bound on the event, and the second one is to | ||
| prove that the event holding implies the | ||
| previous postcondition. *) | ||
| skip => *;split. | ||
| + by smt(dbool1E). | ||
| previous postcondition. A second goal requires the bound to | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The non-negativity check would be a third goal. Here the second goal is mention twice for different things. |
||
| be non-negative. *) | ||
| + skip => *;split. | ||
| + by smt(dbool1E). | ||
| by smt(). | ||
| by smt(). | ||
| qed. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,11 +77,18 @@ let t_auto_rnd = | |
| let rec t_auto_phl_r tc = | ||
| FApi.t_seqs | ||
| [ EcPhlWp.t_wp None; | ||
| FApi.t_ors [ FApi.t_seq t_auto_rnd t_auto_phl_r; | ||
| FApi.t_ors [ FApi.t_seq t_auto_rnd t_auto_phl_rnd_r; | ||
| EcPhlSkip.t_skip; | ||
| t_id ]] | ||
| tc | ||
|
|
||
| (* Recursion guard: a non-trivial [0%r <= bd] left by [bdhoare-rnd] would make | ||
| [t_wp] fail and [auto] silently give up on [rnd]: only recurse into phl goals. *) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a preference for the old comment which was clearer to me : (* [t_auto_rnd] may emit pure side-conditions (the non-negativity of the
bound in [bdhoare-rnd]): only recurse into the program-logic sub-goals. *) |
||
| and t_auto_phl_rnd_r tc = | ||
| match (FApi.tc1_goal tc).f_node with | ||
| | FhoareS _ | FbdHoareS _ | FequivS _ -> t_auto_phl_r tc | ||
| | _ -> t_id tc | ||
|
|
||
| let t_auto_phl = FApi.t_low0 "auto-phl" t_auto_phl_r | ||
|
|
||
| (* -------------------------------------------------------------------- *) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| (* pHL `rnd` with an upper bound (upstream #1119): the bound check is lifted | ||
| into the post-condition of a hoare judgment on the statements preceding | ||
| the sampling, which only constrains their terminating runs. The rule must | ||
| also require the bound to be non-negative; under #1105 a pHL judgment | ||
| with a bound that is negative in some memory is false, so that goal is | ||
| quantified over all memories, unconditionally: after the ordinary goal, | ||
| `0%r <= -1%r` must remain and must be unprovable. *) | ||
| require import AllCore Distr. | ||
|
|
||
| module M = { | ||
| proc f() : unit = { var x : int; while (true) { } x <$ dunit 0; } | ||
| }. | ||
|
|
||
| lemma bad : phoare[M.f : true ==> true] <= (-1)%r. | ||
| proof. | ||
| proc. | ||
| rnd (fun (_ : int) => true). | ||
| + by while (true); auto. | ||
| (* remaining goal: forall &hr, 0%r <= -1%r *) | ||
| move=> &hr. | ||
| fail (by smt()). | ||
| abort. | ||
|
|
||
| (* Same with the event inferred from the post-condition. *) | ||
| module N = { | ||
| proc f() : int = { var x : int; while (true) { } x <$ dunit 0; return x; } | ||
| }. | ||
|
|
||
| lemma bad' : phoare[N.f : true ==> res = 0] <= (-1)%r. | ||
| proof. | ||
| proc. | ||
| rnd. | ||
| + by while (true); auto. | ||
| (* remaining goal: forall &hr, 0%r <= -1%r *) | ||
| move=> &hr. | ||
| fail (by smt()). | ||
| abort. | ||
|
|
||
| (* Loop-free: the prefix terminates, but the bound is still negative. *) | ||
| module L = { | ||
| proc f() : unit = { var y : int; var x : int; y <$ dnull; x <$ dunit 0; } | ||
| }. | ||
|
|
||
| lemma bad'' : phoare[L.f : true ==> true] <= (-1)%r. | ||
| proof. | ||
| proc. | ||
| rnd (fun (_ : int) => true). | ||
| + by auto=> /> y; rewrite supp_dnull. | ||
| (* remaining goal: forall &hr, 0%r <= -1%r *) | ||
| move=> &hr. | ||
| fail (by smt()). | ||
| abort. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this can be simplified :