3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-03-09 22:45:52 +01:00
commit 05c5b3b07b
26 changed files with 331 additions and 125 deletions

View file

@ -112,6 +112,13 @@ else()
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${available_build_types}) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${available_build_types})
endif() endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
# Check the selected build type is valid
list(FIND available_build_types "${CMAKE_BUILD_TYPE}" _build_type_index)
if ("${_build_type_index}" EQUAL "-1")
message(FATAL_ERROR "\"${CMAKE_BUILD_TYPE}\" is an invalid build type.\n"
"Use one of the following build types ${available_build_types}")
endif()
endif() endif()
# CMAKE_BUILD_TYPE has no meaning for multi-configuration generators # CMAKE_BUILD_TYPE has no meaning for multi-configuration generators

View file

@ -168,7 +168,10 @@ python scripts/mk_make.py --prefix=/home/leo --python --pypkgdir=/home/leo/lib/p
If you do need to install to a non standard prefix a better approach is to use If you do need to install to a non standard prefix a better approach is to use
a [Python virtual environment](https://virtualenv.readthedocs.org/en/latest/) a [Python virtual environment](https://virtualenv.readthedocs.org/en/latest/)
and install Z3 there. and install Z3 there. Python packages also work for Python3.
Under Windows, recall to build inside the Visual C++ native command build environment.
Note that the buit/python/z3 directory should be accessible from where python is used with Z3
and it depends on libz3.dll to be in the path.
```bash ```bash
virtualenv venv virtualenv venv
@ -185,3 +188,4 @@ python -c 'import z3; print(z3.get_version_string())'
``` ```
See [``examples/python``](examples/python) for examples. See [``examples/python``](examples/python) for examples.

View file

@ -12,10 +12,6 @@ import shutil
ML_ENABLED=False ML_ENABLED=False
BUILD_DIR='../build' BUILD_DIR='../build'
def norm_path(p):
# We use '/' on mk_project for convenience
return os.path.join(*(p.split('/')))
def display_help(exit_code): def display_help(exit_code):
print("mk_api_doc.py: Z3 documentation generator\n") print("mk_api_doc.py: Z3 documentation generator\n")
print("\nOptions:") print("\nOptions:")
@ -36,7 +32,7 @@ def parse_options():
for opt, arg in options: for opt, arg in options:
if opt in ('-b', '--build'): if opt in ('-b', '--build'):
BUILD_DIR = norm_path(arg) BUILD_DIR = mk_util.norm_path(arg)
elif opt in ('h', '--help'): elif opt in ('h', '--help'):
display_help() display_help()
exit(1) exit(1)

View file

@ -42,7 +42,7 @@ def mk_dir(d):
def set_build_dir(path): def set_build_dir(path):
global BUILD_DIR global BUILD_DIR
BUILD_DIR = path BUILD_DIR = mk_util.norm_path(path)
mk_dir(BUILD_DIR) mk_dir(BUILD_DIR)
def display_help(): def display_help():

View file

@ -153,8 +153,7 @@ def is_cygwin_mingw():
return IS_CYGWIN_MINGW return IS_CYGWIN_MINGW
def norm_path(p): def norm_path(p):
# We use '/' on mk_project for convenience return os.path.expanduser(os.path.normpath(p))
return os.path.join(*(p.split('/')))
def which(program): def which(program):
import os import os

View file

@ -46,7 +46,7 @@ def mk_dir(d):
def set_build_dir(path): def set_build_dir(path):
global BUILD_DIR, BUILD_X86_DIR, BUILD_X64_DIR global BUILD_DIR, BUILD_X86_DIR, BUILD_X64_DIR
BUILD_DIR = path BUILD_DIR = mk_util.norm_path(path)
BUILD_X86_DIR = os.path.join(path, 'x86') BUILD_X86_DIR = os.path.join(path, 'x86')
BUILD_X64_DIR = os.path.join(path, 'x64') BUILD_X64_DIR = os.path.join(path, 'x64')
mk_dir(BUILD_X86_DIR) mk_dir(BUILD_X86_DIR)

View file

@ -710,6 +710,9 @@ def mk_java(java_dir, package_name):
java_wrapper.write(' }\n') java_wrapper.write(' }\n')
elif k == OUT_MANAGED_ARRAY: elif k == OUT_MANAGED_ARRAY:
java_wrapper.write(' *(jlong**)a%s = (jlong*)_a%s;\n' % (i, i)) java_wrapper.write(' *(jlong**)a%s = (jlong*)_a%s;\n' % (i, i))
elif k == IN and param_type(param) == STRING:
java_wrapper.write(' jenv->ReleaseStringUTFChars(a%s, _a%s);\n' % (i, i));
i = i + 1 i = i + 1
# return # return
if result == STRING: if result == STRING:

View file

@ -14,7 +14,6 @@ Author:
Nikolaj Bjorner (nbjorner) 2015-07-16 Nikolaj Bjorner (nbjorner) 2015-07-16
Notes: Notes:
**/ **/
package com.microsoft.z3; package com.microsoft.z3;
@ -23,10 +22,10 @@ import com.microsoft.z3.enumerations.Z3_lbool;
/** /**
* Object for managing optimizization context * Object for managing optimization context
**/ **/
public class Optimize extends Z3Object public class Optimize extends Z3Object {
{
/** /**
* A string that describes all available optimize solver parameters. * A string that describes all available optimize solver parameters.
**/ **/
@ -70,51 +69,75 @@ public class Optimize extends Z3Object
**/ **/
public void Add(BoolExpr ... constraints) public void Add(BoolExpr ... constraints)
{ {
Assert(constraints); Assert(constraints);
} }
/** /**
* Handle to objectives returned by objective functions. * Handle to objectives returned by objective functions.
**/ **/
public class Handle public static class Handle {
{
Optimize opt;
int handle;
Handle(Optimize opt, int h)
{
this.opt = opt;
this.handle = h;
}
/** private final Optimize opt;
* Retrieve a lower bound for the objective handle. private final int handle;
**/
public ArithExpr getLower()
{
return opt.GetLower(handle);
}
/** Handle(Optimize opt, int h)
* Retrieve an upper bound for the objective handle. {
**/ this.opt = opt;
public ArithExpr getUpper() this.handle = h;
{ }
return opt.GetUpper(handle);
}
/** /**
* Retrieve the value of an objective. * Retrieve a lower bound for the objective handle.
**/ **/
public ArithExpr getValue() public ArithExpr getLower()
{ {
return getLower(); return opt.GetLower(handle);
} }
/** /**
* Print a string representation of the handle. * Retrieve an upper bound for the objective handle.
**/ **/
@Override public ArithExpr getUpper()
public String toString() {
return opt.GetUpper(handle);
}
/**
* @return a triple representing the upper bound of the objective handle.
*
* The triple contains values {@code inf, value, eps},
* where the objective value is unbounded iff {@code inf} is non-zero,
* and otherwise is represented by the expression {@code value + eps * EPSILON},
* where {@code EPSILON} is an arbitrarily small real number.
*/
public ArithExpr[] getUpperAsVector()
{
return opt.GetUpperAsVector(handle);
}
/**
* @return a triple representing the upper bound of the objective handle.
*
* <p>See {@link #getUpperAsVector()} for triple semantics.
*/
public ArithExpr[] getLowerAsVector()
{
return opt.GetLowerAsVector(handle);
}
/**
* Retrieve the value of an objective.
**/
public ArithExpr getValue()
{
return getLower();
}
/**
* Print a string representation of the handle.
**/
@Override
public String toString()
{ {
return getValue().toString(); return getValue().toString();
} }
@ -126,7 +149,6 @@ public class Optimize extends Z3Object
* Return an objective which associates with the group of constraints. * Return an objective which associates with the group of constraints.
* *
**/ **/
public Handle AssertSoft(BoolExpr constraint, int weight, String group) public Handle AssertSoft(BoolExpr constraint, int weight, String group)
{ {
getContext().checkContextMatch(constraint); getContext().checkContextMatch(constraint);
@ -134,13 +156,11 @@ public class Optimize extends Z3Object
return new Handle(this, Native.optimizeAssertSoft(getContext().nCtx(), getNativeObject(), constraint.getNativeObject(), Integer.toString(weight), s.getNativeObject())); return new Handle(this, Native.optimizeAssertSoft(getContext().nCtx(), getNativeObject(), constraint.getNativeObject(), Integer.toString(weight), s.getNativeObject()));
} }
/** /**
* Check satisfiability of asserted constraints. * Check satisfiability of asserted constraints.
* Produce a model that (when the objectives are bounded and * Produce a model that (when the objectives are bounded and
* don't use strict inequalities) meets the objectives. * don't use strict inequalities) meets the objectives.
**/ **/
public Status Check() public Status Check()
{ {
Z3_lbool r = Z3_lbool.fromInt(Native.optimizeCheck(getContext().nCtx(), getNativeObject())); Z3_lbool r = Z3_lbool.fromInt(Native.optimizeCheck(getContext().nCtx(), getNativeObject()));
@ -162,13 +182,11 @@ public class Optimize extends Z3Object
Native.optimizePush(getContext().nCtx(), getNativeObject()); Native.optimizePush(getContext().nCtx(), getNativeObject());
} }
/** /**
* Backtrack one backtracking point. * Backtrack one backtracking point.
* *
* Note that an exception is thrown if Pop is called without a corresponding Push. * Note that an exception is thrown if Pop is called without a corresponding Push.
**/ **/
public void Pop() public void Pop()
{ {
Native.optimizePop(getContext().nCtx(), getNativeObject()); Native.optimizePop(getContext().nCtx(), getNativeObject());
@ -218,7 +236,6 @@ public class Optimize extends Z3Object
return (ArithExpr)Expr.create(getContext(), Native.optimizeGetLower(getContext().nCtx(), getNativeObject(), index)); return (ArithExpr)Expr.create(getContext(), Native.optimizeGetLower(getContext().nCtx(), getNativeObject(), index));
} }
/** /**
* Retrieve an upper bound for the objective handle. * Retrieve an upper bound for the objective handle.
**/ **/
@ -227,6 +244,42 @@ public class Optimize extends Z3Object
return (ArithExpr)Expr.create(getContext(), Native.optimizeGetUpper(getContext().nCtx(), getNativeObject(), index)); return (ArithExpr)Expr.create(getContext(), Native.optimizeGetUpper(getContext().nCtx(), getNativeObject(), index));
} }
/**
* @return Triple representing the upper bound for the objective handle.
*
* <p>See {@link Handle#getUpperAsVector}.
*/
private ArithExpr[] GetUpperAsVector(int index) {
return unpackObjectiveValueVector(
Native.optimizeGetUpperAsVector(
getContext().nCtx(), getNativeObject(), index
)
);
}
/**
* @return Triple representing the upper bound for the objective handle.
*
* <p>See {@link Handle#getLowerAsVector}.
*/
private ArithExpr[] GetLowerAsVector(int index) {
return unpackObjectiveValueVector(
Native.optimizeGetLowerAsVector(
getContext().nCtx(), getNativeObject(), index
)
);
}
private ArithExpr[] unpackObjectiveValueVector(long nativeVec) {
ASTVector vec = new ASTVector(
getContext(), nativeVec
);
return new ArithExpr[] {
(ArithExpr) vec.get(0), (ArithExpr) vec.get(1), (ArithExpr) vec.get(2)
};
}
/** /**
* Return a string the describes why the last to check returned unknown * Return a string the describes why the last to check returned unknown
**/ **/
@ -236,7 +289,6 @@ public class Optimize extends Z3Object
getNativeObject()); getNativeObject());
} }
/** /**
* Print the context to a String (SMT-LIB parseable benchmark). * Print the context to a String (SMT-LIB parseable benchmark).
**/ **/

View file

@ -915,7 +915,7 @@ void fpa_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol cons
op_names.push_back(builtin_name("to_fp_unsigned", OP_FPA_TO_FP_UNSIGNED)); op_names.push_back(builtin_name("to_fp_unsigned", OP_FPA_TO_FP_UNSIGNED));
/* Extensions */ /* Extensions */
op_names.push_back(builtin_name("to_ieee_bv", OP_FPA_TO_IEEE_BV)); op_names.push_back(builtin_name("to_ieee_bv", OP_FPA_TO_IEEE_BV));
op_names.push_back(builtin_name("fp.to_ieee_bv", OP_FPA_TO_IEEE_BV)); op_names.push_back(builtin_name("fp.to_ieee_bv", OP_FPA_TO_IEEE_BV));
} }

View file

@ -184,9 +184,20 @@ void rewriter_tpl<Config>::process_app(app * t, frame & fr) {
unsigned num_args = t->get_num_args(); unsigned num_args = t->get_num_args();
while (fr.m_i < num_args) { while (fr.m_i < num_args) {
expr * arg = t->get_arg(fr.m_i); expr * arg = t->get_arg(fr.m_i);
if (fr.m_i >= 1 && m().is_ite(t) && !ProofGen) {
expr * cond = result_stack()[fr.m_spos].get();
if (m().is_true(cond)) {
arg = t->get_arg(1);
}
else if (m().is_false(cond)) {
arg = t->get_arg(2);
}
}
fr.m_i++; fr.m_i++;
if (!visit<ProofGen>(arg, fr.m_max_depth)) if (!visit<ProofGen>(arg, fr.m_max_depth))
return; return;
} }
func_decl * f = t->get_decl(); func_decl * f = t->get_decl();

View file

@ -284,8 +284,54 @@ zstring zstring::operator+(zstring const& other) const {
return result; return result;
} }
std::ostream& zstring::operator<<(std::ostream& out) const { bool zstring::operator==(const zstring& other) const {
return out << encode(); // two strings are equal iff they have the same length and characters
if (length() != other.length()) {
return false;
}
for (unsigned i = 0; i < length(); ++i) {
unsigned Xi = m_buffer[i];
unsigned Yi = other[i];
if (Xi != Yi) {
return false;
}
}
return true;
}
bool zstring::operator!=(const zstring& other) const {
return !(*this == other);
}
std::ostream& operator<<(std::ostream &os, const zstring &str) {
return os << str.encode();
}
bool operator<(const zstring& lhs, const zstring& rhs) {
// This has the same semantics as strcmp()
unsigned len = lhs.length();
if (rhs.length() < len) {
len = rhs.length();
}
for (unsigned i = 0; i < len; ++i) {
unsigned Li = lhs[i];
unsigned Ri = rhs[i];
if (Li < Ri) {
return true;
} else if (Li > Ri) {
return false;
} else {
continue;
}
}
// at this point, all compared characters are equal,
// so decide based on the relative lengths
if (lhs.length() < rhs.length()) {
return true;
} else {
return false;
}
} }
@ -473,6 +519,7 @@ void seq_decl_plugin::init() {
sort* str2TintT[3] = { strT, strT, intT }; sort* str2TintT[3] = { strT, strT, intT };
sort* seqAintT[2] = { seqA, intT }; sort* seqAintT[2] = { seqA, intT };
sort* seq3A[3] = { seqA, seqA, seqA }; sort* seq3A[3] = { seqA, seqA, seqA };
sort* reTintT[2] = { reT, intT };
m_sigs.resize(LAST_SEQ_OP); m_sigs.resize(LAST_SEQ_OP);
// TBD: have (par ..) construct and load parameterized signature from premable. // TBD: have (par ..) construct and load parameterized signature from premable.
m_sigs[OP_SEQ_UNIT] = alloc(psig, m, "seq.unit", 1, 1, &A, seqA); m_sigs[OP_SEQ_UNIT] = alloc(psig, m, "seq.unit", 1, 1, &A, seqA);
@ -516,6 +563,7 @@ void seq_decl_plugin::init() {
m_sigs[_OP_REGEXP_EMPTY] = alloc(psig, m, "re.nostr", 0, 0, 0, reT); m_sigs[_OP_REGEXP_EMPTY] = alloc(psig, m, "re.nostr", 0, 0, 0, reT);
m_sigs[_OP_REGEXP_FULL] = alloc(psig, m, "re.allchar", 0, 0, 0, reT); m_sigs[_OP_REGEXP_FULL] = alloc(psig, m, "re.allchar", 0, 0, 0, reT);
m_sigs[_OP_STRING_SUBSTR] = alloc(psig, m, "str.substr", 0, 3, strTint2T, strT); m_sigs[_OP_STRING_SUBSTR] = alloc(psig, m, "str.substr", 0, 3, strTint2T, strT);
m_sigs[_OP_RE_UNROLL] = alloc(psig, m, "_re.unroll", 0, 2, reTintT, strT);
} }
void seq_decl_plugin::set_manager(ast_manager* m, family_id id) { void seq_decl_plugin::set_manager(ast_manager* m, family_id id) {
@ -672,6 +720,9 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
m.raise_exception("Incorrect number of arguments passed to loop. Expected 1 regular expression and two integer parameters"); m.raise_exception("Incorrect number of arguments passed to loop. Expected 1 regular expression and two integer parameters");
} }
case _OP_RE_UNROLL:
match(*m_sigs[k], arity, domain, range, rng);
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
case OP_STRING_CONST: case OP_STRING_CONST:
if (!(num_parameters == 1 && arity == 0 && parameters[0].is_symbol())) { if (!(num_parameters == 1 && arity == 0 && parameters[0].is_symbol())) {

View file

@ -79,6 +79,7 @@ enum seq_op_kind {
_OP_REGEXP_EMPTY, _OP_REGEXP_EMPTY,
_OP_REGEXP_FULL, _OP_REGEXP_FULL,
_OP_SEQ_SKOLEM, _OP_SEQ_SKOLEM,
_OP_RE_UNROLL,
LAST_SEQ_OP LAST_SEQ_OP
}; };
@ -113,7 +114,11 @@ public:
int indexof(zstring const& other, int offset) const; int indexof(zstring const& other, int offset) const;
zstring extract(int lo, int hi) const; zstring extract(int lo, int hi) const;
zstring operator+(zstring const& other) const; zstring operator+(zstring const& other) const;
std::ostream& operator<<(std::ostream& out) const; bool operator==(const zstring& other) const;
bool operator!=(const zstring& other) const;
friend std::ostream& operator<<(std::ostream &os, const zstring &str);
friend bool operator<(const zstring& lhs, const zstring& rhs);
}; };
class seq_decl_plugin : public decl_plugin { class seq_decl_plugin : public decl_plugin {
@ -334,6 +339,7 @@ public:
MATCH_UNARY(is_opt); MATCH_UNARY(is_opt);
bool is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi); bool is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi);
bool is_loop(expr const* n, expr*& body, unsigned& lo); bool is_loop(expr const* n, expr*& body, unsigned& lo);
bool is_unroll(expr const* n) const { return is_app_of(n, m_fid, _OP_RE_UNROLL); }
}; };
str str; str str;
re re; re re;

View file

@ -50,6 +50,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
unsigned m_max_steps; unsigned m_max_steps;
bool m_model_completion; bool m_model_completion;
bool m_cache; bool m_cache;
bool m_array_equalities;
evaluator_cfg(ast_manager & m, model_core & md, params_ref const & p): evaluator_cfg(ast_manager & m, model_core & md, params_ref const & p):
m_model(md), m_model(md),
@ -81,6 +82,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
m_max_steps = p.max_steps(); m_max_steps = p.max_steps();
m_model_completion = p.completion(); m_model_completion = p.completion();
m_cache = p.cache(); m_cache = p.cache();
m_array_equalities = p.array_equalities();
} }
ast_manager & m() const { return m_model.get_manager(); } ast_manager & m() const { return m_model.get_manager(); }
@ -264,11 +266,14 @@ struct evaluator_cfg : public default_rewriter_cfg {
br_status mk_array_eq(expr* a, expr* b, expr_ref& result) { br_status mk_array_eq(expr* a, expr* b, expr_ref& result) {
return BR_FAILED;
if (a == b) { if (a == b) {
result = m().mk_true(); result = m().mk_true();
return BR_DONE; return BR_DONE;
} }
if (!m_array_equalities) {
return BR_FAILED;
}
// disabled until made more efficient // disabled until made more efficient
vector<expr_ref_vector> stores1, stores2; vector<expr_ref_vector> stores1, stores2;
bool args_are_unique1, args_are_unique2; bool args_are_unique1, args_are_unique2;
@ -508,6 +513,10 @@ void model_evaluator::set_model_completion(bool f) {
m_imp->cfg().m_model_completion = f; m_imp->cfg().m_model_completion = f;
} }
void model_evaluator::set_expand_array_equalities(bool f) {
m_imp->cfg().m_array_equalities = f;
}
unsigned model_evaluator::get_num_steps() const { unsigned model_evaluator::get_num_steps() const {
return m_imp->get_num_steps(); return m_imp->get_num_steps();
} }

View file

@ -35,6 +35,7 @@ public:
ast_manager & m () const; ast_manager & m () const;
void set_model_completion(bool f); void set_model_completion(bool f);
void set_expand_array_equalities(bool f);
void updt_params(params_ref const & p); void updt_params(params_ref const & p);
static void get_param_descrs(param_descrs & r); static void get_param_descrs(param_descrs & r);

View file

@ -3,6 +3,7 @@ def_module_params('model_evaluator',
params=(max_memory_param(), params=(max_memory_param(),
max_steps_param(), max_steps_param(),
('completion', BOOL, False, 'assigns an interptetation to symbols that do not have one in the current model, when evaluating expressions in the current model'), ('completion', BOOL, False, 'assigns an interptetation to symbols that do not have one in the current model, when evaluating expressions in the current model'),
('cache', BOOL, True, 'cache intermediate results in the model evaluator') ('cache', BOOL, True, 'cache intermediate results in the model evaluator'),
('array_equalities', BOOL, True, 'evaluate array equalities')
)) ))

View file

@ -1001,9 +1001,9 @@ namespace opt {
TRACE("opt", tout << "Term does not evaluate " << term << "\n";); TRACE("opt", tout << "Term does not evaluate " << term << "\n";);
return false; return false;
} }
unsigned bv_size; unsigned bvsz;
if (!m_arith.is_numeral(val, r) && !m_bv.is_numeral(val, r, bv_size)) { if (!m_arith.is_numeral(val, r) && !m_bv.is_numeral(val, r, bvsz)) {
TRACE("opt", tout << "model does not evaluate objective to a value, but to " << val << "\n";); TRACE("opt", tout << "model does not evaluate objective to a value\n";);
return false; return false;
} }
if (r != v) { if (r != v) {

View file

@ -93,6 +93,7 @@ bool proto_model::is_select_of_model_value(expr* e) const {
bool proto_model::eval(expr * e, expr_ref & result, bool model_completion) { bool proto_model::eval(expr * e, expr_ref & result, bool model_completion) {
m_eval.set_model_completion(model_completion); m_eval.set_model_completion(model_completion);
m_eval.set_expand_array_equalities(false);
try { try {
m_eval(e, result); m_eval(e, result);
#if 0 #if 0

View file

@ -4136,6 +4136,7 @@ namespace smt {
if (fcs == FC_DONE) { if (fcs == FC_DONE) {
mk_proto_model(l_true); mk_proto_model(l_true);
m_model = m_proto_model->mk_model(); m_model = m_proto_model->mk_model();
add_rec_funs_to_model();
} }
return fcs == FC_DONE; return fcs == FC_DONE;
@ -4188,8 +4189,51 @@ namespace smt {
return m_last_search_failure; return m_last_search_failure;
} }
void context::add_rec_funs_to_model() {
ast_manager& m = m_manager;
SASSERT(m_model);
for (unsigned i = 0; i < m_asserted_formulas.get_num_formulas(); ++i) {
expr* e = m_asserted_formulas.get_formula(i);
if (is_quantifier(e)) {
quantifier* q = to_quantifier(e);
if (!m.is_rec_fun_def(q)) continue;
SASSERT(q->get_num_patterns() == 1);
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
SASSERT(is_app(fn));
func_decl* f = to_app(fn)->get_decl();
expr* eq = q->get_expr();
expr_ref body(m);
if (is_fun_def(fn, q->get_expr(), body)) {
func_interp* fi = alloc(func_interp, m, f->get_arity());
fi->set_else(body);
m_model->register_decl(f, fi);
}
}
}
}
bool context::is_fun_def(expr* f, expr* body, expr_ref& result) {
expr* t1, *t2, *t3;
if (m_manager.is_eq(body, t1, t2) || m_manager.is_iff(body, t1, t2)) {
if (t1 == f) return result = t2, true;
if (t2 == f) return result = t1, true;
return false;
}
if (m_manager.is_ite(body, t1, t2, t3)) {
expr_ref body1(m_manager), body2(m_manager);
if (is_fun_def(f, t2, body1) && is_fun_def(f, t3, body2)) {
// f is not free in t1
result = m_manager.mk_ite(t1, body1, body2);
return true;
}
}
return false;
}
}; };
#ifdef Z3DEBUG #ifdef Z3DEBUG
void pp(smt::context & c) { void pp(smt::context & c) {
c.display(std::cout); c.display(std::cout);

View file

@ -209,6 +209,7 @@ namespace smt {
~scoped_mk_model() { ~scoped_mk_model() {
if (m_ctx.m_proto_model.get() != 0) { if (m_ctx.m_proto_model.get() != 0) {
m_ctx.m_model = m_ctx.m_proto_model->mk_model(); m_ctx.m_model = m_ctx.m_proto_model->mk_model();
m_ctx.add_rec_funs_to_model();
m_ctx.m_proto_model = 0; // proto_model is not needed anymore. m_ctx.m_proto_model = 0; // proto_model is not needed anymore.
} }
} }
@ -1163,6 +1164,10 @@ namespace smt {
bool propagate(); bool propagate();
void add_rec_funs_to_model();
bool is_fun_def(expr* f, expr* q, expr_ref& body);
public: public:
bool can_propagate() const; bool can_propagate() const;

View file

@ -300,7 +300,7 @@ namespace smt {
} }
num_new_instances++; num_new_instances++;
if (num_new_instances >= m_max_cexs || !add_blocking_clause(cex.get(), sks)) { if (num_new_instances >= m_max_cexs || !add_blocking_clause(cex.get(), sks)) {
TRACE("model_checker", tout << "Add blocking clause failed\n";); TRACE("model_checker", tout << "Add blocking clause failed new-instances: " << num_new_instances << " max-cex: " << m_max_cexs << "\n";);
// add_blocking_clause failed... stop the search for new counter-examples... // add_blocking_clause failed... stop the search for new counter-examples...
break; break;
} }
@ -407,6 +407,7 @@ namespace smt {
found_relevant = true; found_relevant = true;
if (m.is_rec_fun_def(q)) { if (m.is_rec_fun_def(q)) {
if (!check_rec_fun(q)) { if (!check_rec_fun(q)) {
TRACE("model_checker", tout << "checking recursive function failed\n";);
num_failures++; num_failures++;
} }
} }
@ -414,6 +415,7 @@ namespace smt {
if (m_params.m_mbqi_trace || get_verbosity_level() >= 5) { if (m_params.m_mbqi_trace || get_verbosity_level() >= 5) {
verbose_stream() << "(smt.mbqi :failed " << q->get_qid() << ")\n"; verbose_stream() << "(smt.mbqi :failed " << q->get_qid() << ")\n";
} }
TRACE("model_checker", tout << "checking quantifier " << mk_pp(q, m) << " failed\n";);
num_failures++; num_failures++;
} }
} }
@ -452,6 +454,7 @@ namespace smt {
} }
bool model_checker::has_new_instances() { bool model_checker::has_new_instances() {
TRACE("model_checker", tout << "instances: " << m_new_instances.size() << "\n";);
return !m_new_instances.empty(); return !m_new_instances.empty();
} }

View file

@ -165,6 +165,8 @@ namespace smt {
virtual void push() = 0; virtual void push() = 0;
virtual void pop(unsigned num_scopes) = 0; virtual void pop(unsigned num_scopes) = 0;
}; };
}; };

View file

@ -228,7 +228,7 @@ public:
if (m_inc_timeout == UINT_MAX) { if (m_inc_timeout == UINT_MAX) {
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";); IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";);
lbool r = m_solver2->check_sat(num_assumptions, assumptions); lbool r = m_solver2->check_sat(num_assumptions, assumptions);
if (r != l_undef || !use_solver1_when_undef()) { if (r != l_undef || !use_solver1_when_undef() || get_manager().canceled()) {
return r; return r;
} }
} }
@ -285,10 +285,9 @@ public:
} }
virtual void collect_statistics(statistics & st) const { virtual void collect_statistics(statistics & st) const {
m_solver2->collect_statistics(st);
if (m_use_solver1_results) if (m_use_solver1_results)
m_solver1->collect_statistics(st); m_solver1->collect_statistics(st);
else
m_solver2->collect_statistics(st);
} }
virtual void get_unsat_core(ptr_vector<expr> & r) { virtual void get_unsat_core(ptr_vector<expr> & r) {

View file

@ -64,7 +64,10 @@ class dt2bv_tactic : public tactic {
return; return;
} }
if (m_t.is_fd(a)) { if (m_t.is_fd(a) && a->get_num_args() > 0) {
m_t.m_non_fd_sorts.insert(get_sort(a));
}
else if (m_t.is_fd(a)) {
m_t.m_fd_sorts.insert(get_sort(a)); m_t.m_fd_sorts.insert(get_sort(a));
} }
else { else {

View file

@ -49,6 +49,7 @@ void extension_model_converter::operator()(model_ref & md, unsigned goal_idx) {
TRACE("extension_mc", model_v2_pp(tout, *md); display_decls_info(tout, md);); TRACE("extension_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
model_evaluator ev(*(md.get())); model_evaluator ev(*(md.get()));
ev.set_model_completion(true); ev.set_model_completion(true);
ev.set_expand_array_equalities(false);
expr_ref val(m()); expr_ref val(m());
unsigned i = m_vars.size(); unsigned i = m_vars.size();
while (i > 0) { while (i > 0) {

View file

@ -28,6 +28,7 @@ Revision History:
#include"ctx_simplify_tactic.h" #include"ctx_simplify_tactic.h"
#include"smt_tactic.h" #include"smt_tactic.h"
#include"elim_term_ite_tactic.h" #include"elim_term_ite_tactic.h"
#include"probe_arith.h"
static tactic * mk_quant_preprocessor(ast_manager & m, bool disable_gaussian = false) { static tactic * mk_quant_preprocessor(ast_manager & m, bool disable_gaussian = false) {
params_ref pull_ite_p; params_ref pull_ite_p;
@ -107,8 +108,10 @@ tactic * mk_lra_tactic(ast_manager & m, params_ref const & p) {
tactic * st = and_then(mk_quant_preprocessor(m), tactic * st = and_then(mk_quant_preprocessor(m),
mk_qe_lite_tactic(m, p), mk_qe_lite_tactic(m, p),
cond(mk_has_quantifier_probe(), cond(mk_has_quantifier_probe(),
or_else(mk_qsat_tactic(m, p), cond(mk_is_lira_probe(),
and_then(mk_qe_tactic(m), mk_smt_tactic())), or_else(mk_qsat_tactic(m, p),
and_then(mk_qe_tactic(m), mk_smt_tactic())),
mk_smt_tactic()),
mk_smt_tactic())); mk_smt_tactic()));
st->updt_params(p); st->updt_params(p);
return st; return st;

View file

@ -374,6 +374,11 @@ public:
} }
} }
void fill(unsigned sz, T const & elem) {
resize(sz);
fill(sz, elem);
}
bool contains(T const & elem) const { bool contains(T const & elem) const {
const_iterator it = begin(); const_iterator it = begin();
const_iterator e = end(); const_iterator e = end();