mirror of
https://github.com/Z3Prover/z3
synced 2026-06-30 04:18:53 +00:00
Merge branch 'master' into c3
This commit is contained in:
commit
e3b80fc578
104 changed files with 10253 additions and 4367 deletions
|
|
@ -66,7 +66,7 @@ z3_add_component(api
|
|||
z3_replayer.cpp
|
||||
${full_path_generated_files}
|
||||
COMPONENT_DEPENDENCIES
|
||||
opt
|
||||
z3_opt
|
||||
euf
|
||||
portfolio
|
||||
realclosure
|
||||
|
|
|
|||
|
|
@ -4925,7 +4925,7 @@ namespace z3 {
|
|||
|
||||
void check_context(rcf_num const& other) const {
|
||||
if (m_ctx != other.m_ctx) {
|
||||
throw exception("rcf_num objects from different contexts");
|
||||
Z3_THROW(exception("rcf_num objects from different contexts"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5105,9 +5105,9 @@ namespace z3 {
|
|||
*/
|
||||
inline std::vector<rcf_num> rcf_roots(context& c, std::vector<rcf_num> const& coeffs) {
|
||||
if (coeffs.empty()) {
|
||||
throw exception("polynomial coefficients cannot be empty");
|
||||
Z3_THROW(exception("polynomial coefficients cannot be empty"));
|
||||
}
|
||||
|
||||
|
||||
unsigned n = static_cast<unsigned>(coeffs.size());
|
||||
std::vector<Z3_rcf_num> a(n);
|
||||
std::vector<Z3_rcf_num> roots(n);
|
||||
|
|
|
|||
|
|
@ -48,17 +48,18 @@ target_include_directories(z3java PRIVATE
|
|||
"${PROJECT_BINARY_DIR}/src/api"
|
||||
${JNI_INCLUDE_DIRS}
|
||||
)
|
||||
# Add header padding for macOS to allow install_name_tool to modify the dylib
|
||||
# On macOS, set rpath so libz3java.dylib can find libz3.dylib in the same directory,
|
||||
# and add header padding to allow install_name_tool to modify the dylib.
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set_target_properties(z3java PROPERTIES
|
||||
MACOSX_RPATH TRUE
|
||||
INSTALL_RPATH "@loader_path"
|
||||
BUILD_RPATH "@loader_path"
|
||||
)
|
||||
target_link_options(z3java PRIVATE "-Wl,-headerpad_max_install_names")
|
||||
endif()
|
||||
# FIXME: Should this library have SONAME and VERSION set?
|
||||
|
||||
# On macOS, add headerpad for install_name_tool compatibility
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
target_link_options(z3java PRIVATE "-Wl,-headerpad_max_install_names")
|
||||
endif()
|
||||
|
||||
# This prevents CMake from automatically defining ``z3java_EXPORTS``
|
||||
set_property(TARGET z3java PROPERTY DEFINE_SYMBOL "")
|
||||
|
||||
|
|
|
|||
|
|
@ -7396,8 +7396,8 @@ class Statistics:
|
|||
>>> s.check()
|
||||
sat
|
||||
>>> st = s.statistics()
|
||||
>>> len(st)
|
||||
7
|
||||
>>> len(st) > 0
|
||||
True
|
||||
"""
|
||||
return int(Z3_stats_size(self.ctx.ref(), self.stats))
|
||||
|
||||
|
|
@ -7410,8 +7410,8 @@ class Statistics:
|
|||
>>> s.check()
|
||||
sat
|
||||
>>> st = s.statistics()
|
||||
>>> len(st)
|
||||
7
|
||||
>>> len(st) > 0
|
||||
True
|
||||
>>> st[0]
|
||||
('nlsat propagations', 2)
|
||||
>>> st[1]
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Revision History:
|
|||
#include "ast/for_each_ast.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
// #define AST_LL_PP_SHOW_FAMILY_NAME
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ class ll_printer {
|
|||
}
|
||||
|
||||
void display_name(func_decl * decl) {
|
||||
m_out << decl->get_name();
|
||||
m_out << ensure_quote(decl->get_name());
|
||||
}
|
||||
|
||||
bool process_numeral(expr * n) {
|
||||
|
|
|
|||
|
|
@ -507,6 +507,7 @@ class smt_printer {
|
|||
case forall_k: m_out << "forall "; break;
|
||||
case exists_k: m_out << "exists "; break;
|
||||
case lambda_k: m_out << "lambda "; break;
|
||||
case choice_k: m_out << "choice "; break;
|
||||
}
|
||||
m_out << "(";
|
||||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
|
|
|
|||
|
|
@ -1951,14 +1951,12 @@ namespace euf {
|
|||
|
||||
enode * get_next_f_app(func_decl * lbl, unsigned num_expected_args, enode * first, enode * curr) {
|
||||
curr = curr->get_next();
|
||||
enode *matching_cgr = nullptr, *min_gen_match = nullptr;
|
||||
while (curr != first) {
|
||||
get_f_app(lbl, num_expected_args, curr, matching_cgr, min_gen_match);
|
||||
if (curr->get_decl() == lbl && curr->num_args() == num_expected_args && curr->is_cgr())
|
||||
return curr;
|
||||
curr = curr->get_next();
|
||||
}
|
||||
if (matching_cgr)
|
||||
update_max_generation(min_gen_match, first);
|
||||
return matching_cgr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ z3_add_component(rewriter
|
|||
rewriter.cpp
|
||||
seq_axioms.cpp
|
||||
seq_eq_solver.cpp
|
||||
seq_subset.cpp
|
||||
seq_rewriter.cpp
|
||||
seq_skolem.cpp
|
||||
th_rewriter.cpp
|
||||
|
|
|
|||
|
|
@ -4525,10 +4525,60 @@ br_status seq_rewriter::mk_str_to_regexp(expr* a, expr_ref& result) {
|
|||
r* ++ r -> r ++ r*
|
||||
*/
|
||||
br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
|
||||
auto accepts_empty_word = [&](expr* r) {
|
||||
auto info = re().get_info(r);
|
||||
return info.interpreted && info.nullable == l_true && info.min_length == 0;
|
||||
};
|
||||
auto starts_with_full_seq = [&](expr* r) {
|
||||
expr* r1 = nullptr, *r2 = nullptr;
|
||||
return re().is_full_seq(r) || (re().is_concat(r, r1, r2) && re().is_full_seq(r1));
|
||||
};
|
||||
auto ends_with_full_seq = [&](expr* r) {
|
||||
expr* r1 = nullptr, *r2 = nullptr;
|
||||
while (re().is_concat(r, r1, r2))
|
||||
r = r2;
|
||||
return re().is_full_seq(r);
|
||||
};
|
||||
auto all_inter_arms_end_with_full_seq = [&](expr* r) {
|
||||
ptr_buffer<expr> todo;
|
||||
todo.push_back(r);
|
||||
while (!todo.empty()) {
|
||||
expr* r1 = nullptr, *r2 = nullptr;
|
||||
expr* t = todo.back();
|
||||
todo.pop_back();
|
||||
if (re().is_intersection(t, r1, r2)) {
|
||||
todo.push_back(r1);
|
||||
todo.push_back(r2);
|
||||
}
|
||||
else if (!ends_with_full_seq(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (re().is_full_seq(a) && re().is_full_seq(b)) {
|
||||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
if (re().is_full_seq(a) && accepts_empty_word(b)) {
|
||||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
if (re().is_full_seq(b) && accepts_empty_word(a)) {
|
||||
result = b;
|
||||
return BR_DONE;
|
||||
}
|
||||
expr* u1 = nullptr, *u2 = nullptr;
|
||||
if (re().is_full_seq(a) && re().is_union(b, u1, u2) &&
|
||||
(starts_with_full_seq(u1) || starts_with_full_seq(u2))) {
|
||||
result = mk_regex_union_normalize(mk_regex_concat(a, u1), mk_regex_concat(a, u2));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (re().is_intersection(a, u1, u2) && re().is_full_seq(b) &&
|
||||
all_inter_arms_end_with_full_seq(a)) {
|
||||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
if (re().is_empty(a)) {
|
||||
result = a;
|
||||
return BR_DONE;
|
||||
|
|
@ -4564,7 +4614,8 @@ br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
|
|||
result = re().mk_to_re(str().mk_concat(a_str, b_str));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
expr* a1 = nullptr, *b1 = nullptr;
|
||||
expr* a1 = nullptr;
|
||||
expr* b1 = nullptr;
|
||||
if (re().is_to_re(a, a1) && re().is_to_re(b, b1)) {
|
||||
result = re().mk_to_re(str().mk_concat(a1, b1));
|
||||
return BR_DONE;
|
||||
|
|
@ -4573,6 +4624,11 @@ br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
|
|||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
expr* b2 = nullptr, *b3 = nullptr;
|
||||
if (re().is_star(a, a1) && re().is_concat(b, b1, b2) && re().is_star(b1, b3) && a1 == b3) {
|
||||
result = b;
|
||||
return BR_DONE;
|
||||
}
|
||||
if (re().is_star(a, a1) && a1 == b) {
|
||||
result = re().mk_concat(b, a);
|
||||
return BR_DONE;
|
||||
|
|
@ -4626,51 +4682,7 @@ bool seq_rewriter::are_complements(expr* r1, expr* r2) const {
|
|||
* basic subset checker.
|
||||
*/
|
||||
bool seq_rewriter::is_subset(expr* r1, expr* r2) const {
|
||||
// return false;
|
||||
expr* ra1 = nullptr, *ra2 = nullptr, *ra3 = nullptr;
|
||||
expr* rb1 = nullptr, *rb2 = nullptr, *rb3 = nullptr;
|
||||
unsigned la, ua, lb, ub;
|
||||
if (re().is_complement(r1, ra1) &&
|
||||
re().is_complement(r2, rb1)) {
|
||||
return is_subset(rb1, ra1);
|
||||
}
|
||||
auto is_concat = [&](expr* r, expr*& a, expr*& b, expr*& c) {
|
||||
return re().is_concat(r, a, b) && re().is_concat(b, b, c);
|
||||
};
|
||||
while (true) {
|
||||
if (r1 == r2)
|
||||
return true;
|
||||
if (re().is_full_seq(r2))
|
||||
return true;
|
||||
if (re().is_dot_plus(r2) && re().get_info(r1).nullable == l_false)
|
||||
return true;
|
||||
if (is_concat(r1, ra1, ra2, ra3) &&
|
||||
is_concat(r2, rb1, rb2, rb3) && ra1 == rb1 && ra2 == rb2) {
|
||||
r1 = ra3;
|
||||
r2 = rb3;
|
||||
continue;
|
||||
}
|
||||
if (re().is_concat(r1, ra1, ra2) &&
|
||||
re().is_concat(r2, rb1, rb2) && re().is_full_seq(rb1)) {
|
||||
r1 = ra2;
|
||||
continue;
|
||||
}
|
||||
// r1=ra3{la,ua}ra2, r2=rb3{lb,ub}rb2, ra3=rb3, lb<=la, ua<=ub
|
||||
if (re().is_concat(r1, ra1, ra2) && re().is_loop(ra1, ra3, la, ua) &&
|
||||
re().is_concat(r2, rb1, rb2) && re().is_loop(rb1, rb3, lb, ub) &&
|
||||
ra3 == rb3 && lb <= la && ua <= ub) {
|
||||
r1 = ra2;
|
||||
r2 = rb2;
|
||||
continue;
|
||||
}
|
||||
// ra1=ra3{la,ua}, r2=rb3{lb,ub}, ra3=rb3, lb<=la, ua<=ub
|
||||
if (re().is_loop(r1, ra3, la, ua) &&
|
||||
re().is_loop(r2, rb3, lb, ub) &&
|
||||
ra3 == rb3 && lb <= la && ua <= ub) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return m_subset.is_subset(r1, r2);
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_re_union0(expr* a, expr* b, expr_ref& result) {
|
||||
|
|
@ -6256,4 +6268,3 @@ bool seq_rewriter::get_bounds(expr* e, unsigned& low, unsigned& high) {
|
|||
}
|
||||
return low <= high;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ Notes:
|
|||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/rewriter/rewriter_types.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
#include "ast/rewriter/seq_subset.h"
|
||||
#include "util/params.h"
|
||||
#include "util/lbool.h"
|
||||
#include "util/sign.h"
|
||||
|
|
@ -128,6 +129,7 @@ class seq_rewriter {
|
|||
};
|
||||
|
||||
seq_util m_util;
|
||||
seq_subset m_subset;
|
||||
arith_util m_autil;
|
||||
bool_rewriter m_br;
|
||||
// re2automaton m_re2aut;
|
||||
|
|
@ -340,7 +342,7 @@ class seq_rewriter {
|
|||
|
||||
public:
|
||||
seq_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m), m_autil(m), m_br(m, p), // m_re2aut(m),
|
||||
m_util(m), m_subset(m_util.re), m_autil(m), m_br(m, p), // m_re2aut(m),
|
||||
m_op_cache(m), m_es(m),
|
||||
m_lhs(m), m_rhs(m), m_coalesce_chars(true) {
|
||||
}
|
||||
|
|
@ -436,4 +438,3 @@ public:
|
|||
*/
|
||||
lbool some_string_in_re(expr* r, zstring& s);
|
||||
};
|
||||
|
||||
|
|
|
|||
146
src/ast/rewriter/seq_subset.cpp
Normal file
146
src/ast/rewriter/seq_subset.cpp
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_subset.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Heuristic regular-expression subset checks used by seq_rewriter.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2026-6-8
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast/rewriter/seq_subset.h"
|
||||
|
||||
bool seq_subset::is_subset_rec(expr* a, expr* b, unsigned depth) const {
|
||||
while (true) {
|
||||
|
||||
if (a == b)
|
||||
return true;
|
||||
if (m_re.is_empty(a))
|
||||
return true;
|
||||
if (m_re.is_full_seq(b))
|
||||
return true;
|
||||
if (m_re.is_epsilon(a) && m_re.get_info(b).nullable == l_true)
|
||||
return true;
|
||||
|
||||
if (depth >= m_max_depth)
|
||||
return false;
|
||||
|
||||
expr* a1 = nullptr, * a2 = nullptr, * b1 = nullptr, * b2 = nullptr;
|
||||
unsigned la, ua, lb, ub;
|
||||
|
||||
// a ⊆ .+ iff a is non-nullable
|
||||
if (m_re.is_dot_plus(b) && m_re.get_info(a).nullable == l_false)
|
||||
return true;
|
||||
|
||||
// a ⊆ a*
|
||||
if (m_re.is_star(b, b1) && is_subset_rec(a, b1, depth))
|
||||
return true;
|
||||
|
||||
// e ⊆ a*
|
||||
if (m_re.is_epsilon(a) && m_re.is_star(b, b1))
|
||||
return true;
|
||||
|
||||
// R ⊆ R*
|
||||
if (m_re.is_star(b, b1) && is_subset_rec(a, b1, depth + 1))
|
||||
return true;
|
||||
|
||||
// R1* ⊆ R2* if R1 ⊆ R2
|
||||
if (m_re.is_star(a, a1) && m_re.is_star(b, b1) && is_subset_rec(a1, b1, depth + 1))
|
||||
return true;
|
||||
|
||||
// R1+ ⊆ R2+ if R1 ⊆ R2
|
||||
if (m_re.is_plus(a, a1) && m_re.is_plus(b, b1) && is_subset_rec(a1, b1, depth))
|
||||
return true;
|
||||
|
||||
// R ⊆ R+
|
||||
if (m_re.is_plus(b, b1) && is_subset_rec(a, b1, depth))
|
||||
return true;
|
||||
|
||||
// R+ ⊆ R*
|
||||
if (m_re.is_plus(a, a1) && m_re.is_star(b, b1) && is_subset_rec(a1, b1, depth + 1))
|
||||
return true;
|
||||
|
||||
// range containment
|
||||
if (m_re.is_range(a, la, ua) && m_re.is_range(b, lb, ub) && lb <= la && ua <= ub)
|
||||
return true;
|
||||
|
||||
// to_re(s) ⊆ range
|
||||
if (m_re.is_to_re(a, a1) && m_re.is_range(b, lb, ub) && is_app(a1)) {
|
||||
func_decl* f = to_app(a1)->get_decl();
|
||||
if (f->get_decl_kind() == OP_STRING_CONST && f->get_num_parameters() == 1) {
|
||||
zstring const& s = f->get_parameter(0).get_zstring();
|
||||
if (s.length() == 1 && lb <= s[0] && s[0] <= ub)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// a ⊆ b1 ∪ b2 if a ⊆ b1 or a ⊆ b2
|
||||
if (m_re.is_union(b, b1, b2) && (is_subset_rec(a, b1, depth + 1) || is_subset_rec(a, b2, depth + 1)))
|
||||
return true;
|
||||
|
||||
// a1 ∪ a2 ⊆ b if a1 ⊆ b and a2 ⊆ b
|
||||
if (m_re.is_union(a, a1, a2) && is_subset_rec(a1, b, depth + 1) && is_subset_rec(a2, b, depth + 1))
|
||||
return true;
|
||||
|
||||
// a1 ∩ a2 ⊆ b if a1 ⊆ b or a2 ⊆ b
|
||||
if (m_re.is_intersection(a, a1, a2) && (is_subset_rec(a1, b, depth + 1) || is_subset_rec(a2, b, depth + 1)))
|
||||
return true;
|
||||
|
||||
// a ⊆ b1 ∩ b2 if a ⊆ b1 and a ⊆ b2
|
||||
if (m_re.is_intersection(b, b1, b2) && is_subset_rec(a, b1, depth + 1) && is_subset_rec(a, b2, depth + 1))
|
||||
return true;
|
||||
|
||||
// R{la,ua} ⊆ R'{lb,ub} if R ⊆ R', lb<=la, ua<=ub
|
||||
if (m_re.is_loop(a, a1, la, ua) &&
|
||||
m_re.is_loop(b, b1, lb, ub) &&
|
||||
lb <= la && ua <= ub && is_subset_rec(a1, b1, depth + 1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// a1 \ a2 ⊆ b if a1 ⊆ b
|
||||
if (m_re.is_diff(a, a1, a2) && is_subset_rec(a1, b, depth + 1))
|
||||
return true;
|
||||
|
||||
// R ⊆ Σ*·R' if R ⊆ R'
|
||||
if (m_re.is_concat(b, b1, b2) && m_re.is_full_seq(b1) && is_subset_rec(a, b2, depth))
|
||||
return true;
|
||||
|
||||
// R ⊆ R'·Σ* if R ⊆ R'
|
||||
if (m_re.is_concat(b, b1, b2) && m_re.is_full_seq(b2) && is_subset_rec(a, b1, depth))
|
||||
return true;
|
||||
|
||||
// star absorption: R·R* ⊆ R*, R*·R ⊆ R*
|
||||
bool const is_concat_star = m_re.is_concat(a, a1, a2) && m_re.is_star(b, b1);
|
||||
if (is_concat_star &&
|
||||
is_subset_rec(a1, b1, depth + 1) && is_subset_rec(a2, b, depth + 1))
|
||||
return true;
|
||||
if (is_concat_star &&
|
||||
is_subset_rec(a2, b1, depth + 1) && is_subset_rec(a1, b, depth + 1))
|
||||
return true;
|
||||
|
||||
// concat monotonicity:
|
||||
// tail-recursive on second arguments (without increasing depth bound).
|
||||
if (m_re.is_concat(a, a1, a2) && m_re.is_concat(b, b1, b2) && is_subset_rec(a1, b1, depth + 1)) {
|
||||
a = a2;
|
||||
b = b2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// complement: ~a ⊆ ~b if b ⊆ a
|
||||
if (m_re.is_complement(a, a1) && m_re.is_complement(b, b1))
|
||||
return is_subset_rec(b1, a1, depth + 1);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool seq_subset::is_subset(expr* a, expr* b) const {
|
||||
return is_subset_rec(a, b, 0);
|
||||
}
|
||||
30
src/ast/rewriter/seq_subset.h
Normal file
30
src/ast/rewriter/seq_subset.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*++
|
||||
Copyright (c) 2026 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
seq_subset.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Heuristic regular-expression subset checks used by seq_rewriter.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2026-6-8
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
|
||||
class seq_subset {
|
||||
seq_util::rex& m_re;
|
||||
static constexpr unsigned m_max_depth = 3;
|
||||
|
||||
bool is_subset_rec(expr* a, expr* b, unsigned depth) const;
|
||||
|
||||
public:
|
||||
explicit seq_subset(seq_util::rex& re) : m_re(re) {}
|
||||
bool is_subset(expr* a, expr* b) const;
|
||||
};
|
||||
|
|
@ -1656,9 +1656,9 @@ seq_util::rex::info seq_util::rex::mk_info_rec(app* e) const {
|
|||
if (e->get_family_id() == u.get_family_id()) {
|
||||
switch (e->get_decl()->get_decl_kind()) {
|
||||
case OP_RE_EMPTY_SET:
|
||||
return info(true, l_false, UINT_MAX);
|
||||
return info(true, l_false, UINT_MAX, false);
|
||||
case OP_RE_FULL_SEQ_SET:
|
||||
return info(true, l_true, 0);
|
||||
return info(true, l_true, 0, true);
|
||||
case OP_RE_STAR:
|
||||
i1 = get_info_rec(e->get_arg(0));
|
||||
return i1.star();
|
||||
|
|
@ -1670,7 +1670,7 @@ seq_util::rex::info seq_util::rex::mk_info_rec(app* e) const {
|
|||
case OP_RE_OF_PRED:
|
||||
//TBD: check if the character predicate contains uninterpreted symbols or is nonground or is unsat
|
||||
//TBD: check if the range is unsat
|
||||
return info(true, l_false, 1);
|
||||
return info(true, l_false, 1, false);
|
||||
case OP_RE_CONCAT:
|
||||
i1 = get_info_rec(e->get_arg(0));
|
||||
i2 = get_info_rec(e->get_arg(1));
|
||||
|
|
@ -1687,7 +1687,7 @@ seq_util::rex::info seq_util::rex::mk_info_rec(app* e) const {
|
|||
min_length = u.str.min_length(e->get_arg(0));
|
||||
is_value = m.is_value(e->get_arg(0));
|
||||
nullable = (is_value && min_length == 0 ? l_true : (min_length > 0 ? l_false : l_undef));
|
||||
return info(is_value, nullable, min_length);
|
||||
return info(is_value, nullable, min_length, true);
|
||||
case OP_RE_REVERSE:
|
||||
return get_info_rec(e->get_arg(0));
|
||||
case OP_RE_PLUS:
|
||||
|
|
@ -1723,7 +1723,8 @@ std::ostream& seq_util::rex::info::display(std::ostream& out) const {
|
|||
if (is_known()) {
|
||||
out << "info("
|
||||
<< "nullable=" << (nullable == l_true ? "T" : (nullable == l_false ? "F" : "U")) << ", "
|
||||
<< "min_length=" << min_length << ")";
|
||||
<< "min_length=" << min_length << ", "
|
||||
<< "classical=" << (classical ? "T" : "F") << ")";
|
||||
}
|
||||
else if (is_valid())
|
||||
out << "UNKNOWN";
|
||||
|
|
@ -1743,13 +1744,13 @@ std::string seq_util::rex::info::str() const {
|
|||
|
||||
seq_util::rex::info seq_util::rex::info::star() const {
|
||||
//if is_known() is false then all mentioned properties will remain false
|
||||
return seq_util::rex::info(interpreted, l_true, 0);
|
||||
return seq_util::rex::info(interpreted, l_true, 0, classical);
|
||||
}
|
||||
|
||||
seq_util::rex::info seq_util::rex::info::plus() const {
|
||||
if (is_known()) {
|
||||
//plus never occurs in a normalized regex
|
||||
return info(interpreted, nullable, min_length);
|
||||
return info(interpreted, nullable, min_length, classical);
|
||||
}
|
||||
else
|
||||
return *this;
|
||||
|
|
@ -1758,14 +1759,14 @@ seq_util::rex::info seq_util::rex::info::plus() const {
|
|||
seq_util::rex::info seq_util::rex::info::opt() const {
|
||||
// if is_known() is false then all mentioned properties will remain false
|
||||
// optional construct never occurs in a normalized regex
|
||||
return seq_util::rex::info(interpreted, l_true, 0);
|
||||
return seq_util::rex::info(interpreted, l_true, 0, classical);
|
||||
}
|
||||
|
||||
seq_util::rex::info seq_util::rex::info::complement() const {
|
||||
if (is_known()) {
|
||||
lbool compl_nullable = (nullable == l_true ? l_false : (nullable == l_false ? l_true : l_undef));
|
||||
unsigned compl_min_length = (compl_nullable == l_false ? 1 : 0);
|
||||
return info(interpreted, compl_nullable, compl_min_length);
|
||||
return info(interpreted, compl_nullable, compl_min_length, false);
|
||||
}
|
||||
else
|
||||
return *this;
|
||||
|
|
@ -1779,7 +1780,8 @@ seq_util::rex::info seq_util::rex::info::concat(seq_util::rex::info const& rhs,
|
|||
m = UINT_MAX;
|
||||
return info(interpreted && rhs.interpreted,
|
||||
((nullable == l_false || rhs.nullable == l_false) ? l_false : ((nullable == l_true && rhs.nullable == l_true) ? l_true : l_undef)),
|
||||
m);
|
||||
m,
|
||||
classical && rhs.classical);
|
||||
}
|
||||
else
|
||||
return rhs;
|
||||
|
|
@ -1793,7 +1795,8 @@ seq_util::rex::info seq_util::rex::info::disj(seq_util::rex::info const& rhs) co
|
|||
//works correctly if one of the arguments is unknown
|
||||
return info(interpreted && rhs.interpreted,
|
||||
((nullable == l_true || rhs.nullable == l_true) ? l_true : ((nullable == l_false && rhs.nullable == l_false) ? l_false : l_undef)),
|
||||
std::min(min_length, rhs.min_length));
|
||||
std::min(min_length, rhs.min_length),
|
||||
classical && rhs.classical);
|
||||
}
|
||||
else
|
||||
return rhs;
|
||||
|
|
@ -1804,7 +1807,8 @@ seq_util::rex::info seq_util::rex::info::conj(seq_util::rex::info const& rhs) co
|
|||
if (rhs.is_known()) {
|
||||
return info(interpreted && rhs.interpreted,
|
||||
((nullable == l_true && rhs.nullable == l_true) ? l_true : ((nullable == l_false || rhs.nullable == l_false) ? l_false : l_undef)),
|
||||
std::max(min_length, rhs.min_length));
|
||||
std::max(min_length, rhs.min_length),
|
||||
false);
|
||||
}
|
||||
else
|
||||
return rhs;
|
||||
|
|
@ -1818,7 +1822,8 @@ seq_util::rex::info seq_util::rex::info::diff(seq_util::rex::info const& rhs) co
|
|||
if (rhs.is_known()) {
|
||||
return info(interpreted & rhs.interpreted,
|
||||
((nullable == l_true && rhs.nullable == l_false) ? l_true : ((nullable == l_false || rhs.nullable == l_false) ? l_false : l_undef)),
|
||||
std::max(min_length, rhs.min_length));
|
||||
std::max(min_length, rhs.min_length),
|
||||
false);
|
||||
}
|
||||
else
|
||||
return rhs;
|
||||
|
|
@ -1835,7 +1840,8 @@ seq_util::rex::info seq_util::rex::info::orelse(seq_util::rex::info const& i) co
|
|||
// TBD: whether ite is interpreted or not depends on whether the condition is interpreted and both branches are interpreted
|
||||
return info(false,
|
||||
((nullable == l_true && i.nullable == l_true) ? l_true : ((nullable == l_false && i.nullable == l_false) ? l_false : l_undef)),
|
||||
std::min(min_length, i.min_length));
|
||||
std::min(min_length, i.min_length),
|
||||
classical && i.classical);
|
||||
}
|
||||
else
|
||||
return i;
|
||||
|
|
@ -1851,7 +1857,7 @@ seq_util::rex::info seq_util::rex::info::loop(unsigned lower, unsigned upper) co
|
|||
if (m > 0 && (m < min_length || m < lower))
|
||||
m = UINT_MAX;
|
||||
lbool loop_nullable = (nullable == l_true || lower == 0 ? l_true : nullable);
|
||||
return info(interpreted, loop_nullable, m);
|
||||
return info(interpreted, loop_nullable, m, classical);
|
||||
}
|
||||
else
|
||||
return *this;
|
||||
|
|
@ -1866,6 +1872,7 @@ seq_util::rex::info& seq_util::rex::info::operator=(info const& other) {
|
|||
interpreted = other.interpreted;
|
||||
nullable = other.nullable;
|
||||
min_length = other.min_length;
|
||||
classical = other.classical;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -447,6 +447,8 @@ public:
|
|||
lbool nullable { l_undef };
|
||||
/* Lower bound on the length of all accepted words. */
|
||||
unsigned min_length { 0 };
|
||||
/* Classical regular expression: does not use complement, intersection, diff, or the empty language (fail). */
|
||||
bool classical { true };
|
||||
|
||||
/*
|
||||
Default constructor of invalid info.
|
||||
|
|
@ -463,11 +465,13 @@ public:
|
|||
*/
|
||||
info(bool is_interpreted,
|
||||
lbool is_nullable,
|
||||
unsigned min_l) :
|
||||
unsigned min_l,
|
||||
bool is_classical) :
|
||||
known(l_true),
|
||||
interpreted(is_interpreted),
|
||||
nullable(is_nullable),
|
||||
min_length(min_l) {}
|
||||
min_length(min_l),
|
||||
classical(is_classical) {}
|
||||
|
||||
/*
|
||||
Appends a string representation of the info into the stream.
|
||||
|
|
|
|||
|
|
@ -172,9 +172,7 @@ namespace sls {
|
|||
return false;
|
||||
if (r > sx.length() && update(x, sx + zstring(random_char())))
|
||||
return false;
|
||||
// This case seems to imply unsat
|
||||
verbose_stream() << "The input might be unsat\n"; // example to trigger: (assert (and (>= (str.len X) 2) (= (str.substr X 0 1) "")))
|
||||
VERIFY(false);
|
||||
// Both updates failed. Treat as unsatisfied and let outer search continue.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -198,8 +196,16 @@ namespace sls {
|
|||
return false;
|
||||
}
|
||||
if (seq.str.is_last_index(e, x, y) && seq.is_string(x->get_sort())) {
|
||||
// TODO
|
||||
NOT_IMPLEMENTED_YET();
|
||||
auto sx = strval0(x);
|
||||
auto sy = strval0(y);
|
||||
rational val_e;
|
||||
if (!a.is_numeral(ctx.get_value(e), val_e))
|
||||
return false;
|
||||
rational actual(sx.last_indexof(sy));
|
||||
if (val_e == actual)
|
||||
continue;
|
||||
update(e, actual);
|
||||
return false;
|
||||
}
|
||||
if (seq.str.is_stoi(e, x) && seq.is_string(x->get_sort())) {
|
||||
auto sx = strval0(x);
|
||||
|
|
@ -753,7 +759,7 @@ namespace sls {
|
|||
for (unsigned j = 1; j <= val_other.length() - i; ++j) {
|
||||
zstring sub = val_other.extract(i, j);
|
||||
if (set.contains(sub))
|
||||
break;
|
||||
continue;
|
||||
set.insert(sub);
|
||||
}
|
||||
}
|
||||
|
|
@ -906,7 +912,7 @@ namespace sls {
|
|||
m_string_updates.reset();
|
||||
u[i][j] = d[i - 1][j];
|
||||
}
|
||||
if (d[i][j - 1] < u[i][j] && b.can_add(i - 1)) {
|
||||
if (d[i][j - 1] < u[i][j] && b.can_add(j - 1)) {
|
||||
m_string_updates.reset();
|
||||
u[i][j] = d[i][j - 1];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,7 +232,9 @@ public:
|
|||
}
|
||||
ctx.validate_check_sat_result(r);
|
||||
}
|
||||
t.collect_statistics(result->m_stats);
|
||||
statistics stats;
|
||||
t.collect_statistics(stats);
|
||||
result->add_statistics(stats);
|
||||
}
|
||||
|
||||
if (ctx.produce_unsat_cores()) {
|
||||
|
|
|
|||
|
|
@ -709,8 +709,8 @@ namespace lp {
|
|||
while (column.size() > 1) {
|
||||
auto& c = column.back();
|
||||
SASSERT(c.var() != last_row_index);
|
||||
m_l_matrix.pivot_row_to_row_given_cell(last_row_index, c, j);
|
||||
m_changed_rows.insert(c.var());
|
||||
m_l_matrix.pivot_row_to_row_given_cell(last_row_index, c, j);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,13 +277,11 @@ pivot_column_tableau(unsigned j, unsigned piv_row_index) {
|
|||
m_A.m_rows[c.var()][c.offset()].offset() = pivot_col_cell_index;
|
||||
}
|
||||
while (column.size() > 1) {
|
||||
auto & c = column.back();
|
||||
auto& c = column.back();
|
||||
SASSERT(c.var() != piv_row_index);
|
||||
if(! m_A.pivot_row_to_row_given_cell(piv_row_index, c, j)) {
|
||||
return false;
|
||||
}
|
||||
if (m_touched_rows!= nullptr)
|
||||
if (m_touched_rows != nullptr)
|
||||
m_touched_rows->insert(c.var());
|
||||
m_A.pivot_row_to_row_given_cell(piv_row_index, c, j);
|
||||
}
|
||||
|
||||
if (m_settings.simplex_strategy() == simplex_strategy_enum::tableau_costs)
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ namespace lp {
|
|||
template void static_matrix<mpq, numeric_pair<mpq> >::set(unsigned int, unsigned int, mpq const&);
|
||||
|
||||
|
||||
template bool static_matrix<mpq, mpq>::pivot_row_to_row_given_cell(unsigned int, column_cell& , unsigned int);
|
||||
template bool static_matrix<mpq, numeric_pair<mpq> >::pivot_row_to_row_given_cell(unsigned int, column_cell&, unsigned int);
|
||||
template void static_matrix<mpq, mpq>::pivot_row_to_row_given_cell(unsigned int, column_cell& , unsigned int);
|
||||
template void static_matrix<mpq, numeric_pair<mpq> >::pivot_row_to_row_given_cell(unsigned int, column_cell&, unsigned int);
|
||||
template void static_matrix<mpq, numeric_pair<mpq> >::pivot_row_to_row_given_cell_with_sign(unsigned int, column_cell&, unsigned int, int);
|
||||
template void static_matrix<mpq, mpq>::pivot_row_to_row_given_cell_with_sign(unsigned int, row_cell<empty_struct>&, unsigned int, int);
|
||||
template void static_matrix<mpq, numeric_pair<mpq> >::add_rows(mpq const&, unsigned int, unsigned int);
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ public:
|
|||
|
||||
|
||||
// pivot row i to row ii
|
||||
bool pivot_row_to_row_given_cell(unsigned i, column_cell& c, unsigned j);
|
||||
void pivot_row_to_row_given_cell(unsigned i, column_cell& c, unsigned j);
|
||||
void pivot_row_to_row_given_cell_with_sign(unsigned piv_row_index, column_cell& c, unsigned j, int j_sign);
|
||||
void transpose_rows(unsigned i, unsigned ii) {
|
||||
auto t = m_rows[i];
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace lp {
|
|||
}
|
||||
|
||||
|
||||
template <typename T, typename X> bool static_matrix<T, X>::pivot_row_to_row_given_cell(unsigned i,
|
||||
template <typename T, typename X> void static_matrix<T, X>::pivot_row_to_row_given_cell(unsigned i,
|
||||
column_cell & c, unsigned pivot_col) {
|
||||
unsigned ii = c.var();
|
||||
SASSERT(i < row_count() && ii < column_count() && i != ii);
|
||||
|
|
@ -82,7 +82,7 @@ namespace lp {
|
|||
if (is_zero(rowii[k].coeff()))
|
||||
remove_element(rowii, rowii[k]);
|
||||
}
|
||||
return !rowii.empty();
|
||||
SASSERT(!rowii.empty());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ namespace spacer {
|
|||
return m_base_defs.is_proxy (a, def);
|
||||
}
|
||||
|
||||
void iuc_solver::collect_statistics (statistics &st) const {
|
||||
void iuc_solver::collect_statistics_core (statistics &st) const {
|
||||
m_solver.collect_statistics (st);
|
||||
st.update ("time.iuc_solver.get_iuc", m_iuc_sw.get_seconds());
|
||||
st.update ("time.iuc_solver.get_iuc.hyp_reduce1", m_hyp_reduce1_sw.get_seconds());
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ public:
|
|||
|
||||
/* check_sat_result interface */
|
||||
|
||||
void collect_statistics(statistics &st) const override ;
|
||||
void collect_statistics_core(statistics &st) const override ;
|
||||
virtual void reset_statistics();
|
||||
|
||||
void get_unsat_core(expr_ref_vector &r) override;
|
||||
|
|
|
|||
|
|
@ -1148,6 +1148,7 @@ class arith_project_util {
|
|||
expr_ref_vector const &lits) {
|
||||
app_ref_vector new_vars(m);
|
||||
expr_ref_vector result(lits);
|
||||
model::scoped_model_completion _smc(mdl, true);
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
app *v = vars.get(i);
|
||||
m_var = alloc(contains_app, m, v);
|
||||
|
|
@ -1183,6 +1184,12 @@ class arith_project_util {
|
|||
expr_map &map) {
|
||||
app_ref_vector new_vars(m);
|
||||
|
||||
// Variables to be projected may not be assigned in the model
|
||||
// (e.g. grounded auxiliary variables that are don't-cares). Enable
|
||||
// model completion so their evaluation yields concrete numerals,
|
||||
// matching the behavior of the native MBP arith projector.
|
||||
model::scoped_model_completion _smc(mdl, true);
|
||||
|
||||
// factor out mod terms by introducing new variables
|
||||
TRACE(qe, tout << "before factoring out mod terms:" << "\n";
|
||||
tout << mk_pp(fml, m) << "\n"; tout << "mdl:\n";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
z3_add_component(opt
|
||||
z3_add_component(z3_opt
|
||||
SOURCES
|
||||
maxcore.cpp
|
||||
maxlex.cpp
|
||||
|
|
|
|||
|
|
@ -1745,7 +1745,7 @@ namespace opt {
|
|||
m_pareto1 = p != nullptr;
|
||||
}
|
||||
|
||||
void context::collect_statistics(statistics& stats) const {
|
||||
void context::collect_statistics_core(statistics& stats) const {
|
||||
if (m_solver)
|
||||
m_solver->collect_statistics(stats);
|
||||
if (m_simplify)
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ namespace opt {
|
|||
void get_model_core(model_ref& _m) override;
|
||||
void get_box_model(model_ref& _m, unsigned index) override;
|
||||
void fix_model(model_ref& _m) override;
|
||||
void collect_statistics(statistics& stats) const override;
|
||||
void collect_statistics_core(statistics& stats) const override;
|
||||
proof* get_proof_core() override { return nullptr; }
|
||||
void get_labels(svector<symbol> & r) override;
|
||||
void get_unsat_core(expr_ref_vector & r) override;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ namespace opt {
|
|||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
m_solver->collect_param_descrs(r);
|
||||
}
|
||||
virtual void collect_statistics(statistics & st) const {
|
||||
virtual void collect_statistics_core(statistics & st) const {
|
||||
m_solver->collect_statistics(st);
|
||||
if (m_bvsls) m_bvsls->collect_statistics(st);
|
||||
if (m_pbsls) m_pbsls->collect_statistics(st);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace opt {
|
|||
m_context.collect_param_descrs(r);
|
||||
}
|
||||
|
||||
void opt_solver::collect_statistics(statistics & st) const {
|
||||
void opt_solver::collect_statistics_core(statistics & st) const {
|
||||
m_context.collect_statistics(st);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ namespace opt {
|
|||
solver* translate(ast_manager& m, params_ref const& p) override;
|
||||
void updt_params(params_ref const& p) override;
|
||||
void collect_param_descrs(param_descrs & r) override;
|
||||
void collect_statistics(statistics & st) const override;
|
||||
void collect_statistics_core(statistics & st) const override;
|
||||
void assert_expr_core(expr * t) override;
|
||||
void push_core() override;
|
||||
void pop_core(unsigned n) override;
|
||||
|
|
|
|||
|
|
@ -166,15 +166,14 @@ struct mbp_dt_tg::impl {
|
|||
// Only apply rm_accessor if the model confirms the argument
|
||||
// has the constructor that this accessor belongs to.
|
||||
// Otherwise we introduce a contradictory is-cons literal.
|
||||
func_decl *cons =
|
||||
func_decl *acc_cons =
|
||||
m_dt_util.get_accessor_constructor(to_app(term)->get_decl());
|
||||
func_decl *rec = m_dt_util.get_constructor_recognizer(cons);
|
||||
func_decl *rec = m_dt_util.get_constructor_recognizer(acc_cons);
|
||||
expr_ref is_rec(m.mk_app(rec, to_app(term)->get_arg(0)), m);
|
||||
if (!m_mdl.is_true(is_rec)) {
|
||||
// Ground the argument so the accessor term becomes
|
||||
// constructively ground. This preserves any enclosing
|
||||
// literal (e.g., (not (is-nil (tl nil)))) as a guard in
|
||||
// the output, preventing an over-approximation.
|
||||
// The accessor's argument does not have the expected constructor in the model.
|
||||
// Add a guard literal and skip rm_accessor so we don't force a contradictory
|
||||
// constructor constraint on the argument.
|
||||
expr_ref is(m.mk_not(is_rec), m);
|
||||
m_tg.add_lit(is);
|
||||
mark_seen(term);
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ public:
|
|||
if (p1.euf() && !get_euf())
|
||||
ensure_euf();
|
||||
}
|
||||
void collect_statistics(statistics & st) const override {
|
||||
void collect_statistics_core(statistics & st) const override {
|
||||
if (m_preprocess) m_preprocess->collect_statistics(st);
|
||||
m_solver.collect_statistics(st);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ public:
|
|||
ensure_euf();
|
||||
}
|
||||
|
||||
void collect_statistics(statistics & st) const override {
|
||||
void collect_statistics_core(statistics & st) const override {
|
||||
m_solver.collect_statistics(st);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ set (shell_object_files "")
|
|||
|
||||
# We are only using these dependencies to enforce a build
|
||||
# order. We don't use this list for actual linking.
|
||||
set(shell_deps api extra_cmds opt sat)
|
||||
set(shell_deps api extra_cmds z3_opt sat)
|
||||
z3_expand_dependencies(shell_expanded_deps ${shell_deps})
|
||||
get_property(Z3_LIBZ3_COMPONENTS_LIST GLOBAL PROPERTY Z3_LIBZ3_COMPONENTS)
|
||||
foreach (component ${Z3_LIBZ3_COMPONENTS_LIST})
|
||||
|
|
|
|||
|
|
@ -104,9 +104,7 @@ namespace smt {
|
|||
return true;
|
||||
for (unsigned i = 0; i < num_args; ++i)
|
||||
d->m_args[i] = d->m_args[i]->get_root();
|
||||
if (m_set.contains(d))
|
||||
return true;
|
||||
return false;
|
||||
return m_set.contains(d);
|
||||
}
|
||||
|
||||
void fingerprint_set::reset() {
|
||||
|
|
|
|||
|
|
@ -1881,8 +1881,10 @@ namespace {
|
|||
m_pool.recycle(v);
|
||||
}
|
||||
|
||||
void update_max_generation(enode * n, enode * prev) {
|
||||
m_max_generation = std::max(m_max_generation, n->get_generation());
|
||||
void update_max_generation(enode * n, enode * prev, enode * min_gen_match=nullptr) {
|
||||
unsigned new_gen = min_gen_match ? min_gen_match->get_generation() : n->get_generation();
|
||||
|
||||
m_max_generation = std::max(m_max_generation, new_gen);
|
||||
|
||||
if (m.has_trace_stream() || is_trace_enabled(TraceTag::causality))
|
||||
m_used_enodes.push_back(std::make_tuple(prev, n));
|
||||
|
|
@ -1910,15 +1912,18 @@ namespace {
|
|||
}
|
||||
while (curr != first);
|
||||
if (matching_cgr)
|
||||
update_max_generation(min_gen_match, first);
|
||||
update_max_generation(matching_cgr, first, min_gen_match);
|
||||
return matching_cgr;
|
||||
}
|
||||
|
||||
enode * get_next_f_app(func_decl * lbl, unsigned num_expected_args, enode * first, enode * curr) {
|
||||
curr = curr->get_next();
|
||||
while (curr != first) {
|
||||
if (curr->get_decl() == lbl && curr->get_num_args() == num_expected_args && curr->is_cgr())
|
||||
if (curr->get_decl() == lbl && curr->get_num_args() == num_expected_args && curr->is_cgr()) {
|
||||
if (m.has_trace_stream() || is_trace_enabled(TraceTag::causality))
|
||||
m_used_enodes.push_back(std::make_tuple(first, curr));
|
||||
return curr;
|
||||
}
|
||||
curr = curr->get_next();
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -258,7 +258,6 @@ namespace smt {
|
|||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i)
|
||||
names.push_back(symbol(i));
|
||||
defined_names dn(m);
|
||||
body = replace_value_from_ctx(body);
|
||||
body = m.mk_lambda(sorts.size(), sorts.data(), names.data(), body);
|
||||
sk_term = body;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ Revision History:
|
|||
#include "util/obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "params/qi_params.h"
|
||||
#include "params/smt_params.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ namespace {
|
|||
insert_ctrl_c(r);
|
||||
}
|
||||
|
||||
void collect_statistics(statistics & st) const override {
|
||||
void collect_statistics_core(statistics & st) const override {
|
||||
m_context.collect_statistics(st);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -494,6 +494,31 @@ namespace smt {
|
|||
else if (is_app(n) && to_app(n)->get_family_id() == get_family_id()) {
|
||||
// These are the conversion functions fp.to_* */
|
||||
SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n));
|
||||
|
||||
// The conversion equality and side conditions for fp.to_* terms are
|
||||
// emitted in internalize_term(), which runs exactly once. Those are
|
||||
// asserted as theory axioms at the current decision level and are
|
||||
// undone on DPLL backtracking, while internalize_term() is not run
|
||||
// again for the already-internalized term (e.g. when the term lives
|
||||
// at the user push base level and its clause is not reinitialized).
|
||||
// The side conditions include the axioms linking FP uninterpreted
|
||||
// functions to their bit-vector counterparts; losing them leaves the
|
||||
// BV counterpart unconstrained and causes an incremental-mode
|
||||
// soundness bug. relevant_eh re-fires on relevancy re-propagation
|
||||
// after a backtrack, so re-emit them here to keep them in force.
|
||||
switch ((fpa_op_kind)to_app(n)->get_decl_kind()) {
|
||||
case OP_FPA_TO_FP:
|
||||
case OP_FPA_TO_UBV:
|
||||
case OP_FPA_TO_SBV:
|
||||
case OP_FPA_TO_REAL:
|
||||
case OP_FPA_TO_IEEE_BV: {
|
||||
expr_ref conv = convert(n);
|
||||
assert_cnstr(m.mk_eq(n, conv));
|
||||
assert_cnstr(mk_side_conditions());
|
||||
break;
|
||||
}
|
||||
default: /* ignore */;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Theory variables can be merged when (= bv-term (bvwrap fp-term)),
|
||||
|
|
|
|||
|
|
@ -70,9 +70,6 @@ simple_check_sat_result::simple_check_sat_result(ast_manager & m):
|
|||
m_proof(m) {
|
||||
}
|
||||
|
||||
void simple_check_sat_result::collect_statistics(statistics & st) const {
|
||||
st.copy(m_stats);
|
||||
}
|
||||
|
||||
void simple_check_sat_result::get_unsat_core(expr_ref_vector & r) {
|
||||
if (m_status == l_false) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ protected:
|
|||
lbool m_status = l_undef;
|
||||
model_converter_ref m_mc0;
|
||||
double m_time = 0;
|
||||
statistics m_stats;
|
||||
|
||||
public:
|
||||
check_sat_result(ast_manager& m): m(m), m_log(m), m_proof(m) {}
|
||||
virtual ~check_sat_result() = default;
|
||||
|
|
@ -53,7 +55,18 @@ public:
|
|||
void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; if (m_ref_count == 0) dealloc(this); }
|
||||
lbool set_status(lbool r) { return m_status = r; }
|
||||
lbool status() const { return m_status; }
|
||||
virtual void collect_statistics(statistics & st) const = 0;
|
||||
void collect_statistics(statistics &st) const {
|
||||
collect_statistics_core(st);
|
||||
st.copy(m_stats);
|
||||
}
|
||||
void add_statistics(statistics const &st) {
|
||||
m_stats.copy(st);
|
||||
}
|
||||
void reset_statistics() {
|
||||
m_stats.reset();
|
||||
}
|
||||
|
||||
virtual void collect_statistics_core(statistics &st) const = 0;
|
||||
virtual void get_unsat_core(expr_ref_vector & r) = 0;
|
||||
void set_model_converter(model_converter* mc) { m_mc0 = mc; }
|
||||
model_converter* mc0() const { return m_mc0.get(); }
|
||||
|
|
@ -92,7 +105,6 @@ public:
|
|||
\brief Very simple implementation of the check_sat_result object.
|
||||
*/
|
||||
struct simple_check_sat_result : public check_sat_result {
|
||||
statistics m_stats;
|
||||
model_ref m_model;
|
||||
expr_ref_vector m_core;
|
||||
proof_ref m_proof;
|
||||
|
|
@ -100,9 +112,9 @@ struct simple_check_sat_result : public check_sat_result {
|
|||
|
||||
simple_check_sat_result(ast_manager & m);
|
||||
ast_manager& get_manager() const override { return m_proof.get_manager(); }
|
||||
void collect_statistics(statistics & st) const override;
|
||||
void get_unsat_core(expr_ref_vector & r) override;
|
||||
void get_model_core(model_ref & m) override;
|
||||
void collect_statistics_core(statistics &st) const override {}
|
||||
proof * get_proof_core() override;
|
||||
std::string reason_unknown() const override;
|
||||
void get_labels(svector<symbol> & r) override;
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ public:
|
|||
return m_solver1->display(out, n, es);
|
||||
}
|
||||
|
||||
void collect_statistics(statistics & st) const override {
|
||||
void collect_statistics_core(statistics & st) const override {
|
||||
m_solver2->collect_statistics(st);
|
||||
if (m_use_solver1_results)
|
||||
m_solver1->collect_statistics(st);
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ public:
|
|||
return s->check_sat_core(num_assumptions, _assumptions.data());
|
||||
}
|
||||
|
||||
void collect_statistics(statistics& st) const override {
|
||||
void collect_statistics_core(statistics& st) const override {
|
||||
s->collect_statistics(st);
|
||||
m_preprocess.collect_statistics(st);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ public:
|
|||
return s->check_sat_core(num_assumptions, assumptions);
|
||||
}
|
||||
|
||||
void collect_statistics(statistics& st) const override { s->collect_statistics(st); }
|
||||
void collect_statistics_core(statistics& st) const override { s->collect_statistics(st); }
|
||||
|
||||
void get_model_core(model_ref& mdl) override { s->get_model_core(mdl); }
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public:
|
|||
void pop_params() override {m_base->pop_params();}
|
||||
|
||||
void collect_param_descrs(param_descrs & r) override { m_base->collect_param_descrs(r); }
|
||||
void collect_statistics(statistics & st) const override { m_base->collect_statistics(st); }
|
||||
void collect_statistics_core(statistics & st) const override { m_base->collect_statistics(st); }
|
||||
unsigned get_num_assertions() const override { return m_base->get_num_assertions(); }
|
||||
expr * get_assertion(unsigned idx) const override { return m_base->get_assertion(idx); }
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class tactic2solver : public solver_na2as {
|
|||
bool m_produce_models;
|
||||
bool m_produce_proofs;
|
||||
bool m_produce_unsat_cores;
|
||||
statistics m_stats;
|
||||
// statistics m_stats;
|
||||
bool m_minimizing = false;
|
||||
|
||||
public:
|
||||
|
|
@ -70,7 +70,7 @@ public:
|
|||
void pop_core(unsigned n) override;
|
||||
lbool check_sat_core2(unsigned num_assumptions, expr * const * assumptions) override;
|
||||
|
||||
void collect_statistics(statistics & st) const override;
|
||||
void collect_statistics_core(statistics & st) const override;
|
||||
void get_unsat_core(expr_ref_vector & r) override;
|
||||
void get_model_core(model_ref & m) override;
|
||||
proof * get_proof_core() override;
|
||||
|
|
@ -284,8 +284,9 @@ lbool tactic2solver::check_sat_core2(unsigned num_assumptions, expr * const * as
|
|||
m_result->m_unknown = ex.what();
|
||||
m_result->m_proof = pr;
|
||||
}
|
||||
m_tactic->collect_statistics(m_result->m_stats);
|
||||
m_tactic->collect_statistics(m_stats);
|
||||
statistics stats;
|
||||
m_tactic->collect_statistics(stats);
|
||||
m_result->add_statistics(stats);
|
||||
m_result->m_model = md;
|
||||
m_result->m_proof = pr;
|
||||
if (m_produce_unsat_cores) {
|
||||
|
|
@ -311,7 +312,7 @@ solver* tactic2solver::translate(ast_manager& m, params_ref const& p) {
|
|||
}
|
||||
|
||||
|
||||
void tactic2solver::collect_statistics(statistics & st) const {
|
||||
void tactic2solver::collect_statistics_core(statistics & st) const {
|
||||
st.copy(m_stats);
|
||||
if (m_stats.size() == 0 && m_tactic)
|
||||
m_tactic->collect_statistics(st);
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ public:
|
|||
void collect_param_descrs(param_descrs & r) override { m_solver->collect_param_descrs(r); }
|
||||
void set_produce_models(bool f) override { m_solver->set_produce_models(f); }
|
||||
void set_progress_callback(progress_callback * callback) override { m_solver->set_progress_callback(callback); }
|
||||
void collect_statistics(statistics & st) const override { m_solver->collect_statistics(st); }
|
||||
void collect_statistics_core(statistics & st) const override { m_solver->collect_statistics(st); }
|
||||
void get_unsat_core(expr_ref_vector & r) override { m_solver->get_unsat_core(r); }
|
||||
void set_phase(expr* e) override { m_solver->set_phase(e); }
|
||||
phase* get_phase() override { return m_solver->get_phase(); }
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public:
|
|||
void collect_param_descrs(param_descrs & r) override { m_solver->collect_param_descrs(r); }
|
||||
void set_produce_models(bool f) override { m_solver->set_produce_models(f); }
|
||||
void set_progress_callback(progress_callback * callback) override { m_solver->set_progress_callback(callback); }
|
||||
void collect_statistics(statistics & st) const override { m_solver->collect_statistics(st); }
|
||||
void collect_statistics_core(statistics & st) const override { m_solver->collect_statistics(st); }
|
||||
void get_unsat_core(expr_ref_vector & r) override { m_solver->get_unsat_core(r); }
|
||||
void set_phase(expr* e) override { m_solver->set_phase(e); }
|
||||
phase* get_phase() override { return m_solver->get_phase(); }
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public:
|
|||
void collect_param_descrs(param_descrs & r) override { m_solver->collect_param_descrs(r); m_rewriter.collect_param_descrs(r);}
|
||||
void set_produce_models(bool f) override { m_solver->set_produce_models(f); }
|
||||
void set_progress_callback(progress_callback * callback) override { m_solver->set_progress_callback(callback); }
|
||||
void collect_statistics(statistics & st) const override {
|
||||
void collect_statistics_core(statistics & st) const override {
|
||||
m_rewriter.collect_statistics(st);
|
||||
m_solver->collect_statistics(st);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2032,7 +2032,7 @@ namespace smtfd {
|
|||
|
||||
void set_produce_models(bool f) override { }
|
||||
void set_progress_callback(progress_callback * callback) override { }
|
||||
void collect_statistics(statistics & st) const override {
|
||||
void collect_statistics_core(statistics & st) const override {
|
||||
if (m_fd_sat_solver) {
|
||||
m_fd_sat_solver->collect_statistics(st);
|
||||
m_fd_core_solver->collect_statistics(st);
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ static void test_dt_multiple_vars() {
|
|||
|
||||
VERIFY(!m.is_false(projected));
|
||||
VERIFY(mdl->is_true(projected));
|
||||
VERIFY(vars.empty());
|
||||
|
||||
std::cout << " PASS\n\n";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -351,4 +351,28 @@ void tst_sls_seq_plugin() {
|
|||
app_ref eq(m.mk_eq(l, r), m);
|
||||
verbose_stream() << eq << "\n";
|
||||
ts.repair_down_str_eq_edit_distance_incremental(eq);
|
||||
|
||||
test_seq::string_instance lhs, rhs;
|
||||
lhs.s = zstring("a");
|
||||
lhs.is_value.push_back(false);
|
||||
lhs.prev_is_var.push_back(false);
|
||||
lhs.next_is_var.push_back(false);
|
||||
rhs.s = zstring("ab");
|
||||
rhs.is_value.push_back(true);
|
||||
rhs.prev_is_var.push_back(false);
|
||||
rhs.next_is_var.push_back(false);
|
||||
rhs.is_value.push_back(false);
|
||||
rhs.prev_is_var.push_back(false);
|
||||
rhs.next_is_var.push_back(false);
|
||||
|
||||
ENSURE(ts.edit_distance_with_updates(lhs, rhs) == 0);
|
||||
ENSURE(ts.m_string_updates.size() == 2);
|
||||
ENSURE(ts.m_string_updates[0].side == test_seq::side_t::right);
|
||||
ENSURE(ts.m_string_updates[0].op == test_seq::op_t::add);
|
||||
ENSURE(ts.m_string_updates[0].i == 0);
|
||||
ENSURE(ts.m_string_updates[0].j == 1);
|
||||
ENSURE(ts.m_string_updates[1].side == test_seq::side_t::right);
|
||||
ENSURE(ts.m_string_updates[1].op == test_seq::op_t::del);
|
||||
ENSURE(ts.m_string_updates[1].i == 1);
|
||||
ENSURE(ts.m_string_updates[1].j == 0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue