Skip to content
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

updates related to issue #5140 #5463

Merged
merged 5 commits into from
Aug 9, 2021
Merged

Conversation

veanes
Copy link
Collaborator

@veanes veanes commented Aug 8, 2021

Fixed some bugs in issue #5140 (work in progress, not all are fixed yet).

Added functionality for dealing with derivatives over nonground sequences s without introducing the mkderivative OP in the ast.
Essentially D(e,s) = ite(s!=()& first(s)=e, rest(s), [])
This avoids stuck-situations -- that I believe lead to unsound unsat results in some cases.

Also, if s in uninterpreted, then
D(e,reverse(s)) = ite(s!=()& last(s)=e, reverse(butlast(s)), [])

Currently:
butlast(s) = substr(s,0,|s|-1)
and the pattern butlast(butlast(s)) is simplified to substr(s,0,|s|-2)

Similarly:
rest(s) = substr(s,1,|s|-1)
rest(rest(s)) = ..TBD.. = substr(s,2,|s|-2)

first(rest(s)) = nth(2,s)

etc..

Fixed also some rex:pp issues (still some TBD).

@@ -1068,6 +1069,10 @@ std::ostream& seq_util::rex::pp::compact_helper_seq(std::ostream& out, expr* s)
for (expr* e : es)
compact_helper_seq(out, e);
}
else if (re.u.str.is_string(s, z)) {
for (int i=0; i < z.length(); i++)
Copy link
Contributor

Choose a reason for hiding this comment

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

space i = 0

*/
void seq_rewriter::replace_all_subvectors(expr_ref_vector const& a, expr_ref_vector const& b, expr* c, expr_ref_vector& result) {
int i = 0;
int k = b.size();
Copy link
Contributor

Choose a reason for hiding this comment

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

use unsigned for i, k, j, b.size() is unsigned.

expr_ref_vector a_vals(m());
expr_ref_vector b_vals(m());
if (try_get_unit_values(a, a_vals) && try_get_unit_values(b, b_vals))
{
Copy link
Contributor

Choose a reason for hiding this comment

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

{ after if is not on separate line (contrast to typical C# conventions).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed this and the ones above in the following commit

expr_ref seq_rewriter::mk_seq_first(expr* t) {
expr_ref result(m());
expr* s, * j, * k;
if (str().is_extract(t, s, j, k))
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this sound?

if j < 0, then extract evaluates to an empty string, then the result should be the same as nth("",0). But you pass nth(s, j) which is under-specified. The rewrite would then restrict interpretations for nth(s, j) for j negative to nth("",0).

A further potential issue is the use of nth_i, which is the interpreted version of nth. It gets introduced as a rewrite nth(s, k) = if 0 <= k < len(s) then nth_i(s, k) else nth_u(s, k).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the constraint of the use of mk_seq_first (in the derivation) is that the context implies is that |t|>0 which should imply that 0 <= j < |t| and also that j + k <= |t|.
This is because mk_seq_first(t) always occurs in conjunction with not(t = ()).
This is why I dropped the additional checks I had originally.

expr_ref seq_rewriter::mk_seq_rest(expr* t) {
expr_ref result(m());
expr* s, * j, * k;
expr* one = m_autil.mk_int(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Pin the reference for uniformity:

expr_ref one(m_autil.mk_int(1), m());

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok, done

@veanes
Copy link
Collaborator Author

veanes commented Aug 9, 2021

In the last commit, I added also a missing case for get_re_head_tail_reversed but disabled it for now because it should not affect correctness but hides a bug I'm chasing.
The bug I'm looking at right now is incorrect model generated for
x in "BA".(ite (x in .*"AB") "B" "A")"AA"
the bug happens after (check-sat) which seems to mess around with if constants remain uninterpreted.

@veanes
Copy link
Collaborator Author

veanes commented Aug 9, 2021

the last commit fixes 2 bugs

  1. ite concat re-order bug in seq_rewriter::mk_der_op_rec
  2. max_length bug in str::max_length

Also enables a missing case in get_re_head_tail_reversed that trteats e.g. (.A)B
same as .
(AB) by lifting out the tail "AB" instead of just the tail "B"

@NikolajBjorner NikolajBjorner merged commit 225204e into Z3Prover:master Aug 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants