mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08:18 +00:00
merge with unstable
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
88df909a6c
|
@ -640,7 +640,7 @@ def is_CXX_gpp():
|
||||||
|
|
||||||
def is_clang_in_gpp_form(cc):
|
def is_clang_in_gpp_form(cc):
|
||||||
version_string = subprocess.check_output([cc, '--version'])
|
version_string = subprocess.check_output([cc, '--version'])
|
||||||
return version_string.find('clang') != -1
|
return str(version_string).find('clang') != -1
|
||||||
|
|
||||||
def is_CXX_clangpp():
|
def is_CXX_clangpp():
|
||||||
if is_compiler(CXX, 'g++'):
|
if is_compiler(CXX, 'g++'):
|
||||||
|
@ -1198,9 +1198,9 @@ class JavaDLLComponent(Component):
|
||||||
deps += '%s ' % os.path.join(self.to_src_dir, 'enumerations', jfile)
|
deps += '%s ' % os.path.join(self.to_src_dir, 'enumerations', jfile)
|
||||||
out.write(deps)
|
out.write(deps)
|
||||||
out.write('\n')
|
out.write('\n')
|
||||||
if IS_WINDOWS:
|
#if IS_WINDOWS:
|
||||||
JAVAC = '"%s"' % JAVAC
|
JAVAC = '"%s"' % JAVAC
|
||||||
JAR = '"%s"' % JAR
|
JAR = '"%s"' % JAR
|
||||||
t = ('\t%s %s.java -d %s\n' % (JAVAC, os.path.join(self.to_src_dir, 'enumerations', '*'), os.path.join('api', 'java', 'classes')))
|
t = ('\t%s %s.java -d %s\n' % (JAVAC, os.path.join(self.to_src_dir, 'enumerations', '*'), os.path.join('api', 'java', 'classes')))
|
||||||
out.write(t)
|
out.write(t)
|
||||||
t = ('\t%s -cp %s %s.java -d %s\n' % (JAVAC,
|
t = ('\t%s -cp %s %s.java -d %s\n' % (JAVAC,
|
||||||
|
@ -1437,7 +1437,7 @@ def mk_config():
|
||||||
'SO_EXT=.dll\n'
|
'SO_EXT=.dll\n'
|
||||||
'SLINK=cl\n'
|
'SLINK=cl\n'
|
||||||
'SLINK_OUT_FLAG=/Fe\n'
|
'SLINK_OUT_FLAG=/Fe\n'
|
||||||
'OS_DEFINES=/D _WINDOWS\n')
|
'OS_DEFINES=/D _WINDOWS\n')
|
||||||
extra_opt = ''
|
extra_opt = ''
|
||||||
if GIT_HASH:
|
if GIT_HASH:
|
||||||
extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH)
|
extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH)
|
||||||
|
@ -1485,7 +1485,7 @@ def mk_config():
|
||||||
print('Java Compiler: %s' % JAVAC)
|
print('Java Compiler: %s' % JAVAC)
|
||||||
else:
|
else:
|
||||||
global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG
|
global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG
|
||||||
OS_DEFINES = ""
|
OS_DEFINES = ""
|
||||||
ARITH = "internal"
|
ARITH = "internal"
|
||||||
check_ar()
|
check_ar()
|
||||||
CXX = find_cxx_compiler()
|
CXX = find_cxx_compiler()
|
||||||
|
@ -1508,7 +1508,7 @@ def mk_config():
|
||||||
SLIBEXTRAFLAGS = '%s %s' % (SLIBEXTRAFLAGS,FOCI2LIB)
|
SLIBEXTRAFLAGS = '%s %s' % (SLIBEXTRAFLAGS,FOCI2LIB)
|
||||||
CPPFLAGS = '%s -D_FOCI2' % CPPFLAGS
|
CPPFLAGS = '%s -D_FOCI2' % CPPFLAGS
|
||||||
else:
|
else:
|
||||||
print "FAILED\n"
|
print("FAILED\n")
|
||||||
FOCI2 = False
|
FOCI2 = False
|
||||||
if GIT_HASH:
|
if GIT_HASH:
|
||||||
CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH)
|
CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH)
|
||||||
|
@ -1536,21 +1536,21 @@ def mk_config():
|
||||||
SLIBFLAGS = '-dynamiclib'
|
SLIBFLAGS = '-dynamiclib'
|
||||||
elif sysname == 'Linux':
|
elif sysname == 'Linux':
|
||||||
CXXFLAGS = '%s -fno-strict-aliasing -D_LINUX_' % CXXFLAGS
|
CXXFLAGS = '%s -fno-strict-aliasing -D_LINUX_' % CXXFLAGS
|
||||||
OS_DEFINES = '-D_LINUX'
|
OS_DEFINES = '-D_LINUX'
|
||||||
SO_EXT = '.so'
|
SO_EXT = '.so'
|
||||||
LDFLAGS = '%s -lrt' % LDFLAGS
|
LDFLAGS = '%s -lrt' % LDFLAGS
|
||||||
SLIBFLAGS = '-shared'
|
SLIBFLAGS = '-shared'
|
||||||
SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
|
SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
|
||||||
elif sysname == 'FreeBSD':
|
elif sysname == 'FreeBSD':
|
||||||
CXXFLAGS = '%s -fno-strict-aliasing -D_FREEBSD_' % CXXFLAGS
|
CXXFLAGS = '%s -fno-strict-aliasing -D_FREEBSD_' % CXXFLAGS
|
||||||
OS_DEFINES = '-D_FREEBSD_'
|
OS_DEFINES = '-D_FREEBSD_'
|
||||||
SO_EXT = '.so'
|
SO_EXT = '.so'
|
||||||
LDFLAGS = '%s -lrt' % LDFLAGS
|
LDFLAGS = '%s -lrt' % LDFLAGS
|
||||||
SLIBFLAGS = '-shared'
|
SLIBFLAGS = '-shared'
|
||||||
SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
|
SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
|
||||||
elif sysname[:6] == 'CYGWIN':
|
elif sysname[:6] == 'CYGWIN':
|
||||||
CXXFLAGS = '%s -D_CYGWIN -fno-strict-aliasing' % CXXFLAGS
|
CXXFLAGS = '%s -D_CYGWIN -fno-strict-aliasing' % CXXFLAGS
|
||||||
OS_DEFINES = '-D_CYGWIN'
|
OS_DEFINES = '-D_CYGWIN'
|
||||||
SO_EXT = '.dll'
|
SO_EXT = '.dll'
|
||||||
SLIBFLAGS = '-shared'
|
SLIBFLAGS = '-shared'
|
||||||
else:
|
else:
|
||||||
|
@ -1586,7 +1586,7 @@ def mk_config():
|
||||||
config.write('SLINK_FLAGS=%s\n' % SLIBFLAGS)
|
config.write('SLINK_FLAGS=%s\n' % SLIBFLAGS)
|
||||||
config.write('SLINK_EXTRA_FLAGS=%s\n' % SLIBEXTRAFLAGS)
|
config.write('SLINK_EXTRA_FLAGS=%s\n' % SLIBEXTRAFLAGS)
|
||||||
config.write('SLINK_OUT_FLAG=-o \n')
|
config.write('SLINK_OUT_FLAG=-o \n')
|
||||||
config.write('OS_DEFINES=%s\n' % OS_DEFINES)
|
config.write('OS_DEFINES=%s\n' % OS_DEFINES)
|
||||||
if is_verbose():
|
if is_verbose():
|
||||||
print('Host platform: %s' % sysname)
|
print('Host platform: %s' % sysname)
|
||||||
print('C++ Compiler: %s' % CXX)
|
print('C++ Compiler: %s' % CXX)
|
||||||
|
|
|
@ -523,7 +523,7 @@ def mk_java():
|
||||||
java_native.write(' public static class LongPtr { public long value; }\n')
|
java_native.write(' public static class LongPtr { public long value; }\n')
|
||||||
java_native.write(' public static class StringPtr { public String value; }\n')
|
java_native.write(' public static class StringPtr { public String value; }\n')
|
||||||
java_native.write(' public static native void setInternalErrorHandler(long ctx);\n\n')
|
java_native.write(' public static native void setInternalErrorHandler(long ctx);\n\n')
|
||||||
if IS_WINDOWS:
|
if IS_WINDOWS or os.uname()[0]=="CYGWIN":
|
||||||
java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name)
|
java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name)
|
||||||
else:
|
else:
|
||||||
java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name[3:]) # We need 3: to extract the prexi 'lib' form the dll_name
|
java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name[3:]) # We need 3: to extract the prexi 'lib' form the dll_name
|
||||||
|
@ -588,6 +588,9 @@ def mk_java():
|
||||||
java_wrapper = open(java_wrapperf, 'w')
|
java_wrapper = open(java_wrapperf, 'w')
|
||||||
pkg_str = get_component('java').package_name.replace('.', '_')
|
pkg_str = get_component('java').package_name.replace('.', '_')
|
||||||
java_wrapper.write('// Automatically generated file\n')
|
java_wrapper.write('// Automatically generated file\n')
|
||||||
|
java_wrapper.write('#ifdef _CYGWIN\n')
|
||||||
|
java_wrapper.write('typedef long long __int64;\n')
|
||||||
|
java_wrapper.write('#endif\n')
|
||||||
java_wrapper.write('#include<jni.h>\n')
|
java_wrapper.write('#include<jni.h>\n')
|
||||||
java_wrapper.write('#include<stdlib.h>\n')
|
java_wrapper.write('#include<stdlib.h>\n')
|
||||||
java_wrapper.write('#include"z3.h"\n')
|
java_wrapper.write('#include"z3.h"\n')
|
||||||
|
|
|
@ -586,7 +586,7 @@ class FuncDeclRef(AstRef):
|
||||||
return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
|
return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
|
||||||
|
|
||||||
def as_func_decl(self):
|
def as_func_decl(self):
|
||||||
return self.ast
|
return self.ast
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the function declaration `self`.
|
"""Return the name of the function declaration `self`.
|
||||||
|
|
|
@ -478,6 +478,25 @@ class smt2_printer {
|
||||||
ast_manager & m() const { return m_manager; }
|
ast_manager & m() const { return m_manager; }
|
||||||
ast_manager & fm() const { return format_ns::fm(m()); }
|
ast_manager & fm() const { return format_ns::fm(m()); }
|
||||||
|
|
||||||
|
std::string ensure_quote(symbol const& s) {
|
||||||
|
std::string str;
|
||||||
|
if (is_smt2_quoted_symbol(s))
|
||||||
|
str = mk_smt2_quoted_symbol(s);
|
||||||
|
else
|
||||||
|
str = s.str();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol ensure_quote_sym(symbol const& s) {
|
||||||
|
if (is_smt2_quoted_symbol(s)) {
|
||||||
|
std::string str;
|
||||||
|
str = mk_smt2_quoted_symbol(s);
|
||||||
|
return symbol(str.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void pp_var(var * v) {
|
void pp_var(var * v) {
|
||||||
format * f;
|
format * f;
|
||||||
if (v->get_idx() < m_var_names.size()) {
|
if (v->get_idx() < m_var_names.size()) {
|
||||||
|
@ -507,11 +526,7 @@ class smt2_printer {
|
||||||
}
|
}
|
||||||
|
|
||||||
format * pp_simple_attribute(char const * attr, symbol const & s) {
|
format * pp_simple_attribute(char const * attr, symbol const & s) {
|
||||||
std::string str;
|
std::string str = ensure_quote(s);
|
||||||
if (is_smt2_quoted_symbol(s))
|
|
||||||
str = mk_smt2_quoted_symbol(s);
|
|
||||||
else
|
|
||||||
str = s.str();
|
|
||||||
return mk_compose(m(), mk_string(m(), attr), mk_string(m(), str.c_str()));
|
return mk_compose(m(), mk_string(m(), attr), mk_string(m(), str.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,7 +794,7 @@ class smt2_printer {
|
||||||
void register_var_names(quantifier * q) {
|
void register_var_names(quantifier * q) {
|
||||||
unsigned num_decls = q->get_num_decls();
|
unsigned num_decls = q->get_num_decls();
|
||||||
for (unsigned i = 0; i < num_decls; i++) {
|
for (unsigned i = 0; i < num_decls; i++) {
|
||||||
symbol name = q->get_decl_name(i);
|
symbol name = ensure_quote_sym(q->get_decl_name(i));
|
||||||
if (name.is_numerical()) {
|
if (name.is_numerical()) {
|
||||||
unsigned idx = 1;
|
unsigned idx = 1;
|
||||||
name = next_name("x", idx);
|
name = next_name("x", idx);
|
||||||
|
@ -1003,6 +1018,7 @@ public:
|
||||||
unsigned idx = 1;
|
unsigned idx = 1;
|
||||||
for (unsigned i = 0; i < num; i++) {
|
for (unsigned i = 0; i < num; i++) {
|
||||||
symbol name = next_name(var_prefix, idx);
|
symbol name = next_name(var_prefix, idx);
|
||||||
|
name = ensure_quote_sym(name);
|
||||||
var_names.push_back(name);
|
var_names.push_back(name);
|
||||||
m_var_names_set.insert(name);
|
m_var_names_set.insert(name);
|
||||||
m_var_names.push_back(name);
|
m_var_names.push_back(name);
|
||||||
|
|
|
@ -753,12 +753,7 @@ br_status arith_rewriter::mk_rem_core(expr * arg1, expr * arg2, expr_ref & resul
|
||||||
}
|
}
|
||||||
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && !v2.is_zero()) {
|
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && !v2.is_zero()) {
|
||||||
if (is_add(arg1) || is_mul(arg1)) {
|
if (is_add(arg1) || is_mul(arg1)) {
|
||||||
ptr_buffer<expr> new_args;
|
return BR_FAILED;
|
||||||
unsigned num_args = to_app(arg1)->get_num_args();
|
|
||||||
for (unsigned i = 0; i < num_args; i++)
|
|
||||||
new_args.push_back(m_util.mk_rem(to_app(arg1)->get_arg(i), arg2));
|
|
||||||
result = m().mk_app(to_app(arg1)->get_decl(), new_args.size(), new_args.c_ptr());
|
|
||||||
return BR_REWRITE2;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (v2.is_neg()) {
|
if (v2.is_neg()) {
|
||||||
|
|
|
@ -310,6 +310,8 @@ struct check_logic::imp {
|
||||||
return false;
|
return false;
|
||||||
non_numeral = arg;
|
non_numeral = arg;
|
||||||
}
|
}
|
||||||
|
if (non_numeral == 0)
|
||||||
|
return true;
|
||||||
if (is_diff_var(non_numeral))
|
if (is_diff_var(non_numeral))
|
||||||
return true;
|
return true;
|
||||||
if (!m_a_util.is_add(non_numeral) && !m_a_util.is_sub(non_numeral))
|
if (!m_a_util.is_add(non_numeral) && !m_a_util.is_sub(non_numeral))
|
||||||
|
|
|
@ -515,6 +515,25 @@ bool pdatatype_decl::has_missing_refs(symbol & missing) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pdatatype_decl::has_duplicate_accessors(symbol & duplicated) const {
|
||||||
|
hashtable<symbol, symbol_hash_proc, symbol_eq_proc> names;
|
||||||
|
ptr_vector<pconstructor_decl>::const_iterator it = m_constructors.begin();
|
||||||
|
ptr_vector<pconstructor_decl>::const_iterator end = m_constructors.end();
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
ptr_vector<paccessor_decl> const& acc = (*it)->m_accessors;
|
||||||
|
for (unsigned i = 0; i < acc.size(); ++i) {
|
||||||
|
symbol const& name = acc[i]->get_name();
|
||||||
|
if (names.contains(name)) {
|
||||||
|
duplicated = name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
names.insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool pdatatype_decl::fix_missing_refs(dictionary<int> const & symbol2idx, symbol & missing) {
|
bool pdatatype_decl::fix_missing_refs(dictionary<int> const & symbol2idx, symbol & missing) {
|
||||||
ptr_vector<pconstructor_decl>::iterator it = m_constructors.begin();
|
ptr_vector<pconstructor_decl>::iterator it = m_constructors.begin();
|
||||||
ptr_vector<pconstructor_decl>::iterator end = m_constructors.end();
|
ptr_vector<pconstructor_decl>::iterator end = m_constructors.end();
|
||||||
|
|
|
@ -169,6 +169,7 @@ public:
|
||||||
class paccessor_decl : public pdecl {
|
class paccessor_decl : public pdecl {
|
||||||
friend class pdecl_manager;
|
friend class pdecl_manager;
|
||||||
friend class pconstructor_decl;
|
friend class pconstructor_decl;
|
||||||
|
friend class pdatatype_decl;
|
||||||
symbol m_name;
|
symbol m_name;
|
||||||
ptype m_type;
|
ptype m_type;
|
||||||
paccessor_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, ptype const & r);
|
paccessor_decl(unsigned id, unsigned num_params, pdecl_manager & m, symbol const & n, ptype const & r);
|
||||||
|
@ -222,6 +223,7 @@ public:
|
||||||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s);
|
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s);
|
||||||
virtual void display(std::ostream & out) const;
|
virtual void display(std::ostream & out) const;
|
||||||
bool has_missing_refs(symbol & missing) const;
|
bool has_missing_refs(symbol & missing) const;
|
||||||
|
bool has_duplicate_accessors(symbol & repeated) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
28
src/duality/duality.h
Normal file → Executable file
28
src/duality/duality.h
Normal file → Executable file
|
@ -25,7 +25,7 @@ Revision History:
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
// make hash_map and hash_set available
|
// make hash_map and hash_set available
|
||||||
#ifndef WIN32
|
#ifndef _WINDOWS
|
||||||
using namespace stl_ext;
|
using namespace stl_ext;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -782,7 +782,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
__declspec(dllexport)
|
__declspec(dllexport)
|
||||||
#endif
|
#endif
|
||||||
void FromClauses(const std::vector<Term> &clauses);
|
void FromClauses(const std::vector<Term> &clauses);
|
||||||
|
@ -1184,7 +1184,13 @@ namespace Duality {
|
||||||
hash_map<Edge *, Edge *> EdgeCloneMap;
|
hash_map<Edge *, Edge *> EdgeCloneMap;
|
||||||
std::vector<expr> alit_stack;
|
std::vector<expr> alit_stack;
|
||||||
std::vector<unsigned> alit_stack_sizes;
|
std::vector<unsigned> alit_stack_sizes;
|
||||||
hash_map<Edge *, uptr<LogicSolver> > edge_solvers;
|
|
||||||
|
// to let us use one solver per edge
|
||||||
|
struct edge_solver {
|
||||||
|
hash_map<ast,expr> AssumptionLits;
|
||||||
|
uptr<solver> slvr;
|
||||||
|
};
|
||||||
|
hash_map<Edge *, edge_solver > edge_solvers;
|
||||||
|
|
||||||
#ifdef LIMIT_STACK_WEIGHT
|
#ifdef LIMIT_STACK_WEIGHT
|
||||||
struct weight_counter {
|
struct weight_counter {
|
||||||
|
@ -1236,19 +1242,23 @@ namespace Duality {
|
||||||
|
|
||||||
void GetTermTreeAssertionLiteralsRec(TermTree *assumptions);
|
void GetTermTreeAssertionLiteralsRec(TermTree *assumptions);
|
||||||
|
|
||||||
LogicSolver *SolverForEdge(Edge *edge, bool models);
|
edge_solver &SolverForEdge(Edge *edge, bool models, bool axioms);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct scoped_solver_for_edge {
|
struct scoped_solver_for_edge {
|
||||||
LogicSolver *orig_ls;
|
solver *orig_slvr;
|
||||||
RPFP_caching *rpfp;
|
RPFP_caching *rpfp;
|
||||||
scoped_solver_for_edge(RPFP_caching *_rpfp, Edge *edge, bool models = false){
|
edge_solver *es;
|
||||||
|
scoped_solver_for_edge(RPFP_caching *_rpfp, Edge *edge, bool models = false, bool axioms = false){
|
||||||
rpfp = _rpfp;
|
rpfp = _rpfp;
|
||||||
orig_ls = rpfp->ls;
|
orig_slvr = rpfp->ls->slvr;
|
||||||
rpfp->ls = rpfp->SolverForEdge(edge,models);
|
es = &(rpfp->SolverForEdge(edge,models,axioms));
|
||||||
|
rpfp->ls->slvr = es->slvr.get();
|
||||||
|
rpfp->AssumptionLits.swap(es->AssumptionLits);
|
||||||
}
|
}
|
||||||
~scoped_solver_for_edge(){
|
~scoped_solver_for_edge(){
|
||||||
rpfp->ls = orig_ls;
|
rpfp->ls->slvr = orig_slvr;
|
||||||
|
rpfp->AssumptionLits.swap(es->AssumptionLits);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
53
src/duality/duality_rpfp.cpp
Normal file → Executable file
53
src/duality/duality_rpfp.cpp
Normal file → Executable file
|
@ -2711,10 +2711,12 @@ namespace Duality {
|
||||||
const std::vector<expr> &theory = ls->get_axioms();
|
const std::vector<expr> &theory = ls->get_axioms();
|
||||||
for(unsigned i = 0; i < theory.size(); i++)
|
for(unsigned i = 0; i < theory.size(); i++)
|
||||||
s.add(theory[i]);
|
s.add(theory[i]);
|
||||||
if(s.check(lits.size(),&lits[0]) != unsat)
|
for(int k = 0; k < 100; k++) // keep trying, maybe MBQI will do something!
|
||||||
throw "should be unsat";
|
if(s.check(lits.size(),&lits[0]) == unsat)
|
||||||
|
goto is_unsat;
|
||||||
|
throw "should be unsat";
|
||||||
}
|
}
|
||||||
|
is_unsat:
|
||||||
for(unsigned i = 0; i < conjuncts.size(); ){
|
for(unsigned i = 0; i < conjuncts.size(); ){
|
||||||
std::swap(conjuncts[i],conjuncts.back());
|
std::swap(conjuncts[i],conjuncts.back());
|
||||||
std::swap(lits[i],lits.back());
|
std::swap(lits[i],lits.back());
|
||||||
|
@ -2747,8 +2749,20 @@ namespace Duality {
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
check_result res = CheckCore(lits,full_core);
|
check_result res = CheckCore(lits,full_core);
|
||||||
if(res != unsat)
|
if(res != unsat){
|
||||||
|
// add the axioms in the off chance they are useful
|
||||||
|
const std::vector<expr> &theory = ls->get_axioms();
|
||||||
|
for(unsigned i = 0; i < theory.size(); i++)
|
||||||
|
GetAssumptionLits(theory[i],assumps);
|
||||||
|
lits = assumps;
|
||||||
|
std::copy(core.begin(),core.end(),std::inserter(lits,lits.end()));
|
||||||
|
|
||||||
|
for(int k = 0; k < 100; k++) // keep trying, maybe MBQI will do something!
|
||||||
|
if((res = CheckCore(lits,full_core)) == unsat)
|
||||||
|
goto is_unsat;
|
||||||
throw "should be unsat";
|
throw "should be unsat";
|
||||||
|
}
|
||||||
|
is_unsat:
|
||||||
FilterCore(core,full_core);
|
FilterCore(core,full_core);
|
||||||
|
|
||||||
std::vector<expr> dummy;
|
std::vector<expr> dummy;
|
||||||
|
@ -2889,13 +2903,20 @@ namespace Duality {
|
||||||
timer_stop("Generalize");
|
timer_stop("Generalize");
|
||||||
}
|
}
|
||||||
|
|
||||||
RPFP::LogicSolver *RPFP_caching::SolverForEdge(Edge *edge, bool models){
|
RPFP_caching::edge_solver &RPFP_caching::SolverForEdge(Edge *edge, bool models, bool axioms){
|
||||||
uptr<LogicSolver> &p = edge_solvers[edge];
|
edge_solver &es = edge_solvers[edge];
|
||||||
|
uptr<solver> &p = es.slvr;
|
||||||
if(!p.get()){
|
if(!p.get()){
|
||||||
scoped_no_proof no_proofs_please(ctx.m()); // no proofs
|
scoped_no_proof no_proofs_please(ctx.m()); // no proofs
|
||||||
p.set(new iZ3LogicSolver(ctx,models)); // no models
|
p.set(new solver(ctx,true,models)); // no models
|
||||||
|
if(axioms){
|
||||||
|
RPFP::LogicSolver *ls = edge->owner->ls;
|
||||||
|
const std::vector<expr> &axs = ls->get_axioms();
|
||||||
|
for(unsigned i = 0; i < axs.size(); i++)
|
||||||
|
p.get()->add(axs[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return p.get();
|
return es;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3362,6 +3383,8 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool some_labels = false;
|
||||||
|
|
||||||
// create the edges
|
// create the edges
|
||||||
|
|
||||||
for(unsigned i = 0; i < clauses.size(); i++){
|
for(unsigned i = 0; i < clauses.size(); i++){
|
||||||
|
@ -3397,17 +3420,23 @@ namespace Duality {
|
||||||
Term labeled = body;
|
Term labeled = body;
|
||||||
std::vector<label_struct > lbls; // TODO: throw this away for now
|
std::vector<label_struct > lbls; // TODO: throw this away for now
|
||||||
body = RemoveLabels(body,lbls);
|
body = RemoveLabels(body,lbls);
|
||||||
|
if(!eq(labeled,body))
|
||||||
|
some_labels = true; // remember if there are labels, as we then can't do qe_lite
|
||||||
// body = IneqToEq(body); // UFO converts x=y to (x<=y & x >= y). Undo this.
|
// body = IneqToEq(body); // UFO converts x=y to (x<=y & x >= y). Undo this.
|
||||||
body = body.simplify();
|
body = body.simplify();
|
||||||
|
|
||||||
#ifdef USE_QE_LITE
|
#ifdef USE_QE_LITE
|
||||||
std::set<int> idxs;
|
std::set<int> idxs;
|
||||||
for(unsigned j = 0; j < Indparams.size(); j++)
|
if(!some_labels){ // can't do qe_lite if we have to reconstruct labels
|
||||||
if(Indparams[j].is_var())
|
for(unsigned j = 0; j < Indparams.size(); j++)
|
||||||
idxs.insert(Indparams[j].get_index_value());
|
if(Indparams[j].is_var())
|
||||||
body = body.qe_lite(idxs,false);
|
idxs.insert(Indparams[j].get_index_value());
|
||||||
|
body = body.qe_lite(idxs,false);
|
||||||
|
}
|
||||||
hash_map<int,hash_map<ast,Term> > sb_memo;
|
hash_map<int,hash_map<ast,Term> > sb_memo;
|
||||||
body = SubstBoundRec(sb_memo,substs[i],0,body);
|
body = SubstBoundRec(sb_memo,substs[i],0,body);
|
||||||
|
if(some_labels)
|
||||||
|
labeled = SubstBoundRec(sb_memo,substs[i],0,labeled);
|
||||||
for(unsigned j = 0; j < Indparams.size(); j++)
|
for(unsigned j = 0; j < Indparams.size(); j++)
|
||||||
Indparams[j] = SubstBoundRec(sb_memo, substs[i], 0, Indparams[j]);
|
Indparams[j] = SubstBoundRec(sb_memo, substs[i], 0, Indparams[j]);
|
||||||
#endif
|
#endif
|
||||||
|
|
29
src/duality/duality_solver.cpp
Normal file → Executable file
29
src/duality/duality_solver.cpp
Normal file → Executable file
|
@ -51,12 +51,17 @@ Revision History:
|
||||||
// #define TOP_DOWN
|
// #define TOP_DOWN
|
||||||
// #define EFFORT_BOUNDED_STRAT
|
// #define EFFORT_BOUNDED_STRAT
|
||||||
#define SKIP_UNDERAPPROX_NODES
|
#define SKIP_UNDERAPPROX_NODES
|
||||||
#define USE_RPFP_CLONE
|
|
||||||
// #define KEEP_EXPANSIONS
|
// #define KEEP_EXPANSIONS
|
||||||
// #define USE_CACHING_RPFP
|
// #define USE_CACHING_RPFP
|
||||||
// #define PROPAGATE_BEFORE_CHECK
|
// #define PROPAGATE_BEFORE_CHECK
|
||||||
|
|
||||||
|
#define USE_RPFP_CLONE
|
||||||
#define USE_NEW_GEN_CANDS
|
#define USE_NEW_GEN_CANDS
|
||||||
|
|
||||||
|
//#define NO_PROPAGATE
|
||||||
|
//#define NO_GENERALIZE
|
||||||
|
//#define NO_DECISIONS
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
// TODO: must be a better place for this...
|
// TODO: must be a better place for this...
|
||||||
|
@ -129,13 +134,11 @@ namespace Duality {
|
||||||
{
|
{
|
||||||
scoped_no_proof no_proofs_please(ctx.m());
|
scoped_no_proof no_proofs_please(ctx.m());
|
||||||
#ifdef USE_RPFP_CLONE
|
#ifdef USE_RPFP_CLONE
|
||||||
clone_ls = new RPFP::iZ3LogicSolver(ctx, false); // no models needed for this one
|
clone_rpfp = new RPFP_caching(rpfp->ls);
|
||||||
clone_rpfp = new RPFP_caching(clone_ls);
|
|
||||||
clone_rpfp->Clone(rpfp);
|
clone_rpfp->Clone(rpfp);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NEW_GEN_CANDS
|
#ifdef USE_NEW_GEN_CANDS
|
||||||
gen_cands_ls = new RPFP::iZ3LogicSolver(ctx);
|
gen_cands_rpfp = new RPFP_caching(rpfp->ls);
|
||||||
gen_cands_rpfp = new RPFP_caching(gen_cands_ls);
|
|
||||||
gen_cands_rpfp->Clone(rpfp);
|
gen_cands_rpfp->Clone(rpfp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -144,20 +147,16 @@ namespace Duality {
|
||||||
~Duality(){
|
~Duality(){
|
||||||
#ifdef USE_RPFP_CLONE
|
#ifdef USE_RPFP_CLONE
|
||||||
delete clone_rpfp;
|
delete clone_rpfp;
|
||||||
delete clone_ls;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NEW_GEN_CANDS
|
#ifdef USE_NEW_GEN_CANDS
|
||||||
delete gen_cands_rpfp;
|
delete gen_cands_rpfp;
|
||||||
delete gen_cands_ls;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_RPFP_CLONE
|
#ifdef USE_RPFP_CLONE
|
||||||
RPFP::LogicSolver *clone_ls;
|
|
||||||
RPFP_caching *clone_rpfp;
|
RPFP_caching *clone_rpfp;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NEW_GEN_CANDS
|
#ifdef USE_NEW_GEN_CANDS
|
||||||
RPFP::LogicSolver *gen_cands_ls;
|
|
||||||
RPFP_caching *gen_cands_rpfp;
|
RPFP_caching *gen_cands_rpfp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1255,7 +1254,7 @@ namespace Duality {
|
||||||
slvr.pop(1);
|
slvr.pop(1);
|
||||||
delete checker;
|
delete checker;
|
||||||
#else
|
#else
|
||||||
RPFP_caching::scoped_solver_for_edge(gen_cands_rpfp,edge,true /* models */);
|
RPFP_caching::scoped_solver_for_edge ssfe(gen_cands_rpfp,edge,true /* models */, true /*axioms*/);
|
||||||
gen_cands_rpfp->Push();
|
gen_cands_rpfp->Push();
|
||||||
Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp);
|
Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp);
|
||||||
if(gen_cands_rpfp->Check(root) != unsat){
|
if(gen_cands_rpfp->Check(root) != unsat){
|
||||||
|
@ -1940,11 +1939,15 @@ namespace Duality {
|
||||||
for(unsigned i = 0; i < expansions.size(); i++){
|
for(unsigned i = 0; i < expansions.size(); i++){
|
||||||
Node *node = expansions[i];
|
Node *node = expansions[i];
|
||||||
tree->SolveSingleNode(top,node);
|
tree->SolveSingleNode(top,node);
|
||||||
|
#ifdef NO_GENERALIZE
|
||||||
|
node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify();
|
||||||
|
#else
|
||||||
if(expansions.size() == 1 && NodeTooComplicated(node))
|
if(expansions.size() == 1 && NodeTooComplicated(node))
|
||||||
SimplifyNode(node);
|
SimplifyNode(node);
|
||||||
else
|
else
|
||||||
node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify();
|
node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify();
|
||||||
Generalize(node);
|
Generalize(node);
|
||||||
|
#endif
|
||||||
if(RecordUpdate(node))
|
if(RecordUpdate(node))
|
||||||
update_count++;
|
update_count++;
|
||||||
else
|
else
|
||||||
|
@ -1984,7 +1987,9 @@ namespace Duality {
|
||||||
if(stack.size() == 1)break;
|
if(stack.size() == 1)break;
|
||||||
if(prev_level_used){
|
if(prev_level_used){
|
||||||
Node *node = stack.back().expansions[0];
|
Node *node = stack.back().expansions[0];
|
||||||
|
#ifndef NO_PROPAGATE
|
||||||
if(!Propagate(node)) break;
|
if(!Propagate(node)) break;
|
||||||
|
#endif
|
||||||
if(!RecordUpdate(node)) break; // shouldn't happen!
|
if(!RecordUpdate(node)) break; // shouldn't happen!
|
||||||
RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list
|
RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list
|
||||||
propagated = true;
|
propagated = true;
|
||||||
|
@ -2006,11 +2011,13 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
was_sat = true;
|
was_sat = true;
|
||||||
tree->Push();
|
tree->Push();
|
||||||
std::vector<Node *> &expansions = stack.back().expansions;
|
std::vector<Node *> &expansions = stack.back().expansions;
|
||||||
|
#ifndef NO_DECISIONS
|
||||||
for(unsigned i = 0; i < expansions.size(); i++){
|
for(unsigned i = 0; i < expansions.size(); i++){
|
||||||
tree->FixCurrentState(expansions[i]->Outgoing);
|
tree->FixCurrentState(expansions[i]->Outgoing);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
if(tree->slvr().check() == unsat)
|
if(tree->slvr().check() == unsat)
|
||||||
throw "help!";
|
throw "help!";
|
||||||
|
|
0
src/duality/duality_wrapper.cpp
Normal file → Executable file
0
src/duality/duality_wrapper.cpp
Normal file → Executable file
|
@ -1402,7 +1402,7 @@ namespace hash_space {
|
||||||
}
|
}
|
||||||
|
|
||||||
// to make Duality::ast hashable in windows
|
// to make Duality::ast hashable in windows
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
template <> inline
|
template <> inline
|
||||||
size_t stdext::hash_value<Duality::ast >(const Duality::ast& s)
|
size_t stdext::hash_value<Duality::ast >(const Duality::ast& s)
|
||||||
{
|
{
|
||||||
|
@ -1446,7 +1446,7 @@ namespace hash_space {
|
||||||
}
|
}
|
||||||
|
|
||||||
// to make Duality::func_decl hashable in windows
|
// to make Duality::func_decl hashable in windows
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
template <> inline
|
template <> inline
|
||||||
size_t stdext::hash_value<Duality::func_decl >(const Duality::func_decl& s)
|
size_t stdext::hash_value<Duality::func_decl >(const Duality::func_decl& s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,7 +42,7 @@ Revision History:
|
||||||
#include <ext/hash_map>
|
#include <ext/hash_map>
|
||||||
#include <ext/hash_set>
|
#include <ext/hash_set>
|
||||||
#else
|
#else
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
#define stl_ext stdext
|
#define stl_ext stdext
|
||||||
#define hash_space std
|
#define hash_space std
|
||||||
#include <hash_map>
|
#include <hash_map>
|
||||||
|
@ -61,7 +61,7 @@ Revision History:
|
||||||
|
|
||||||
// stupid STL doesn't include hash function for class string
|
// stupid STL doesn't include hash function for class string
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef _WINDOWS
|
||||||
|
|
||||||
namespace stl_ext {
|
namespace stl_ext {
|
||||||
template <>
|
template <>
|
||||||
|
@ -86,7 +86,7 @@ namespace hash_space {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
template <> inline
|
template <> inline
|
||||||
size_t stdext::hash_value<std::pair<int,int> >(const std::pair<int,int>& p)
|
size_t stdext::hash_value<std::pair<int,int> >(const std::pair<int,int>& p)
|
||||||
{ // hash _Keyval to size_t value one-to-one
|
{ // hash _Keyval to size_t value one-to-one
|
||||||
|
@ -112,7 +112,7 @@ size_t stdext::hash_value<std::pair<T *, T *> >(const std::pair<T *, T *>& p)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
|
@ -139,7 +139,7 @@ namespace std {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef _WINDOWS
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
namespace stl_ext {
|
namespace stl_ext {
|
||||||
|
@ -155,7 +155,7 @@ namespace stl_ext {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
23
src/interp/iz3mgr.cpp
Normal file → Executable file
23
src/interp/iz3mgr.cpp
Normal file → Executable file
|
@ -249,6 +249,9 @@ iz3mgr::ast iz3mgr::clone(const ast &t, const std::vector<ast> &_args){
|
||||||
|
|
||||||
|
|
||||||
void iz3mgr::show(ast t){
|
void iz3mgr::show(ast t){
|
||||||
|
if(t.null()){
|
||||||
|
std::cout << "(null)" << std::endl;
|
||||||
|
}
|
||||||
params_ref p;
|
params_ref p;
|
||||||
p.set_bool("flat_assoc",false);
|
p.set_bool("flat_assoc",false);
|
||||||
std::cout << mk_pp(t.raw(), m(), p) << std::endl;
|
std::cout << mk_pp(t.raw(), m(), p) << std::endl;
|
||||||
|
@ -693,10 +696,13 @@ void iz3mgr::linear_comb(ast &P, const ast &c, const ast &Q, bool round_off){
|
||||||
throw "not an inequality";
|
throw "not an inequality";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Qrhs = make(Times,c,Qrhs);
|
bool pstrict = op(P) == Lt;
|
||||||
bool pstrict = op(P) == Lt, strict = pstrict || qstrict;
|
if(qstrict && round_off && (pstrict || !(c == make_int(rational(1))))){
|
||||||
if(pstrict && qstrict && round_off)
|
|
||||||
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
||||||
|
qstrict = false;
|
||||||
|
}
|
||||||
|
Qrhs = make(Times,c,Qrhs);
|
||||||
|
bool strict = pstrict || qstrict;
|
||||||
if(strict)
|
if(strict)
|
||||||
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
||||||
else
|
else
|
||||||
|
@ -881,3 +887,14 @@ iz3mgr::ast iz3mgr::apply_quant(opr quantifier, ast var, ast e){
|
||||||
std::vector<ast> bvs; bvs.push_back(var);
|
std::vector<ast> bvs; bvs.push_back(var);
|
||||||
return make_quant(quantifier,bvs,e);
|
return make_quant(quantifier,bvs,e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void iz3mgr::get_bound_substitutes(stl_ext::hash_map<ast,bool> &memo, const ast &e, const ast &var, std::vector<ast> &substs){
|
||||||
|
std::pair<ast,bool> foo(e,false);
|
||||||
|
std::pair<hash_map<ast,bool>::iterator,bool> bar = memo.insert(foo);
|
||||||
|
if(bar.second){
|
||||||
|
if(op(e) ==
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
2
src/interp/iz3mgr.h
Normal file → Executable file
2
src/interp/iz3mgr.h
Normal file → Executable file
|
@ -127,7 +127,7 @@ namespace hash_space {
|
||||||
}
|
}
|
||||||
|
|
||||||
// to make ast_r hashable in windows
|
// to make ast_r hashable in windows
|
||||||
#ifdef WIN32
|
#ifdef _WINDOWS
|
||||||
template <> inline
|
template <> inline
|
||||||
size_t stdext::hash_value<ast_r >(const ast_r& s)
|
size_t stdext::hash_value<ast_r >(const ast_r& s)
|
||||||
{
|
{
|
||||||
|
|
255
src/interp/iz3proof_itp.cpp
Normal file → Executable file
255
src/interp/iz3proof_itp.cpp
Normal file → Executable file
|
@ -579,18 +579,36 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return is_ineq(ineq);
|
return is_ineq(ineq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast destruct_cond_ineq(const ast &ineq, ast &Aproves, ast &Bproves){
|
||||||
|
ast res = ineq;
|
||||||
|
opr o = op(res);
|
||||||
|
if(o == And){
|
||||||
|
Aproves = my_and(Aproves,arg(res,0));
|
||||||
|
res = arg(res,1);
|
||||||
|
o = op(res);
|
||||||
|
}
|
||||||
|
if(o == Implies){
|
||||||
|
Bproves = my_and(Bproves,arg(res,0));
|
||||||
|
res = arg(res,1);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
ast simplify_sum(std::vector<ast> &args){
|
ast simplify_sum(std::vector<ast> &args){
|
||||||
ast Aproves = mk_true(), Bproves = mk_true();
|
ast Aproves = mk_true(), Bproves = mk_true();
|
||||||
ast ineq = args[0];
|
ast ineq = destruct_cond_ineq(args[0],Aproves,Bproves);
|
||||||
if(!is_normal_ineq(ineq)) throw cannot_simplify();
|
if(!is_normal_ineq(ineq)) throw cannot_simplify();
|
||||||
sum_cond_ineq(ineq,args[1],args[2],Aproves,Bproves);
|
sum_cond_ineq(ineq,args[1],args[2],Aproves,Bproves);
|
||||||
return my_and(Aproves,my_implies(Bproves,ineq));
|
return my_and(Aproves,my_implies(Bproves,ineq));
|
||||||
}
|
}
|
||||||
|
|
||||||
ast simplify_rotate_sum(const ast &pl, const ast &pf){
|
ast simplify_rotate_sum(const ast &pl, const ast &pf){
|
||||||
ast cond = mk_true();
|
ast Aproves = mk_true(), Bproves = mk_true();
|
||||||
ast ineq = make(Leq,make_int("0"),make_int("0"));
|
ast ineq = make(Leq,make_int("0"),make_int("0"));
|
||||||
return rotate_sum_rec(pl,pf,cond,ineq);
|
ineq = rotate_sum_rec(pl,pf,Aproves,Bproves,ineq);
|
||||||
|
if(is_true(Aproves) && is_true(Bproves))
|
||||||
|
return ineq;
|
||||||
|
return my_and(Aproves,my_implies(Bproves,ineq));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_rewrite_chain(const ast &chain){
|
bool is_rewrite_chain(const ast &chain){
|
||||||
|
@ -623,7 +641,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
|
|
||||||
void sum_cond_ineq(ast &ineq, const ast &coeff2, const ast &ineq2, ast &Aproves, ast &Bproves){
|
void sum_cond_ineq(ast &ineq, const ast &coeff2, const ast &ineq2, ast &Aproves, ast &Bproves){
|
||||||
opr o = op(ineq2);
|
opr o = op(ineq2);
|
||||||
if(o == Implies){
|
if(o == And){
|
||||||
|
sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves);
|
||||||
|
Aproves = my_and(Aproves,arg(ineq2,0));
|
||||||
|
}
|
||||||
|
else if(o == Implies){
|
||||||
sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves);
|
sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves);
|
||||||
Bproves = my_and(Bproves,arg(ineq2,0));
|
Bproves = my_and(Bproves,arg(ineq2,0));
|
||||||
}
|
}
|
||||||
|
@ -683,23 +705,20 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return make(op(ineq),mk_idiv(arg(ineq,0),divisor),mk_idiv(arg(ineq,1),divisor));
|
return make(op(ineq),mk_idiv(arg(ineq,0),divisor),mk_idiv(arg(ineq,1),divisor));
|
||||||
}
|
}
|
||||||
|
|
||||||
ast rotate_sum_rec(const ast &pl, const ast &pf, ast &Bproves, ast &ineq){
|
ast rotate_sum_rec(const ast &pl, const ast &pf, ast &Aproves, ast &Bproves, ast &ineq){
|
||||||
if(pf == pl)
|
if(pf == pl){
|
||||||
return my_implies(Bproves,simplify_ineq(ineq));
|
if(sym(ineq) == normal)
|
||||||
|
return ineq;
|
||||||
|
return simplify_ineq(ineq);
|
||||||
|
}
|
||||||
if(op(pf) == Uninterpreted && sym(pf) == sum){
|
if(op(pf) == Uninterpreted && sym(pf) == sum){
|
||||||
if(arg(pf,2) == pl){
|
if(arg(pf,2) == pl){
|
||||||
ast Aproves = mk_true();
|
|
||||||
sum_cond_ineq(ineq,make_int("1"),arg(pf,0),Aproves,Bproves);
|
sum_cond_ineq(ineq,make_int("1"),arg(pf,0),Aproves,Bproves);
|
||||||
if(!is_true(Aproves))
|
|
||||||
throw "help!";
|
|
||||||
ineq = idiv_ineq(ineq,arg(pf,1));
|
ineq = idiv_ineq(ineq,arg(pf,1));
|
||||||
return my_implies(Bproves,ineq);
|
return ineq;
|
||||||
}
|
}
|
||||||
ast Aproves = mk_true();
|
|
||||||
sum_cond_ineq(ineq,arg(pf,1),arg(pf,2),Aproves,Bproves);
|
sum_cond_ineq(ineq,arg(pf,1),arg(pf,2),Aproves,Bproves);
|
||||||
if(!is_true(Aproves))
|
return rotate_sum_rec(pl,arg(pf,0),Aproves,Bproves,ineq);
|
||||||
throw "help!";
|
|
||||||
return rotate_sum_rec(pl,arg(pf,0),Bproves,ineq);
|
|
||||||
}
|
}
|
||||||
throw cannot_simplify();
|
throw cannot_simplify();
|
||||||
}
|
}
|
||||||
|
@ -749,6 +768,28 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast unmixed_eq2ineq(const ast &lhs, const ast &rhs, opr comp_op, const ast &equa, ast &cond){
|
||||||
|
ast ineqs= chain_ineqs(comp_op,LitA,equa,lhs,rhs); // chain must be from lhs to rhs
|
||||||
|
cond = my_and(cond,chain_conditions(LitA,equa));
|
||||||
|
ast Bconds = z3_simplify(chain_conditions(LitB,equa));
|
||||||
|
if(is_true(Bconds) && op(ineqs) != And)
|
||||||
|
return my_implies(cond,ineqs);
|
||||||
|
if(op(ineqs) != And)
|
||||||
|
return my_and(Bconds,my_implies(cond,ineqs));
|
||||||
|
throw "help!";
|
||||||
|
}
|
||||||
|
|
||||||
|
ast add_mixed_eq2ineq(const ast &lhs, const ast &rhs, const ast &equa, const ast &itp){
|
||||||
|
if(is_true(equa))
|
||||||
|
return itp;
|
||||||
|
std::vector<ast> args(3);
|
||||||
|
args[0] = itp;
|
||||||
|
args[1] = make_int("1");
|
||||||
|
ast ineq = make(Leq,make_int(rational(0)),make_int(rational(0)));
|
||||||
|
args[2] = make_normal(ineq,cons_normal(fix_normal(lhs,rhs,equa),mk_true()));
|
||||||
|
return simplify_sum(args);
|
||||||
|
}
|
||||||
|
|
||||||
ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){
|
ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){
|
||||||
if(pl == arg(pf,1)){
|
if(pl == arg(pf,1)){
|
||||||
ast cond = mk_true();
|
ast cond = mk_true();
|
||||||
|
@ -756,20 +797,21 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
if(is_equivrel_chain(equa)){
|
if(is_equivrel_chain(equa)){
|
||||||
ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove
|
ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove
|
||||||
LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs);
|
LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs);
|
||||||
if(lhst != LitMixed && rhst != LitMixed){
|
if(lhst != LitMixed && rhst != LitMixed)
|
||||||
ast ineqs= chain_ineqs(op(arg(neg_equality,0)),LitA,equa,lhs,rhs); // chain must be from lhs to rhs
|
return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond);
|
||||||
cond = my_and(cond,chain_conditions(LitA,equa));
|
|
||||||
ast Bconds = z3_simplify(chain_conditions(LitB,equa));
|
|
||||||
if(is_true(Bconds) && op(ineqs) != And)
|
|
||||||
return my_implies(cond,ineqs);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
ast itp = make(Leq,make_int(rational(0)),make_int(rational(0)));
|
ast left, left_term, middle, right_term, right;
|
||||||
return make_normal(itp,cons_normal(fix_normal(lhs,rhs,equa),mk_true()));
|
left = get_left_movers(equa,lhs,middle,left_term);
|
||||||
|
middle = get_right_movers(middle,rhs,right,right_term);
|
||||||
|
ast itp = unmixed_eq2ineq(left_term, right_term, op(arg(neg_equality,0)), middle, cond);
|
||||||
|
// itp = my_implies(cond,itp);
|
||||||
|
itp = add_mixed_eq2ineq(lhs, left_term, left, itp);
|
||||||
|
itp = add_mixed_eq2ineq(right_term, rhs, right, itp);
|
||||||
|
return itp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw cannot_simplify();
|
throw "help!";
|
||||||
}
|
}
|
||||||
|
|
||||||
void reverse_modpon(std::vector<ast> &args){
|
void reverse_modpon(std::vector<ast> &args){
|
||||||
|
@ -836,6 +878,8 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
ast equa = sep_cond(args[0],cond);
|
ast equa = sep_cond(args[0],cond);
|
||||||
if(is_equivrel_chain(equa))
|
if(is_equivrel_chain(equa))
|
||||||
return my_implies(cond,reverse_chain(equa));
|
return my_implies(cond,reverse_chain(equa));
|
||||||
|
if(is_negation_chain(equa))
|
||||||
|
return commute_negation_chain(equa);
|
||||||
throw cannot_simplify();
|
throw cannot_simplify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,7 +953,9 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
get_subterm_normals(ineq1,ineq2,tail,nc,top_pos,memo, Aproves, Bproves);
|
get_subterm_normals(ineq1,ineq2,tail,nc,top_pos,memo, Aproves, Bproves);
|
||||||
ast itp;
|
ast itp;
|
||||||
if(is_rewrite_side(LitA,head)){
|
if(is_rewrite_side(LitA,head)){
|
||||||
itp = ineq1;
|
itp = make(Leq,make_int("0"),make_int("0"));
|
||||||
|
linear_comb(itp,make_int("1"),ineq1); // make sure it is normal form
|
||||||
|
//itp = ineq1;
|
||||||
ast mc = z3_simplify(chain_side_proves(LitB,pref));
|
ast mc = z3_simplify(chain_side_proves(LitB,pref));
|
||||||
Bproves = my_and(Bproves,mc);
|
Bproves = my_and(Bproves,mc);
|
||||||
}
|
}
|
||||||
|
@ -951,7 +997,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
ast simplify_modpon(const std::vector<ast> &args){
|
ast simplify_modpon(const std::vector<ast> &args){
|
||||||
ast Aproves = mk_true(), Bproves = mk_true();
|
ast Aproves = mk_true(), Bproves = mk_true();
|
||||||
ast chain = simplify_modpon_fwd(args,Bproves);
|
ast chain = simplify_modpon_fwd(args,Bproves);
|
||||||
ast Q2 = sep_cond(args[2],Bproves);
|
ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves);
|
||||||
ast interp;
|
ast interp;
|
||||||
if(is_normal_ineq(Q2)){ // inequalities are special
|
if(is_normal_ineq(Q2)){ // inequalities are special
|
||||||
ast nQ2 = rewrite_chain_to_normal_ineq(chain,Aproves,Bproves);
|
ast nQ2 = rewrite_chain_to_normal_ineq(chain,Aproves,Bproves);
|
||||||
|
@ -1450,6 +1496,50 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return is_negation_chain(rest);
|
return is_negation_chain(rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast commute_negation_chain(const ast &chain){
|
||||||
|
if(is_true(chain))
|
||||||
|
return chain;
|
||||||
|
ast last = chain_last(chain);
|
||||||
|
ast rest = chain_rest(chain);
|
||||||
|
if(is_true(rest)){
|
||||||
|
ast old = rewrite_rhs(last);
|
||||||
|
if(!(op(old) == Not))
|
||||||
|
throw "bad negative equality chain";
|
||||||
|
ast equ = arg(old,0);
|
||||||
|
if(!is_equivrel(equ))
|
||||||
|
throw "bad negative equality chain";
|
||||||
|
last = rewrite_update_rhs(last,top_pos,make(Not,make(op(equ),arg(equ,1),arg(equ,0))),make(True));
|
||||||
|
return chain_cons(rest,last);
|
||||||
|
}
|
||||||
|
ast pos = rewrite_pos(last);
|
||||||
|
if(pos == top_pos)
|
||||||
|
throw "bad negative equality chain";
|
||||||
|
int idx = pos_arg(pos);
|
||||||
|
if(idx != 0)
|
||||||
|
throw "bad negative equality chain";
|
||||||
|
pos = arg(pos,1);
|
||||||
|
if(pos == top_pos){
|
||||||
|
ast lhs = rewrite_lhs(last);
|
||||||
|
ast rhs = rewrite_rhs(last);
|
||||||
|
if(op(lhs) != Equal || op(rhs) != Equal)
|
||||||
|
throw "bad negative equality chain";
|
||||||
|
last = make_rewrite(rewrite_side(last),rewrite_pos(last),rewrite_cond(last),
|
||||||
|
make(Iff,make(Equal,arg(lhs,1),arg(lhs,0)),make(Equal,arg(rhs,1),arg(rhs,0))));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idx = pos_arg(pos);
|
||||||
|
if(idx == 0)
|
||||||
|
idx = 1;
|
||||||
|
else if(idx == 1)
|
||||||
|
idx = 0;
|
||||||
|
else
|
||||||
|
throw "bad negative equality chain";
|
||||||
|
pos = pos_add(0,pos_add(idx,arg(pos,1)));
|
||||||
|
last = make_rewrite(rewrite_side(last),pos,rewrite_cond(last),rewrite_equ(last));
|
||||||
|
}
|
||||||
|
return chain_cons(commute_negation_chain(rest),last);
|
||||||
|
}
|
||||||
|
|
||||||
// split a rewrite chain into head and tail at last top-level rewrite
|
// split a rewrite chain into head and tail at last top-level rewrite
|
||||||
ast get_head_chain(const ast &chain, ast &tail, bool is_not = true){
|
ast get_head_chain(const ast &chain, ast &tail, bool is_not = true){
|
||||||
ast last = chain_last(chain);
|
ast last = chain_last(chain);
|
||||||
|
@ -1466,6 +1556,47 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// split a rewrite chain into head and tail at last non-mixed term
|
||||||
|
ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){
|
||||||
|
if(is_true(chain) || get_term_type(rhs) != LitMixed){
|
||||||
|
mid = rhs;
|
||||||
|
tail = mk_true();
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
ast last = chain_last(chain);
|
||||||
|
ast rest = chain_rest(chain);
|
||||||
|
ast mm = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last));
|
||||||
|
ast res = get_right_movers(rest,mm,tail,mid);
|
||||||
|
tail = chain_cons(tail,last);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// split a rewrite chain into head and tail at first non-mixed term
|
||||||
|
ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){
|
||||||
|
if(is_true(chain)){
|
||||||
|
mid = lhs;
|
||||||
|
if(get_term_type(lhs) != LitMixed){
|
||||||
|
tail = mk_true();
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
return ast();
|
||||||
|
}
|
||||||
|
ast last = chain_last(chain);
|
||||||
|
ast rest = chain_rest(chain);
|
||||||
|
ast res = get_left_movers(rest,lhs,tail,mid);
|
||||||
|
if(res.null()){
|
||||||
|
mid = subst_in_pos(mid,rewrite_pos(last),rewrite_rhs(last));
|
||||||
|
if(get_term_type(mid) != LitMixed){
|
||||||
|
tail = mk_true();
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
return ast();
|
||||||
|
}
|
||||||
|
tail = chain_cons(tail,last);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct cannot_split {};
|
struct cannot_split {};
|
||||||
|
|
||||||
/** Split a chain of rewrites two chains, operating on positions 0 and 1.
|
/** Split a chain of rewrites two chains, operating on positions 0 and 1.
|
||||||
|
@ -1668,11 +1799,13 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast fix_normal(const ast &lhs, const ast &rhs, const ast &proof){
|
ast fix_normal(const ast &lhs, const ast &rhs, const ast &proof){
|
||||||
|
LitType lhst = get_term_type(lhs);
|
||||||
LitType rhst = get_term_type(rhs);
|
LitType rhst = get_term_type(rhs);
|
||||||
if(rhst != LitMixed || ast_id(lhs) < ast_id(rhs))
|
if(lhst == LitMixed && (rhst != LitMixed || ast_id(lhs) < ast_id(rhs)))
|
||||||
return make_normal_step(lhs,rhs,proof);
|
return make_normal_step(lhs,rhs,proof);
|
||||||
else
|
if(rhst == LitMixed && (lhst != LitMixed || ast_id(rhs) < ast_id(lhs)))
|
||||||
return make_normal_step(rhs,lhs,reverse_chain(proof));
|
return make_normal_step(rhs,lhs,reverse_chain(proof));
|
||||||
|
throw "help!";
|
||||||
}
|
}
|
||||||
|
|
||||||
ast chain_side_proves(LitType side, const ast &chain){
|
ast chain_side_proves(LitType side, const ast &chain){
|
||||||
|
@ -1692,8 +1825,10 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
ast lhs2 = normal_lhs(f2);
|
ast lhs2 = normal_lhs(f2);
|
||||||
int id1 = ast_id(lhs1);
|
int id1 = ast_id(lhs1);
|
||||||
int id2 = ast_id(lhs2);
|
int id2 = ast_id(lhs2);
|
||||||
if(id1 < id2) return cons_normal(f1,merge_normal_chains_rec(normal_rest(chain1),chain2,trans,Aproves,Bproves));
|
if(id1 < id2)
|
||||||
if(id2 < id1) return cons_normal(f2,merge_normal_chains_rec(chain1,normal_rest(chain2),trans,Aproves,Bproves));
|
return cons_normal(f1,merge_normal_chains_rec(normal_rest(chain1),chain2,trans,Aproves,Bproves));
|
||||||
|
if(id2 < id1)
|
||||||
|
return cons_normal(f2,merge_normal_chains_rec(chain1,normal_rest(chain2),trans,Aproves,Bproves));
|
||||||
ast rhs1 = normal_rhs(f1);
|
ast rhs1 = normal_rhs(f1);
|
||||||
ast rhs2 = normal_rhs(f2);
|
ast rhs2 = normal_rhs(f2);
|
||||||
LitType t1 = get_term_type(rhs1);
|
LitType t1 = get_term_type(rhs1);
|
||||||
|
@ -1719,9 +1854,13 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
Aproves = my_and(Aproves,mcB);
|
Aproves = my_and(Aproves,mcB);
|
||||||
ast rep = apply_rewrite_chain(rhs1,Aproof);
|
ast rep = apply_rewrite_chain(rhs1,Aproof);
|
||||||
new_proof = concat_rewrite_chain(pf1,Aproof);
|
new_proof = concat_rewrite_chain(pf1,Aproof);
|
||||||
new_normal = make_normal_step(rhs1,rep,new_proof);
|
new_normal = make_normal_step(lhs1,rep,new_proof);
|
||||||
|
ast A_normal = make_normal_step(rhs1,rep,Aproof);
|
||||||
|
ast res = cons_normal(new_normal,merge_normal_chains_rec(normal_rest(chain1),normal_rest(chain2),trans,Aproves,Bproves));
|
||||||
|
res = merge_normal_chains_rec(res,cons_normal(A_normal,make(True)),trans,Aproves,Bproves);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else if(t1 == LitA && t2 == LitB)
|
else if(t1 == LitB && t2 == LitA)
|
||||||
return merge_normal_chains_rec(chain2,chain1,trans,Aproves,Bproves);
|
return merge_normal_chains_rec(chain2,chain1,trans,Aproves,Bproves);
|
||||||
else if(t1 == LitA) {
|
else if(t1 == LitA) {
|
||||||
ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2);
|
ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2);
|
||||||
|
@ -1743,17 +1882,20 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return chain;
|
return chain;
|
||||||
ast f = normal_first(chain);
|
ast f = normal_first(chain);
|
||||||
ast r = normal_rest(chain);
|
ast r = normal_rest(chain);
|
||||||
|
r = trans_normal_chain(r,trans);
|
||||||
ast rhs = normal_rhs(f);
|
ast rhs = normal_rhs(f);
|
||||||
hash_map<ast,ast>::iterator it = trans.find(rhs);
|
hash_map<ast,ast>::iterator it = trans.find(rhs);
|
||||||
ast new_normal;
|
ast new_normal;
|
||||||
if(it != trans.end()){
|
if(it != trans.end() && get_term_type(normal_lhs(f)) == LitMixed){
|
||||||
const ast &f2 = it->second;
|
const ast &f2 = it->second;
|
||||||
ast pf = concat_rewrite_chain(normal_proof(f),normal_proof(f2));
|
ast pf = concat_rewrite_chain(normal_proof(f),normal_proof(f2));
|
||||||
new_normal = make_normal_step(normal_lhs(f),normal_rhs(f2),pf);
|
new_normal = make_normal_step(normal_lhs(f),normal_rhs(f2),pf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
new_normal = f;
|
new_normal = f;
|
||||||
return cons_normal(new_normal,trans_normal_chain(r,trans));
|
if(get_term_type(normal_lhs(f)) == LitMixed)
|
||||||
|
trans[normal_lhs(f)] = new_normal;
|
||||||
|
return cons_normal(new_normal,r);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast merge_normal_chains(const ast &chain1, const ast &chain2, ast &Aproves, ast &Bproves){
|
ast merge_normal_chains(const ast &chain1, const ast &chain2, ast &Aproves, ast &Bproves){
|
||||||
|
@ -2011,8 +2153,14 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
/** Make a Reflexivity node. This rule produces |- x = x */
|
/** Make a Reflexivity node. This rule produces |- x = x */
|
||||||
|
|
||||||
virtual node make_reflexivity(ast con){
|
virtual node make_reflexivity(ast con){
|
||||||
throw proof_error();
|
if(get_term_type(con) == LitA)
|
||||||
}
|
return mk_false();
|
||||||
|
if(get_term_type(con) == LitB)
|
||||||
|
return mk_true();
|
||||||
|
ast itp = make(And,make(contra,no_proof,mk_false()),
|
||||||
|
make(contra,mk_true(),mk_not(con)));
|
||||||
|
return itp;
|
||||||
|
}
|
||||||
|
|
||||||
/** Make a Symmetry node. This takes a derivation of |- x = y and
|
/** Make a Symmetry node. This takes a derivation of |- x = y and
|
||||||
produces | y = x. Ditto for ~(x=y) */
|
produces | y = x. Ditto for ~(x=y) */
|
||||||
|
@ -2247,10 +2395,19 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
throw proof_error();
|
throw proof_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Qrhs = make(Times,c,Qrhs);
|
#if 0
|
||||||
bool pstrict = op(P) == Lt, strict = pstrict || qstrict;
|
bool pstrict = op(P) == Lt, strict = pstrict || qstrict;
|
||||||
if(pstrict && qstrict && round_off)
|
if(pstrict && qstrict && round_off)
|
||||||
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
||||||
|
#else
|
||||||
|
bool pstrict = op(P) == Lt;
|
||||||
|
if(qstrict && round_off && (pstrict || !(c == make_int(rational(1))))){
|
||||||
|
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
||||||
|
qstrict = false;
|
||||||
|
}
|
||||||
|
Qrhs = make(Times,c,Qrhs);
|
||||||
|
bool strict = pstrict || qstrict;
|
||||||
|
#endif
|
||||||
if(strict)
|
if(strict)
|
||||||
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
||||||
else
|
else
|
||||||
|
@ -2269,8 +2426,14 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
itp = mk_true();
|
itp = mk_true();
|
||||||
break;
|
break;
|
||||||
default: { // mixed equality
|
default: { // mixed equality
|
||||||
if(get_term_type(x) == LitMixed || get_term_type(y) == LitMixed)
|
if(get_term_type(x) == LitMixed || get_term_type(y) == LitMixed){
|
||||||
std::cerr << "WARNING: mixed term in leq2eq\n";
|
// std::cerr << "WARNING: mixed term in leq2eq\n";
|
||||||
|
std::vector<ast> lits;
|
||||||
|
lits.push_back(con);
|
||||||
|
lits.push_back(make(Not,xleqy));
|
||||||
|
lits.push_back(make(Not,yleqx));
|
||||||
|
return make_axiom(lits);
|
||||||
|
}
|
||||||
std::vector<ast> conjs; conjs.resize(3);
|
std::vector<ast> conjs; conjs.resize(3);
|
||||||
conjs[0] = mk_not(con);
|
conjs[0] = mk_not(con);
|
||||||
conjs[1] = xleqy;
|
conjs[1] = xleqy;
|
||||||
|
@ -2405,7 +2568,15 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
frng = srng; // this term will be localized
|
frng = srng; // this term will be localized
|
||||||
}
|
}
|
||||||
else if(o == Plus || o == Times){ // don't want bound variables inside arith ops
|
else if(o == Plus || o == Times){ // don't want bound variables inside arith ops
|
||||||
frng = erng; // this term will be localized
|
// std::cout << "WARNING: non-local arithmetic\n";
|
||||||
|
// frng = erng; // this term will be localized
|
||||||
|
}
|
||||||
|
else if(o == Select){ // treat the array term like a function symbol
|
||||||
|
prover::range srng = pv->ast_scope(arg(e,0));
|
||||||
|
if(!(srng.lo > srng.hi) && pv->ranges_intersect(srng,rng)) // localize to desired range if possible
|
||||||
|
frng = pv->range_glb(srng,rng);
|
||||||
|
else
|
||||||
|
frng = srng; // this term will be localized
|
||||||
}
|
}
|
||||||
std::vector<ast> largs(nargs);
|
std::vector<ast> largs(nargs);
|
||||||
std::vector<ast> eqs;
|
std::vector<ast> eqs;
|
||||||
|
@ -2434,7 +2605,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
return e; // this term occurs in range, so it's O.K.
|
return e; // this term occurs in range, so it's O.K.
|
||||||
|
|
||||||
if(is_array_type(get_type(e)))
|
if(is_array_type(get_type(e)))
|
||||||
throw "help!";
|
std::cerr << "WARNING: array quantifier\n";
|
||||||
|
|
||||||
// choose a frame for the constraint that is close to range
|
// choose a frame for the constraint that is close to range
|
||||||
int frame = pv->range_near(pv->ast_scope(e),rng);
|
int frame = pv->range_near(pv->ast_scope(e),rng);
|
||||||
|
|
|
@ -188,6 +188,15 @@ public:
|
||||||
get_Z3_lits(con, lits);
|
get_Z3_lits(con, lits);
|
||||||
iproof->make_axiom(lits);
|
iproof->make_axiom(lits);
|
||||||
}
|
}
|
||||||
|
#ifdef LOCALIZATION_KLUDGE
|
||||||
|
else if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST
|
||||||
|
&& get_locality_rec(prem(proof,1)) == INT_MAX){
|
||||||
|
std::vector<ast> lits;
|
||||||
|
ast con = conc(proof);
|
||||||
|
get_Z3_lits(con, lits);
|
||||||
|
iproof->make_axiom(lits);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else {
|
else {
|
||||||
unsigned nprems = num_prems(proof);
|
unsigned nprems = num_prems(proof);
|
||||||
for(unsigned i = 0; i < nprems; i++){
|
for(unsigned i = 0; i < nprems; i++){
|
||||||
|
@ -1271,6 +1280,84 @@ public:
|
||||||
return make(Plus,args);
|
return make(Plus,args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ast replace_summands_with_fresh_vars(const ast &t, hash_map<ast,ast> &map){
|
||||||
|
if(op(t) == Plus){
|
||||||
|
int nargs = num_args(t);
|
||||||
|
std::vector<ast> args(nargs);
|
||||||
|
for(int i = 0; i < nargs; i++)
|
||||||
|
args[i] = replace_summands_with_fresh_vars(arg(t,i),map);
|
||||||
|
return make(Plus,args);
|
||||||
|
}
|
||||||
|
if(op(t) == Times)
|
||||||
|
return make(Times,arg(t,0),replace_summands_with_fresh_vars(arg(t,1),map));
|
||||||
|
if(map.find(t) == map.end())
|
||||||
|
map[t] = mk_fresh_constant("@s",get_type(t));
|
||||||
|
return map[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
ast painfully_normalize_ineq(const ast &ineq, hash_map<ast,ast> &map){
|
||||||
|
ast res = normalize_inequality(ineq);
|
||||||
|
ast lhs = arg(res,0);
|
||||||
|
lhs = replace_summands_with_fresh_vars(lhs,map);
|
||||||
|
res = make(op(res),SortSum(lhs),arg(res,1));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iproof::node painfully_reconstruct_farkas(const std::vector<ast> &prems, const std::vector<Iproof::node> &pfs, const ast &con){
|
||||||
|
int nprems = prems.size();
|
||||||
|
std::vector<ast> pcons(nprems),npcons(nprems);
|
||||||
|
hash_map<ast,ast> pcon_to_pf, npcon_to_pcon, pain_map;
|
||||||
|
for(int i = 0; i < nprems; i++){
|
||||||
|
pcons[i] = conc(prems[i]);
|
||||||
|
npcons[i] = painfully_normalize_ineq(pcons[i],pain_map);
|
||||||
|
pcon_to_pf[npcons[i]] = pfs[i];
|
||||||
|
npcon_to_pcon[npcons[i]] = pcons[i];
|
||||||
|
}
|
||||||
|
// ast leq = make(Leq,arg(con,0),arg(con,1));
|
||||||
|
ast ncon = painfully_normalize_ineq(mk_not(con),pain_map);
|
||||||
|
pcons.push_back(mk_not(con));
|
||||||
|
npcons.push_back(ncon);
|
||||||
|
// ast assumps = make(And,pcons);
|
||||||
|
ast new_proof;
|
||||||
|
if(is_sat(npcons,new_proof))
|
||||||
|
throw "Proof error!";
|
||||||
|
pfrule dk = pr(new_proof);
|
||||||
|
int nnp = num_prems(new_proof);
|
||||||
|
std::vector<Iproof::node> my_prems;
|
||||||
|
std::vector<ast> farkas_coeffs, my_pcons;
|
||||||
|
|
||||||
|
if(dk == PR_TH_LEMMA
|
||||||
|
&& get_theory_lemma_theory(new_proof) == ArithTheory
|
||||||
|
&& get_theory_lemma_kind(new_proof) == FarkasKind)
|
||||||
|
get_farkas_coeffs(new_proof,farkas_coeffs);
|
||||||
|
else if(dk == PR_UNIT_RESOLUTION && nnp == 2){
|
||||||
|
for(int i = 0; i < nprems; i++)
|
||||||
|
farkas_coeffs.push_back(make_int(rational(1)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw "cannot reconstruct farkas proof";
|
||||||
|
|
||||||
|
for(int i = 0; i < nnp; i++){
|
||||||
|
ast p = conc(prem(new_proof,i));
|
||||||
|
p = really_normalize_ineq(p);
|
||||||
|
if(pcon_to_pf.find(p) != pcon_to_pf.end()){
|
||||||
|
my_prems.push_back(pcon_to_pf[p]);
|
||||||
|
my_pcons.push_back(npcon_to_pcon[p]);
|
||||||
|
}
|
||||||
|
else if(p == ncon){
|
||||||
|
my_prems.push_back(iproof->make_hypothesis(mk_not(con)));
|
||||||
|
my_pcons.push_back(mk_not(con));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw "cannot reconstruct farkas proof";
|
||||||
|
}
|
||||||
|
Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ast really_normalize_ineq(const ast &ineq){
|
ast really_normalize_ineq(const ast &ineq){
|
||||||
ast res = normalize_inequality(ineq);
|
ast res = normalize_inequality(ineq);
|
||||||
res = make(op(res),SortSum(arg(res,0)),arg(res,1));
|
res = make(op(res),SortSum(arg(res,0)),arg(res,1));
|
||||||
|
@ -1309,7 +1396,7 @@ public:
|
||||||
farkas_coeffs.push_back(make_int(rational(1)));
|
farkas_coeffs.push_back(make_int(rational(1)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw "cannot reconstruct farkas proof";
|
return painfully_reconstruct_farkas(prems,pfs,con);
|
||||||
|
|
||||||
for(int i = 0; i < nnp; i++){
|
for(int i = 0; i < nnp; i++){
|
||||||
ast p = conc(prem(new_proof,i));
|
ast p = conc(prem(new_proof,i));
|
||||||
|
@ -1452,9 +1539,11 @@ public:
|
||||||
lits.push_back(from_ast(con));
|
lits.push_back(from_ast(con));
|
||||||
|
|
||||||
// pattern match some idioms
|
// pattern match some idioms
|
||||||
if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST && pr(prem(proof,1)) == PR_REWRITE ) {
|
if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST){
|
||||||
res = iproof->make_axiom(lits);
|
if(get_locality_rec(prem(proof,1)) == INT_MAX) {
|
||||||
return res;
|
res = iproof->make_axiom(lits);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or){
|
if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or){
|
||||||
Iproof::node clause = translate_main(prem(proof,0),true);
|
Iproof::node clause = translate_main(prem(proof,0),true);
|
||||||
|
@ -1465,12 +1554,20 @@ public:
|
||||||
if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or)
|
if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or)
|
||||||
std::cout << "foo!\n";
|
std::cout << "foo!\n";
|
||||||
|
|
||||||
|
#if 0
|
||||||
if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){
|
if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){
|
||||||
Iproof::node clause = translate_main(prem(proof,0),true);
|
Iproof::node clause = translate_main(prem(proof,0),true);
|
||||||
res = make(commute,clause,conc(prem(proof,0))); // HACK -- we depend on Iproof::node being same as ast.
|
res = make(commute,clause,conc(prem(proof,0))); // HACK -- we depend on Iproof::node being same as ast.
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,0)) == PR_COMMUTATIVITY){
|
||||||
|
Iproof::node clause = translate_main(prem(proof,1),true);
|
||||||
|
res = make(commute,clause,conc(prem(proof,1))); // HACK -- we depend on Iproof::node being same as ast.
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(dk == PR_TRANSITIVITY && is_eq_propagate(prem(proof,1))){
|
if(dk == PR_TRANSITIVITY && is_eq_propagate(prem(proof,1))){
|
||||||
try {
|
try {
|
||||||
res = CombineEqPropagate(proof);
|
res = CombineEqPropagate(proof);
|
||||||
|
@ -1627,9 +1724,10 @@ public:
|
||||||
break;
|
break;
|
||||||
case ArrayTheory: {// nothing fancy for this
|
case ArrayTheory: {// nothing fancy for this
|
||||||
ast store_array;
|
ast store_array;
|
||||||
if(!get_store_array(con,store_array))
|
if(get_store_array(con,store_array))
|
||||||
throw unsupported();
|
res = iproof->make_axiom(lits,ast_scope(store_array));
|
||||||
res = iproof->make_axiom(lits,ast_scope(store_array));
|
else
|
||||||
|
res = iproof->make_axiom(lits); // for array extensionality axiom
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1653,6 +1751,12 @@ public:
|
||||||
res = args[0];
|
res = args[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PR_COMMUTATIVITY: {
|
||||||
|
ast comm_equiv = make(op(con),arg(con,0),arg(con,0));
|
||||||
|
ast pf = iproof->make_reflexivity(comm_equiv);
|
||||||
|
res = make(commute,pf,comm_equiv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(0 && "translate_main: unsupported proof rule");
|
assert(0 && "translate_main: unsupported proof rule");
|
||||||
throw unsupported();
|
throw unsupported();
|
||||||
|
|
|
@ -1465,6 +1465,10 @@ namespace datalog {
|
||||||
if (m_rules.get_num_rules() == 0) {
|
if (m_rules.get_num_rules() == 0) {
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
|
if (m_rules.get_predicate_rules(m_query_pred).empty()) {
|
||||||
|
return l_false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (is_linear()) {
|
if (is_linear()) {
|
||||||
if (m_ctx.get_engine() == QBMC_ENGINE) {
|
if (m_ctx.get_engine() == QBMC_ENGINE) {
|
||||||
|
|
0
src/muz/duality/duality_dl_interface.cpp
Normal file → Executable file
0
src/muz/duality/duality_dl_interface.cpp
Normal file → Executable file
|
@ -850,6 +850,13 @@ namespace smt2 {
|
||||||
for (unsigned i = 0; i < sz; i++) {
|
for (unsigned i = 0; i < sz; i++) {
|
||||||
pdatatype_decl * d = new_dt_decls[i];
|
pdatatype_decl * d = new_dt_decls[i];
|
||||||
SASSERT(d != 0);
|
SASSERT(d != 0);
|
||||||
|
symbol duplicated;
|
||||||
|
if (d->has_duplicate_accessors(duplicated)) {
|
||||||
|
std::string err_msg = "invalid datatype declaration, repeated accessor identifier '";
|
||||||
|
err_msg += duplicated.str();
|
||||||
|
err_msg += "'";
|
||||||
|
throw parser_exception(err_msg, line, pos);
|
||||||
|
}
|
||||||
m_ctx.insert(d);
|
m_ctx.insert(d);
|
||||||
if (d->get_num_params() == 0) {
|
if (d->get_num_params() == 0) {
|
||||||
// if datatype is not parametric... then force instantiation to register accessor, recognizers and constructors...
|
// if datatype is not parametric... then force instantiation to register accessor, recognizers and constructors...
|
||||||
|
@ -2070,6 +2077,7 @@ namespace smt2 {
|
||||||
|
|
||||||
void parse_option_value() {
|
void parse_option_value() {
|
||||||
switch (curr()) {
|
switch (curr()) {
|
||||||
|
case scanner::BV_TOKEN:
|
||||||
case scanner::INT_TOKEN:
|
case scanner::INT_TOKEN:
|
||||||
case scanner::FLOAT_TOKEN:
|
case scanner::FLOAT_TOKEN:
|
||||||
m_curr_cmd->set_next_arg(m_ctx, m_scanner.get_number());
|
m_curr_cmd->set_next_arg(m_ctx, m_scanner.get_number());
|
||||||
|
|
|
@ -87,7 +87,7 @@ void display_usage() {
|
||||||
std::cout << "\nResources:\n";
|
std::cout << "\nResources:\n";
|
||||||
// timeout and memout are now available on Linux and OSX too.
|
// timeout and memout are now available on Linux and OSX too.
|
||||||
std::cout << " -T:timeout set the timeout (in seconds).\n";
|
std::cout << " -T:timeout set the timeout (in seconds).\n";
|
||||||
std::cout << " -t:timeout set the soft timeout (in seconds). It only kills the current query.\n";
|
std::cout << " -t:timeout set the soft timeout (in milli seconds). It only kills the current query.\n";
|
||||||
std::cout << " -memory:Megabytes set a limit for virtual memory consumption.\n";
|
std::cout << " -memory:Megabytes set a limit for virtual memory consumption.\n";
|
||||||
//
|
//
|
||||||
std::cout << "\nOutput:\n";
|
std::cout << "\nOutput:\n";
|
||||||
|
|
|
@ -28,7 +28,6 @@ enum arith_solver_id {
|
||||||
AS_ARITH,
|
AS_ARITH,
|
||||||
AS_DENSE_DIFF_LOGIC,
|
AS_DENSE_DIFF_LOGIC,
|
||||||
AS_UTVPI,
|
AS_UTVPI,
|
||||||
AS_HORN,
|
|
||||||
AS_OPTINF
|
AS_OPTINF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -441,10 +441,10 @@ namespace smt {
|
||||||
virtual bool mbqi_enabled(quantifier *q) const {
|
virtual bool mbqi_enabled(quantifier *q) const {
|
||||||
if(!m_fparams->m_mbqi_id) return true;
|
if(!m_fparams->m_mbqi_id) return true;
|
||||||
const symbol &s = q->get_qid();
|
const symbol &s = q->get_qid();
|
||||||
unsigned len = strlen(m_fparams->m_mbqi_id);
|
size_t len = strlen(m_fparams->m_mbqi_id);
|
||||||
if(s == symbol::null || s.is_numerical())
|
if(s == symbol::null || s.is_numerical())
|
||||||
return len == 0;
|
return len == 0;
|
||||||
return strncmp(s.bare_str(),m_fparams->m_mbqi_id,static_cast<unsigned>(len)) == 0;
|
return strncmp(s.bare_str(),m_fparams->m_mbqi_id,len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Quantifier id's must begin with the prefix specified by
|
/* Quantifier id's must begin with the prefix specified by
|
||||||
|
|
|
@ -22,7 +22,6 @@ Revision History:
|
||||||
#include"theory_arith.h"
|
#include"theory_arith.h"
|
||||||
#include"theory_dense_diff_logic.h"
|
#include"theory_dense_diff_logic.h"
|
||||||
#include"theory_diff_logic.h"
|
#include"theory_diff_logic.h"
|
||||||
#include"theory_horn_ineq.h"
|
|
||||||
#include"theory_utvpi.h"
|
#include"theory_utvpi.h"
|
||||||
#include"theory_array.h"
|
#include"theory_array.h"
|
||||||
#include"theory_array_full.h"
|
#include"theory_array_full.h"
|
||||||
|
@ -731,12 +730,6 @@ namespace smt {
|
||||||
m_context.register_plugin(alloc(smt::theory_dense_mi, m_manager, m_params));
|
m_context.register_plugin(alloc(smt::theory_dense_mi, m_manager, m_params));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AS_HORN:
|
|
||||||
if (m_params.m_arith_int_only)
|
|
||||||
m_context.register_plugin(alloc(smt::theory_ihi, m_manager));
|
|
||||||
else
|
|
||||||
m_context.register_plugin(alloc(smt::theory_rhi, m_manager));
|
|
||||||
break;
|
|
||||||
case AS_UTVPI:
|
case AS_UTVPI:
|
||||||
if (m_params.m_arith_int_only)
|
if (m_params.m_arith_int_only)
|
||||||
m_context.register_plugin(alloc(smt::theory_iutvpi, m_manager));
|
m_context.register_plugin(alloc(smt::theory_iutvpi, m_manager));
|
||||||
|
|
|
@ -139,22 +139,32 @@ protected:
|
||||||
SASSERT(g.is_well_sorted());
|
SASSERT(g.is_well_sorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct expr_pos {
|
||||||
|
unsigned m_parent;
|
||||||
|
unsigned m_self;
|
||||||
|
unsigned m_idx;
|
||||||
|
expr* m_expr;
|
||||||
|
expr_pos(unsigned p, unsigned s, unsigned i, expr* e):
|
||||||
|
m_parent(p), m_self(s), m_idx(i), m_expr(e)
|
||||||
|
{}
|
||||||
|
expr_pos():
|
||||||
|
m_parent(0), m_self(0), m_idx(0), m_expr(0)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
void reduce(expr_ref& result){
|
void reduce(expr_ref& result){
|
||||||
SASSERT(m.is_bool(result));
|
SASSERT(m.is_bool(result));
|
||||||
ptr_vector<expr> todo;
|
|
||||||
ptr_vector<expr> names;
|
ptr_vector<expr> names;
|
||||||
svector<bool> is_checked;
|
svector<expr_pos> todo;
|
||||||
svector<unsigned> parent_ids, self_ids;
|
|
||||||
expr_ref_vector fresh_vars(m), trail(m);
|
expr_ref_vector fresh_vars(m), trail(m);
|
||||||
expr_ref res(m), tmp(m);
|
expr_ref res(m), tmp(m);
|
||||||
obj_map<expr,std::pair<unsigned, expr*> > cache;
|
obj_map<expr, expr_pos> cache;
|
||||||
unsigned id = 1;
|
unsigned id = 1, child_id = 0;
|
||||||
expr_ref n2(m), fml(m);
|
expr_ref n2(m), fml(m);
|
||||||
unsigned path_id = 0, self_pos = 0;
|
unsigned parent_pos = 0, self_pos = 0, self_idx = 0;
|
||||||
app * a;
|
app * a;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
std::pair<unsigned,expr*> path_r;
|
expr_pos path_r;
|
||||||
ptr_vector<expr> found;
|
|
||||||
expr_ref_vector args(m);
|
expr_ref_vector args(m);
|
||||||
expr_ref n = mk_fresh(id, m.mk_bool_sort());
|
expr_ref n = mk_fresh(id, m.mk_bool_sort());
|
||||||
trail.push_back(n);
|
trail.push_back(n);
|
||||||
|
@ -163,26 +173,25 @@ protected:
|
||||||
tmp = m.mk_not(m.mk_iff(fml, n));
|
tmp = m.mk_not(m.mk_iff(fml, n));
|
||||||
m_solver.assert_expr(tmp);
|
m_solver.assert_expr(tmp);
|
||||||
|
|
||||||
todo.push_back(fml);
|
todo.push_back(expr_pos(0,0,0,fml));
|
||||||
names.push_back(n);
|
names.push_back(n);
|
||||||
is_checked.push_back(false);
|
|
||||||
parent_ids.push_back(0);
|
|
||||||
self_ids.push_back(0);
|
|
||||||
m_solver.push();
|
m_solver.push();
|
||||||
|
|
||||||
while (!todo.empty() && !m_cancel) {
|
while (!todo.empty() && !m_cancel) {
|
||||||
expr_ref res(m);
|
expr_ref res(m);
|
||||||
args.reset();
|
args.reset();
|
||||||
expr* e = todo.back();
|
expr* e = todo.back().m_expr;
|
||||||
unsigned pos = parent_ids.back();
|
self_pos = todo.back().m_self;
|
||||||
|
parent_pos = todo.back().m_parent;
|
||||||
|
self_idx = todo.back().m_idx;
|
||||||
n = names.back();
|
n = names.back();
|
||||||
bool checked = is_checked.back();
|
|
||||||
|
|
||||||
if (cache.contains(e)) {
|
if (cache.contains(e)) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (m.is_bool(e) && !checked && simplify_bool(n, res)) {
|
if (m.is_bool(e) && simplify_bool(n, res)) {
|
||||||
TRACE("ctx_solver_simplify_tactic", tout << "simplified: " << mk_pp(e, m) << " |-> " << mk_pp(res, m) << "\n";);
|
TRACE("ctx_solver_simplify_tactic",
|
||||||
|
tout << "simplified: " << mk_pp(e, m) << " |-> " << mk_pp(res, m) << "\n";);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (!is_app(e)) {
|
if (!is_app(e)) {
|
||||||
|
@ -191,49 +200,31 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
a = to_app(e);
|
a = to_app(e);
|
||||||
if (!is_checked.back()) {
|
sz = a->get_num_args();
|
||||||
self_ids.back() = ++path_id;
|
|
||||||
is_checked.back() = true;
|
|
||||||
}
|
|
||||||
self_pos = self_ids.back();
|
|
||||||
sz = a->get_num_args();
|
|
||||||
|
|
||||||
n2 = 0;
|
n2 = 0;
|
||||||
|
|
||||||
found.reset(); // arguments already simplified.
|
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
expr* arg = a->get_arg(i);
|
expr* arg = a->get_arg(i);
|
||||||
if (cache.find(arg, path_r) && !found.contains(arg)) {
|
if (cache.find(arg, path_r)) {
|
||||||
//
|
//
|
||||||
// This is a single traversal version of the context
|
// This is a single traversal version of the context
|
||||||
// simplifier. It simplifies only the first occurrence of
|
// simplifier. It simplifies only the first occurrence of
|
||||||
// a sub-term with respect to the context.
|
// a sub-term with respect to the context.
|
||||||
//
|
//
|
||||||
|
|
||||||
found.push_back(arg);
|
if (path_r.m_parent == self_pos && path_r.m_idx == i) {
|
||||||
if (path_r.first == self_pos) {
|
args.push_back(path_r.m_expr);
|
||||||
TRACE("ctx_solver_simplify_tactic", tout << "cached " << mk_pp(arg, m) << " |-> " << mk_pp(path_r.second, m) << "\n";);
|
|
||||||
args.push_back(path_r.second);
|
|
||||||
}
|
|
||||||
else if (m.is_bool(arg)) {
|
|
||||||
res = local_simplify(a, n, id, i);
|
|
||||||
TRACE("ctx_solver_simplify_tactic",
|
|
||||||
tout << "Already cached: " << path_r.first << " " << mk_pp(arg, m) << " |-> " << mk_pp(res, m) << "\n";);
|
|
||||||
args.push_back(res);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
args.push_back(arg);
|
args.push_back(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!n2 && !found.contains(arg)) {
|
else if (!n2) {
|
||||||
n2 = mk_fresh(id, m.get_sort(arg));
|
n2 = mk_fresh(id, m.get_sort(arg));
|
||||||
trail.push_back(n2);
|
trail.push_back(n2);
|
||||||
todo.push_back(arg);
|
todo.push_back(expr_pos(self_pos, child_id++, i, arg));
|
||||||
parent_ids.push_back(self_pos);
|
|
||||||
self_ids.push_back(0);
|
|
||||||
names.push_back(n2);
|
names.push_back(n2);
|
||||||
args.push_back(n2);
|
args.push_back(n2);
|
||||||
is_checked.push_back(false);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
args.push_back(arg);
|
args.push_back(arg);
|
||||||
|
@ -251,22 +242,16 @@ protected:
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (res) {
|
if (res) {
|
||||||
cache.insert(e, std::make_pair(pos, res));
|
cache.insert(e, expr_pos(parent_pos, self_pos, self_idx, res));
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("ctx_solver_simplify_tactic",
|
|
||||||
tout << mk_pp(e, m) << " checked: " << checked << " cached: " << mk_pp(res?res.get():e, m) << "\n";);
|
|
||||||
|
|
||||||
todo.pop_back();
|
todo.pop_back();
|
||||||
parent_ids.pop_back();
|
|
||||||
self_ids.pop_back();
|
|
||||||
names.pop_back();
|
names.pop_back();
|
||||||
is_checked.pop_back();
|
|
||||||
m_solver.pop(1);
|
m_solver.pop(1);
|
||||||
}
|
}
|
||||||
if (!m_cancel) {
|
if (!m_cancel) {
|
||||||
VERIFY(cache.find(fml, path_r));
|
VERIFY(cache.find(fml, path_r));
|
||||||
result = path_r.second;
|
result = path_r.m_expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,32 +291,6 @@ protected:
|
||||||
}
|
}
|
||||||
return expr_ref(m.mk_app(fn, m_arith.mk_numeral(rational(id++), true)), m);
|
return expr_ref(m.mk_app(fn, m_arith.mk_numeral(rational(id++), true)), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
expr_ref local_simplify(app* a, expr* n, unsigned& id, unsigned index) {
|
|
||||||
SASSERT(index < a->get_num_args());
|
|
||||||
SASSERT(m.is_bool(a->get_arg(index)));
|
|
||||||
expr_ref n2(m), result(m), tmp(m);
|
|
||||||
n2 = mk_fresh(id, m.get_sort(a->get_arg(index)));
|
|
||||||
ptr_buffer<expr> args;
|
|
||||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
|
||||||
if (i == index) {
|
|
||||||
args.push_back(n2);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args.push_back(a->get_arg(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_mk_app(a->get_decl(), args.size(), args.c_ptr(), result);
|
|
||||||
m_solver.push();
|
|
||||||
tmp = m.mk_eq(result, n);
|
|
||||||
m_solver.assert_expr(tmp);
|
|
||||||
if (!simplify_bool(n2, result)) {
|
|
||||||
result = a->get_arg(index);
|
|
||||||
}
|
|
||||||
m_solver.pop(1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,236 +0,0 @@
|
||||||
/*++
|
|
||||||
Copyright (c) 2013 Microsoft Corporation
|
|
||||||
|
|
||||||
Module Name:
|
|
||||||
|
|
||||||
theory_horn_ineq.h
|
|
||||||
|
|
||||||
Author:
|
|
||||||
|
|
||||||
Nikolaj Bjorner (nbjorner) 2013-04-18
|
|
||||||
|
|
||||||
Revision History:
|
|
||||||
|
|
||||||
The implementaton is derived from theory_diff_logic.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
#include "theory_horn_ineq.h"
|
|
||||||
#include "theory_horn_ineq_def.h"
|
|
||||||
|
|
||||||
namespace smt {
|
|
||||||
|
|
||||||
template class theory_horn_ineq<ihi_ext>;
|
|
||||||
template class theory_horn_ineq<rhi_ext>;
|
|
||||||
|
|
||||||
// similar to test_diff_logic:
|
|
||||||
|
|
||||||
horn_ineq_tester::horn_ineq_tester(ast_manager& m): m(m), a(m) {}
|
|
||||||
|
|
||||||
bool horn_ineq_tester::operator()(expr* e) {
|
|
||||||
m_todo.reset();
|
|
||||||
m_pols.reset();
|
|
||||||
pos_mark.reset();
|
|
||||||
neg_mark.reset();
|
|
||||||
m_todo.push_back(e);
|
|
||||||
m_pols.push_back(l_true);
|
|
||||||
while (!m_todo.empty()) {
|
|
||||||
expr* e = m_todo.back();
|
|
||||||
lbool p = m_pols.back();
|
|
||||||
m_todo.pop_back();
|
|
||||||
m_pols.pop_back();
|
|
||||||
switch (p) {
|
|
||||||
case l_true:
|
|
||||||
if (pos_mark.is_marked(e)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pos_mark.mark(e, true);
|
|
||||||
break;
|
|
||||||
case l_false:
|
|
||||||
if (neg_mark.is_marked(e)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
neg_mark.mark(e, true);
|
|
||||||
break;
|
|
||||||
case l_undef:
|
|
||||||
if (pos_mark.is_marked(e) && neg_mark.is_marked(e)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pos_mark.mark(e, true);
|
|
||||||
neg_mark.mark(e, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!test_expr(p, e)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<std::pair<expr*,rational> > const& horn_ineq_tester::get_linearization() const {
|
|
||||||
return m_terms;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool horn_ineq_tester::test_expr(lbool p, expr* e) {
|
|
||||||
expr* e1, *e2, *e3;
|
|
||||||
if (is_var(e)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!is_app(e)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
app* ap = to_app(e);
|
|
||||||
if (m.is_and(ap) || m.is_or(ap)) {
|
|
||||||
for (unsigned i = 0; i < ap->get_num_args(); ++i) {
|
|
||||||
m_todo.push_back(ap->get_arg(i));
|
|
||||||
m_pols.push_back(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m.is_not(e, e1)) {
|
|
||||||
m_todo.push_back(e);
|
|
||||||
m_pols.push_back(~p);
|
|
||||||
}
|
|
||||||
else if (m.is_ite(e, e1, e2, e3)) {
|
|
||||||
m_todo.push_back(e1);
|
|
||||||
m_pols.push_back(l_undef);
|
|
||||||
m_todo.push_back(e2);
|
|
||||||
m_pols.push_back(p);
|
|
||||||
m_todo.push_back(e3);
|
|
||||||
m_pols.push_back(p);
|
|
||||||
}
|
|
||||||
else if (m.is_iff(e, e1, e2)) {
|
|
||||||
m_todo.push_back(e1);
|
|
||||||
m_pols.push_back(l_undef);
|
|
||||||
m_todo.push_back(e2);
|
|
||||||
m_pols.push_back(l_undef);
|
|
||||||
m_todo.push_back(e2);
|
|
||||||
}
|
|
||||||
else if (m.is_implies(e, e1, e2)) {
|
|
||||||
m_todo.push_back(e1);
|
|
||||||
m_pols.push_back(~p);
|
|
||||||
m_todo.push_back(e2);
|
|
||||||
m_pols.push_back(p);
|
|
||||||
}
|
|
||||||
else if (m.is_eq(e, e1, e2)) {
|
|
||||||
return linearize(e1, e2) == diff;
|
|
||||||
}
|
|
||||||
else if (m.is_true(e) || m.is_false(e)) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
else if (a.is_le(e, e1, e2) || a.is_ge(e, e2, e1) ||
|
|
||||||
a.is_lt(e, e1, e2) || a.is_gt(e, e2, e1)) {
|
|
||||||
if (p == l_false) {
|
|
||||||
std::swap(e2, e1);
|
|
||||||
}
|
|
||||||
classify_t cl = linearize(e1, e2);
|
|
||||||
switch(p) {
|
|
||||||
case l_undef:
|
|
||||||
return cl == diff;
|
|
||||||
case l_true:
|
|
||||||
case l_false:
|
|
||||||
return cl == horn || cl == diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!is_uninterp_const(e)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool horn_ineq_tester::operator()(unsigned num_fmls, expr* const* fmls) {
|
|
||||||
for (unsigned i = 0; i < num_fmls; ++i) {
|
|
||||||
if (!(*this)(fmls[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
horn_ineq_tester::classify_t horn_ineq_tester::linearize(expr* e) {
|
|
||||||
m_terms.reset();
|
|
||||||
m_terms.push_back(std::make_pair(e, rational(1)));
|
|
||||||
return linearize();
|
|
||||||
}
|
|
||||||
|
|
||||||
horn_ineq_tester::classify_t horn_ineq_tester::linearize(expr* e1, expr* e2) {
|
|
||||||
m_terms.reset();
|
|
||||||
m_terms.push_back(std::make_pair(e1, rational(1)));
|
|
||||||
m_terms.push_back(std::make_pair(e2, rational(-1)));
|
|
||||||
return linearize();
|
|
||||||
}
|
|
||||||
|
|
||||||
horn_ineq_tester::classify_t horn_ineq_tester::linearize() {
|
|
||||||
|
|
||||||
m_weight.reset();
|
|
||||||
m_coeff_map.reset();
|
|
||||||
|
|
||||||
while (!m_terms.empty()) {
|
|
||||||
expr* e1, *e2;
|
|
||||||
rational num;
|
|
||||||
rational mul = m_terms.back().second;
|
|
||||||
expr* e = m_terms.back().first;
|
|
||||||
m_terms.pop_back();
|
|
||||||
if (a.is_add(e)) {
|
|
||||||
for (unsigned i = 0; i < to_app(e)->get_num_args(); ++i) {
|
|
||||||
m_terms.push_back(std::make_pair(to_app(e)->get_arg(i), mul));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (a.is_mul(e, e1, e2) && a.is_numeral(e1, num)) {
|
|
||||||
m_terms.push_back(std::make_pair(e2, mul*num));
|
|
||||||
}
|
|
||||||
else if (a.is_mul(e, e2, e1) && a.is_numeral(e1, num)) {
|
|
||||||
m_terms.push_back(std::make_pair(e2, mul*num));
|
|
||||||
}
|
|
||||||
else if (a.is_sub(e, e1, e2)) {
|
|
||||||
m_terms.push_back(std::make_pair(e1, mul));
|
|
||||||
m_terms.push_back(std::make_pair(e2, -mul));
|
|
||||||
}
|
|
||||||
else if (a.is_uminus(e, e1)) {
|
|
||||||
m_terms.push_back(std::make_pair(e1, -mul));
|
|
||||||
}
|
|
||||||
else if (a.is_numeral(e, num)) {
|
|
||||||
m_weight += num*mul;
|
|
||||||
}
|
|
||||||
else if (a.is_to_real(e, e1)) {
|
|
||||||
m_terms.push_back(std::make_pair(e1, mul));
|
|
||||||
}
|
|
||||||
else if (!is_uninterp_const(e)) {
|
|
||||||
return non_horn;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_coeff_map.insert_if_not_there2(e, rational(0))->get_data().m_value += mul;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsigned num_negative = 0;
|
|
||||||
unsigned num_positive = 0;
|
|
||||||
bool is_unit_pos = true, is_unit_neg = true;
|
|
||||||
obj_map<expr, rational>::iterator it = m_coeff_map.begin();
|
|
||||||
obj_map<expr, rational>::iterator end = m_coeff_map.end();
|
|
||||||
for (; it != end; ++it) {
|
|
||||||
rational r = it->m_value;
|
|
||||||
if (r.is_zero()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
m_terms.push_back(std::make_pair(it->m_key, r));
|
|
||||||
if (r.is_pos()) {
|
|
||||||
is_unit_pos = is_unit_pos && r.is_one();
|
|
||||||
num_positive++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
is_unit_neg = is_unit_neg && r.is_minus_one();
|
|
||||||
num_negative++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num_negative <= 1 && is_unit_pos && is_unit_neg && num_positive <= 1) {
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
if (num_positive <= 1 && is_unit_pos) {
|
|
||||||
return horn;
|
|
||||||
}
|
|
||||||
if (num_negative <= 1 && is_unit_neg) {
|
|
||||||
return co_horn;
|
|
||||||
}
|
|
||||||
return non_horn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,328 +0,0 @@
|
||||||
/*++
|
|
||||||
Copyright (c) 2013 Microsoft Corporation
|
|
||||||
|
|
||||||
Module Name:
|
|
||||||
|
|
||||||
theory_horn_ineq.h
|
|
||||||
|
|
||||||
Abstract:
|
|
||||||
|
|
||||||
A*x <= weight + D*x, coefficients to A and D are non-negative,
|
|
||||||
D is a diagonal matrix.
|
|
||||||
Coefficients to weight may have both signs.
|
|
||||||
|
|
||||||
Label variables by weight.
|
|
||||||
Select inequality that is not satisfied.
|
|
||||||
Set delta(LHS) := 0
|
|
||||||
Set delta(RHS(x)) := weight(x) - b
|
|
||||||
Propagate weight increment through inequalities.
|
|
||||||
|
|
||||||
Author:
|
|
||||||
|
|
||||||
Nikolaj Bjorner (nbjorner) 2013-04-18
|
|
||||||
|
|
||||||
Revision History:
|
|
||||||
|
|
||||||
The implementaton is derived from theory_diff_logic.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
|
|
||||||
#ifndef _THEORY_HORN_INEQ_H_
|
|
||||||
#define _THEORY_HORN_INEQ_H_
|
|
||||||
|
|
||||||
#include"rational.h"
|
|
||||||
#include"inf_rational.h"
|
|
||||||
#include"inf_int_rational.h"
|
|
||||||
#include"inf_eps_rational.h"
|
|
||||||
#include"smt_theory.h"
|
|
||||||
#include"arith_decl_plugin.h"
|
|
||||||
#include"smt_justification.h"
|
|
||||||
#include"map.h"
|
|
||||||
#include"smt_params.h"
|
|
||||||
#include"arith_eq_adapter.h"
|
|
||||||
#include"smt_model_generator.h"
|
|
||||||
#include"numeral_factory.h"
|
|
||||||
#include"smt_clause.h"
|
|
||||||
|
|
||||||
namespace smt {
|
|
||||||
|
|
||||||
class horn_ineq_tester {
|
|
||||||
ast_manager& m;
|
|
||||||
arith_util a;
|
|
||||||
ptr_vector<expr> m_todo;
|
|
||||||
svector<lbool> m_pols;
|
|
||||||
ast_mark pos_mark, neg_mark;
|
|
||||||
obj_map<expr, rational> m_coeff_map;
|
|
||||||
rational m_weight;
|
|
||||||
vector<std::pair<expr*, rational> > m_terms;
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum classify_t {
|
|
||||||
co_horn,
|
|
||||||
horn,
|
|
||||||
diff,
|
|
||||||
non_horn
|
|
||||||
};
|
|
||||||
horn_ineq_tester(ast_manager& m);
|
|
||||||
|
|
||||||
// test if formula is in the Horn inequality fragment:
|
|
||||||
bool operator()(expr* fml);
|
|
||||||
bool operator()(unsigned num_fmls, expr* const* fmls);
|
|
||||||
|
|
||||||
// linearize inequality/equality
|
|
||||||
classify_t linearize(expr* e);
|
|
||||||
classify_t linearize(expr* e1, expr* e2);
|
|
||||||
|
|
||||||
// retrieve linearization
|
|
||||||
vector<std::pair<expr*,rational> > const& get_linearization() const;
|
|
||||||
rational const& get_weight() const { return m_weight; }
|
|
||||||
private:
|
|
||||||
bool test_expr(lbool p, expr* e);
|
|
||||||
classify_t linearize();
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Ext>
|
|
||||||
class theory_horn_ineq : public theory, private Ext {
|
|
||||||
|
|
||||||
typedef typename Ext::numeral numeral;
|
|
||||||
typedef typename Ext::inf_numeral inf_numeral;
|
|
||||||
typedef literal explanation;
|
|
||||||
typedef theory_var th_var;
|
|
||||||
typedef svector<th_var> th_var_vector;
|
|
||||||
typedef unsigned clause_id;
|
|
||||||
typedef vector<std::pair<th_var, rational> > coeffs;
|
|
||||||
|
|
||||||
class clause;
|
|
||||||
class graph;
|
|
||||||
class assignment_trail;
|
|
||||||
class parent_trail;
|
|
||||||
|
|
||||||
class atom {
|
|
||||||
protected:
|
|
||||||
bool_var m_bvar;
|
|
||||||
bool m_true;
|
|
||||||
int m_pos;
|
|
||||||
int m_neg;
|
|
||||||
public:
|
|
||||||
atom(bool_var bv, int pos, int neg) :
|
|
||||||
m_bvar(bv), m_true(false),
|
|
||||||
m_pos(pos), m_neg(neg) {}
|
|
||||||
~atom() {}
|
|
||||||
bool_var get_bool_var() const { return m_bvar; }
|
|
||||||
bool is_true() const { return m_true; }
|
|
||||||
void assign_eh(bool is_true) { m_true = is_true; }
|
|
||||||
int get_asserted_edge() const { return this->m_true?m_pos:m_neg; }
|
|
||||||
int get_pos() const { return m_pos; }
|
|
||||||
int get_neg() const { return m_neg; }
|
|
||||||
std::ostream& display(theory_horn_ineq const& th, std::ostream& out) const;
|
|
||||||
};
|
|
||||||
typedef svector<atom> atoms;
|
|
||||||
|
|
||||||
struct scope {
|
|
||||||
unsigned m_atoms_lim;
|
|
||||||
unsigned m_asserted_atoms_lim;
|
|
||||||
unsigned m_asserted_qhead_old;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stats {
|
|
||||||
unsigned m_num_conflicts;
|
|
||||||
unsigned m_num_assertions;
|
|
||||||
unsigned m_num_core2th_eqs;
|
|
||||||
unsigned m_num_core2th_diseqs;
|
|
||||||
|
|
||||||
void reset() {
|
|
||||||
memset(this, 0, sizeof(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
stats() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
stats m_stats;
|
|
||||||
smt_params m_params;
|
|
||||||
arith_util a;
|
|
||||||
arith_eq_adapter m_arith_eq_adapter;
|
|
||||||
th_var m_zero_int; // cache the variable representing the zero variable.
|
|
||||||
th_var m_zero_real; // cache the variable representing the zero variable.
|
|
||||||
|
|
||||||
graph* m_graph;
|
|
||||||
atoms m_atoms;
|
|
||||||
unsigned_vector m_asserted_atoms; // set of asserted atoms
|
|
||||||
unsigned m_asserted_qhead;
|
|
||||||
u_map<unsigned> m_bool_var2atom;
|
|
||||||
svector<scope> m_scopes;
|
|
||||||
|
|
||||||
double m_agility;
|
|
||||||
bool m_lia;
|
|
||||||
bool m_lra;
|
|
||||||
bool m_non_horn_ineq_exprs;
|
|
||||||
|
|
||||||
horn_ineq_tester m_test;
|
|
||||||
|
|
||||||
|
|
||||||
arith_factory * m_factory;
|
|
||||||
rational m_delta;
|
|
||||||
rational m_lambda;
|
|
||||||
|
|
||||||
|
|
||||||
// Set a conflict due to a negative cycle.
|
|
||||||
void set_neg_cycle_conflict();
|
|
||||||
|
|
||||||
// Create a new theory variable.
|
|
||||||
virtual th_var mk_var(enode* n);
|
|
||||||
|
|
||||||
virtual th_var mk_var(expr* n);
|
|
||||||
|
|
||||||
void compute_delta();
|
|
||||||
|
|
||||||
void found_non_horn_ineq_expr(expr * n);
|
|
||||||
|
|
||||||
bool is_interpreted(app* n) const {
|
|
||||||
return n->get_family_id() == get_family_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
theory_horn_ineq(ast_manager& m);
|
|
||||||
|
|
||||||
virtual ~theory_horn_ineq();
|
|
||||||
|
|
||||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_horn_ineq, get_manager()); }
|
|
||||||
|
|
||||||
virtual char const * get_name() const { return "horn-inequality-logic"; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
\brief See comment in theory::mk_eq_atom
|
|
||||||
*/
|
|
||||||
virtual app * mk_eq_atom(expr * lhs, expr * rhs) { return a.mk_eq(lhs, rhs); }
|
|
||||||
|
|
||||||
virtual void init(context * ctx);
|
|
||||||
|
|
||||||
virtual bool internalize_atom(app * atom, bool gate_ctx);
|
|
||||||
|
|
||||||
virtual bool internalize_term(app * term);
|
|
||||||
|
|
||||||
virtual void internalize_eq_eh(app * atom, bool_var v);
|
|
||||||
|
|
||||||
virtual void assign_eh(bool_var v, bool is_true);
|
|
||||||
|
|
||||||
virtual void new_eq_eh(th_var v1, th_var v2) {
|
|
||||||
m_arith_eq_adapter.new_eq_eh(v1, v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool use_diseqs() const { return true; }
|
|
||||||
|
|
||||||
virtual void new_diseq_eh(th_var v1, th_var v2) {
|
|
||||||
m_arith_eq_adapter.new_diseq_eh(v1, v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void push_scope_eh();
|
|
||||||
|
|
||||||
virtual void pop_scope_eh(unsigned num_scopes);
|
|
||||||
|
|
||||||
virtual void restart_eh() {
|
|
||||||
m_arith_eq_adapter.restart_eh();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void relevant_eh(app* e) {}
|
|
||||||
|
|
||||||
virtual void init_search_eh() {
|
|
||||||
m_arith_eq_adapter.init_search_eh();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual final_check_status final_check_eh();
|
|
||||||
|
|
||||||
virtual bool is_shared(th_var v) const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool can_propagate() {
|
|
||||||
SASSERT(m_asserted_qhead <= m_asserted_atoms.size());
|
|
||||||
return m_asserted_qhead != m_asserted_atoms.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void propagate();
|
|
||||||
|
|
||||||
virtual justification * why_is_diseq(th_var v1, th_var v2) {
|
|
||||||
UNREACHABLE();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void reset_eh();
|
|
||||||
|
|
||||||
virtual void init_model(model_generator & m);
|
|
||||||
|
|
||||||
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
|
|
||||||
|
|
||||||
virtual bool validate_eq_in_model(th_var v1, th_var v2, bool is_true) const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void display(std::ostream & out) const;
|
|
||||||
|
|
||||||
virtual void collect_statistics(::statistics & st) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
virtual void new_eq_eh(th_var v1, th_var v2, justification& j) {
|
|
||||||
m_stats.m_num_core2th_eqs++;
|
|
||||||
new_eq_or_diseq(true, v1, v2, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void new_diseq_eh(th_var v1, th_var v2, justification& j) {
|
|
||||||
m_stats.m_num_core2th_diseqs++;
|
|
||||||
new_eq_or_diseq(false, v1, v2, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
void negate(coeffs& coeffs, rational& weight);
|
|
||||||
numeral mk_weight(bool is_real, bool is_strict, rational const& w) const;
|
|
||||||
void mk_coeffs(vector<std::pair<expr*,rational> >const& terms, coeffs& coeffs, rational& w);
|
|
||||||
|
|
||||||
void del_atoms(unsigned old_size);
|
|
||||||
|
|
||||||
void propagate_core();
|
|
||||||
|
|
||||||
bool propagate_atom(atom const& a);
|
|
||||||
|
|
||||||
th_var mk_term(app* n);
|
|
||||||
|
|
||||||
th_var mk_num(app* n, rational const& r);
|
|
||||||
|
|
||||||
bool is_consistent() const;
|
|
||||||
|
|
||||||
th_var expand(bool pos, th_var v, rational & k);
|
|
||||||
|
|
||||||
void new_eq_or_diseq(bool is_eq, th_var v1, th_var v2, justification& eq_just);
|
|
||||||
|
|
||||||
th_var get_zero(sort* s) const { return a.is_int(s)?m_zero_int:m_zero_real; }
|
|
||||||
|
|
||||||
th_var get_zero(expr* e) const { return get_zero(get_manager().get_sort(e)); }
|
|
||||||
|
|
||||||
void inc_conflicts();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rhi_ext {
|
|
||||||
typedef inf_rational inf_numeral;
|
|
||||||
typedef inf_eps_rational<inf_rational> numeral;
|
|
||||||
numeral m_epsilon;
|
|
||||||
numeral m_minus_infty;
|
|
||||||
rhi_ext() : m_epsilon(inf_rational(rational(), true)), m_minus_infty(rational(-1),inf_rational()) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ihi_ext {
|
|
||||||
typedef rational inf_numeral;
|
|
||||||
typedef inf_eps_rational<rational> numeral;
|
|
||||||
numeral m_epsilon;
|
|
||||||
numeral m_minus_infty;
|
|
||||||
ihi_ext() : m_epsilon(rational(1)), m_minus_infty(rational(-1),rational(0)) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef theory_horn_ineq<rhi_ext> theory_rhi;
|
|
||||||
typedef theory_horn_ineq<ihi_ext> theory_ihi;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _THEORY_HORN_INEQ_H_ */
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,7 @@ Notes:
|
||||||
#include"bv_decl_plugin.h"
|
#include"bv_decl_plugin.h"
|
||||||
#include"expr_replacer.h"
|
#include"expr_replacer.h"
|
||||||
#include"extension_model_converter.h"
|
#include"extension_model_converter.h"
|
||||||
|
#include"filter_model_converter.h"
|
||||||
#include"ast_smt2_pp.h"
|
#include"ast_smt2_pp.h"
|
||||||
|
|
||||||
class bv_size_reduction_tactic : public tactic {
|
class bv_size_reduction_tactic : public tactic {
|
||||||
|
@ -60,6 +61,7 @@ struct bv_size_reduction_tactic::imp {
|
||||||
obj_map<app, numeral> m_unsigned_lowers;
|
obj_map<app, numeral> m_unsigned_lowers;
|
||||||
obj_map<app, numeral> m_unsigned_uppers;
|
obj_map<app, numeral> m_unsigned_uppers;
|
||||||
ref<bv_size_reduction_mc> m_mc;
|
ref<bv_size_reduction_mc> m_mc;
|
||||||
|
ref<filter_model_converter> m_fmc;
|
||||||
scoped_ptr<expr_replacer> m_replacer;
|
scoped_ptr<expr_replacer> m_replacer;
|
||||||
bool m_produce_models;
|
bool m_produce_models;
|
||||||
volatile bool m_cancel;
|
volatile bool m_cancel;
|
||||||
|
@ -121,7 +123,7 @@ struct bv_size_reduction_tactic::imp {
|
||||||
negated = true;
|
negated = true;
|
||||||
f = to_app(f)->get_arg(0);
|
f = to_app(f)->get_arg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_util.is_bv_sle(f, lhs, rhs)) {
|
if (m_util.is_bv_sle(f, lhs, rhs)) {
|
||||||
bv_sz = m_util.get_bv_size(lhs);
|
bv_sz = m_util.get_bv_size(lhs);
|
||||||
if (is_uninterp_const(lhs) && m_util.is_numeral(rhs, val, bv_sz)) {
|
if (is_uninterp_const(lhs) && m_util.is_numeral(rhs, val, bv_sz)) {
|
||||||
|
@ -155,6 +157,7 @@ struct bv_size_reduction_tactic::imp {
|
||||||
else update_signed_lower(to_app(rhs), val);
|
else update_signed_lower(to_app(rhs), val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
else if (m_util.is_bv_ule(f, lhs, rhs)) {
|
else if (m_util.is_bv_ule(f, lhs, rhs)) {
|
||||||
if (is_uninterp_const(lhs) && m_util.is_numeral(rhs, val, bv_sz)) {
|
if (is_uninterp_const(lhs) && m_util.is_numeral(rhs, val, bv_sz)) {
|
||||||
|
@ -215,6 +218,7 @@ struct bv_size_reduction_tactic::imp {
|
||||||
numeral u = m_util.norm(entry->get_data().m_value, bv_sz, true);
|
numeral u = m_util.norm(entry->get_data().m_value, bv_sz, true);
|
||||||
TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << "\n";);
|
TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << "\n";);
|
||||||
expr * new_def = 0;
|
expr * new_def = 0;
|
||||||
|
app * new_const = 0;
|
||||||
if (l > u) {
|
if (l > u) {
|
||||||
g.assert_expr(m.mk_false());
|
g.assert_expr(m.mk_false());
|
||||||
return;
|
return;
|
||||||
|
@ -227,15 +231,19 @@ struct bv_size_reduction_tactic::imp {
|
||||||
if (l.is_neg()) {
|
if (l.is_neg()) {
|
||||||
unsigned i_nb = (u - l).get_num_bits();
|
unsigned i_nb = (u - l).get_num_bits();
|
||||||
unsigned v_nb = m_util.get_bv_size(v);
|
unsigned v_nb = m_util.get_bv_size(v);
|
||||||
if (i_nb < v_nb)
|
if (i_nb < v_nb) {
|
||||||
new_def = m_util.mk_sign_extend(v_nb - i_nb, m.mk_fresh_const(0, m_util.mk_sort(i_nb)));
|
new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb));
|
||||||
|
new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 0 <= l <= v <= u
|
// 0 <= l <= v <= u
|
||||||
unsigned u_nb = u.get_num_bits();
|
unsigned u_nb = u.get_num_bits();
|
||||||
unsigned v_nb = m_util.get_bv_size(v);
|
unsigned v_nb = m_util.get_bv_size(v);
|
||||||
if (u_nb < v_nb)
|
if (u_nb < v_nb) {
|
||||||
new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), m.mk_fresh_const(0, m_util.mk_sort(u_nb)));
|
new_const = m.mk_fresh_const(0, m_util.mk_sort(u_nb));
|
||||||
|
new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), new_const);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +253,10 @@ struct bv_size_reduction_tactic::imp {
|
||||||
if (!m_mc)
|
if (!m_mc)
|
||||||
m_mc = alloc(bv_size_reduction_mc, m);
|
m_mc = alloc(bv_size_reduction_mc, m);
|
||||||
m_mc->insert(v->get_decl(), new_def);
|
m_mc->insert(v->get_decl(), new_def);
|
||||||
|
if (!m_fmc && new_const)
|
||||||
|
m_fmc = alloc(filter_model_converter, m);
|
||||||
|
if (new_const)
|
||||||
|
m_fmc->insert(new_const->get_decl());
|
||||||
}
|
}
|
||||||
num_reduced++;
|
num_reduced++;
|
||||||
}
|
}
|
||||||
|
@ -283,6 +295,7 @@ struct bv_size_reduction_tactic::imp {
|
||||||
|
|
||||||
TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << "\n";);
|
TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << "\n";);
|
||||||
expr * new_def = 0;
|
expr * new_def = 0;
|
||||||
|
app * new_const = 0;
|
||||||
if (l > u) {
|
if (l > u) {
|
||||||
g.assert_expr(m.mk_false());
|
g.assert_expr(m.mk_false());
|
||||||
return;
|
return;
|
||||||
|
@ -294,8 +307,10 @@ struct bv_size_reduction_tactic::imp {
|
||||||
// 0 <= l <= v <= u
|
// 0 <= l <= v <= u
|
||||||
unsigned u_nb = u.get_num_bits();
|
unsigned u_nb = u.get_num_bits();
|
||||||
unsigned v_nb = m_util.get_bv_size(v);
|
unsigned v_nb = m_util.get_bv_size(v);
|
||||||
if (u_nb < v_nb)
|
if (u_nb < v_nb) {
|
||||||
new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), m.mk_fresh_const(0, m_util.mk_sort(u_nb)));
|
new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), new_const);
|
||||||
|
new_const = m.mk_fresh_const(0, m_util.mk_sort(u_nb));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_def) {
|
if (new_def) {
|
||||||
|
@ -304,6 +319,10 @@ struct bv_size_reduction_tactic::imp {
|
||||||
if (!m_mc)
|
if (!m_mc)
|
||||||
m_mc = alloc(bv_size_reduction_mc, m);
|
m_mc = alloc(bv_size_reduction_mc, m);
|
||||||
m_mc->insert(v->get_decl(), new_def);
|
m_mc->insert(v->get_decl(), new_def);
|
||||||
|
if (!m_fmc && new_const)
|
||||||
|
m_fmc = alloc(filter_model_converter, m);
|
||||||
|
if (new_const)
|
||||||
|
m_fmc->insert(new_const->get_decl());
|
||||||
}
|
}
|
||||||
num_reduced++;
|
num_reduced++;
|
||||||
TRACE("bv_size_reduction", tout << "New definition = " << mk_ismt2_pp(new_def, m) << "\n";);
|
TRACE("bv_size_reduction", tout << "New definition = " << mk_ismt2_pp(new_def, m) << "\n";);
|
||||||
|
@ -328,7 +347,11 @@ struct bv_size_reduction_tactic::imp {
|
||||||
g.update(i, new_f);
|
g.update(i, new_f);
|
||||||
}
|
}
|
||||||
mc = m_mc.get();
|
mc = m_mc.get();
|
||||||
|
if (m_fmc) {
|
||||||
|
mc = concat(m_fmc.get(), mc.get());
|
||||||
|
}
|
||||||
m_mc = 0;
|
m_mc = 0;
|
||||||
|
m_fmc = 0;
|
||||||
}
|
}
|
||||||
report_tactic_progress(":bv-reduced", num_reduced);
|
report_tactic_progress(":bv-reduced", num_reduced);
|
||||||
TRACE("after_bv_size_reduction", g.display(tout); if (m_mc) m_mc->display(tout););
|
TRACE("after_bv_size_reduction", g.display(tout); if (m_mc) m_mc->display(tout););
|
||||||
|
|
|
@ -1368,12 +1368,12 @@ void fpa2bv_converter::mk_fusedma(func_decl * f, unsigned num, expr * const * ar
|
||||||
not_e_sgn = m_bv_util.mk_bv_not(e_sgn);
|
not_e_sgn = m_bv_util.mk_bv_not(e_sgn);
|
||||||
not_f_sgn = m_bv_util.mk_bv_not(f_sgn);
|
not_f_sgn = m_bv_util.mk_bv_not(f_sgn);
|
||||||
not_sign_bv = m_bv_util.mk_bv_not(sign_bv);
|
not_sign_bv = m_bv_util.mk_bv_not(sign_bv);
|
||||||
res_sgn_c1 = m.mk_app(bvfid, OP_BAND, not_e_sgn, e_sgn, sign_bv);
|
res_sgn_c1 = m.mk_app(bvfid, OP_BAND, not_e_sgn, f_sgn, sign_bv);
|
||||||
res_sgn_c2 = m.mk_app(bvfid, OP_BAND, e_sgn, not_f_sgn, not_sign_bv);
|
res_sgn_c2 = m.mk_app(bvfid, OP_BAND, e_sgn, not_f_sgn, not_sign_bv);
|
||||||
res_sgn_c3 = m.mk_app(bvfid, OP_BAND, e_sgn, f_sgn);
|
res_sgn_c3 = m.mk_app(bvfid, OP_BAND, e_sgn, f_sgn);
|
||||||
expr * res_sgn_or_args[3] = { res_sgn_c1, res_sgn_c2, res_sgn_c3 };
|
expr * res_sgn_or_args[3] = { res_sgn_c1, res_sgn_c2, res_sgn_c3 };
|
||||||
res_sgn = m_bv_util.mk_bv_or(3, res_sgn_or_args);
|
res_sgn = m_bv_util.mk_bv_or(3, res_sgn_or_args);
|
||||||
|
|
||||||
sticky_raw = m_bv_util.mk_extract(sbits-5, 0, sig_abs);
|
sticky_raw = m_bv_util.mk_extract(sbits-5, 0, sig_abs);
|
||||||
sticky = m_bv_util.mk_zero_extend(sbits+3, m.mk_app(bvfid, OP_BREDOR, sticky_raw.get()));
|
sticky = m_bv_util.mk_zero_extend(sbits+3, m.mk_app(bvfid, OP_BREDOR, sticky_raw.get()));
|
||||||
dbg_decouple("fpa2bv_fma_add_sum_sticky", sticky);
|
dbg_decouple("fpa2bv_fma_add_sum_sticky", sticky);
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct is_non_qffpa_predicate {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
float_util u;
|
float_util u;
|
||||||
|
|
||||||
is_non_qffpa_predicate(ast_manager & _m) :m(_m), u(m) {}
|
is_non_qffpa_predicate(ast_manager & _m) : m(_m), u(m) {}
|
||||||
|
|
||||||
void operator()(var *) { throw found(); }
|
void operator()(var *) { throw found(); }
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ struct is_non_qffpa_predicate {
|
||||||
|
|
||||||
void operator()(app * n) {
|
void operator()(app * n) {
|
||||||
sort * s = get_sort(n);
|
sort * s = get_sort(n);
|
||||||
if (!(m.is_bool(s) || u.is_float(s) || u.is_rm(s)))
|
if (!m.is_bool(s) && !u.is_float(s) && !u.is_rm(s))
|
||||||
throw found();
|
throw found();
|
||||||
family_id fid = n->get_family_id();
|
family_id fid = n->get_family_id();
|
||||||
if (fid == m.get_basic_family_id())
|
if (fid == m.get_basic_family_id())
|
||||||
|
@ -70,7 +70,7 @@ struct is_non_qffpabv_predicate {
|
||||||
bv_util bu;
|
bv_util bu;
|
||||||
float_util fu;
|
float_util fu;
|
||||||
|
|
||||||
is_non_qffpabv_predicate(ast_manager & _m) :m(_m), bu(m), fu(m) {}
|
is_non_qffpabv_predicate(ast_manager & _m) : m(_m), bu(m), fu(m) {}
|
||||||
|
|
||||||
void operator()(var *) { throw found(); }
|
void operator()(var *) { throw found(); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue