Skip to content

Fix SMT2 encoding of array_comprehension_exprt #5973

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

Merged
merged 1 commit into from
Mar 31, 2021

Conversation

SaswatPadhi
Copy link
Contributor

@SaswatPadhi SaswatPadhi commented Mar 25, 2021

The SMT conversion routines were missing a rule for translating array_comprehension_exprt.

This PR creates a new translation rule leveraging the lambda construct in SMTLIB2.

NOTE: There may be several other broken-smt-backend regression tests that may be fixed by this change; I haven't checked (there are too many!).

  • Each commit message has a non-empty body, explaining why the change was made.
  • NA Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • NA The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • NA My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • NA White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@SaswatPadhi SaswatPadhi added SMT Backend Interface bugfix aws Bugs or features of importance to AWS CBMC users labels Mar 25, 2021
@SaswatPadhi SaswatPadhi self-assigned this Mar 25, 2021
@SaswatPadhi SaswatPadhi force-pushed the smt2_array_comprehension branch from e99097e to 1a5a4d3 Compare March 25, 2021 00:40
@SaswatPadhi SaswatPadhi changed the title Fix SMT2 encoding of array_comprehension Fix SMT2 encoding of array_comprehension_exprt Mar 25, 2021
@codecov
Copy link

codecov bot commented Mar 25, 2021

Codecov Report

Merging #5973 (c499ff7) into develop (e76d811) will increase coverage by 0.02%.
The diff coverage is 37.50%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5973      +/-   ##
===========================================
+ Coverage    75.12%   75.14%   +0.02%     
===========================================
  Files         1435     1444       +9     
  Lines       156301   157307    +1006     
===========================================
+ Hits        117416   118207     +791     
- Misses       38885    39100     +215     
Impacted Files Coverage Δ
src/solvers/smt2/smt2_conv.h 100.00% <ø> (ø)
src/solvers/smt2/smt2_conv.cpp 59.95% <12.76%> (+0.56%) ⬆️
src/memory-analyzer/gdb_api.cpp 86.89% <50.00%> (ø)
unit/memory-analyzer/gdb_api.cpp 86.46% <94.73%> (ø)
src/util/std_expr.h 92.62% <0.00%> (-0.53%) ⬇️
src/memory-analyzer/analyze_symbol.cpp 72.60% <0.00%> (ø)
...rc/memory-analyzer/memory_analyzer_parse_options.h 100.00% <0.00%> (ø)
src/memory-analyzer/analyze_symbol.h 88.23% <0.00%> (ø)
src/memory-analyzer/memory_analyzer_main.cpp 100.00% <0.00%> (ø)
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e42cc6c...c499ff7. Read the comment docs.

@kroening
Copy link
Member

If you can use an SMT-LIB expression that maps directly onto what you want to translate, you no longer need the defined_expressions mechanism!

Copy link
Collaborator

@martin-cs martin-cs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Is you think it fixes other things, please can you take the time to find out what they are? Someone will have to do this at some point and it would be better that it is connected with the change that fixes them.
  2. I'm pretty sure lambda isn't in SMT-LIB 2. It has been /proposed/ for SMT-LIB 3 but we shouldn't be outputting it in an SMT-LIB 2.0 back-end.


const irep_idt id =
"array_comprehension." + std::to_string(defined_expressions.size());
out << "(define-fun " << id << " () ";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you creating a function with no arguments that returns a lambda?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I have got the wrong end of the stick completely, I think you can implement this without the lambda.

Copy link
Contributor Author

@SaswatPadhi SaswatPadhi Mar 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arrays are infinite maps in SMT and are represented just like key -> value functions. The function with no arguments returns a lambda, because we want to return an array.

This has been tested with both Z3 -- you can run the attached regression test with cbmc --smt2.
I am not super sure about the official status of lambda within SMTLIB2 vs SMTLIB3, but Z3 supports it for a while now.

AFAIK, the only other way to implement array comprehension would be to use quantifiers, but that did not work even for the simpler case of array_of where the lambda expression was a constant (independent of the index).

Copy link
Contributor Author

@SaswatPadhi SaswatPadhi Mar 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will make this translation solver-specific then -- only emit SMT2 output using lambda if solver is Z3. Otherwise, fall back to quantifier-based initialization.

[Also, more info about lambda handling here: Z3Prover/z3/issues/2221]

@SaswatPadhi SaswatPadhi force-pushed the smt2_array_comprehension branch from 1a5a4d3 to 0e2e339 Compare March 25, 2021 22:47
@SaswatPadhi
Copy link
Contributor Author

I have tested this (the attached regression test) locally with both --z3 and --cvc4 and it works correctly.

However, with CVC4 (and other solvers that don't allow lambda as an array), the SMT logic needs to be set to AUFBV instead of QF_AUFBV [see #5977] because we fallback to universally quantified initialization of the array.

Copy link
Collaborator

@martin-cs martin-cs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather not have the default logic change to be quantified as it will block some solvers. Beyond that, looks OK.

@SaswatPadhi
Copy link
Contributor Author

Thanks for taking a look, @martin-cs.

I agree with not changing the default logic to allow quantifiers. I opened #5977 to discuss more about this issue.

Z3 treats arrays and lambdas as identical structures, so we use lambdas in the
z3-specific encoding of `array_comprehension_exprt`. For other solvers, we fall
back to a universally quantified expression to initialize the array.
@SaswatPadhi SaswatPadhi force-pushed the smt2_array_comprehension branch from 0c4f8b3 to c499ff7 Compare March 31, 2021 20:20
@SaswatPadhi SaswatPadhi merged commit cee5acf into diffblue:develop Mar 31, 2021
@SaswatPadhi SaswatPadhi deleted the smt2_array_comprehension branch March 31, 2021 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aws Bugs or features of importance to AWS CBMC users bugfix SMT Backend Interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants