Skip to content

Commit a337a51

Browse files
fixes for #2513
Signed-off-by: Nikolaj Bjorner <[email protected]>
1 parent de69b01 commit a337a51

28 files changed

+486
-144
lines changed

src/ast/rewriter/seq_rewriter.cpp

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Module Name:
2121
#include "ast/rewriter/seq_rewriter.h"
2222
#include "ast/arith_decl_plugin.h"
2323
#include "ast/ast_pp.h"
24+
#include "ast/ast_ll_pp.h"
2425
#include "ast/ast_util.h"
2526
#include "util/uint_set.h"
2627
#include "math/automata/automaton.h"
@@ -546,7 +547,7 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
546547
case _OP_STRING_STRIDOF:
547548
UNREACHABLE();
548549
}
549-
CTRACE("seq", st != BR_FAILED, tout << result << "\n";);
550+
CTRACE("seq_verbose", st != BR_FAILED, tout << result << "\n";);
550551
return st;
551552
}
552553

@@ -643,14 +644,38 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
643644
result = m_autil.mk_add(es.size(), es.c_ptr());
644645
return BR_REWRITE2;
645646
}
647+
expr* c = nullptr, *t = nullptr, *e = nullptr;
648+
if (m().is_ite(a, c, t, e) && (t->get_ref_count() == 1 || e->get_ref_count() == 1)) {
649+
result = m().mk_ite(c, m_util.str.mk_length(t), m_util.str.mk_length(e));
650+
return BR_REWRITE3;
651+
}
652+
#if 0
653+
expr* s = nullptr, *offs = nullptr, *l = nullptr;
654+
// len(extract(s, offs, len(s) - offs)) = max(0, len(s) - offs)
655+
//
656+
if (m_util.str.is_extract(a, s, offs, l) && is_suffix(s, offs, l)) {
657+
expr_ref zero(m_autil.mk_int(0), m());
658+
result = m_autil.mk_sub(m_util.str.mk_length(s), offs);
659+
result = m().mk_ite(m_autil.mk_ge(result, zero), result, zero);
660+
return BR_REWRITE_FULL;
661+
}
662+
#endif
646663
return BR_FAILED;
647664
}
648665

666+
bool seq_rewriter::is_suffix(expr* s, expr* offset, expr* len) {
667+
expr_ref_vector lens(m());
668+
rational a, b;
669+
return
670+
get_lengths(len, lens, a) &&
671+
(a.neg(), m_autil.is_numeral(offset, b) && b.is_pos() && a == b);
672+
}
673+
649674
br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result) {
650675
zstring s;
651676
rational pos, len;
652677

653-
TRACE("seq", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << " " << mk_pp(c, m()) << "\n";);
678+
TRACE("seq_verbose", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << " " << mk_pp(c, m()) << "\n";);
654679
bool constantBase = m_util.str.is_string(a, s);
655680
bool constantPos = m_autil.is_numeral(b, pos);
656681
bool constantLen = m_autil.is_numeral(c, len);
@@ -702,7 +727,8 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
702727
m_lhs.reset();
703728
expr_ref_vector lens(m());
704729
m_util.str.get_concat(a, m_lhs);
705-
if (!get_lengths(b, lens, pos)) {
730+
TRACE("seq", tout << m_lhs << " " << pos << " " << lens << "\n";);
731+
if (!get_lengths(b, lens, pos) || pos.is_neg()) {
706732
return BR_FAILED;
707733
}
708734
unsigned i = 0;
@@ -742,9 +768,20 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu
742768

743769
// (extract s 0 (len s)) = s
744770
expr* a2 = nullptr;
745-
if (_pos == 0 && m_util.str.is_length(c, a2) && a == a2) {
746-
result = a;
747-
return BR_DONE;
771+
if (_pos == 0 && m_util.str.is_length(c, a2)) {
772+
m_lhs.reset();
773+
m_util.str.get_concat(a, m_lhs);
774+
if (!m_lhs.empty() && m_lhs.get(0) == a2) {
775+
result = a2;
776+
return BR_DONE;
777+
}
778+
}
779+
780+
expr* a1 = nullptr, *b1 = nullptr, *c1 = nullptr;
781+
if (m_util.str.is_extract(a, a1, b1, c1) &&
782+
is_suffix(a1, b1, c1) && is_suffix(a, b, c)) {
783+
result = m_util.str.mk_substr(a1, m_autil.mk_add(b1, b), m_autil.mk_sub(c1, b));
784+
return BR_REWRITE3;
748785
}
749786

750787
unsigned offset = 0;
@@ -799,7 +836,7 @@ bool seq_rewriter::get_lengths(expr* e, expr_ref_vector& lens, rational& pos) {
799836
else {
800837
return false;
801838
}
802-
return !pos.is_neg();
839+
return true;
803840
}
804841

805842
bool seq_rewriter::cannot_contain_suffix(expr* a, expr* b) {
@@ -992,9 +1029,28 @@ br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) {
9921029
}
9931030

9941031
br_status seq_rewriter::mk_seq_nth(expr* a, expr* b, expr_ref& result) {
1032+
1033+
rational pos1, pos2;
1034+
expr* s = nullptr, *p = nullptr, *len = nullptr;
1035+
if (m_util.str.is_unit(a, s) && m_autil.is_numeral(b, pos1) && pos1.is_zero()) {
1036+
result = s;
1037+
return BR_DONE;
1038+
}
1039+
if (m_util.str.is_extract(a, s, p, len) && m_autil.is_numeral(p, pos1)) {
1040+
expr_ref_vector lens(m());
1041+
rational pos2;
1042+
if (get_lengths(len, lens, pos2) && (pos1 == -pos2) && (lens.size() == 1) && (lens.get(0) == s)) {
1043+
expr_ref idx(m_autil.mk_int(pos1), m());
1044+
idx = m_autil.mk_add(b, idx);
1045+
expr* es[2] = { s, idx };
1046+
result = m().mk_app(m_util.get_family_id(), OP_SEQ_NTH, 2, es);
1047+
return BR_REWRITE_FULL;
1048+
}
1049+
}
1050+
9951051
expr* es[2] = { a, b};
9961052
expr* la = m_util.str.mk_length(a);
997-
result = m().mk_ite(m().mk_and(m_autil.mk_le(m_autil.mk_int(0), b), m_autil.mk_lt(b, la)),
1053+
result = m().mk_ite(m().mk_and(m_autil.mk_ge(b, m_autil.mk_int(0)), m().mk_not(m_autil.mk_ge(b, la))),
9981054
m().mk_app(m_util.get_family_id(), OP_SEQ_NTH_I, 2, es),
9991055
m().mk_app(m_util.get_family_id(), OP_SEQ_NTH_U, 2, es));
10001056
return BR_REWRITE_FULL;
@@ -1078,10 +1134,26 @@ br_status seq_rewriter::mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& resu
10781134
result = a;
10791135
return BR_DONE;
10801136
}
1137+
if (a == b) {
1138+
result = c;
1139+
return BR_DONE;
1140+
}
10811141
if (m_util.str.is_empty(b)) {
10821142
result = m_util.str.mk_concat(c, a);
10831143
return BR_REWRITE1;
10841144
}
1145+
1146+
if (m_util.str.is_string(b, s2)) {
1147+
m_lhs.reset();
1148+
m_util.str.get_concat(a, m_lhs);
1149+
if (!m_lhs.empty() && m_util.str.is_string(m_lhs.get(0), s1) &&
1150+
s1.contains(s2)) {
1151+
m_lhs[0] = m_util.str.mk_string(s1.replace(s2, s3));
1152+
result = m_util.str.mk_concat(m_lhs.size(), m_lhs.c_ptr());
1153+
return BR_REWRITE1;
1154+
}
1155+
}
1156+
10851157
return BR_FAILED;
10861158
}
10871159

@@ -1835,7 +1907,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
18351907
zstring s;
18361908
bool lchange = false;
18371909
SASSERT(lhs.empty());
1838-
TRACE("seq", tout << ls << "\n"; tout << rs << "\n";);
1910+
TRACE("seq_verbose", tout << ls << "\n"; tout << rs << "\n";);
18391911
// solve from back
18401912
while (true) {
18411913
while (!rs.empty() && m_util.str.is_empty(rs.back())) {
@@ -1943,7 +2015,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
19432015
else {
19442016
break;
19452017
}
1946-
TRACE("seq", tout << ls << " == " << rs << "\n";);
2018+
TRACE("seq_verbose", tout << ls << " == " << rs << "\n";);
19472019

19482020
change = true;
19492021
lchange = true;
@@ -2106,7 +2178,7 @@ bool seq_rewriter::reduce_eq(expr* l, expr* r, expr_ref_vector& lhs, expr_ref_ve
21062178
return true;
21072179
}
21082180
else {
2109-
TRACE("seq", tout << mk_pp(l, m()) << " != " << mk_pp(r, m()) << "\n";);
2181+
TRACE("seq", tout << mk_bounded_pp(l, m()) << " != " << mk_bounded_pp(r, m()) << "\n";);
21102182
return false;
21112183
}
21122184
}

src/ast/rewriter/seq_rewriter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ class seq_rewriter {
139139
bool cannot_contain_prefix(expr* a, expr* b);
140140
bool cannot_contain_suffix(expr* a, expr* b);
141141

142+
bool is_suffix(expr* s, expr* offset, expr* len);
143+
142144
bool set_empty(unsigned sz, expr* const* es, bool all, expr_ref_vector& lhs, expr_ref_vector& rhs);
143145
bool is_subsequence(unsigned n, expr* const* l, unsigned m, expr* const* r,
144146
expr_ref_vector& lhs, expr_ref_vector& rhs, bool& is_sat);

src/ast/static_features.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,7 @@ void static_features::update_core(expr * e) {
346346
m_num_uninterpreted_functions++;
347347
}
348348
if (!_is_eq && !_is_gate) {
349-
unsigned num_args = to_app(e)->get_num_args();
350-
for (unsigned i = 0; i < num_args; i++) {
351-
expr * arg = to_app(e)->get_arg(i);
349+
for (expr * arg : *to_app(e)) {
352350
sort * arg_s = m_manager.get_sort(arg);
353351
if (!m_manager.is_uninterp(arg_s)) {
354352
family_id fid_arg = arg_s->get_family_id();

src/cmd_context/cmd_context.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Module Name:
3636
#include "ast/rewriter/var_subst.h"
3737
#include "ast/pp.h"
3838
#include "ast/ast_smt2_pp.h"
39+
#include "ast/ast_ll_pp.h"
3940
#include "ast/decl_collector.h"
4041
#include "ast/well_sorted.h"
4142
#include "ast/for_each_expr.h"
@@ -1896,7 +1897,7 @@ void cmd_context::validate_model() {
18961897
continue;
18971898
}
18981899
TRACE("model_validate", model_smt2_pp(tout, *this, *md, 0););
1899-
IF_VERBOSE(10, verbose_stream() << "model check failed on: " << mk_pp(a, m()) << "\n";);
1900+
analyze_failure(evaluator, a, true);
19001901
IF_VERBOSE(11, model_smt2_pp(verbose_stream(), *this, *md, 0););
19011902
invalid_model = true;
19021903
}
@@ -1907,6 +1908,73 @@ void cmd_context::validate_model() {
19071908
}
19081909
}
19091910

1911+
void cmd_context::analyze_failure(model_evaluator& ev, expr* a, bool expected_value) {
1912+
if (expected_value && m().is_and(a)) {
1913+
for (expr* arg : *to_app(a)) {
1914+
if (ev.is_false(arg)) {
1915+
analyze_failure(ev, arg, true);
1916+
return;
1917+
}
1918+
}
1919+
}
1920+
expr* c = nullptr, *t = nullptr, *e = nullptr;
1921+
if (expected_value && m().is_ite(a, c, t, e)) {
1922+
if (ev.is_true(c) && ev.is_false(t)) {
1923+
analyze_failure(ev, t, true);
1924+
return;
1925+
}
1926+
if (ev.is_false(c) && ev.is_false(e)) {
1927+
analyze_failure(ev, e, true);
1928+
return;
1929+
}
1930+
}
1931+
if (m().is_not(a, e)) {
1932+
analyze_failure(ev, e, !expected_value);
1933+
return;
1934+
}
1935+
if (!expected_value && m().is_or(a)) {
1936+
for (expr* arg : *to_app(a)) {
1937+
if (ev.is_false(arg)) {
1938+
analyze_failure(ev, arg, false);
1939+
return;
1940+
}
1941+
}
1942+
}
1943+
if (!expected_value && m().is_ite(a, c, t, e)) {
1944+
if (ev.is_true(c) && ev.is_true(t)) {
1945+
analyze_failure(ev, t, false);
1946+
return;
1947+
}
1948+
if (ev.is_false(c) && ev.is_true(e)) {
1949+
analyze_failure(ev, e, false);
1950+
return;
1951+
}
1952+
}
1953+
IF_VERBOSE(10, verbose_stream() << "model check failed on: " << " " << mk_pp(a, m()) << "\n";);
1954+
IF_VERBOSE(10, verbose_stream() << "expected value: " << (expected_value?"true":"false") << "\n";);
1955+
1956+
IF_VERBOSE(10, display_detailed_analysis(verbose_stream(), ev, a));
1957+
}
1958+
1959+
void cmd_context::display_detailed_analysis(std::ostream& out, model_evaluator& ev, expr* e) {
1960+
ptr_vector<expr> es;
1961+
es.push_back(e);
1962+
expr_mark visited;
1963+
for (unsigned i = 0; i < es.size(); ++i) {
1964+
e = es[i];
1965+
if (visited.is_marked(e)) {
1966+
continue;
1967+
}
1968+
visited.mark(e, true);
1969+
expr_ref val = ev(e);
1970+
out << "#" << e->get_id() << ": " << mk_bounded_pp(e, m(), 1) << " " << val << "\n";
1971+
if (is_app(e)) {
1972+
for (expr* arg : *to_app(e)) {
1973+
es.push_back(arg);
1974+
}
1975+
}
1976+
}
1977+
}
19101978

19111979
void cmd_context::mk_solver() {
19121980
bool proofs_enabled, models_enabled, unsat_core_enabled;

src/cmd_context/cmd_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ class cmd_context : public progress_callback, public tactic_manager, public ast_
367367
check_sat_state cs_state() const;
368368
void complete_model(model_ref& mdl) const;
369369
void validate_model();
370+
void analyze_failure(model_evaluator& ev, expr* e, bool expected_value);
371+
void display_detailed_analysis(std::ostream& out, model_evaluator& ev, expr* e);
370372
void display_model(model_ref& mdl);
371373

372374
void register_plugin(symbol const & name, decl_plugin * p, bool install_names);

src/qe/nlqsat.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ namespace qe {
641641
}
642642
}
643643
fml = mk_and(paxioms);
644+
std::cout << fml << "\n";
644645
}
645646
}
646647

src/sat/sat_config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ namespace sat {
181181
m_drat_file = p.drat_file();
182182
m_drat = (m_drat_check_unsat || m_drat_file != symbol("") || m_drat_check_sat) && p.threads() == 1;
183183
m_drat_binary = p.drat_binary();
184+
m_drat_activity = p.drat_activity();
184185
m_dyn_sub_res = p.dyn_sub_res();
185186

186187
// Parameters used in Liang, Ganesh, Poupart, Czarnecki AAAI 2016.

src/sat/sat_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ namespace sat {
168168
symbol m_drat_file;
169169
bool m_drat_check_unsat;
170170
bool m_drat_check_sat;
171+
bool m_drat_activity;
171172

172173
bool m_card_solver;
173174
bool m_xor_solver;

0 commit comments

Comments
 (0)