-
Notifications
You must be signed in to change notification settings - Fork 274
Implement sending commands to solver in incremental SMT2 backend #6357
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
Implement sending commands to solver in incremental SMT2 backend #6357
Conversation
So that the z3 sub process is actually started and expecting smt2 commands from the pipe in this test.
So that we can see the text sent to the solver when debugging and so that the text can be checked in regression tests. The commands are shown as debug output messages rather than written to file because a file based approach is not well suited to incremental solving.
send_to_solver(smt_set_option_commandt{smt_option_produce_modelst{true}}); | ||
send_to_solver(smt_set_logic_commandt{ | ||
smt_logic_quantifier_free_uninterpreted_functions_bit_vectorst{}}); |
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.
Do we want to send these at solver construction time, or do we want to send/update these per query? I don't have a good answer now, but there was comment on another issue/PR that the logic could vary for different calls/inputs. Also do we want to be able to change these later (and is this allowed/easy to do)?
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.
According to section 4.1 of the SMTLIB standard version 2.6, the set-logic
command can only be issued whilst the solver is in "Start mode" and the only way to return to this mode is to issue the reset
command. The actions of the reset
command include undefining all functions and assertions we have sent to the solver. Therefore if we were reseting and setting different logics for different rounds of solving, then we would no longer be carrying out incremental solving.
TLDR; We should be sending these commands at construction time.
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
So that instances of `symbol_exprt` can be handled correctly.
The identifier for guards includes the `\` character. Therefore this commit is needed for allowing smt identifiers to be constructed including this character and converted to string.
In order to check that guards are converted ok.
cee99cf
to
74a83f7
Compare
Codecov Report
@@ Coverage Diff @@
## develop #6357 +/- ##
===========================================
+ Coverage 75.90% 75.93% +0.03%
===========================================
Files 1515 1521 +6
Lines 164002 164232 +230
===========================================
+ Hits 124482 124715 +233
+ Misses 39520 39517 -3
Continue to review full report at Codecov.
|
number_of_solver_calls{0}, | ||
solver_process{split_string(solver_command, ' ', false, true)} | ||
solver_process{split_string(solver_command, ' ', false, true)}, |
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 split_string looks brittle.
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 arguments are provided to cbmc
in space separated form. Therefore they currently need to be split in order separate them. Any suggestions for making this less brittle?
|
||
/// \brief Defines any functions which \p expr depends on, which have not yet | ||
/// been defined, along with their dependencies in turn. | ||
void smt2_incremental_decision_proceduret::define_dependent_functions( |
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.
Would be great to unit-test this somehow.
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 have added unit tests of smt2_incremental_decision_proceduret
these tests indirectly test the functionality of this define_dependent_functions
function, via the handle
and set_to
functions of the public interface.
These tests currently fail when run on Windows due to issues with `piped_processt`. This commit can be reverted once the debugging is complete.
288cdad
to
ca5c91c
Compare
So that `smt2_incremental_decision_proceduret` can be unit tested in isolation using a mock smt solver process.
ca5c91c
to
3bc5ee4
Compare
Because there was previously an assumption that all symbols in the symbol table had values and it is more straight forward to make the this code deal with that than to add an invariant.
The previous implementation contained 2x "not" operations. By appling De Morgan's laws these operations can be dispensed with and the code is thus made more readable.
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 rest of the stuff looks good, but the refactoring of the condition expression changed its semantics.
In order to improve the chances of being able to see what is wrong when/if the tests fail.
This makes the behaviour of the conversion predictable. This has the advantage of being easier to unit test and reducing the possiblity of hard to re-produce bugs.
5491bd6
to
71d746a
Compare
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.
Nothing blocking - though I've left a couple of small comments that might be worth considering.
return expr_identifier.first; | ||
}); | ||
std::stack<exprt> to_be_defined; | ||
const auto dependencies_needed = [&](const exprt &expr) { |
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.
Any particular reason why this is a lambda, rather than a helper function, such as a hypothetical push_dependencies_needed(exprt, std::stack<exprt>)
which might be more descriptive? Either way, I'd be tempted to change the name to make its behaviour more explicit... At the moment, it superficially looks like a call to dependencies_needed(e)
would be state-free - but actually its changing the state of the method via the stack of exprts... I'd make that behaviour explicit in the name for ease of code reading...
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.
Because it was the quickest way for me to de-duplicate this code in the 2 places it is needed. A separate function would also have needed an additional parameter. I agree that the name I assigned to this lambda isn't necessarily the best. I think doing some pair programming together could be helpful in trying to come up with a more readable implementation.
@@ -50,7 +50,7 @@ bool smt_bool_literal_termt::value() const | |||
|
|||
static bool is_valid_smt_identifier(irep_idt identifier) | |||
{ | |||
static const std::regex valid{R"(^[^\|\\]*$)"}; | |||
static const std::regex valid{R"(^[^\|]*$)"}; |
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.
Minor quibble - but for the more hieroglyphic regex's like this its nice to include a comment showing an/some examples of what the regex is attempting to match.
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 agree this would be better with a comment. I didn't add one when I first wrote this, as it is relatively short and I am relatively comfortable with regex. I'll try and remember to comment this in a follow-up PR.
This PR includes implementation of sending commands to solver in incremental SMT2 backend, based on the exprts recieved. This is sufficient to get a sat/unsat response from the solver in sufficiently simple cases. However parsing the result from the solver is not included in this PR and will be in a follow up PR.
My commit message includes data points confirming performance improvements (if claimed).