mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 06:03:23 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
05c5b3b07b
26 changed files with 331 additions and 125 deletions
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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.
|
||||||
**/
|
**/
|
||||||
|
@ -76,10 +75,11 @@ public class Optimize extends Z3Object
|
||||||
/**
|
/**
|
||||||
* Handle to objectives returned by objective functions.
|
* Handle to objectives returned by objective functions.
|
||||||
**/
|
**/
|
||||||
public class Handle
|
public static class Handle {
|
||||||
{
|
|
||||||
Optimize opt;
|
private final Optimize opt;
|
||||||
int handle;
|
private final int handle;
|
||||||
|
|
||||||
Handle(Optimize opt, int h)
|
Handle(Optimize opt, int h)
|
||||||
{
|
{
|
||||||
this.opt = opt;
|
this.opt = opt;
|
||||||
|
@ -102,6 +102,29 @@ public class Optimize extends Z3Object
|
||||||
return opt.GetUpper(handle);
|
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.
|
* Retrieve the value of an objective.
|
||||||
**/
|
**/
|
||||||
|
@ -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).
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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())) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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')
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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(),
|
||||||
|
cond(mk_is_lira_probe(),
|
||||||
or_else(mk_qsat_tactic(m, p),
|
or_else(mk_qsat_tactic(m, p),
|
||||||
and_then(mk_qe_tactic(m), mk_smt_tactic())),
|
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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue