-
Notifications
You must be signed in to change notification settings - Fork 231
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
calc
statements
#1607
calc
statements
#1607
Conversation
Underlying implementation for calculational proofs
Since `calc` will soon be a keyword
src/parser/FStar.Parser.Dep.fs
Outdated
@@ -709,6 +712,17 @@ let collect_one | |||
collect_term t | |||
| Attributes cattributes -> | |||
List.iter collect_term cattributes | |||
| CalcProof (rel, init, steps) -> | |||
(* TODO: add the Calc module too *) |
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.
What's this remark about? In the next line, you correctly add FStar.Calc
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.
I forgot to remove the comment :)
Looks great overall. Couple of suggestions: Thanks! Please merge once you're able to sign the cla. |
|
||
open FStar.Preorder (* for `relation` *) | ||
|
||
noeq |
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.
Can this type be abstract
? We will also have to make calc_init
and calc_step
as abstract
.
ulib/FStar.Calc.fst
Outdated
= CalcStep rs #p (pf ()) (j ()) | ||
|
||
let calc_finish (#t:Type) (#rs : list (relation t)) (p : relation t) (#x #y :t) (pf : calc_proof rs x y) | ||
: Lemma (requires (calc_chain_compatible rs p)) |
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.
Curious to understand how this works. To satisfy the precondition of the lemma, how is calc_chain_compatible
proven? As in, would it involve unfolding of the recursive definition calc_chain_related
by Z3 (and thus constrained by the fuel setting)?
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.
Ah, yes, I forgot I wanted to add a normalize_term
to this so the unfolding would happen in the normalizer, leaving Z3 only with a quantification to be proven. Without that, large chains do fail. I'm playing with that now.
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.
This pattern may be useful: hacl-star/hacl-star@7623202#r31557851
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.
You can also mark calc_chain_compatible
as opaque_to_smt
.
open FStar.Mul | ||
open FStar.Calc | ||
open FStar.Preorder | ||
|
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.
A small, say 2 steps example, that shows the desugaring in the comments would be useful here.
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.
Yes, will add!
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 a version of the same program written without any syntactic sugar?
|
||
(* Every chain of `t`'s related by `rs` **(reversed!)** has its endpoints related by p *) | ||
let calc_chain_compatible (#t : Type) (rs : list (relation t)) (p : relation t) : Type0 = | ||
forall x y. calc_chain_related rs x y ==> p x y |
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.
We could add a pattern here calc_chain_related rs x y
(Z3 could also be picking the same automatically).
Looks good to me too. Added a few comments. Thanks! |
This fails pointing to the
|
Would be great to test calc proofs in the wild. For example, here's a proof that could have benefited from it: One thing to check, as also mentioned by @parno, is that error messages are reported properly for each failing step of a calc proof, rather than blaming the calc proof as a whole. |
FWIW, here's an example of a calc-style proof in the "wild": |
This avoids Z3 having to reason about the recursive definition of `calc_chain_related`
We do not want the SMT to have to unfold this, we will fully unfold and normalize it beforehand.
Added a wiki page and a paragraph in |
solve_t' should only be called with properly compressed problems, and that is not the case here
please go ahead and merge. |
Will do after refreshing the snapshot. |
Sweet! |
@parno I'm also moving the proof you mentioned to calc-style. It's taking me a bit, it seems to be working---even with nesting, which I should have tried beforehand but I was glad to see it worked on a first try :). |
Nice! I'm running the Vale regression suite against the new version of F*, in the hopes of upgrading today. |
This PR introduces support for
calc
statements, similar to the ones in Dafny, as asked for in issue #1549 by @parno.Here's a brief overview of how they work:
The
FStar.Calc
module defines a set of combinator to structure calculational proofs, and a way to eliminate them asLemma
s (which ensures they will be erased by extraction).A calculational proof is a sequence of expressions (of some type
t
) related by steps plus a top-level relation (i.e. a term of typet -> t -> Type0
). Each step is composed of a relation and a justification (a proof that the expressions are indeed related). For instance:Is a proof that
3 > 1 + 1
. This succeds sincea)
3 > 2
(with proof()
)b)
2 == 1 + 1
(with proof()
)and c) forall
x,y,z
, ifx > y == z
, thenx > z
.This last condition is currently sent to the SMT solver.
Justifications inside
{}
can be omitted in they are()
. Internally, all justifications are thunked by the desugarer.All relations
r
are expanded tofun x y -> r x y <: Type0
in order to accept boolean operations like(>) : int -> int -> bool
and properly obtain theb2t
coercion where needed.Justifications and steps are not in "logical scope" of each other: admitting a step should not affect others. However, everything is encoded in a single VC for now. We might want to split some parts of it out.