-
Notifications
You must be signed in to change notification settings - Fork 277
CONTRACTS: Documenting semantic of loop invariant synthesizers #7089
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
CONTRACTS: Documenting semantic of loop invariant synthesizers #7089
Conversation
Codecov ReportBase: 77.86% // Head: 77.88% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## develop #7089 +/- ##
===========================================
+ Coverage 77.86% 77.88% +0.02%
===========================================
Files 1574 1576 +2
Lines 181363 181855 +492
===========================================
+ Hits 141223 141644 +421
- Misses 40140 40211 +71
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
@Herbping @SaswatPadhi @remi-delmas-3000 maybe we should create a folder inside |
assertions fail or success; | ||
2. the base-case is from the whole GOTO program with a main | ||
function as the entry point. | ||
|
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.
Could you provide an example 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.
I find these two points somewhat unclear. An example might help, as Felipe mentioned, especially for point 1.
I would probably just remove point 2. "main
function" need not be the entrypoint for CBMC (can be overriden), and the base case is no different from any other symex path -- the path constraint along a path that reaches the loop head is the base case.
It might be worth adding a pointer to semantics of loop invariants (contracts-invariants.md#semantics), which already covers the induction principle.
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.
The first point I want to make here is that we only care about if the invariant is inductive, but not other checks (even if there is assert(0);
in the loop). The purpose of the second point is to distinguish: 1) the invariants are inductive for any inputs of the function, and 2) the invariants are inductive for only paths in the given GOTO binary.
As an example, k == 1
is an inductive invariant in the following program. However, it is not always inductive if we only consider the function foo
---it doesn't hold when the parameter k
is not 1.
void foo(int k)
{
for(int i = 0; i < 5; i++)
{
if(k != 1)
k = 2;
}
}
void main()
{
foo(1);
}
You are right that the semantics of loop invariants is enough to illustrate the point. I will update the text and add a link to the semantics of loop invariants.
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 still few this section needs an example. Take a small program, check the program with pointer checks enable using a bound, synthesize the invariant, check the problem again without the bound. One of the most important part of the documentation is to walk potential users and future developers in the process of how to use this tool.
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 like the idea of examples. It would also be good to discuss what the initial state is as part of defining / saying they are inductive.
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.
If the invariants are inferred in the context of a proof harness that does not fully cover the input space of the function that contains the loop, is there a risk that we could assume the invariant in a different context where it could actually not hold without realizing it?
Or would we attempt to re-prove the inferred invariant in each context in which the function that contains the loop gets called ?
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.
It could happen but it should not be silent as the check for whether it is a loop invariant should fail in the new context. I presume we have tests for "__CPROVER_invariant
that aren't actually true?
src/goto-instrument/synthesizer/enumerative_loop_invariant_synthesizer.h
Outdated
Show resolved
Hide resolved
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.
Requesting some more clarification on a few things.
assertions fail or success; | ||
2. the base-case is from the whole GOTO program with a main | ||
function as the entry point. | ||
|
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 find these two points somewhat unclear. An example might help, as Felipe mentioned, especially for point 1.
I would probably just remove point 2. "main
function" need not be the entrypoint for CBMC (can be overriden), and the base case is no different from any other symex path -- the path constraint along a path that reaches the loop head is the base case.
It might be worth adding a pointer to semantics of loop invariants (contracts-invariants.md#semantics), which already covers the induction principle.
85bf8c2
to
3864e9e
Compare
/// It handles `goto_model` containing only checks instrumented by | ||
/// `goto-instrument` with the `--pointer-check` flag. | ||
/// It is designed for `goto_model` containing only checks instrumented by | ||
/// `goto-instrument` with the `--pointer-check` flag. H |
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.
/// `goto-instrument` with the `--pointer-check` flag. H | |
/// `goto-instrument` with the `--pointer-check` flag. |
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.
Mistakenly marked as resolved?
assertions fail or success; | ||
2. the base-case is from the whole GOTO program with a main | ||
function as the entry point. | ||
|
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 still few this section needs an example. Take a small program, check the program with pointer checks enable using a bound, synthesize the invariant, check the problem again without the bound. One of the most important part of the documentation is to walk potential users and future developers in the process of how to use this tool.
@@ -1146,7 +1146,7 @@ void goto_instrument_parse_optionst::instrument_goto_program() | |||
goto_model.goto_functions.update(); | |||
} | |||
|
|||
if(cmdline.isset("synthesize-loop-invariants")) | |||
if(cmdline.isset("synthesize-loop-invariants-enumerative")) |
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.
It seems this commit has more than just "documentation?" I'd recommend to factor out the actual code changes into a commit of their own, even if that makes it just a 3-or-so lines commit.
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.
+1 what @tautschnig says.
This is a loop invariant synthesizer built in goto-instrument that | ||
synthesize [loop invariants](contracts-invariants.md) for a | ||
pre-existing GOTO binary, annotate the invariant clause into | ||
the GOTO binary, and produce an annotated binary as output. |
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.
Is it really most important to talk about goto-instrument
here? I'd expect that users first want to know a sentence about what loop invariants are (and, specifically, what kinds of loop invariants are being synthesized - inductive ones?), and then what capabilities/limitations this synthesizer has (it's an undecidable problem).
assertions fail or success; | ||
2. the base-case is from the whole GOTO program with a main | ||
function as the entry point. | ||
|
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 like the idea of examples. It would also be good to discuss what the initial state is as part of defining / saying they are inductive.
|
||
Strategy | Flag | Guarantees | ||
-----------------|------------------------------------------------|---- | ||
Enumerative | --synthesize-loop-invariants-enumerative | All checks will succeeded in the annotated GOTO binary |
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 happens if the asserts (I presume that is what you mean by checks) are false?
@@ -1146,7 +1146,7 @@ void goto_instrument_parse_optionst::instrument_goto_program() | |||
goto_model.goto_functions.update(); | |||
} | |||
|
|||
if(cmdline.isset("synthesize-loop-invariants")) | |||
if(cmdline.isset("synthesize-loop-invariants-enumerative")) |
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.
+1 what @tautschnig says.
/// It handles `goto_model` containing only checks instrumented by | ||
/// `goto-instrument` with the `--pointer-check` flag. | ||
/// It is designed for `goto_model` containing only checks instrumented by | ||
/// `goto-instrument` with the `--pointer-check` flag. H |
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.
Mistakenly marked as resolved?
On the manual: Please keep in mind that the "CPROVER Manual" is meant to be a beginners' tutorial, and not a reference manual. May I suggest finding a different place for documenting this functionality. |
Perhaps we could move the entire contracts-related documentation from that manual to the man pages? I would rather not see us open yet another place that users need to go to in order to find documentation. |
I agree with @tautschnig about not creating another place that users need to go to. However, I think the CPROVER Documentation generated using Doxygen would be a better place than the man pages, right? |
3864e9e
to
bf6ba31
Compare
I think we can put the semantic, syntax, and usage of contracts in the CPROVER Documentation generated using Doxygen as Felipe suggested; and put the tutorial and examples in the CBMC training material . We may also want to point to the training material from the reference manual so that users can find them easily. |
@jimgrundy @markrtuttle @SaswatPadhi @nwetzler any recommendations? |
Linking to #7006 |
bf6ba31
to
83b85eb
Compare
This PR now contains only code comments explaining the semantic of the synthesizer. I will put the manual parts to the cbmc-documentation. |
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.
LGTM.
Comments have been addressed
@peterschrammel could you take another look at this PR? |
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.
Definitely an improvement, so, merge. I would still like some more extensive documentation and examples but that can be another PR>
This PR contains only documentations. It explain the semantic of the loop-invariant synthesizer interface and the enumerative synthesizer. The motivating discussion is in the PR#7007.