Skip to content

Commit 24c3cd3

Browse files
add v0 of equality solver
1 parent 05e0532 commit 24c3cd3

File tree

4 files changed

+113
-3
lines changed

4 files changed

+113
-3
lines changed

src/ast/seq_decl_plugin.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,17 @@ void seq_util::str::get_concat(expr* e, expr_ref_vector& es) const {
945945
}
946946
}
947947

948+
void seq_util::str::get_concat(expr* e, ptr_vector<expr>& es) const {
949+
expr* e1, * e2;
950+
while (is_concat(e, e1, e2)) {
951+
get_concat(e1, es);
952+
e = e2;
953+
}
954+
if (!is_empty(e)) {
955+
es.push_back(e);
956+
}
957+
}
958+
948959
/*
949960
Returns true if s is an expression of the form (l = |u|) |u|-k or (-k)+|u| or |u|+(-k).
950961
Also returns true and assigns k=0 and l=s if s is |u|.

src/ast/seq_decl_plugin.h

+1
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ class seq_util {
424424
MATCH_UNARY(is_unit);
425425

426426
void get_concat(expr* e, expr_ref_vector& es) const;
427+
void get_concat(expr* e, ptr_vector<expr>& es) const;
427428
void get_concat_units(expr* e, expr_ref_vector& es) const;
428429
expr* get_leftmost_concat(expr* e) const { expr* e1, *e2; while (is_concat(e, e1, e2)) e = e1; return e; }
429430
expr* get_rightmost_concat(expr* e) const { expr* e1, *e2; while (is_concat(e, e1, e2)) e = e2; return e; }

src/ast/sls/sls_seq_plugin.cpp

+97-3
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,23 @@ namespace sls {
224224
return m_values.get(id, nullptr);
225225
}
226226

227+
ptr_vector<expr> const& seq_plugin::lhs(expr* eq) {
228+
auto& ev = get_eval(eq);
229+
if (ev.lhs.empty()) {
230+
expr* x, * y;
231+
VERIFY(m.is_eq(eq, x, y));
232+
seq.str.get_concat(x, ev.lhs);
233+
seq.str.get_concat(y, ev.rhs);
234+
}
235+
return ev.lhs;
236+
}
237+
238+
ptr_vector<expr> const& seq_plugin::rhs(expr* eq) {
239+
lhs(eq);
240+
auto& e = get_eval(eq);
241+
return e.rhs;
242+
}
243+
227244
zstring& seq_plugin::strval0(expr* e) {
228245
SASSERT(seq.is_string(e->get_sort()));
229246
return get_eval(e).val0.svalue;
@@ -557,8 +574,10 @@ namespace sls {
557574
bool is_true = ctx.is_true(e);
558575
expr* x, * y;
559576
VERIFY(m.is_eq(e, x, y));
560-
verbose_stream() << is_true << ": " << mk_bounded_pp(e, m, 3) << "\n";
577+
IF_VERBOSE(3, verbose_stream() << is_true << ": " << mk_bounded_pp(e, m, 3) << "\n");
561578
if (ctx.is_true(e)) {
579+
if (ctx.rand(10) != 0)
580+
return repair_down_str_eq_unify(e);
562581
if (!is_value(x))
563582
m_str_updates.push_back({ x, strval1(y), 1 });
564583
if (!is_value(y))
@@ -579,6 +598,81 @@ namespace sls {
579598
return apply_update();
580599
}
581600

601+
bool seq_plugin::repair_down_str_eq_unify(app* eq) {
602+
auto const& L = lhs(eq);
603+
auto const& R = rhs(eq);
604+
unsigned i = 0, j = 0; // position into current string
605+
unsigned ni = 0, nj = 0; // current string in concatenation
606+
double depth = 1.0; // priority of update. Doubled when depth of equal strings are increased.
607+
while (ni < L.size() && nj < R.size()) {
608+
auto const& xi = L[ni];
609+
auto const& yj = R[nj];
610+
auto const& vi = strval0(xi);
611+
auto const& vj = strval0(yj);
612+
IF_VERBOSE(4,
613+
verbose_stream() << "unify: \"" << vi << "\" = \"" << vj << "\" incides " << i << " " << j << "\n";
614+
verbose_stream() << vi.length() << " " << vj.length() << "\n");
615+
if (vi.length() == i && vj.length() == j) {
616+
depth *= 2;
617+
if (nj + 1 < R.size() && !strval0(R[nj + 1]).empty())
618+
m_str_updates.push_back({ xi, vi + zstring(strval0(R[nj + 1])[0]), depth });
619+
if (ni + 1 < L.size() && !strval0(L[ni + 1]).empty())
620+
m_str_updates.push_back({ yj, vj + zstring(strval0(L[ni + 1])[0]), depth });
621+
i = 0;
622+
j = 0;
623+
++ni;
624+
++nj;
625+
continue;
626+
}
627+
if (vi.length() == i) {
628+
// xi -> vi + vj[j]
629+
SASSERT(j < vj.length());
630+
m_str_updates.push_back({ xi, vi + zstring(vj[j]), depth});
631+
depth *= 2;
632+
i = 0;
633+
++ni;
634+
continue;
635+
}
636+
if (vj.length() == j) {
637+
// yj -> vj + vi[i]
638+
SASSERT(i < vi.length());
639+
m_str_updates.push_back({ yj, vj + zstring(vi[i]), depth });
640+
depth *= 2;
641+
j = 0;
642+
++nj;
643+
continue;
644+
}
645+
SASSERT(i < vi.length());
646+
SASSERT(j < vj.length());
647+
if (is_value(xi) && is_value(yj)) {
648+
++i, ++j;
649+
continue;
650+
}
651+
if (vi[i] == vj[j]) {
652+
++i, ++j;
653+
continue;
654+
}
655+
if (!is_value(xi)) {
656+
m_str_updates.push_back({ xi, vi.extract(0, i), depth });
657+
m_str_updates.push_back({ xi, vi.extract(0, i) + zstring(vj[j]), depth});
658+
}
659+
if (!is_value(yj)) {
660+
m_str_updates.push_back({ yj, vj.extract(0, j), depth });
661+
m_str_updates.push_back({ yj, vj.extract(0, j) + zstring(vi[i]), depth });
662+
}
663+
break;
664+
}
665+
for (; ni < L.size(); ++ni)
666+
if (!is_value(L[ni]))
667+
m_str_updates.push_back({ L[ni], zstring(), depth });
668+
669+
for (; nj < R.size(); ++nj)
670+
if (!is_value(R[nj]))
671+
m_str_updates.push_back({ R[nj], zstring(), depth });
672+
673+
return apply_update();
674+
}
675+
582676
bool seq_plugin::repair_down_seq(app* e) {
583677
switch (e->get_decl_kind()) {
584678
case OP_SEQ_CONTAINS:
@@ -1021,7 +1115,7 @@ namespace sls {
10211115
auto [e, value, score] = m_str_updates[i];
10221116

10231117
if (update(e, value)) {
1024-
verbose_stream() << "set value " << mk_bounded_pp(e, m) << " := \"" << value << "\"\n";
1118+
IF_VERBOSE(3, verbose_stream() << "set value " << mk_bounded_pp(e, m) << " := \"" << value << "\"\n");
10251119
m_str_updates.reset();
10261120
m_int_updates.reset();
10271121
return true;
@@ -1034,7 +1128,7 @@ namespace sls {
10341128
else {
10351129
auto [e, value, score] = m_int_updates[i];
10361130

1037-
verbose_stream() << "set value " << mk_bounded_pp(e, m) << " := " << value << "\n";
1131+
IF_VERBOSE(3, verbose_stream() << "set value " << mk_bounded_pp(e, m) << " := " << value << "\n");
10381132

10391133
if (update(e, value)) {
10401134
m_int_updates.reset();

src/ast/sls/sls_seq_plugin.h

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace sls {
3838
bool is_value = false;
3939
unsigned min_length = 0;
4040
unsigned max_length = UINT_MAX;
41+
ptr_vector<expr> lhs, rhs;
4142
};
4243

4344
seq_util seq;
@@ -69,6 +70,7 @@ namespace sls {
6970

7071
bool repair_down_seq(app* e);
7172
bool repair_down_eq(app* e);
73+
bool repair_down_str_eq_unify(app* e);
7274
bool repair_down_str_eq(app* e);
7375
bool repair_down_str_extract(app* e);
7476
bool repair_down_str_contains(expr* e);
@@ -107,6 +109,8 @@ namespace sls {
107109

108110
eval& get_eval(expr* e);
109111
eval* get_eval(expr* e) const;
112+
ptr_vector<expr> const& lhs(expr* eq);
113+
ptr_vector<expr> const& rhs(expr* eq);
110114

111115
bool is_value(expr* e);
112116
public:

0 commit comments

Comments
 (0)