diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 7c1786f29..3eef9e3e8 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -24,12 +24,12 @@ def init_project_def(): add_lib('parser_util', ['ast'], 'parsers/util') add_lib('grobner', ['ast'], 'math/grobner') add_lib('euclid', ['util'], 'math/euclid') - # Old (non-modular) parameter framework. It has been subsumed by util\params.h. - # However, it is still used by many old components. - add_lib('old_params', ['ast']) + # Front-end-params module still contain a lot of parameters for smt solver component. + # This should be fixed + add_lib('front_end_params', ['ast']) # Simplifier module will be deleted in the future. # It has been replaced with rewriter module. - add_lib('simplifier', ['rewriter', 'old_params'], 'ast/simplifier') + add_lib('simplifier', ['rewriter', 'front_end_params'], 'ast/simplifier') add_lib('normal_forms', ['rewriter', 'simplifier'], 'ast/normal_forms') add_lib('core_tactics', ['tactic', 'normal_forms'], 'tactic/core') add_lib('sat_tactic', ['tactic', 'sat'], 'sat/tactic') @@ -37,21 +37,22 @@ def init_project_def(): add_lib('nlsat_tactic', ['nlsat', 'sat_tactic', 'arith_tactics'], 'nlsat/tactic') add_lib('subpaving_tactic', ['core_tactics', 'subpaving'], 'math/subpaving/tactic') add_lib('aig_tactic', ['tactic'], 'tactic/aig') - add_lib('cmd_context', ['tactic', 'rewriter', 'model', 'old_params']) + add_lib('solver', ['model', 'tactic', 'front_end_params']) + add_lib('cmd_context', ['solver', 'rewriter']) add_lib('extra_cmds', ['cmd_context', 'subpaving_tactic', 'arith_tactics'], 'cmd_context/extra_cmds') add_lib('smt2parser', ['cmd_context', 'parser_util'], 'parsers/smt2') add_lib('pattern', ['normal_forms', 'smt2parser'], 'ast/pattern') - add_lib('macros', ['simplifier', 'old_params'], 'ast/macros') - add_lib('proof_checker', ['rewriter', 'old_params'], 'ast/proof_checker') - add_lib('bit_blaster', ['rewriter', 'simplifier', 'old_params'], 'ast/rewriter/bit_blaster') - add_lib('proto_model', ['model', 'simplifier', 'old_params'], 'smt/proto_model') + add_lib('macros', ['simplifier', 'front_end_params'], 'ast/macros') + add_lib('proof_checker', ['rewriter', 'front_end_params'], 'ast/proof_checker') + add_lib('bit_blaster', ['rewriter', 'simplifier', 'front_end_params'], 'ast/rewriter/bit_blaster') + add_lib('proto_model', ['model', 'simplifier', 'front_end_params'], 'smt/proto_model') add_lib('smt', ['bit_blaster', 'macros', 'normal_forms', 'cmd_context', 'proto_model', 'substitution', 'grobner', 'euclid', 'proof_checker', 'pattern', 'parser_util']) add_lib('user_plugin', ['smt'], 'smt/user_plugin') add_lib('bv_tactics', ['tactic', 'bit_blaster'], 'tactic/bv') add_lib('fuzzing', ['ast'], 'test/fuzzing') add_lib('fpa', ['core_tactics', 'bv_tactics', 'sat_tactic'], 'tactic/fpa') - add_lib('smt_tactic', ['smt'], 'tactic/smt') + add_lib('smt_tactic', ['smt'], 'smt/tactic') add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls') # TODO: split muz_qe into muz, qe. Perhaps, we should also consider breaking muz into muz and pdr. add_lib('muz_qe', ['smt', 'sat', 'smt2parser']) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 82865a4ac..3d316dcb8 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1086,7 +1086,8 @@ def mk_def_files(): def cp_z3pyc_to_build(): mk_dir(BUILD_DIR) - compileall.compile_dir(Z3PY_SRC_DIR, force=1) + if compileall.compile_dir(Z3PY_SRC_DIR, force=1) != 1: + raise MKException("failed to compile Z3Py sources") for pyc in filter(lambda f: f.endswith('.pyc'), os.listdir(Z3PY_SRC_DIR)): try: os.remove('%s/%s' % (BUILD_DIR, pyc)) diff --git a/scripts/update_api.py b/scripts/update_api.py index 237fa80a6..53159f10e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -76,7 +76,7 @@ def lib(): except: pass try: - init('%s%slibz3.%s' % (_dir, ext)) + init(os.path.join(_dir, 'libz3.%s' % ext)) break except: pass @@ -670,6 +670,11 @@ mk_py_wrappers() mk_dotnet() mk_dotnet_wrappers() +log_h.close() +log_c.close() +exe_c.close() +core_py.close() + if is_verbose(): print "Generated '%s'" % ('%s/api_log_macros.h' % api_dir) print "Generated '%s'" % ('%s/api_log_macros.cpp' % api_dir) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 71a24c534..9b3619a6e 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -80,7 +80,7 @@ extern "C" { LOG_Z3_mk_solver_from_tactic(c, t); RESET_ERROR_CODE(); Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = alloc(tactic2solver_api, to_tactic_ref(t)); + s->m_solver = alloc(tactic2solver, to_tactic_ref(t)); s->m_solver->set_front_end_params(mk_c(c)->fparams()); s->m_solver->init(mk_c(c)->m(), symbol::null); mk_c(c)->save_object(s); diff --git a/src/api/dotnet/dead/Microsoft.Z3V3/AssemblyInfo.cpp b/src/api/dotnet/dead/Microsoft.Z3V3/AssemblyInfo.cpp deleted file mode 100644 index 86a8775e6..000000000 --- a/src/api/dotnet/dead/Microsoft.Z3V3/AssemblyInfo.cpp +++ /dev/null @@ -1,34 +0,0 @@ -using namespace System; -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Permissions; - -// -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -// -[assembly:AssemblyTitleAttribute("Z3 .NET Interface")]; -[assembly:AssemblyDescriptionAttribute(".NET Interface to the Z3 Theorem Prover")]; -[assembly:AssemblyConfigurationAttribute("")]; -[assembly:AssemblyCompanyAttribute("Microsoft Corporation")]; -[assembly:AssemblyProductAttribute("Z3")]; -[assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft Corporation 2006")]; -[assembly:AssemblyTrademarkAttribute("")]; -[assembly:AssemblyCultureAttribute("")]; - -[assembly:ComVisible(false)]; -[assembly:CLSCompliantAttribute(true)]; -[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; - -[assembly:AssemblyVersionAttribute("4.2.0.0")]; -[assembly:AssemblyFileVersionAttribute("4.2.0.0")]; - -//#ifdef DELAYSIGN -//[assembly:AssemblyKeyFile("35MSSharedLib1024.snk")]; -//[assembly:AssemblyDelaySign(true)]; -//#else -//[assembly:AssemblyKeyFile("z3.snk")]; -//[assembly:AssemblyDelaySign(true)]; -//#endif diff --git a/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.cpp b/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.cpp deleted file mode 100644 index 0e3b08eb2..000000000 --- a/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.cpp +++ /dev/null @@ -1,3260 +0,0 @@ -/*++ -Copyright (c) 2007 Microsoft Corporation - -Module Name: - - Microsoft.Z3V3.cpp - -Abstract: - - Z3 Managed API. - -Author: - - Nikolaj Bjorner (nbjorner) - Leonardo de Moura (leonardo) 2007-06-8 - -Notes: - ---*/ - -//#include "stdafx.h" -#include "Microsoft.Z3V3.h" -#include "..\lib\util.h" -#include "..\lib\z3_private.h" -#include -#include -#include -#include "../lib/rational.h" -#include "../lib/z3_private.h" - - -using namespace System::Text; -using namespace Microsoft::Z3V3; - -// ------------------------------- -// ref_context - -ref_context* ref_context::mk(Z3_context ctx, bool owned, bool scoped) { - return alloc(ref_context, ctx, owned, scoped); -} - -void ref_context::dec_ref() { - --m_count; - if (0 == m_count) { - if (m_owned) { - if (m_dl) { - Z3_fixedpoint_dec_ref(m_ctx, m_dl); - } - Z3_del_context(m_ctx); - } - dealloc(this); - } -} - -void ref_context::inc_ref() { - ++m_count; -} - -Z3_fixedpoint ref_context::dl() { - if (!m_dl) { - m_dl = Z3_mk_fixedpoint(m_ctx); - Z3_fixedpoint_inc_ref(m_ctx, m_dl); - } - return m_dl; -} - - -// ------------------------------- -// static functions - - -static std::string -CreateString( - String^ string - ) -{ - std::string s; - array^ bytes = - Encoding::Convert( - Encoding::Unicode, - Encoding::ASCII, - Encoding::Unicode->GetBytes(string) - ); - - for (int i = 0; i < bytes->Length; ++i) { - s += bytes[i]; - } - return s; -} - -bool Z3Log::Open(String^ filename) { - m_open = true; - return Z3_TRUE == Z3_open_log(CreateString(filename).c_str()); -} - -void Z3Log::Append(String^ s) { - Z3_append_log(CreateString(s).c_str()); -} - -void Z3Log::Close() { - m_open = false; - Z3_close_log(); -} - -template -class scoped_array { -public: - scoped_array(unsigned length) - : m_length(length), - m_data(new T[length]) - { - } - - scoped_array(array^ a) - { - m_length = a?a->Length:0; - m_data = a?(new T[m_length]):0; - for (unsigned i = 0; i < m_length; ++i) { - m_data[i] = a[i]; - } - } - - virtual ~scoped_array() { - delete[] m_data; - } - - T* c_ptr() { return m_data; } - - T const* c_ptr() const { return m_data; } - - T& operator[](int i) { return m_data[i]; } - - unsigned size() { return m_length; } -protected: - unsigned m_length; - T* m_data; -}; - -template -class scoped_Z3_ast_array : public scoped_array { -public: - scoped_Z3_ast_array(array^ asts) - : scoped_array((!asts)?0:asts->Length) - { - for (unsigned i = 0; i < m_length; ++i) { - c_ptr()[i] = static_cast(asts[i].ToPointer()); - } - } - scoped_Z3_ast_array(int length) - : scoped_array(length) {} -}; - - -class scoped_Z3_symbol_array : public scoped_array { -public: - scoped_Z3_symbol_array(array^ symbols) - : scoped_array((!symbols)?0:symbols->Length) - { - for (unsigned i = 0; i < m_length; ++i) { - c_ptr()[i] = symbols[i]->get(); - } - } - - scoped_Z3_symbol_array(Z3_context ctx, array^ symbols) - : scoped_array((!symbols)?0:symbols->Length) - { - for (unsigned i = 0; i < m_length; ++i) { - c_ptr()[i] = Z3_mk_string_symbol(ctx, CreateString(symbols[i]).c_str()); - } - } - - scoped_Z3_symbol_array(unsigned n): scoped_array(n) {} -}; - -static void CopyFuncDecl(scoped_Z3_ast_array& src, - array^ dst) { - SASSERT(dst->Length == src.size()); - for (unsigned i = 0; i < src.size(); ++i) { - dst[i] = FuncDeclPtr(src[i]); - } -} - -static array^ MkArray(unsigned n, Z3_ast const* args) { - array^ result = gcnew array(n); - for (unsigned i = 0; i < n; ++i) { - result[i] = TermPtr(args[i]); - } - return result; -} - -static SearchFailureExplanation ConvertExplanation(Z3_search_failure f) { - switch(f) { - case Z3_NO_FAILURE: - return SearchFailureExplanation::NoFailure; - case Z3_UNKNOWN: - return SearchFailureExplanation::Unknown; - case Z3_TIMEOUT: - return SearchFailureExplanation::TimeOut; - case Z3_MEMOUT_WATERMARK: - return SearchFailureExplanation::MemOut; - case Z3_CANCELED: - return SearchFailureExplanation::UserCanceled; - case Z3_NUM_CONFLICTS: - return SearchFailureExplanation::MaxConflicts; - case Z3_THEORY: - return SearchFailureExplanation::Theory; - case Z3_QUANTIFIERS: - return SearchFailureExplanation::Quantifiers; - } - return SearchFailureExplanation::Unknown; -} - -//---------------------------------------- -// Config - -Config::Config() { m_config = Z3_mk_config(); } - -Config::~Config() { - if (m_config) { - Z3_del_config(m_config); - m_config = 0; - } -} - -Config::!Config() { - if (m_config) { - if (RawContext::m_error_handler ) { - RawContext::m_error_handler->Handler(ErrorCode::NonDisposedConfig); - } - else { - verbose_stream() << "WARNING: configuration was not disposed\n"; - } - } -} - - -void Config::SetParamValue(String^ param_id, String^ param_value) { - Z3_set_param_value(m_config, CreateString(param_id).c_str(), CreateString(param_value).c_str()); -} - - -//---------------------------------------- -// Model - -RawModel::~RawModel() { - Reset(); -} - -RawModel::!RawModel() { - if (m_model) { - if (RawContext::m_error_handler ) { - RawContext::m_error_handler->Handler(ErrorCode::NonDisposedModel); - } - else { - verbose_stream() << "WARNING: model was not disposed\n"; - } - } -} - -void RawModel::Reset() { - if (m_model != 0) { - Z3_del_model(m_context(), m_model); - m_context.dec_ref(); - m_model = 0; - } -} - -array^ RawModel::GetModelConstants() { - unsigned num_consts = Z3_get_model_num_constants(m_context(), m_model); - array^ result = gcnew array(num_consts); - for (unsigned i = 0; i < num_consts; ++i) { - result[i] = FuncDeclPtr(Z3_get_model_constant(m_context(), m_model, i)); - } - return result; -} - - -String^ RawContext::GetNumeralString(TermPtr v) { - return gcnew String(Z3_get_numeral_string(ctx(), get_ast(v))); -} - -int RawContext::GetNumeralInt(TermPtr v) { - int result = 0; - if (!Z3_get_numeral_int(ctx(), get_ast(v), &result)) { - throw gcnew System::ArgumentException("Expecting value of integer type"); - } - return result; -} - -bool RawContext::TryGetNumeralInt(TermPtr v, int% i) { - int result = 0; - if (!Z3_get_numeral_int(ctx(), get_ast(v), &result)) { - return false; - } - i = result; - return true; -} - -unsigned RawContext::GetNumeralUInt(TermPtr v) { - unsigned result = 0; - if (!Z3_get_numeral_uint(ctx(), get_ast(v), &result)) { - throw gcnew System::ArgumentException("Expecting TermPtr of unsigned integer type"); - } - return result; -} - -bool RawContext::TryGetNumeralUInt(TermPtr v, unsigned% u) { - unsigned result = 0; - if (!Z3_get_numeral_uint(ctx(), get_ast(v), &result)) { - return false; - } - u = result; - return true; -} - - -__int64 RawContext::GetNumeralInt64(TermPtr v) { - __int64 result = 0; - if (!Z3_get_numeral_int64(ctx(), get_ast(v), &result)) { - throw gcnew System::ArgumentException("Expecting value of signed 64 bit integer type"); - } - return result; -} - -bool RawContext::TryGetNumeralInt64(TermPtr v, __int64% i) { - __int64 result = 0; - if (!Z3_get_numeral_int64(ctx(), get_ast(v), &result)) { - return false; - } - i = result; - return true; -} - - -unsigned __int64 RawContext::GetNumeralUInt64(TermPtr v) { - unsigned __int64 result = 0; - if (!Z3_get_numeral_uint64(ctx(), get_ast(v), &result)) { - throw gcnew System::ArgumentException("Expecting value of unsigned 64 bit integer type"); - } - return result; -} - -bool RawContext::TryGetNumeralUInt64(TermPtr v, unsigned __int64% u) { - unsigned __int64 result = 0; - if (!Z3_get_numeral_uint64(ctx(), get_ast(v), &result)) { - return false; - } - u = result; - return true; -} - -bool RawContext::TryGetNumeral(TermPtr v, [Out] __int64% num, [Out] __int64% den) { - __int64 _num, _den; - if (!Z3_get_numeral_rational_int64(ctx(), get_ast(v), &_num, &_den)) { - return false; - } - num = _num; - den = _den; - return true; -} - - -void RawContext::GetNumeral(TermPtr v, [Out] System::Numerics::BigInteger% num, [Out] System::Numerics::BigInteger% den) { - rational r; - if (!Z3_get_numeral_rational(ctx(), get_ast(v), r)) { - Z3_error_handler(Z3_INVALID_ARG); - return; - } - rational d = denominator(r); - rational n = numerator(r); - rational ten(10); - bool is_neg = false; - SASSERT(!d.is_neg()); - if (n.is_neg()) { - is_neg = true; - n = -n; - } - num = 0; - System::Numerics::BigInteger mul = 1; - while (n.is_pos()) { - num += mul * mod(n,ten).get_unsigned(); - n = div(n,ten); - mul *= 10; - } - if (is_neg) { - num = -num; - } - den = 0; - mul = 1; - while (d.is_pos()) { - den += mul * mod(d,ten).get_unsigned(); - d = div(d,ten); - mul *= 10; - } -} - - -LBool RawContext::GetBoolValue(TermPtr a) { - switch (Z3_get_bool_value(ctx(), get_ast(a))) { - case Z3_L_FALSE: return LBool::False; - case Z3_L_UNDEF: return LBool::Undef; - case Z3_L_TRUE: return LBool::True; - default: - UNREACHABLE(); - return LBool::Undef; - } -} - - -bool RawModel::TryGetArrayValue(TermPtr v, RawArrayValue^% av) { - unsigned num_entries; - if (!Z3_is_array_value(m_context(), m_model, get_ast(v), & num_entries)) { - return false; - } - scoped_Z3_ast_array _indices(num_entries); - scoped_Z3_ast_array _values(num_entries); - Z3_ast else_value; - Z3_get_array_value(m_context(), m_model, get_ast(v), num_entries, _indices.c_ptr(), _values.c_ptr(), &else_value); - av = gcnew RawArrayValue(); - av->Domain = gcnew array(num_entries); - av->Range = gcnew array(num_entries); - av->ElseCase = TermPtr(else_value); - for (unsigned i = 0; i < num_entries; ++i) { - av->Domain[i] = TermPtr(_indices[i]); - av->Range[i] = TermPtr(_values[i]); - } - return true; -} - -TermPtr RawContext::GetAssignments() { - return TermPtr(Z3_get_context_assignment(ctx())); -} - - -TermPtr RawContext::UpdateTerm(TermPtr t, array^ new_args) { - scoped_Z3_ast_array _new_args(new_args); - return TermPtr(Z3_update_term(ctx(), get_ast(t), - _new_args.size(), _new_args.c_ptr())); -} - -Dictionary^ RawModel::GetFunctionGraphs() { - if (m_graphs) { - return m_graphs; - } - SASSERT(m_model); - unsigned _num_funs = Z3_get_model_num_funcs(m_context(), m_model); - - Dictionary^ graphs = - gcnew Dictionary(); - - for (unsigned i = 0; i < _num_funs; ++i) { - unsigned num_entries = Z3_get_model_func_num_entries(m_context(), m_model, i); - FuncDeclPtr decl = FuncDeclPtr(Z3_get_model_func_decl(m_context(), m_model, i)); - RawFunctionGraph^ graph = gcnew RawFunctionGraph(); - graphs[decl] = graph; - graph->Declaration = decl; - graph->Else = TermPtr(Z3_get_model_func_else(m_context(), m_model, i)); - graph->Entries = gcnew array(num_entries); - - for (unsigned j = 0; j < num_entries; ++j) { - unsigned num_args = Z3_get_model_func_entry_num_args(m_context(), m_model, i, j); - graph->Entries[j] = gcnew RawFunctionEntry(); - graph->Entries[j]->Arguments = gcnew array(num_args); - for (unsigned k = 0; k < num_args; ++k) { - graph->Entries[j]->Arguments[k] = TermPtr(Z3_get_model_func_entry_arg(m_context(), m_model, i, j, k)); - } - graph->Entries[j]->Result = TermPtr(Z3_get_model_func_entry_value(m_context(), m_model, i, j)); - } - } - m_graphs = graphs; - return graphs; -} - -TermPtr RawModel::Eval(TermPtr t) { - Z3_ast v = 0; - if (!Z3_eval(m_context(), m_model, get_ast(t), &v)) { - return IntPtr::Zero; - } - return TermPtr(v); -} - -TermPtr RawModel::Eval(FuncDeclPtr decl, array^ args) { - Z3_ast v = 0; - scoped_Z3_ast_array _args(args); - - if (!Z3_eval_decl(m_context(), m_model, get_func_decl(decl), - _args.size(), _args.c_ptr(), &v)) { - return IntPtr::Zero; - } - return TermPtr(v); -} - -String^ RawModel::ToString() { - return gcnew String(Z3_model_to_string(m_context(), m_model)); -} - -void RawModel::Display(System::IO::TextWriter^ w) { - w->Write(ToString()); -} - -RawTheory^ RawContext::MkTheory(String^ name) { - return gcnew RawTheory(*m_context, name); -} - - -void RawContext::RegisterRelation(FuncDeclPtr r) { - Z3_fixedpoint_register_relation(ctx(), dl(), get_func_decl(r)); -} - -void RawContext::AddRule(TermPtr term, Symbol^ name) { - Z3_fixedpoint_add_rule(ctx(), dl(), get_ast(term), name?name->get():0); -} - -LBool RawContext::Query(TermPtr query) { - switch(Z3_fixedpoint_query(ctx(), dl(), get_ast(query))) { - case Z3_L_FALSE: return LBool::False; - case Z3_L_TRUE: return LBool::True; - default: return LBool::Undef; - } -} - -String^ RawContext::GetQueryStatus() { - return gcnew String(Z3_fixedpoint_get_reason_unknown(ctx(),dl())); -} - -TermPtr RawContext::GetQueryAnswer() { - return TermPtr(Z3_fixedpoint_get_answer(ctx(),dl())); -} - -static void fixedpoint_assign_callback(void* c, Z3_func_decl f, unsigned n, Z3_ast const* _args, unsigned m, Z3_ast const* outs) { - RawContext::fixedpoint_assign_callback(c, f, n, _args, m, outs); -} - -static void fixedpoint_apply_callback(void* c, Z3_func_decl f, unsigned n, Z3_ast const* _args, Z3_ast* out) { - RawContext::fixedpoint_apply_callback(c, f, n, _args, out); -} - -void RawContext::init_fixedpoint_callbacks() { - if (contexts == nullptr) { - contexts = gcnew Dictionary(); - } - if (m_fixedpoint_gch == IntPtr::Zero) { - int id = contexts->Count; - GCHandle h = GCHandle::Alloc(id, GCHandleType::Pinned); - contexts[h] = this; - m_fixedpoint_gch = GCHandle::ToIntPtr(h); - Z3_fixedpoint_init(ctx(), dl(), m_fixedpoint_gch.ToPointer()); - Z3_fixedpoint_set_reduce_assign_callback(ctx(), dl(), ::fixedpoint_assign_callback); - Z3_fixedpoint_set_reduce_app_callback(ctx(), dl(), ::fixedpoint_apply_callback); - } -} - - -void RawContext::fixedpoint_assign_callback(void* ud, Z3_func_decl f, unsigned n, Z3_ast const* args, unsigned m, Z3_ast const* outs) { - RawContext^ ctx = contexts[GCHandle::FromIntPtr(IntPtr(ud))]; - if (ctx->m_fixedpoint_assign != nullptr) { - array^ _args = MkArray(n, args); - array^ _outs = MkArray(m, outs); - ctx->m_fixedpoint_assign(TermPtr(f), _args, _outs); - } -} - -void RawContext::fixedpoint_apply_callback(void* ud, Z3_func_decl f, unsigned n, Z3_ast const* args, Z3_ast* out) { - RawContext^ ctx = contexts[GCHandle::FromIntPtr(IntPtr(ud))]; - if (ctx->m_fixedpoint_apply != nullptr) { - array^ _args = MkArray(n, args); - TermPtr r = ctx->m_fixedpoint_apply(TermPtr(f), _args); - if (out) *out = get_ast(r); - } -} - -String^ RawContext::FixedpointToString(array^ queries) { - scoped_Z3_ast_array _queries(queries); - return gcnew String(Z3_fixedpoint_to_string( - ctx(), dl(), - _queries.size(), _queries.c_ptr())); -} - -array^ RawContext::SimplifyFixedpointRules(array^ rules, array^ output_predicates) { - scoped_Z3_ast_array _rules(rules); - scoped_Z3_ast_array _outputs(output_predicates); - Z3_ast_vector new_rules = Z3_fixedpoint_simplify_rules( - ctx(), dl(), _rules.size(), _rules.c_ptr(), - _outputs.size(), _outputs.c_ptr()); - unsigned num_rules = Z3_ast_vector_size(ctx(), new_rules); - Z3_ast_vector_inc_ref(ctx(), new_rules); - array^ result = gcnew array(num_rules); - for (unsigned i = 0; i < num_rules; ++i) { - result[i] = TermPtr(Z3_ast_vector_get(ctx(), new_rules, i)); - } - Z3_ast_vector_dec_ref(ctx(), new_rules); - return result; -} - -//---------------------------------------- -// RawContext - -static void error_handler(Z3_context ctx, Z3_error_code c) { - ErrorCode code; - switch(c) { - case Z3_OK: code = ErrorCode::Ok; break; - case Z3_SORT_ERROR: code = ErrorCode::TypeError; break; - case Z3_IOB: code = ErrorCode::IndexOutOfBounds; break; - case Z3_INVALID_ARG: code = ErrorCode::InvalidArgument; break; - case Z3_PARSER_ERROR: code = ErrorCode::ParserError; break; - case Z3_NO_PARSER: code = ErrorCode::NoParser; break; - case Z3_INVALID_PATTERN: code = ErrorCode::InvalidPattern; break; - case Z3_MEMOUT_FAIL: throw gcnew OutOfMemoryException(); - case Z3_INTERNAL_FATAL: code = ErrorCode::InternalFatal; break; - case Z3_INVALID_USAGE: code = ErrorCode::InvalidUsage; break; - case Z3_FILE_ACCESS_ERROR: code = ErrorCode::FileAccessError; break; - default: - UNREACHABLE(); - code = ErrorCode::InvalidArgument; break; - } - if (RawContext::m_error_handler ) { - RawContext::m_error_handler->Handler(code); - } - // we throw if you don't - throw gcnew Z3Error(code); -} - - -// ----------------------------- -// LabeledLiterals - - -LabeledLiterals::!LabeledLiterals() { - if (m_labels) { - if (RawContext::m_error_handler ) { - RawContext::m_error_handler->Handler(ErrorCode::NonDisposedLiterals); - } - else { - verbose_stream() << "WARNING: labeled literals have not been disposed\n"; - } - } -} - -// ----------------------------- -// RawTheory - -void RawTheory::static_delete_callback(Z3_theory th) -{ - RawTheory^ theory = GetTheory(th); - if (theory->delete_handler) { - theory->delete_handler(); - } - Z3_theory_data td = Z3_theory_get_ext_data(th); - theories->Remove(GCHandle::FromIntPtr(IntPtr(td))); - GCHandle::FromIntPtr(IntPtr(td)).Free(); -} - -static void static_delete_callback(Z3_theory th) { - RawTheory::static_delete_callback(th); -} - -RawTheory::RawTheory(ref_context& ctx, String^ name): m_context(ctx), m_name(name) -{ - if (!theories) theories = gcnew Dictionary(); - int id = theories->Count; - GCHandle h = GCHandle::Alloc(id, GCHandleType::Pinned); - theories[h] = this; - IntPtr gch = GCHandle::ToIntPtr(h); - m_theory = Z3_mk_theory(ctx(), CreateString(name).c_str(), gch.ToPointer()); - m_context.inc_ref(); - Z3_set_delete_callback(m_theory, ::static_delete_callback); -} - -RawTheory::~RawTheory() { - m_context.dec_ref(); -} - -Z3_bool RawTheory::reduce_eq_callback(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast* r) { - RawTheory^ theory = GetTheory(th); - TermPtr res = theory->reduce_eq(TermPtr(a), TermPtr(b)); - if (res != TermPtr::Zero) { - *r = get_ast(res); - } - return res != TermPtr::Zero; -} - -static Z3_bool reduce_eq_callback(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast* r) { - return RawTheory::reduce_eq_callback(th, a, b, r); -} - -void RawTheory::set_reduce_eq(Func2^ value) { - reduce_eq = value; - Z3_set_reduce_eq_callback(m_theory, ::reduce_eq_callback); -} - -Z3_bool RawTheory::reduce_app_callback(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r) { - RawTheory^ theory = GetTheory(th); - array^ argv = MkArray(num_args, args); - TermPtr res = theory->reduce_app(TermPtr(f), argv); - if (r && res != TermPtr::Zero) { - *r = get_ast(res); - } - return res != TermPtr::Zero; -} - -static Z3_bool reduce_app_callback(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r) { - return RawTheory::reduce_app_callback(th, f, num_args, args, r); -} - -void RawTheory::set_reduce_app(Func2^, TermPtr>^ value) { - reduce_app = value; - Z3_set_reduce_app_callback(m_theory, ::reduce_app_callback); -} - -Z3_bool RawTheory::reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r) { - RawTheory^ theory = GetTheory(th); - TermPtr res = theory->reduce_distinct(MkArray(n, args)); - if (r && res != TermPtr::Zero) { - *r = get_ast(res); - } - return res != TermPtr::Zero; -} - -static Z3_bool reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r) { - return RawTheory::reduce_distinct_callback(th, n, args, r); -} - -void RawTheory::set_reduce_distinct(Func1^, TermPtr>^ value) { - reduce_distinct = value; - Z3_set_reduce_distinct_callback(m_theory, ::reduce_distinct_callback); -} - -static void new_relevant_callback(Z3_theory t, Z3_ast a) { - RawTheory::GetTheory(t)->new_relevant(TermPtr(a)); -} - -void RawTheory::set_new_relevant(Action^ value) { - new_relevant = value; - Z3_set_new_relevant_callback(m_theory, ::new_relevant_callback); -} - -static void new_app_callback(Z3_theory t, Z3_ast a) { - RawTheory::GetTheory(t)->new_app(TermPtr(a)); -} - -void RawTheory::set_new_app(Action^ value) { - new_app = value; - Z3_set_new_app_callback(m_theory, ::new_app_callback); -} - - -static void new_elem_callback(Z3_theory t, Z3_ast a) { - RawTheory::GetTheory(t)->new_elem(TermPtr(a)); -} - -void RawTheory::set_new_elem(Action^ value) { - new_elem = value; - Z3_set_new_elem_callback(m_theory, ::new_elem_callback); -} - -static void init_search_callback(Z3_theory t) { - RawTheory::GetTheory(t)->init_search(); -} - -void RawTheory::set_init_search(Action0^ value) { - init_search = value; - Z3_set_init_search_callback(m_theory, ::init_search_callback); -} - -static void push_callback(Z3_theory t) { - RawTheory::GetTheory(t)->push(); -} - -void RawTheory::set_push(Action0^ value) { - push = value; - Z3_set_push_callback(m_theory, ::push_callback); -} - - -static void pop_callback(Z3_theory t) { - RawTheory::GetTheory(t)->pop(); -} - -void RawTheory::set_pop(Action0^ value) { - pop = value; - Z3_set_pop_callback(m_theory, ::pop_callback); -} - - -static void reset_callback(Z3_theory t) { - RawTheory::GetTheory(t)->reset(); -} - -void RawTheory::set_reset(Action0^ value) { - reset = value; - Z3_set_reset_callback(m_theory, ::reset_callback); -} - - -static void restart_callback(Z3_theory t) { - RawTheory::GetTheory(t)->restart(); -} - -void RawTheory::set_restart(Action0^ value) { - restart = value; - Z3_set_restart_callback(m_theory, ::restart_callback); -} - - -static Z3_bool final_check_callback(Z3_theory t) { - return RawTheory::GetTheory(t)->final_check(); -} - -void RawTheory::set_final_check(Func0^ value) { - final_check = value; - Z3_set_final_check_callback(m_theory, ::final_check_callback); -} - -static void new_eq_callback(Z3_theory t, Z3_ast a, Z3_ast b) { - RawTheory::GetTheory(t)->new_eq(TermPtr(a), TermPtr(b)); -} - -void RawTheory::set_new_eq(Action2^ value) { - new_eq = value; - Z3_set_new_eq_callback(m_theory, ::new_eq_callback); -} - - -static void new_diseq_callback(Z3_theory t, Z3_ast a, Z3_ast b) { - RawTheory::GetTheory(t)->new_diseq(TermPtr(a), TermPtr(b)); -} - -void RawTheory::set_new_diseq(Action2^ value) { - new_diseq = value; - Z3_set_new_diseq_callback(m_theory, ::new_diseq_callback); -} - -static void new_assignment_callback(Z3_theory t, Z3_ast a, Z3_bool b) -{ - RawTheory::GetTheory(t)->new_assignment(TermPtr(a), b?true:false); -} - -void RawTheory::set_new_assignment(Action2^ value) { - new_assignment = value; - Z3_set_new_assignment_callback(m_theory, ::new_assignment_callback); -} - -FuncDeclPtr RawTheory::MkFuncDecl(Symbol^ n, array^ domain, SortPtr range) { - scoped_Z3_ast_array _domain(domain); - return FuncDeclPtr(Z3_theory_mk_func_decl(m_context(), m_theory, n->get(), - _domain.size(), _domain.c_ptr(), get_sort(range))); -} - - -SortPtr RawTheory::MkSort(String^ s) { - return SortPtr(Z3_theory_mk_sort(m_context(), m_theory, Z3_mk_string_symbol(m_context(), CreateString(s).c_str()))); -} - -TermPtr RawTheory::MkValue(String^ s, SortPtr srt) { - Z3_symbol sym = Z3_mk_string_symbol(m_context(), CreateString(s).c_str()); - return TermPtr(Z3_theory_mk_value(m_context(), m_theory, sym, get_sort(srt))); -} - -TermPtr RawTheory::MkConstant(String^ s, SortPtr srt) { - Z3_symbol sym = Z3_mk_string_symbol(m_context(), CreateString(s).c_str()); - return TermPtr(Z3_theory_mk_constant(m_context(), m_theory, sym, get_sort(srt))); -} - -FuncDeclPtr RawTheory::MkFuncDecl(String^ s, array^ domain, SortPtr range) { - Z3_symbol sym = Z3_mk_string_symbol(m_context(), CreateString(s).c_str()); - scoped_Z3_ast_array _domain(domain); - return FuncDeclPtr(Z3_theory_mk_func_decl(m_context(), m_theory, sym, - _domain.size(), _domain.c_ptr(), get_sort(range))); - -} - - -// ----------------------------- -// Constructor - -Constructor::Constructor( - ref_context& context, - String^ name, - String^ tester, - array^ field_names, - array^ field_sorts, - array^ field_refs - ): - m_context(context), - m_constructor(0), - m_name(name), - m_tester_name(tester), - m_field_names(field_names), - m_field_sorts(field_sorts), - m_field_refs(field_refs), - m_constructor_decl(FuncDeclPtr()), - m_tester(FuncDeclPtr()), - m_accessors(nullptr) -{ - m_context.inc_ref(); -} - - -Z3_constructor Constructor::Get() -{ - if (m_constructor) { - return m_constructor; - } - Z3_symbol _name = Z3_mk_string_symbol(m_context(), CreateString(m_name).c_str()); - Z3_symbol _tester = Z3_mk_string_symbol(m_context(), CreateString(m_tester_name).c_str()); - unsigned num_fields = (!m_field_names)?0:m_field_names->Length; - scoped_Z3_symbol_array _field_names(m_context(), m_field_names); - scoped_Z3_ast_array _field_sorts(m_field_sorts); - scoped_array _field_refs(m_field_refs); - SASSERT(_field_names.size() == _field_sorts.size()); - SASSERT(_field_names.size() == _field_refs.size()); - m_constructor = Z3_mk_constructor(m_context(), _name, _tester, num_fields, - _field_names.c_ptr(), _field_sorts.c_ptr(), _field_refs.c_ptr()); - return m_constructor; -} - -Z3_constructor Constructor::Query() { - Z3_constructor result = 0; - if (!m_accessors) { - SASSERT(m_constructor); - result = m_constructor; - unsigned num_fields = (!m_field_names)?0:m_field_names->Length; - m_accessors = gcnew array(num_fields); - Z3_func_decl constructor_decl, tester_decl; - scoped_array accs(num_fields); - Z3_query_constructor(m_context(), - m_constructor, - num_fields, - &constructor_decl, - &tester_decl, - accs.c_ptr()); - m_constructor_decl = FuncDeclPtr(constructor_decl); - m_tester = FuncDeclPtr(tester_decl); - for (unsigned i = 0; i < num_fields; ++i) { - m_accessors[i] = FuncDeclPtr(accs[i]); - } - m_constructor = 0; - } - SASSERT(!m_constructor); - return result; -} - -Constructor::!Constructor() { - SASSERT(!m_constructor); -} - - -Constructor::~Constructor() { - SASSERT(!m_constructor); - m_context.dec_ref(); -} - - -FuncDeclPtr Constructor::GetConstructor() { - if (!m_constructor && !m_accessors) { - throw gcnew Z3Error(ErrorCode::InvalidUsage); - } - Z3_constructor c = Query(); - SASSERT(!c); - return FuncDeclPtr(m_constructor_decl); -} - -FuncDeclPtr Constructor::GetTester() { - if (!m_constructor && !m_accessors) { - throw gcnew Z3Error(ErrorCode::InvalidUsage); - } - Z3_constructor c = Query(); - SASSERT(!c); - return FuncDeclPtr(m_tester); -} - -array^ Constructor::GetAccessors() { - if (!m_constructor && !m_accessors) { - throw gcnew Z3Error(ErrorCode::InvalidUsage); - } - Z3_constructor c = Query(); - SASSERT(!c); - return m_accessors; -} - - - - -// ----------------------------- -// RawContext - - -void RawContext::Init() { - m_disposed = false; - s_nonempty = false; - if (s_todec == nullptr) { - s_todec = gcnew List >(); - s_monitor = gcnew IntPtr(0); - } - Z3_set_error_handler(ctx(), error_handler); -} - -RawContext::RawContext(Config^ config) { - m_context = ref_context::mk(Z3_mk_context(config->get()), true, true); - Init(); -} - -RawContext::RawContext(Config^ config, ReferenceCounted^ rc) { - m_context = ref_context::mk(Z3_mk_context_rc(config->get()), true, false); - Init(); -} - -RawContext::RawContext() { - m_context = ref_context::mk(Z3_mk_context(0), true, true); - Init(); -} - -void RawContext::SetContext(Z3_context ctx) { - Reset(); - m_context = ref_context::mk(ctx, false, true); -} - -RawContext::!RawContext() { - if (!m_disposed) { - if (RawContext::m_error_handler ) { - RawContext::m_error_handler->Handler(ErrorCode::NonDisposedContext); - } - else { - verbose_stream() << "WARNING: context was not disposed\n"; - } - } -} - - -void -RawContext::Reset() { - System::Threading::Monitor::Enter(s_monitor); - if (!m_disposed) { - m_context->dec_ref(); - m_disposed = true; - } - System::Threading::Monitor::Exit(s_monitor); -} - -RawContext::~RawContext() { - Reset(); -} - -#include "..\lib\vector.h" -#include "..\lib\trace.h" - -void RawContext::EnableDebugTrace(String^ tag) { - static vector pinned; - std::string s = CreateString(tag); - pinned.push_back(new std::string(s)); - enable_trace(pinned.back()->c_str()); -} - -void RawContext::ToggleWarningMessages(bool enabled) { - Z3_toggle_warning_messages(enabled); -} - -void RawContext::UpdateParamValue(String^ p, String^ v) { - Z3_update_param_value(ctx(), CreateString(p).c_str(), CreateString(v).c_str()); -} - -String^ RawContext::GetParamValue(String^ p) { - Z3_string vl = ""; - if (!Z3_get_param_value(ctx(), CreateString(p).c_str(), &vl)) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return gcnew String(vl); -} - -bool RawContext::SetLogic(String^ l) { - return Z3_TRUE == Z3_set_logic(ctx(), CreateString(l).c_str()); -} - -Symbol^ RawContext::MkSymbol(String^ s) { - return gcnew Symbol(ctx(), Z3_mk_string_symbol(ctx(), CreateString(s).c_str())); -} -Symbol^ RawContext::MkSymbol(int i) { - return gcnew Symbol(ctx(), Z3_mk_int_symbol(ctx(), i)); -} - -SortPtr RawContext::MkSort(Symbol^ s) { - return SortPtr(Z3_mk_uninterpreted_sort(ctx(), s->get())); -} - -SortPtr RawContext::MkSort(String^ s) { - return SortPtr(Z3_mk_uninterpreted_sort(ctx(), Z3_mk_string_symbol(ctx(), CreateString(s).c_str()))); -} - -SortPtr RawContext::MkSort(int i) { - return SortPtr(Z3_mk_uninterpreted_sort(ctx(), Z3_mk_int_symbol(ctx(), i))); -} - -SortPtr RawContext::MkBoolSort() { return SortPtr(Z3_mk_bool_sort(ctx())); } - -SortPtr RawContext::MkIntSort() { return SortPtr(Z3_mk_int_sort(ctx())); } - -SortPtr RawContext::MkRealSort() { return SortPtr(Z3_mk_real_sort(ctx())); } - -SortPtr RawContext::MkBvSort(unsigned sz) { return SortPtr(Z3_mk_bv_sort(ctx(), sz)); } - -SortPtr RawContext::MkArraySort(SortPtr domain, SortPtr range) { - return SortPtr(Z3_mk_array_sort(ctx(), get_sort(domain), get_sort(range))); -} - -SortPtr RawContext::MkFiniteDomainSort(String^ s, unsigned __int64 domain_size) { - return SortPtr(Z3_mk_finite_domain_sort(ctx(), Z3_mk_string_symbol(ctx(), CreateString(s).c_str()), domain_size)); -} - -SortPtr RawContext::MkTupleSort( - Symbol^ mk_tuple_name, - array^ field_names, - array^ field_types, - FuncDeclPtr% mk_tuple_decl, - array^ proj_decls - ) -{ - if (!field_names || - !field_types || - !proj_decls || - field_names->Length != field_types->Length || - field_names->Length != proj_decls->Length) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - scoped_Z3_symbol_array syms(field_names); - scoped_Z3_ast_array types(field_types); - scoped_Z3_ast_array projs(field_names->Length); - Z3_func_decl decl; - - Z3_sort ty = - Z3_mk_tuple_sort( - ctx(), - mk_tuple_name->get(), - syms.size(), - syms.c_ptr(), - types.c_ptr(), - &decl, - projs.c_ptr() - ); - - mk_tuple_decl = FuncDeclPtr(decl); - CopyFuncDecl(projs, proj_decls); - return SortPtr(ty); -} - -SortPtr RawContext::MkTupleSort( - String^ mk_tuple_name, - array^ field_names, - array^ field_types, - FuncDeclPtr% mk_tuple_decl, - array^ proj_decls - ) -{ - Symbol^ tn = MkSymbol(mk_tuple_name); - array^ fields = gcnew array(field_names->Length); - for (int i = 0; i < fields->Length; ++i) { - fields[i] = MkSymbol(field_names[i]); - } - return MkTupleSort(tn, fields, field_types, mk_tuple_decl, proj_decls); - -} - -SortPtr RawContext::MkEnumerationSort( - String^ name, - array^ enum_names, - array^ enum_consts, - array^ enum_testers) { - - Z3_symbol _name(Z3_mk_string_symbol(ctx(), CreateString(name).c_str())); - scoped_Z3_symbol_array _enum_names(ctx(), enum_names); - scoped_Z3_ast_array _enum_consts(enum_consts); - scoped_Z3_ast_array _enum_testers(enum_testers); - unsigned sz = _enum_names.size(); - SASSERT(sz == _enum_consts.size()); - SASSERT(sz == _enum_testers.size()); - Z3_sort s = Z3_mk_enumeration_sort(ctx(), _name, sz, _enum_names.c_ptr(), _enum_consts.c_ptr(), _enum_testers.c_ptr()); - CopyFuncDecl(_enum_consts, enum_consts); - CopyFuncDecl(_enum_testers, enum_testers); - return SortPtr(s); -} - -SortPtr RawContext::MkListSort( - String^ name, - SortPtr elem_sort, - FuncDeclPtr% nil_decl, - FuncDeclPtr% is_nil_decl, - FuncDeclPtr% cons_decl, - FuncDeclPtr% is_cons_decl, - FuncDeclPtr% head_decl, - FuncDeclPtr% tail_decl - ) -{ - Z3_func_decl _nil_decl, _is_nil_decl, _cons_decl, _is_cons_decl, _head_decl, _tail_decl; - Z3_symbol _name = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); - Z3_sort _elem_sort = get_sort(elem_sort); - - Z3_sort s = Z3_mk_list_sort(ctx(), _name, _elem_sort, - &_nil_decl, &_is_nil_decl, &_cons_decl, - &_is_cons_decl, &_head_decl, &_tail_decl); - - is_nil_decl = FuncDeclPtr(_is_nil_decl); - nil_decl = FuncDeclPtr(_nil_decl); - is_cons_decl = FuncDeclPtr(_is_cons_decl); - cons_decl = FuncDeclPtr(_cons_decl); - head_decl = FuncDeclPtr(_head_decl); - tail_decl = FuncDeclPtr(_tail_decl); - return SortPtr(s); -} - - - -Constructor^ RawContext::MkConstructor( - String^ name, - String^ tester, - array^ field_names, - array^ field_sorts, - array^ field_refs - ) -{ - - int l1 = (!field_names)?0:field_names->Length; - int l2 = (!field_sorts)?0:field_sorts->Length; - int l3 = (!field_refs)?0:field_refs->Length; - if (l1 != l2 || l1 != l3) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return gcnew Constructor(*m_context, name, tester, - field_names, field_sorts, field_refs); -} - - -SortPtr RawContext::MkDataType( - String^ name, - array^ constructors - ) -{ - Z3_symbol _name = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); - scoped_array _cons(constructors->Length); - for (int i = 0; i < constructors->Length; ++i) { - _cons[i] = constructors[i]->Get(); - } - Z3_sort s = Z3_mk_datatype(ctx(), _name, _cons.size(), _cons.c_ptr()); - for (int i = 0; i < constructors->Length; ++i) { - Z3_constructor c = constructors[i]->Query(); - Z3_del_constructor(ctx(), c); - } - return SortPtr(s); -} - -array^ RawContext::MkDataTypes( - array^ names, - array^>^ constructors_list - ) -{ - if (!names || - !constructors_list || - names->Length != constructors_list->Length) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - - } - unsigned num_sorts = names->Length; - scoped_array sort_names(num_sorts); - scoped_array clist(num_sorts); - scoped_array sort_sorts(num_sorts); - array^ result = gcnew array(num_sorts); - unsigned num_constructors = 0; - for (unsigned j = 0; j < num_sorts; ++j) { - num_constructors += constructors_list[j]->Length; - } - scoped_array constructor_vec(num_constructors); - svector constructors_q; - unsigned constructor_idx = 0; - - for (unsigned j = 0; j < num_sorts; ++j) { - String^ name = names[j]; - array^ constructors = constructors_list[j]; - - // add sort name - Z3_symbol _name = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); - sort_names[j] = _name; - - // create constructor_list - scoped_array _cons(constructors->Length); - for (int i = 0; i < constructors->Length; ++i) { - _cons[i] = constructors[i]->Get(); - constructor_vec[constructor_idx++] = _cons[i]; - } - Z3_constructor_list cl = Z3_mk_constructor_list(ctx(), _cons.size(), _cons.c_ptr()); - clist[j] = cl; - } - Z3_mk_datatypes(ctx(), num_sorts, sort_names.c_ptr(), sort_sorts.c_ptr(), clist.c_ptr()); - - for (unsigned j = 0; j < num_sorts; ++j) { - Z3_del_constructor_list(ctx(), clist[j]); - result[j] = SortPtr(sort_sorts[j]); - // populate the constructors - array^ constructors = constructors_list[j]; - for (int i = 0; i < constructors->Length; ++i) { - constructors_q.push_back(constructors[i]->Query()); - } - } - for (unsigned i = 0; i < constructors_q.size(); ++i) { - Z3_constructor c = constructors_q[i]; - if (c) { - Z3_del_constructor(ctx(), c); - } - } - return result; -} - - - -FuncDeclPtr RawContext::MkFuncDecl(Symbol^ s, array^ domain, SortPtr range) { - scoped_Z3_ast_array types(domain); - return FuncDeclPtr(Z3_mk_func_decl(ctx(), s->get(), types.size(), types.c_ptr(), get_sort(range))); -} - -FuncDeclPtr RawContext::MkFuncDecl(String^ s, array^ domain, SortPtr range) { - scoped_Z3_ast_array types(domain); - Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(s).c_str()); - return FuncDeclPtr(Z3_mk_func_decl(ctx(), sym, types.size(), types.c_ptr(), get_sort(range))); -} - -FuncDeclPtr RawContext::MkFuncDecl(Symbol^ s, SortPtr domain, SortPtr range) { - Z3_sort dom[1] = { get_sort(domain) }; - return FuncDeclPtr(Z3_mk_func_decl(ctx(), s->get(), 1, dom, get_sort(range))); -} - -FuncDeclPtr RawContext::MkFuncDecl(Symbol^ s, SortPtr d1, SortPtr d2, SortPtr range) { - Z3_sort dom[2] = { get_sort(d1), get_sort(d2) }; - return FuncDeclPtr(Z3_mk_func_decl(ctx(), s->get(), 2, dom, get_sort(range))); -} - -FuncDeclPtr RawContext::MkFuncDecl(String^ s, SortPtr domain, SortPtr range) { - Z3_sort dom[1] = { get_sort(domain) }; - Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(s).c_str()); - return FuncDeclPtr(Z3_mk_func_decl(ctx(), sym, 1, dom, get_sort(range))); -} - -FuncDeclPtr RawContext::MkFuncDecl(String^ s, SortPtr d1, SortPtr d2, SortPtr range) { - Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(s).c_str()); - Z3_sort dom[2] = { get_sort(d1), get_sort(d2) }; - return FuncDeclPtr(Z3_mk_func_decl(ctx(), sym, 2, dom, get_sort(range))); -} - -TermPtr RawContext::MkApp(FuncDeclPtr d, array^ args) { - scoped_Z3_ast_array z3_args(args); - return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), z3_args.size(), z3_args.c_ptr())); -} - -TermPtr RawContext::MkApp(FuncDeclPtr d, TermPtr arg) { - Z3_ast args[1] = { get_ast(arg) }; - return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), 1, args)); -} - -TermPtr RawContext::MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2) { - Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; - return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), 2, args)); -} - -TermPtr RawContext::MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2, TermPtr arg3) { - Z3_ast args[3] = { get_ast(arg1), get_ast(arg2), get_ast(arg3) }; - return TermPtr(Z3_mk_app(ctx(), get_func_decl(d), 3, args)); -} - - -TermPtr RawContext::MkConst(FuncDeclPtr d) { - return TermPtr(Z3_mk_app(ctx(),get_func_decl(d), 0, 0)); -} - -TermPtr RawContext::MkConst(String^ s, SortPtr ty) { - Z3_symbol sym = Z3_mk_string_symbol(ctx(),CreateString(s).c_str()); - Z3_func_decl d = Z3_mk_func_decl(ctx(), sym, 0, 0, get_sort(ty)); - return TermPtr(Z3_mk_app(ctx(), d, 0, 0)); -} - -TermPtr RawContext::MkConst(Symbol^ s, SortPtr ty) { - Z3_func_decl d = Z3_mk_func_decl(ctx(), s->get(), 0, 0, get_sort(ty)); - return TermPtr(Z3_mk_app(ctx(), d, 0, 0)); -} - -FuncDeclPtr RawContext::MkFreshFuncDecl(String^ prefix, array^ domain, SortPtr range) { - scoped_Z3_ast_array types(domain); - return FuncDeclPtr(Z3_mk_fresh_func_decl(ctx(), CreateString(prefix).c_str(), types.size(), types.c_ptr(), get_sort(range))); -} - -TermPtr RawContext::MkFreshConst(String^ prefix, SortPtr ty) { - return TermPtr(Z3_mk_fresh_const(ctx(), CreateString(prefix).c_str(), get_sort(ty))); -} - -TermPtr RawContext::MkLabel(Symbol^ name, bool pos, TermPtr fml) { - return TermPtr(Z3_mk_label(ctx(), name->get(), pos, get_ast(fml))); -} - - -TermPtr RawContext::MkEq(TermPtr l, TermPtr r) { - return TermPtr(Z3_mk_eq(ctx(), get_ast(l), get_ast(r))); -} - -TermPtr RawContext::MkDistinct(array^ _args) { - scoped_Z3_ast_array args(_args); - return TermPtr(Z3_mk_distinct(ctx(), args.size(), args.c_ptr())); -} - -TermPtr RawContext::MkNot(TermPtr arg) { - return TermPtr(Z3_mk_not(ctx(), get_ast(arg))); -} - -TermPtr RawContext::MkIte(TermPtr t1, TermPtr t2, TermPtr t3) { - return TermPtr(Z3_mk_ite(ctx(), get_ast(t1), get_ast(t2), get_ast(t3))); -} - -#define MK_BINARY(fn, t1, t2) return TermPtr(Z3_mk_ ## fn (ctx(), get_ast(t1), get_ast(t2))) - -#define MK_UNARY(fn, t1) return TermPtr(Z3_mk_ ## fn (ctx(), get_ast(t1))) - -#define MK_NARY(fn, _args_) { scoped_Z3_ast_array my_args(_args_); return TermPtr(Z3_mk_ ## fn (ctx(), my_args.size(), my_args.c_ptr())); } - -TermPtr RawContext::MkIff(TermPtr t1, TermPtr t2) { - MK_BINARY(iff, t1, t2); -} - -TermPtr RawContext::MkImplies(TermPtr t1, TermPtr t2) { - MK_BINARY(implies, t1, t2); -} - -TermPtr RawContext::MkXor(TermPtr t1, TermPtr t2) { - MK_BINARY(xor, t1, t2); -} - -TermPtr RawContext::MkAnd(array^ args) { - MK_NARY(and, args); -} - -TermPtr RawContext::MkAnd(TermPtr arg1, TermPtr arg2) { - Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; - return TermPtr(Z3_mk_and(ctx(), 2, args)); -} - -TermPtr RawContext::MkOr(array^ args) { - MK_NARY(or, args); -} - -TermPtr RawContext::MkOr(TermPtr arg1, TermPtr arg2) { - Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; - return TermPtr(Z3_mk_or(ctx(), 2, args)); -} - -TermPtr RawContext::MkAdd(array^ args) { - MK_NARY(add, args); -} - -TermPtr RawContext::MkAdd(TermPtr arg1, TermPtr arg2) { - Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; - return TermPtr(Z3_mk_add(ctx(), 2, args)); -} - -TermPtr RawContext::MkMul(array^ args) { - MK_NARY(mul, args); -} - -TermPtr RawContext::MkMul(TermPtr arg1, TermPtr arg2) { - Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; - return TermPtr(Z3_mk_mul(ctx(), 2, args)); -} - -TermPtr RawContext::MkSub(array^ args) { - MK_NARY(sub, args); -} - -TermPtr RawContext::MkSub(TermPtr arg1, TermPtr arg2) { - Z3_ast args[2] = { get_ast(arg1), get_ast(arg2) }; - return TermPtr(Z3_mk_sub(ctx(), 2, args)); -} - -TermPtr RawContext::MkUnaryMinus(TermPtr arg) { - MK_UNARY(unary_minus, arg); -} - -TermPtr RawContext::MkDiv(TermPtr arg1, TermPtr arg2) { - MK_BINARY(div, arg1, arg2); -} - -TermPtr RawContext::MkMod(TermPtr arg1, TermPtr arg2) { - MK_BINARY(mod, arg1, arg2); -} - -TermPtr RawContext::MkRem(TermPtr arg1, TermPtr arg2) { - MK_BINARY(rem, arg1, arg2); -} - -TermPtr RawContext::MkToReal(TermPtr arg) { - MK_UNARY(int2real, arg); -} - - -TermPtr RawContext::MkToInt(TermPtr arg) { - MK_UNARY(real2int, arg); -} - -TermPtr RawContext::MkIsInt(TermPtr arg) { - MK_UNARY(is_int, arg); -} - -TermPtr RawContext::MkLt(TermPtr arg1, TermPtr arg2) { - MK_BINARY(lt, arg1, arg2); -} - -TermPtr RawContext::MkLe(TermPtr arg1, TermPtr arg2) { - MK_BINARY(le, arg1, arg2); -} - -TermPtr RawContext::MkGt(TermPtr arg1, TermPtr arg2) { - MK_BINARY(gt, arg1, arg2); -} - -TermPtr RawContext::MkGe(TermPtr arg1, TermPtr arg2) { - MK_BINARY(ge, arg1, arg2); -} - -TermPtr RawContext::MkBvNot(TermPtr t1) { - MK_UNARY(bvnot, t1); -} - -TermPtr RawContext::MkBvReduceAnd(TermPtr t1) { - MK_UNARY(bvredand, t1); -} - -TermPtr RawContext::MkBvReduceOr(TermPtr t1) { - MK_UNARY(bvredor, t1); -} - -TermPtr RawContext::MkBvAnd(TermPtr t1, TermPtr t2) { - MK_BINARY(bvand, t1, t2); -} - -TermPtr RawContext::MkBvOr(TermPtr t1, TermPtr t2) { - MK_BINARY(bvor, t1, t2); -} - -TermPtr RawContext::MkBvXor(TermPtr t1, TermPtr t2) { - MK_BINARY(bvxor, t1, t2); -} - -TermPtr RawContext::MkBvNand(TermPtr t1, TermPtr t2) { - MK_BINARY(bvnand, t1, t2); -} - -TermPtr RawContext::MkBvNor(TermPtr t1, TermPtr t2) { - MK_BINARY(bvnor, t1, t2); -} - -TermPtr RawContext::MkBvXnor(TermPtr t1, TermPtr t2) { - MK_BINARY(bvxnor, t1, t2); -} - -TermPtr RawContext::MkBvNeg(TermPtr t1) { - MK_UNARY(bvneg, t1); -} - -TermPtr RawContext::MkBvAdd(TermPtr t1, TermPtr t2) { - MK_BINARY(bvadd, t1, t2); -} - -TermPtr RawContext::MkBvSub(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsub, t1, t2); -} - -TermPtr RawContext::MkBvMul(TermPtr t1, TermPtr t2) { - MK_BINARY(bvmul, t1, t2); -} - -TermPtr RawContext::MkBvUdiv(TermPtr t1, TermPtr t2) { - MK_BINARY(bvudiv, t1, t2); -} - -TermPtr RawContext::MkBvSdiv(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsdiv, t1, t2); -} - -TermPtr RawContext::MkBvUrem(TermPtr t1, TermPtr t2) { - MK_BINARY(bvurem, t1, t2); -} -TermPtr RawContext::MkBvSrem(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsrem, t1, t2); -} - -TermPtr RawContext::MkBvSmod(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsmod, t1, t2); -} - -TermPtr RawContext::MkBvUlt(TermPtr t1, TermPtr t2) { - MK_BINARY(bvult, t1, t2); -} - -TermPtr RawContext::MkBvSlt(TermPtr t1, TermPtr t2) { - MK_BINARY(bvslt, t1, t2); -} - -TermPtr RawContext::MkBvUle(TermPtr t1, TermPtr t2) { - MK_BINARY(bvule, t1, t2); -} - -TermPtr RawContext::MkBvSle(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsle, t1, t2); -} - -TermPtr RawContext::MkBvUge(TermPtr t1, TermPtr t2) { - MK_BINARY(bvuge, t1, t2); -} - -TermPtr RawContext::MkBvSge(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsge, t1, t2); -} - -TermPtr RawContext::MkBvUgt(TermPtr t1, TermPtr t2) { - MK_BINARY(bvugt, t1, t2); -} - -TermPtr RawContext::MkBvSgt(TermPtr t1, TermPtr t2) { - MK_BINARY(bvsgt, t1, t2); -} - -TermPtr RawContext::MkBvConcat(TermPtr t1, TermPtr t2) { - MK_BINARY(concat, t1, t2); -} - -TermPtr RawContext::MkBvExtract(unsigned high, unsigned low, TermPtr t) { - return TermPtr(Z3_mk_extract(ctx(), high, low, get_ast(t))); -} - -TermPtr RawContext::MkBvSignExt(unsigned i, TermPtr t) { - return TermPtr(Z3_mk_sign_ext(ctx(), i, get_ast(t))); -} - -TermPtr RawContext::MkBvZeroExt(unsigned i, TermPtr t) { - return TermPtr(Z3_mk_zero_ext(ctx(), i, get_ast(t))); -} - -TermPtr RawContext::MkBvRepeat(unsigned i, TermPtr t) { - return TermPtr(Z3_mk_repeat(ctx(), i, get_ast(t))); -} - -TermPtr RawContext::MkBvShl(TermPtr t1, TermPtr t2) { - MK_BINARY(bvshl, t1, t2); -} - -TermPtr RawContext::MkBvLshr(TermPtr t1, TermPtr t2) { - MK_BINARY(bvlshr, t1, t2); -} - -TermPtr RawContext::MkBvAshr(TermPtr t1, TermPtr t2) { - MK_BINARY(bvashr, t1, t2); -} - -TermPtr RawContext::MkBvRotateLeft(unsigned i, TermPtr t1) { - return TermPtr(Z3_mk_rotate_left(ctx(), i, get_ast(t1))); -} - -TermPtr RawContext::MkBvRotateRight(unsigned i, TermPtr t1) { - return TermPtr(Z3_mk_rotate_right(ctx(), i, get_ast(t1))); -} - -TermPtr RawContext::MkBvRotateLeft(TermPtr t1, TermPtr t2) { - return TermPtr(Z3_mk_ext_rotate_left(ctx(), get_ast(t1), get_ast(t2))); -} - -TermPtr RawContext::MkBvRotateRight(TermPtr t1, TermPtr t2) { - return TermPtr(Z3_mk_ext_rotate_right(ctx(), get_ast(t1), get_ast(t2))); -} - -TermPtr RawContext::MkInt2Bv(unsigned i, TermPtr t1) { - return TermPtr(Z3_mk_int2bv(ctx(), i, get_ast(t1))); -} - -TermPtr RawContext::MkBv2Int(TermPtr t1, bool is_signed) { - return TermPtr(Z3_mk_bv2int(ctx(), get_ast(t1), is_signed)); -} - -TermPtr RawContext::MkBvAddNoOverflow(TermPtr t1, TermPtr t2, bool is_signed) { - return TermPtr(Z3_mk_bvadd_no_overflow(ctx(), get_ast(t1), get_ast(t2), is_signed)); -} - -TermPtr RawContext::MkBvAddNoUnderflow(TermPtr t1, TermPtr t2) { - return TermPtr(Z3_mk_bvadd_no_underflow(ctx(), get_ast(t1), get_ast(t2))); -} - -TermPtr RawContext::MkBvSubNoOverflow(TermPtr t1, TermPtr t2) { - return TermPtr(Z3_mk_bvsub_no_overflow(ctx(), get_ast(t1), get_ast(t2))); -} - -TermPtr RawContext::MkBvSubNoUnderflow(TermPtr t1, TermPtr t2, bool is_signed) { - return TermPtr(Z3_mk_bvsub_no_underflow(ctx(), get_ast(t1), get_ast(t2), is_signed)); -} - -TermPtr RawContext::MkBvSDivNoOverflow(TermPtr t1, TermPtr t2) { - return TermPtr(Z3_mk_bvsdiv_no_overflow(ctx(), get_ast(t1), get_ast(t2))); -} - -TermPtr RawContext::MkBvNegNoOverflow(TermPtr t1) { - return TermPtr(Z3_mk_bvneg_no_overflow(ctx(), get_ast(t1))); -} - -TermPtr RawContext::MkBvMulNoOverflow(TermPtr t1, TermPtr t2, bool is_signed) { - return TermPtr(Z3_mk_bvmul_no_overflow(ctx(), get_ast(t1), get_ast(t2), is_signed)); -} - -TermPtr RawContext::MkBvMulNoUnderflow(TermPtr t1, TermPtr t2) { - return TermPtr(Z3_mk_bvmul_no_underflow(ctx(), get_ast(t1), get_ast(t2))); -} - -TermPtr RawContext::MkArraySelect(TermPtr a, TermPtr i) { - return TermPtr(Z3_mk_select(ctx(), get_ast(a), get_ast(i))); -} - -TermPtr RawContext::MkArrayStore(TermPtr a, TermPtr i, TermPtr v) { - return TermPtr(Z3_mk_store(ctx(), get_ast(a), get_ast(i), get_ast(v))); -} - -TermPtr RawContext::MkArrayMap(FuncDeclPtr d, array^ args) { - scoped_Z3_ast_array _args(args); - return TermPtr(Z3_mk_map(ctx(), get_func_decl(d), _args.size(), _args.c_ptr())); -} - -TermPtr RawContext::MkArrayConst(SortPtr domain, TermPtr v) { - return TermPtr(Z3_mk_const_array(ctx(), get_sort(domain), get_ast(v))); -} - -TermPtr RawContext::MkArrayDefault(TermPtr a) { - return TermPtr(Z3_mk_array_default(ctx(), get_ast(a))); -} - -TermPtr RawContext::MkSetUnion(array^ sets) { - scoped_Z3_ast_array _sets(sets); - return TermPtr(Z3_mk_set_union(ctx(), _sets.size(), _sets.c_ptr())); -} - -TermPtr RawContext::MkSetUnion(TermPtr set1, TermPtr set2) { - Z3_ast args[2] = { get_ast(set1), get_ast(set2) }; - return TermPtr(Z3_mk_set_union(ctx(), 2, args)); -} - -TermPtr RawContext::MkSetIntersect(array^ sets) { - scoped_Z3_ast_array _sets(sets); - return TermPtr(Z3_mk_set_intersect(ctx(), _sets.size(), _sets.c_ptr())); -} - -TermPtr RawContext::MkSetIntersect(TermPtr set1, TermPtr set2) { - Z3_ast args[2] = { get_ast(set1), get_ast(set2) }; - return TermPtr(Z3_mk_set_intersect(ctx(), 2, args)); -} - -FuncDeclPtr RawContext::MkInjectiveFunction(String^ name, array^ domain, SortPtr range) { - scoped_Z3_ast_array types(domain); - Z3_symbol sym = Z3_mk_string_symbol(ctx(), CreateString(name).c_str()); - return FuncDeclPtr(Z3_mk_injective_function(ctx(), sym, types.size(), types.c_ptr(), get_sort(range))); -} - -FuncDeclPtr RawContext::MkInjectiveFunction(Symbol^ name, array^ domain, SortPtr range) { - scoped_Z3_ast_array types(domain); - return FuncDeclPtr(Z3_mk_injective_function(ctx(), name->get(), types.size(), types.c_ptr(), get_sort(range))); -} - - -TermPtr RawContext::MkNumeral(String^ numeral, SortPtr ty) { - return TermPtr(Z3_mk_numeral(ctx(), CreateString(numeral).c_str(), get_sort(ty))); -} - -TermPtr RawContext::MkNumeral(int n, SortPtr ty) { - return TermPtr(Z3_mk_int(ctx(), n, get_sort(ty))); -} - -TermPtr RawContext::MkNumeral(unsigned n, SortPtr ty) { - return TermPtr(Z3_mk_unsigned_int(ctx(), n, get_sort(ty))); -} - -TermPtr RawContext::MkNumeral(__int64 n, SortPtr ty) { - return TermPtr(Z3_mk_int64(ctx(), n, get_sort(ty))); -} - -TermPtr RawContext::MkNumeral(unsigned __int64 n, SortPtr ty) { - return TermPtr(Z3_mk_unsigned_int64(ctx(), n, get_sort(ty))); -} - -PatternPtr RawContext::MkPattern(array^ terms) { - scoped_Z3_ast_array args(terms); - return PatternPtr(Z3_mk_pattern(ctx(), args.size(), args.c_ptr())); -} - -TermPtr RawContext::MkBound(unsigned index, SortPtr ty) { - return TermPtr(Z3_mk_bound(ctx(), index, get_sort(ty))); -} - -TermPtr RawContext::MkForall( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ) -{ - scoped_Z3_ast_array _patterns(patterns); - scoped_Z3_ast_array _types(types); - scoped_Z3_symbol_array _names(names); - return TermPtr( - Z3_mk_forall( - ctx(), - weight, - _patterns.size(), - _patterns.c_ptr(), - _types.size(), - _types.c_ptr(), - _names.c_ptr(), - get_ast(body) - ) - ); -} - -TermPtr RawContext::MkForall( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ) -{ - if (!names) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - array^ nameSymbols = gcnew array(names->Length); - for (int i = 0; i < nameSymbols->Length; ++i) { - nameSymbols[i] = MkSymbol(names[i]); - } - return MkForall(weight, patterns, types, nameSymbols, body); -} - -TermPtr RawContext::MkForall( - unsigned weight, - array^ bound, - array^ patterns, - TermPtr body - ) -{ - scoped_Z3_ast_array _bound(bound); - scoped_Z3_ast_array _patterns(patterns); - return TermPtr( - Z3_mk_forall_const( - ctx(), - weight, - _bound.size(), - _bound.c_ptr(), - _patterns.size(), - _patterns.c_ptr(), - get_ast(body) - )); -} - -TermPtr RawContext::MkExists( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ) -{ - scoped_Z3_ast_array _patterns(patterns); - scoped_Z3_ast_array _types(types); - scoped_Z3_symbol_array _names(names); - return TermPtr( - Z3_mk_exists( - ctx(), - weight, - _patterns.size(), - _patterns.c_ptr(), - _types.size(), - _types.c_ptr(), - _names.c_ptr(), - get_ast(body) - ) - ); -} - -TermPtr RawContext::MkExists( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ) -{ - if (!names) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - array^ nameSymbols = gcnew array(names->Length); - for (int i = 0; i < nameSymbols->Length; ++i) { - nameSymbols[i] = MkSymbol(names[i]); - } - return MkExists(weight, patterns, types, nameSymbols, body); -} - -TermPtr RawContext::MkExists( - unsigned weight, - array^ bound, - array^ patterns, - TermPtr body - ) -{ - scoped_Z3_ast_array _bound(bound); - scoped_Z3_ast_array _patterns(patterns); - return TermPtr( - Z3_mk_exists_const( - ctx(), - weight, - _bound.size(), - _bound.c_ptr(), - _patterns.size(), - _patterns.c_ptr(), - get_ast(body) - )); -} - -TermPtr RawContext::MkQuantifier( - bool is_forall, - unsigned weight, - Symbol^ quantifier_id, - Symbol^ skolem_id, - array^ patterns, - array^ no_patterns, - array^ types, - array^ names, - TermPtr body - ) -{ - scoped_Z3_ast_array _patterns(patterns); - scoped_Z3_ast_array _no_patterns(no_patterns); - scoped_Z3_ast_array _types(types); - scoped_Z3_symbol_array _names(names); - return TermPtr( - Z3_mk_quantifier_ex( - ctx(), - is_forall, - weight, - quantifier_id?quantifier_id->get():0, - skolem_id?skolem_id->get():0, - _patterns.size(), - _patterns.c_ptr(), - _no_patterns.size(), - _no_patterns.c_ptr(), - _types.size(), - _types.c_ptr(), - _names.c_ptr(), - get_ast(body) - ) - ); -} - -TermPtr RawContext::MkQuantifier( - bool is_forall, - unsigned weight, - Symbol^ quantifier_id, - Symbol^ skolem_id, - array^ patterns, - array^ no_patterns, - array^ bound, - TermPtr body - ) -{ - scoped_Z3_ast_array _patterns(patterns); - scoped_Z3_ast_array _no_patterns(no_patterns); - scoped_Z3_ast_array _bound(bound); - return TermPtr( - Z3_mk_quantifier_const_ex( - ctx(), - is_forall, - weight, - quantifier_id?quantifier_id->get():0, - skolem_id?skolem_id->get():0, - _bound.size(), _bound.c_ptr(), - _patterns.size(), - _patterns.c_ptr(), - _no_patterns.size(), - _no_patterns.c_ptr(), - get_ast(body) - ) - ); -} - -unsigned RawContext::GetTermId(TermPtr t) { - return Z3_get_ast_id(ctx(), get_ast(t)); -} - -unsigned RawContext::GetFuncDeclId(FuncDeclPtr t) { - return Z3_get_func_decl_id(ctx(), get_func_decl(t)); -} - -unsigned RawContext::GetSortId(SortPtr t) { - return Z3_get_sort_id(ctx(), get_sort(t)); -} - -SymbolKind RawContext::GetSymbolKind(Symbol^ s) { - switch(Z3_get_symbol_kind(ctx(), s->get())) { - case Z3_INT_SYMBOL: - return SymbolKind::Int; - case Z3_STRING_SYMBOL: - return SymbolKind::String; - default: - UNREACHABLE(); - } - return SymbolKind::Int; -} - -int RawContext::GetSymbolInt(Symbol^ s) { - return Z3_get_symbol_int(ctx(), s->get()); -} - -String^ Symbol::ToString() { - return gcnew String(Z3_get_symbol_string(m_ctx, m_symbol)); -} - -String^ RawContext::GetSymbolString(Symbol^ s) { - return gcnew String(Z3_get_symbol_string(ctx(), s->get())); -} - -bool RawContext::IsEq(TermPtr t1, TermPtr t2) { - return Z3_TRUE == Z3_is_eq_ast(ctx(), get_ast(t1), get_ast(t2)); -} - -bool RawContext::IsWellSorted(TermPtr t) { - return Z3_is_well_sorted(ctx(), get_ast(t)) == Z3_TRUE; -} - -TermKind RawContext::GetTermKind(TermPtr a) { - switch(Z3_get_ast_kind(ctx(), get_ast(a))) { - case Z3_NUMERAL_AST: - return TermKind::Numeral; - case Z3_APP_AST: - return TermKind::App; - case Z3_VAR_AST: - return TermKind::Var; - case Z3_QUANTIFIER_AST: - return TermKind::Quantifier; - case Z3_UNKNOWN_AST: - return TermKind::Unknown; - } - UNREACHABLE(); - return TermKind::Unknown; -} - -DeclKind RawContext::GetDeclKind(FuncDeclPtr d) { - switch(Z3_get_decl_kind(ctx(), get_func_decl(d))) { - case Z3_OP_TRUE: return DeclKind::True; - case Z3_OP_FALSE: return DeclKind::False; - case Z3_OP_EQ: return DeclKind::Eq; - case Z3_OP_DISTINCT: return DeclKind::Distinct; - case Z3_OP_ITE: return DeclKind::Ite; - case Z3_OP_AND: return DeclKind::And; - case Z3_OP_OR: return DeclKind::Or; - case Z3_OP_IFF: return DeclKind::Iff; - case Z3_OP_XOR: return DeclKind::Xor; - case Z3_OP_NOT: return DeclKind::Not; - case Z3_OP_IMPLIES: return DeclKind::Implies; - case Z3_OP_ANUM: return DeclKind::ArithNum; - case Z3_OP_LE: return DeclKind::Le; - case Z3_OP_GE: return DeclKind::Ge; - case Z3_OP_LT: return DeclKind::Lt; - case Z3_OP_GT: return DeclKind::Gt; - case Z3_OP_ADD: return DeclKind::Add; - case Z3_OP_SUB: return DeclKind::Sub; - case Z3_OP_UMINUS: return DeclKind::Uminus; - case Z3_OP_MUL: return DeclKind::Mul; - case Z3_OP_DIV: return DeclKind::Div; - case Z3_OP_IDIV: return DeclKind::IDiv; - case Z3_OP_REM: return DeclKind::Rem; - case Z3_OP_MOD: return DeclKind::Mod; - case Z3_OP_TO_REAL: return DeclKind::ToReal; - case Z3_OP_TO_INT: return DeclKind::ToInt; - case Z3_OP_IS_INT: return DeclKind::IsInt; - case Z3_OP_STORE: return DeclKind::Store; - case Z3_OP_SELECT: return DeclKind::Select; - case Z3_OP_CONST_ARRAY: return DeclKind::ConstArray; - case Z3_OP_ARRAY_DEFAULT: return DeclKind::DefaultArray; - case Z3_OP_ARRAY_MAP: return DeclKind::MapArray; - case Z3_OP_SET_UNION: return DeclKind::Union; - case Z3_OP_SET_INTERSECT: return DeclKind::Intersect; - case Z3_OP_SET_DIFFERENCE: return DeclKind::Difference; - case Z3_OP_SET_COMPLEMENT: return DeclKind::Complement; - case Z3_OP_SET_SUBSET: return DeclKind::Subset; - case Z3_OP_AS_ARRAY: return DeclKind::AsArray; - case Z3_OP_BNUM: return DeclKind::BitNum; - case Z3_OP_BIT1: return DeclKind::Bit1 ; - case Z3_OP_BIT0: return DeclKind::Bit0 ; - case Z3_OP_BNEG: return DeclKind::BNeg ; - case Z3_OP_BADD: return DeclKind::BAdd ; - case Z3_OP_BSUB: return DeclKind::BSub ; - case Z3_OP_BMUL: return DeclKind::BMul ; - - case Z3_OP_BSDIV: return DeclKind::BSDiv ; - case Z3_OP_BUDIV: return DeclKind::BUDiv ; - case Z3_OP_BSREM: return DeclKind::BSRem ; - case Z3_OP_BUREM: return DeclKind::BURem ; - case Z3_OP_BSMOD: return DeclKind::BSMod ; - - // special functions to record the division by 0 cases - // these are internal functions - case Z3_OP_BSDIV0: return DeclKind::BSDiv0 ; - case Z3_OP_BUDIV0: return DeclKind::BUDiv0 ; - case Z3_OP_BSREM0: return DeclKind::BSRem0 ; - case Z3_OP_BUREM0: return DeclKind::BURem0 ; - case Z3_OP_BSMOD0: return DeclKind::BSMod0 ; - - case Z3_OP_ULEQ: return DeclKind::BULeq ; - case Z3_OP_SLEQ: return DeclKind::BSLeq ; - case Z3_OP_UGEQ: return DeclKind::BUGeq ; - case Z3_OP_SGEQ: return DeclKind::BSGeq ; - case Z3_OP_ULT: return DeclKind::BULt ; - case Z3_OP_SLT: return DeclKind::BSLt ; - case Z3_OP_UGT: return DeclKind::BUGt ; - case Z3_OP_SGT: return DeclKind::BSGt ; - - case Z3_OP_BAND: return DeclKind::BAnd ; - case Z3_OP_BOR: return DeclKind::BOr ; - case Z3_OP_BNOT: return DeclKind::BNot; - case Z3_OP_BXOR: return DeclKind::BXor ; - case Z3_OP_BNAND: return DeclKind::BNand ; - case Z3_OP_BNOR: return DeclKind::BNor ; - case Z3_OP_BXNOR: return DeclKind::BXnor ; - - case Z3_OP_CONCAT: return DeclKind::BConcat ; - case Z3_OP_SIGN_EXT: return DeclKind::BSignExt ; - case Z3_OP_ZERO_EXT: return DeclKind::BZeroExt ; - case Z3_OP_EXTRACT: return DeclKind::BExtract ; - case Z3_OP_REPEAT: return DeclKind::BRepeat ; - - case Z3_OP_BREDOR: return DeclKind::BRedOr ; - case Z3_OP_BREDAND: return DeclKind::BRedAnd ; - case Z3_OP_BCOMP: return DeclKind::BComp ; - - case Z3_OP_BSHL: return DeclKind::BShl ; - case Z3_OP_BLSHR: return DeclKind::BLShr ; - case Z3_OP_BASHR: return DeclKind::BAShr ; - case Z3_OP_ROTATE_LEFT: return DeclKind::BRotateLeft ; - case Z3_OP_ROTATE_RIGHT: return DeclKind::BRotateRight ; - case Z3_OP_EXT_ROTATE_LEFT: return DeclKind::BExtRotateLeft ; - case Z3_OP_EXT_ROTATE_RIGHT: return DeclKind::BExtRotateRight ; - - case Z3_OP_INT2BV: return DeclKind::BInt2Bv ; - case Z3_OP_BV2INT: return DeclKind::BBv2Int ; - case Z3_OP_CARRY: return DeclKind::BCarry; - case Z3_OP_XOR3: return DeclKind::BXor3; - - case Z3_OP_PR_ASSERTED: return DeclKind::PrAsserted ; - case Z3_OP_PR_GOAL: return DeclKind::PrGoal ; - case Z3_OP_PR_MODUS_PONENS: return DeclKind::PrModusPonens ; - case Z3_OP_PR_REFLEXIVITY: return DeclKind::PrReflexivity ; - case Z3_OP_PR_SYMMETRY: return DeclKind::PrSymmetry ; - case Z3_OP_PR_TRANSITIVITY: return DeclKind::PrTransitivity ; - case Z3_OP_PR_TRANSITIVITY_STAR: return DeclKind::PrTransitivityStar ; - case Z3_OP_PR_MONOTONICITY: return DeclKind::PrMonotonicity ; - case Z3_OP_PR_QUANT_INTRO: return DeclKind::PrQuantIntro ; - case Z3_OP_PR_DISTRIBUTIVITY: return DeclKind::PrDistributivity ; - case Z3_OP_PR_AND_ELIM: return DeclKind::PrAndElim ; - case Z3_OP_PR_NOT_OR_ELIM: return DeclKind::PrNotOrElim ; - case Z3_OP_PR_REWRITE: return DeclKind::PrRewrite ; - case Z3_OP_PR_REWRITE_STAR: return DeclKind::PrRewriteStar ; - case Z3_OP_PR_PULL_QUANT: return DeclKind::PrPullQuant ; - case Z3_OP_PR_PULL_QUANT_STAR: return DeclKind::PrPullQuantStar ; - case Z3_OP_PR_PUSH_QUANT: return DeclKind::PrPushQuant ; - case Z3_OP_PR_ELIM_UNUSED_VARS: return DeclKind::PrElimUnusedVars ; - case Z3_OP_PR_DER: return DeclKind::PrDer ; - case Z3_OP_PR_QUANT_INST: return DeclKind::PrQuantInst ; - case Z3_OP_PR_HYPOTHESIS: return DeclKind::PrHypothesis ; - case Z3_OP_PR_LEMMA: return DeclKind::PrLemma ; - case Z3_OP_PR_UNIT_RESOLUTION: return DeclKind::PrUnitResolution ; - case Z3_OP_PR_IFF_TRUE: return DeclKind::PrIffTrue ; - case Z3_OP_PR_IFF_FALSE: return DeclKind::PrIffFalse ; - case Z3_OP_PR_COMMUTATIVITY: return DeclKind::PrCommutativity ; - case Z3_OP_PR_DEF_AXIOM: return DeclKind::PrDefAxiom ; - case Z3_OP_PR_DEF_INTRO: return DeclKind::PrDefIntro ; - case Z3_OP_PR_APPLY_DEF: return DeclKind::PrApplyDef ; - case Z3_OP_PR_IFF_OEQ: return DeclKind::PrIffOeq ; - case Z3_OP_PR_NNF_POS: return DeclKind::PrNnfPos ; - case Z3_OP_PR_NNF_NEG: return DeclKind::PrNnfNeg ; - case Z3_OP_PR_NNF_STAR: return DeclKind::PrNnfStar ; - case Z3_OP_PR_SKOLEMIZE: return DeclKind::PrSkolemize ; - case Z3_OP_PR_CNF_STAR: return DeclKind::PrCnfStar ; - case Z3_OP_PR_MODUS_PONENS_OEQ: return DeclKind::PrModusPonensOeq ; - case Z3_OP_PR_TH_LEMMA: return DeclKind::PrThLemma ; - case Z3_OP_LABEL: return DeclKind::Label; - case Z3_OP_LABEL_LIT: return DeclKind::LabelLit; - case Z3_OP_RA_STORE: return DeclKind::RaStore; - case Z3_OP_RA_EMPTY: return DeclKind::RaEmpty; - case Z3_OP_RA_IS_EMPTY: return DeclKind::RaIsEmpty; - case Z3_OP_RA_JOIN: return DeclKind::RaJoin; - case Z3_OP_RA_UNION: return DeclKind::RaUnion; - case Z3_OP_RA_WIDEN: return DeclKind::RaWiden; - case Z3_OP_RA_PROJECT: return DeclKind::RaProject; - case Z3_OP_RA_FILTER: return DeclKind::RaFilter; - case Z3_OP_RA_NEGATION_FILTER: return DeclKind::RaNegationFilter; - case Z3_OP_RA_RENAME: return DeclKind::RaRename; - case Z3_OP_RA_COMPLEMENT: return DeclKind::RaComplement; - case Z3_OP_RA_SELECT: return DeclKind::RaSelect; - case Z3_OP_RA_CLONE: return DeclKind::RaClone; - - case Z3_OP_UNINTERPRETED: return DeclKind::Uninterpreted; - default: - UNREACHABLE(); - return DeclKind::Uninterpreted; - } -} - -array^ RawContext::GetDeclParameters(FuncDeclPtr d) { - Z3_func_decl fd = get_func_decl(d); - unsigned num_params = Z3_get_decl_num_parameters(ctx(), fd); - array^ params = gcnew array(num_params); - for (unsigned i = 0; i < num_params; ++i) { - switch(Z3_get_decl_parameter_kind(ctx(), fd, i)) { - case Z3_PARAMETER_INT: - params[i] = gcnew IntParameter(Z3_get_decl_int_parameter(ctx(), fd, i)); - break; - case Z3_PARAMETER_DOUBLE: - params[i] = gcnew DoubleParameter(Z3_get_decl_double_parameter(ctx(), fd, i)); - break; - case Z3_PARAMETER_RATIONAL: { - Z3_string s = Z3_get_decl_rational_parameter(ctx(), fd, i); - params[i] = gcnew RationalParameter(gcnew String(s)); - break; - } - case Z3_PARAMETER_SYMBOL: { - Z3_symbol s = Z3_get_decl_symbol_parameter(ctx(), fd, i); - params[i] = gcnew SymbolParameter(gcnew Symbol(ctx(), s)); - break; - } - case Z3_PARAMETER_SORT: - params[i] = gcnew SortPtrParameter(SortPtr(Z3_get_decl_sort_parameter(ctx(), fd, i))); - break; - case Z3_PARAMETER_AST: - params[i] = gcnew TermPtrParameter(TermPtr(Z3_get_decl_ast_parameter(ctx(), fd, i))); - break; - case Z3_PARAMETER_FUNC_DECL: - params[i] = gcnew FuncDeclPtrParameter(FuncDeclPtr(Z3_get_decl_func_decl_parameter(ctx(), fd, i))); - break; - default: - UNREACHABLE(); - break; - } - } - return params; -} - -FuncDeclPtr RawContext::GetAppDecl(AppPtr a) { - if (GetTermKind(a) != TermKind::App) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return FuncDeclPtr(Z3_get_app_decl(ctx(), get_const_ast(a))); -} - -array^ RawContext::GetAppArgs(AppPtr a) { - if (GetTermKind(a) != TermKind::App) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - - unsigned num_args = Z3_get_app_num_args(ctx(), get_const_ast(a)); - array^ result = gcnew array(num_args); - for (unsigned i = 0; i < num_args; ++i) { - result[i] = TermPtr(Z3_get_app_arg(ctx(), get_const_ast(a), i)); - } - return result; -} - -RawQuantifier^ RawContext::GetQuantifier(TermPtr a) { - if (GetTermKind(a) != TermKind::Quantifier) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - RawQuantifier^ t = gcnew RawQuantifier(); - Z3_ast ast = get_ast(a); - t->IsForall = Z3_TRUE == Z3_is_quantifier_forall(ctx(), ast); - t->Weight = Z3_get_quantifier_weight(ctx(), ast); - t->Patterns = gcnew array(Z3_get_quantifier_num_patterns(ctx(), ast)); - t->NoPatterns = gcnew array(Z3_get_quantifier_num_no_patterns(ctx(), ast)); - t->Sorts = gcnew array(Z3_get_quantifier_num_bound(ctx(), ast)); - t->Names = gcnew array(Z3_get_quantifier_num_bound(ctx(), ast)); - t->Body = TermPtr(Z3_get_quantifier_body(ctx(), ast)); - for (int i = 0; i < t->Sorts->Length; ++i) { - t->Sorts[i] = SortPtr(Z3_get_quantifier_bound_sort(ctx(), ast, i)); - t->Names[i] = gcnew Symbol(ctx(), Z3_get_quantifier_bound_name(ctx(), ast, i)); - } - for (int i = 0; i < t->Patterns->Length; ++i) { - t->Patterns[i] = PatternPtr(Z3_get_quantifier_pattern_ast(ctx(), ast, i)); - } - for (int i = 0; i < t->NoPatterns->Length; ++i) { - t->NoPatterns[i] = TermPtr(Z3_get_quantifier_no_pattern_ast(ctx(), ast, i)); - } - return t; -}; - -array^ RawContext::GetPatternTerms(PatternPtr p) { - unsigned np = Z3_get_pattern_num_terms(ctx(), get_pattern(p)); - array^ result = gcnew array(np); - for (unsigned i = 0; i < np; ++i) { - result[i] = TermPtr(Z3_get_pattern(ctx(), get_pattern(p), i)); - } - return result; -} - -Symbol^ RawContext::GetDeclName(FuncDeclPtr d) { - return gcnew Symbol(ctx(), Z3_get_decl_name(ctx(), get_func_decl(d))); -} - -Symbol^ RawContext::GetSortName(SortPtr ty) { - return gcnew Symbol(ctx(), Z3_get_sort_name(ctx(), get_sort(ty))); -} - -SortPtr RawContext::GetSort(TermPtr a) { - return SortPtr(Z3_get_sort(ctx(), get_ast(a))); -} - -array^ RawContext::GetDomain(FuncDeclPtr d) { - unsigned num_args = Z3_get_domain_size(ctx(), get_func_decl(d)); - array^ result = gcnew array(num_args); - for (unsigned i = 0; i < num_args; ++i) { - result[i] = TermPtr(Z3_get_domain(ctx(), get_func_decl(d), i)); - } - return result; -} - - -SortPtr RawContext::GetRange(FuncDeclPtr d) { - return SortPtr(Z3_get_range(ctx(), get_func_decl(d))); -} - -SortKind RawContext::GetSortKind(SortPtr t) { - switch(Z3_get_sort_kind(ctx(), get_sort(t))) { - case Z3_UNINTERPRETED_SORT: return SortKind::Uninterpreted; - case Z3_BOOL_SORT: return SortKind::Bool; - case Z3_INT_SORT: return SortKind::Int; - case Z3_REAL_SORT: return SortKind::Real; - case Z3_BV_SORT: return SortKind::BitVector; - case Z3_ARRAY_SORT: return SortKind::Array; - case Z3_DATATYPE_SORT: return SortKind::Datatype; - case Z3_UNKNOWN_SORT: return SortKind::Unknown; - default: UNREACHABLE(); return SortKind::Unknown; - } -} - -SearchFailureExplanation RawContext::GetSearchFailureExplanation() { - return ConvertExplanation(Z3_get_search_failure(ctx())); -} - -unsigned RawContext::GetBvSortSize(SortPtr t) { - return Z3_get_bv_sort_size(ctx(), get_sort(t)); -} - -SortPtr RawContext::GetArraySortDomain(SortPtr t) { - return SortPtr(Z3_get_array_sort_domain(ctx(), get_sort(t))); -} - -SortPtr RawContext::GetArraySortRange(SortPtr t) { - return SortPtr(Z3_get_array_sort_range(ctx(), get_sort(t))); -} - -FuncDeclPtr RawContext::GetTupleConstructor(SortPtr t) { - return FuncDeclPtr(Z3_get_tuple_sort_mk_decl(ctx(), get_sort(t))); -} - -array^ RawContext::GetTupleFields(SortPtr t) { - unsigned num_args = Z3_get_tuple_sort_num_fields(ctx(), get_sort(t)); - array^ result = gcnew array(num_args); - for (unsigned i = 0; i < num_args; ++i) { - result[i] = FuncDeclPtr(Z3_get_tuple_sort_field_decl(ctx(), get_sort(t), i)); - } - return result; -} - -void RawContext::Push() { - Z3_push(ctx()); -} - -void RawContext::Pop(unsigned num_scopes) { - Z3_pop(ctx(), num_scopes); -} - -unsigned RawContext::GetNumScopes() { - return Z3_get_num_scopes(ctx()); -} - -void RawContext::PersistTerm(TermPtr t, unsigned num_scopes) { - Z3_persist_ast(ctx(), get_ast(t), num_scopes); -} - -void RawContext::IncRef(IntPtr ast) { - Z3_inc_ref(ctx(), get_ast(ast)); - // decrement reference counts of whatever is gc'ed. - if (s_nonempty) { - System::Threading::Monitor::Enter(s_monitor); - for (int i = 0; i < s_todec->Count; ++i) { - AstPtr a = s_todec[i].Key; - RawContext^ c = s_todec[i].Value; - SASSERT(c->ref_context().is_ref_counted()); - Z3_dec_ref(c->ctx(), get_ast(a)); - c->ref_context().dec_ref(); - } - s_todec->Clear(); - s_nonempty = false; - System::Threading::Monitor::Exit(s_monitor); - } -} - -void RawContext::EnqueueDecRef(IntPtr ast) { - System::Threading::Monitor::Enter(s_monitor); - s_todec->Add(KeyValuePair(ast, this)); - s_nonempty = true; - System::Threading::Monitor::Exit(s_monitor); -} - -void RawContext::AssertCnstr(TermPtr a) { - Z3_assert_cnstr(ctx(), get_ast(a)); -} - -LBool RawContext::CheckAndGetModel(RawModel^% m) { - m = nullptr; - Z3_model model = 0; - Z3_lbool lb = Z3_check_and_get_model(ctx(), & model); - - if (model) { - m = gcnew RawModel(*m_context, model); - } - else { - m = nullptr; - } - return ToLBool(lb); -} - -LBool RawContext::Check() { - Z3_lbool lb = Z3_check(ctx()); - return ToLBool(lb); -} - -LBool RawContext::CheckAssumptions(RawModel^% m, array^ assumptions, TermPtr% proof, array^% core) { - scoped_Z3_ast_array _assumptions(assumptions); - scoped_Z3_ast_array _core(assumptions); - unsigned core_size = 0; - Z3_ast _proof = 0; - Z3_model model = 0; - Z3_lbool lb = Z3_check_assumptions( - ctx(), - _assumptions.size(), - _assumptions.c_ptr(), - &model, - &_proof, - &core_size, - _core.c_ptr()); - - core = gcnew array(core_size); - for (unsigned i = 0; i < core_size; ++i) { - core[i] = TermPtr(_core[i]); - } - if(_proof) { - proof = TermPtr(_proof); - } - if (model) { - m = gcnew RawModel(*m_context, model); - } - return ToLBool(lb); -} - -void RawContext::SoftCheckCancel() { - Z3_soft_check_cancel(ctx()); -} - -LBool RawContext::GetImpliedEqualities( - [In] array^ terms, - [Out] array^% class_ids) { - scoped_Z3_ast_array _terms(terms); - scoped_array _class_ids(_terms.size()); - Z3_lbool lb = Z3_get_implied_equalities(ctx(), _terms.size(), _terms.c_ptr(), _class_ids.c_ptr()); - class_ids = gcnew array(_terms.size()); - for (unsigned i = 0; i < _terms.size(); ++i) { - class_ids[i] = _class_ids[i]; - } - return ToLBool(lb); -} - -LabeledLiterals^ RawContext::GetRelevantLabels() { - Z3_literals lbls = Z3_get_relevant_labels(ctx()); - return gcnew LabeledLiterals(*m_context, lbls); -} - -LabeledLiterals^ RawContext::GetRelevantLiterals() { - Z3_literals lbls = Z3_get_relevant_literals(ctx()); - return gcnew LabeledLiterals(*m_context, lbls); -} - -LabeledLiterals^ RawContext::GetGuessedLiterals() { - Z3_literals lbls = Z3_get_guessed_literals(ctx()); - return gcnew LabeledLiterals(*m_context, lbls); -} - -void RawContext::BlockLiterals(LabeledLiterals^ lbls) { - Z3_block_literals(ctx(), lbls->Get()); -} - -TermPtr RawContext::Simplify(TermPtr a) { - return TermPtr(Z3_simplify(ctx(), get_ast(a))); -} - - -String^ RawContext::ToString() { - return gcnew String(Z3_context_to_string(ctx())); -} - -void RawContext::SetPrintMode(PrintMode mode) { - Z3_ast_print_mode m = Z3_PRINT_SMTLIB_FULL; - switch(mode) { - case PrintMode::SmtlibFull: - m = Z3_PRINT_SMTLIB_FULL; - break; - case PrintMode::LowLevel: - m = Z3_PRINT_LOW_LEVEL; - break; - case PrintMode::Smtlib2Compliant: - m = Z3_PRINT_SMTLIB2_COMPLIANT; - break; - case PrintMode::SmtlibCompliant: - m = Z3_PRINT_SMTLIB_COMPLIANT; - break; - default: - UNREACHABLE(); - break; - } - Z3_set_ast_print_mode(ctx(), m); -} - -void RawContext::Display(System::IO::TextWriter^ w) { - w->Write(ToString()); -} - -String^ RawContext::BenchmarkToSmtlib( - String^ name, - String^ logic, - String^ status, - String^ attributes, - array^ assumptions, - TermPtr formula) { - scoped_Z3_ast_array _assumptions(assumptions); - return gcnew String(Z3_benchmark_to_smtlib_string( - ctx(), - (name )?CreateString(name).c_str():0, - (logic )?CreateString(logic).c_str():0, - (status )?CreateString(status).c_str():0, - (attributes )?CreateString(attributes).c_str():0, - _assumptions.size(), - _assumptions.c_ptr(), - get_ast(formula))); -} - - -void RawContext::ParseSmtlibString( - String^ string, - [In] array^ sorts, - [In] array^ old_decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ) -{ - scoped_Z3_ast_array _types(sorts); - scoped_Z3_ast_array _decls(old_decls); - scoped_Z3_symbol_array _sort_names(_types.size()); - scoped_Z3_symbol_array _decl_names(_decls.size()); - for (unsigned i = 0; i < _sort_names.size(); ++i) { - _sort_names[i] = Z3_get_sort_name(ctx(), _types[i]); - } - for (unsigned i = 0; i < _decl_names.size(); ++i) { - _decl_names[i] = Z3_get_decl_name(ctx(), _decls[i]); - } - - try { - Z3_parse_smtlib_string( - ctx(), - CreateString(string).c_str(), - _types.size(), - _sort_names.c_ptr(), - _types.c_ptr(), - _decls.size(), - _decl_names.c_ptr(), - _decls.c_ptr() - ); - } - catch(...) { - parser_out = gcnew String(Z3_get_smtlib_error(ctx())); - throw; - } - parser_out = gcnew String(Z3_get_smtlib_error(ctx())); - - unsigned count = Z3_get_smtlib_num_formulas(ctx()); - formulas = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - formulas[i] = TermPtr(Z3_get_smtlib_formula(ctx(), i)); - } - - count = Z3_get_smtlib_num_assumptions(ctx()); - assumptions = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - assumptions[i] = TermPtr(Z3_get_smtlib_assumption(ctx(), i)); - } - - count = Z3_get_smtlib_num_decls(ctx()); - new_decls = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - new_decls[i] = FuncDeclPtr(Z3_get_smtlib_decl(ctx(), i)); - } - count = Z3_get_smtlib_num_sorts(ctx()); - new_sorts = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - new_sorts[i] = SortPtr(Z3_get_smtlib_sort(ctx(), i)); - } -} - -void RawContext::ParseSmtlibFile( - String^ file, - [In] array^ sorts, - [In] array^ old_decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ) -{ - scoped_Z3_ast_array _sorts(sorts); - scoped_Z3_ast_array _decls(old_decls); - scoped_Z3_symbol_array _sort_names(_sorts.size()); - scoped_Z3_symbol_array _decl_names(_decls.size()); - for (unsigned i = 0; i < _sort_names.size(); ++i) { - _sort_names[i] = Z3_get_sort_name(ctx(), _sorts[i]); - } - for (unsigned i = 0; i < _decl_names.size(); ++i) { - _decl_names[i] = Z3_get_decl_name(ctx(), _decls[i]); - } - - try { - Z3_parse_smtlib_file( - ctx(), - CreateString(file).c_str(), - _sorts.size(), - _sort_names.c_ptr(), - _sorts.c_ptr(), - _decls.size(), - _decl_names.c_ptr(), - _decls.c_ptr() - ); - } - catch(...) { - parser_out = gcnew String(Z3_get_smtlib_error(ctx())); - throw; - } - parser_out = gcnew String(Z3_get_smtlib_error(ctx())); - - unsigned count = Z3_get_smtlib_num_formulas(ctx()); - formulas = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - formulas[i] = TermPtr(Z3_get_smtlib_formula(ctx(), i)); - } - - count = Z3_get_smtlib_num_assumptions(ctx()); - assumptions = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - assumptions[i] = TermPtr(Z3_get_smtlib_assumption(ctx(), i)); - } - - count = Z3_get_smtlib_num_decls(ctx()); - new_decls = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - new_decls[i] = FuncDeclPtr(Z3_get_smtlib_decl(ctx(), i)); - } - count = Z3_get_smtlib_num_sorts(ctx()); - new_sorts = gcnew array(count); - for (unsigned i = 0; i < count; ++i) { - new_sorts[i] = SortPtr(Z3_get_smtlib_sort(ctx(), i)); - } -} - - - - - -TermPtr RawContext::ParseZ3String(String^ s) { - return TermPtr(Z3_parse_z3_string(ctx(), CreateString(s).c_str())); -} - -TermPtr RawContext::ParseZ3File(String^ file) { - return TermPtr(Z3_parse_z3_file(ctx(), CreateString(file).c_str())); -} - - -#define PROCESS_SMTLIB2(_fn) \ - scoped_Z3_ast_array _sorts(sorts); \ - scoped_Z3_ast_array _decls(decls); \ - scoped_Z3_symbol_array _sort_names(_sorts.size()); \ - scoped_Z3_symbol_array _decl_names(_decls.size()); \ - for (unsigned i = 0; i < _sort_names.size(); ++i) { \ - _sort_names[i] = Z3_get_sort_name(ctx(), _sorts[i]); \ - std::cout << Z3_get_symbol_string(ctx(), _sort_names[i]) << "\n"; \ - } \ - for (unsigned i = 0; i < _decl_names.size(); ++i) { \ - _decl_names[i] = Z3_get_decl_name(ctx(), _decls[i]); \ - std::cout << Z3_get_symbol_string(ctx(), _decl_names[i]) << "\n"; \ - } \ - return TermPtr(_fn(ctx(), CreateString(s).c_str(), \ - _sorts.size(), _sort_names.c_ptr(), _sorts.c_ptr(), \ - _decls.size(), _decl_names.c_ptr(), _decls.c_ptr())); \ - - -TermPtr RawContext::ParseSmtlib2String(String^ s, array^ sorts, array^ decls) { - PROCESS_SMTLIB2(Z3_parse_smtlib2_string); -} - -TermPtr RawContext::ParseSmtlib2File(String^ s, array^ sorts, array^ decls) { - PROCESS_SMTLIB2(Z3_parse_smtlib2_file); -} - -TermPtr RawContext::ExecSmtlib2String(String^ s, array^ sorts, array^ decls) { - PROCESS_SMTLIB2(Z3_exec_smtlib2_string); -} - -TermPtr RawContext::ExecSmtlib2File(String^ s, array^ sorts, array^ decls) { - PROCESS_SMTLIB2(Z3_exec_smtlib2_file); -} - -void RawContext::SetErrorHandler(IErrorHandler^ h) { - m_error_handler = h; -} - - -String^ RawContext::GetErrorMessage(ErrorCode h) { - Z3_error_code code; - switch(h) { - case ErrorCode::Ok: code = Z3_OK; break; - case ErrorCode::TypeError: code = Z3_SORT_ERROR; break; - case ErrorCode::IndexOutOfBounds: code = Z3_IOB; break; - case ErrorCode::InvalidArgument: code = Z3_INVALID_ARG; break; - case ErrorCode::ParserError: code = Z3_PARSER_ERROR; break; - case ErrorCode::NoParser: code = Z3_NO_PARSER; break; - case ErrorCode::InvalidUsage: code = Z3_INVALID_USAGE; break; - case ErrorCode::InternalFatal: - case ErrorCode::FileAccessError: - code = Z3_INVALID_ARG; - break; - default: - UNREACHABLE(); - code = Z3_INVALID_ARG; - } - return gcnew String(Z3_get_error_msg(code)); -} - -void RawContext::ResetMemory() { - Z3_reset_memory(); -} - -String^ RawContext::ToString(AstPtr a) { - return gcnew String(Z3_ast_to_string(ctx(), get_ast(a))); -} - -void RawContext::Display(System::IO::TextWriter^ w, AstPtr a) { - w->Write(ToString(a)); -} - - -void RawContext::GetVersion(unsigned% major, unsigned% minor, unsigned% build_number, unsigned% version_number) { - unsigned ma, mi, bn, vn; - Z3_get_version(&ma,&mi,&bn,&vn); - major = ma; - minor = mi; - build_number = bn; - version_number = vn; -} - -// ----------------------------- -// Ast - -Ast::Ast(RawContext^ c, AstPtr a) : m_ast(a), m_ctx(c) { - SASSERT(m_ast != IntPtr(0)); - if (c->ref_context().is_ref_counted()) { - c->IncRef(a); - c->ref_context().inc_ref(); - } -} - -Ast::!Ast() { - if (m_ctx->ref_context().is_ref_counted()) { - m_ctx->EnqueueDecRef(m_ast); - } -} - -Ast::~Ast() {} - -bool Ast::Equals(Object^ obj) { - if (!obj) { - return false; - } - Ast^ a = dynamic_cast(obj); - if (!a) { - return false; - } - return a->GetPtr() == GetPtr(); -} - -int Ast::GetHashCode() { - return GetId(); -} - -String^ Ast::ToString() { - return m_ctx->ToString(m_ast); -} - -int Ast::CompareTo(Object^ other) { - Ast^ a = dynamic_cast(other); - if (!a) { - return -1; - } - return GetId() - a->GetId(); -} - -#if 0 -bool Ast::operator==(Object^ other) { - return this->Equals(other); -} - -bool Ast::operator!=(Object^ other) { - return !this->Equals(other); -} -#endif - -String^ Sort::GetName() { - return m_ctx->GetSymbolString(m_ctx->GetSortName(m_ast)); -} - -String^ FuncDecl::GetDeclName() { - return m_ctx->GetSymbolString(m_ctx->GetDeclName(m_ast)); -} - -DeclKind FuncDecl::GetKind() { - return m_ctx->GetDeclKind(m_ast); -} - -// ---------------------------- -// Term -// Assumption: contexts are equal -// Note: overloading && and || is possible, -// but C# does not seem to perform the -// correct type inference when they are used. - -Term^ Term::operator!(Term^ t) { - return gcnew Term(t->m_ctx, t->m_ctx->MkNot(t())); -} - -Term^ Term::operator+(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkAdd(t1(), t2())); -} - -Term^ Term::operator^(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkXor(t1(), t2())); -} - -Term^ Term::operator&(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkAnd(t1(), t2())); -} - -Term^ Term::operator|(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkOr(t1(), t2())); -} -Term^ Term::operator*(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkMul(t1(), t2())); -} - -Term^ Term::operator-(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkSub(t1(), t2())); -} - -Term^ Term::operator/(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkDiv(t1(), t2())); -} - -Term^ Term::operator<(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkLt(t1(), t2())); -} - -Term^ Term::operator<=(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkLe(t1(), t2())); -} - -Term^ Term::operator>(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkGt(t1(), t2())); -} - -Term^ Term::operator>=(Term^ t1, Term^ t2) { - return gcnew Term(t1->m_ctx, t1->m_ctx->MkGe(t1(), t2())); -} - -Term^ Term::operator[](Term^ index) { - return gcnew Term(m_ctx, m_ctx->MkArraySelect(m_ast, index())); -} - -TermKind Term::GetKind() { - return m_ctx->GetTermKind(m_ast); -} - -FuncDecl^ Term::GetAppDecl() { - return gcnew FuncDecl(m_ctx, m_ctx->GetAppDecl(m_ast)); -} - -array^ Term::GetAppArgs() { - return Context::CopyTermArray(m_ctx, m_ctx->GetAppArgs(m_ast)); -} - -Sort^ Term::GetSort() { - return gcnew Sort(m_ctx, m_ctx->GetSort(m_ast)); -} - -String^ Term::GetNumeralString() { - return m_ctx->GetNumeralString(m_ast); -} - -unsigned Term::GetVarIndex() { - return m_ctx->GetVarIndex(m_ast); -} - -Quantifier^ Term::GetQuantifier() { - return Context::GetQuantifier(m_ctx, this); -} -// ----------------------------- -// Context - - -LBool Context::CheckAndGetModel(Model^% m) { - RawModel^ md = nullptr; - LBool is_sat = m_ctx->CheckAndGetModel(md); - if (md ) { - m = gcnew Model(md, this); - } - else { - md = nullptr; - } - return is_sat; -} - -LBool Context::CheckAssumptions( - Model^% m, array^ assumptions, Term^% proof, array^% core) { - RawModel^ md = nullptr; - array^ _core = nullptr; - TermPtr _proof; - LBool is_sat = m_ctx->CheckAssumptions(md, CopyArray(assumptions), _proof, _core); - core = nullptr; - proof = nullptr; - m = nullptr; - if (md ) { - m = gcnew Model(md, this); - } - if (_proof != TermPtr()) { - proof = gcnew Term(m_ctx, _proof); - } - if (_core ) { - core = CopyTermArray(_core); - } - return is_sat; -} - -void Context::SoftCheckCancel() { - m_ctx->SoftCheckCancel(); -} - - -LBool Context::GetImpliedEqualities( - [In] array^ terms, - [Out] array^% class_ids) { - return m_ctx->GetImpliedEqualities(CopyArray(terms), class_ids); -} - - - -Quantifier^ Context::GetQuantifier(RawContext^ ctx, Term^ t) { - RawQuantifier^ q0 = ctx->GetQuantifier(t()); - Quantifier^ q = gcnew Quantifier(); - q->IsForall = q0->IsForall; - q->Weight = q0->Weight; - q->Patterns = gcnew array(q0->Patterns->Length); - for (int i = 0; i < q0->Patterns->Length; ++i) { - q->Patterns[i] = gcnew Pattern(ctx, q0->Patterns[i]); - } - q->NoPatterns = gcnew array(q0->NoPatterns->Length); - for (int i = 0; i < q0->NoPatterns->Length; ++i) { - q->NoPatterns[i] = gcnew Term(ctx, q0->Patterns[i]); - } - q->Names = q0->Names; - q->Body = gcnew Term(ctx, q0->Body); - q->Sorts = CopySortArray(ctx, q0->Sorts); - return q; -} - - -Sort^ Context::MkTupleSort( - Symbol^ mk_tuple_name, - array^ field_names, - array^ field_types, - FuncDecl^% mk_tuple_decl, - array^ proj_decl - ) { - array^ ftypes = gcnew array(field_types->Length); - for (int i = 0; i < field_types->Length; ++i) { - ftypes[i] = field_types[i](); - } - array^ pdecls = gcnew array(proj_decl->Length); - FuncDeclPtr mk_tupled; - SortPtr res = m_ctx->MkTupleSort(mk_tuple_name, field_names, ftypes, mk_tupled, pdecls); - for (int i = 0; i < pdecls->Length; ++i) { - proj_decl[i] = gcnew FuncDecl(m_ctx,pdecls[i]); - } - mk_tuple_decl = gcnew FuncDecl(m_ctx,mk_tupled); - return gcnew Sort(m_ctx,res); -} - -Sort^ Context::MkTupleSort( - String^ mk_tuple_name, - array^ field_names, - array^ field_types, - FuncDecl^% mk_tuple_decl, - array^ proj_decl - ) { - array^ ftypes = gcnew array(field_types->Length); - for (int i = 0; i < field_types->Length; ++i) { - ftypes[i] = field_types[i](); - } - array^ pdecls = gcnew array(proj_decl->Length); - FuncDeclPtr mk_tupled; - SortPtr res = m_ctx->MkTupleSort(mk_tuple_name, field_names, ftypes, mk_tupled, pdecls); - for (int i = 0; i < pdecls->Length; ++i) { - proj_decl[i] = gcnew FuncDecl(m_ctx,pdecls[i]); - } - mk_tuple_decl = gcnew FuncDecl(m_ctx,mk_tupled); - return gcnew Sort(m_ctx,res); -} - -Sort^ Context::MkEnumerationSort( - String^ name, - array^ enum_names, - array^ enum_consts, - array^ enum_testers) { - - array^ _enum_consts = CopyArray(enum_consts); - array^ _enum_testers = CopyArray(enum_testers); - - SortPtr s = m_ctx->MkEnumerationSort(name, enum_names, _enum_consts, _enum_testers); - - for (int i = 0; i < enum_consts->Length; ++i) { - enum_consts[i] = gcnew FuncDecl(m_ctx, _enum_consts[i]); - enum_testers[i] = gcnew FuncDecl(m_ctx, _enum_testers[i]); - } - return gcnew Sort(m_ctx, s); -} - -Sort^ Context::MkListSort( - String^ name, - Sort^ elem_sort, - FuncDecl^% nil_decl, - FuncDecl^% is_nil_decl, - FuncDecl^% cons_decl, - FuncDecl^% is_cons_decl, - FuncDecl^% head_decl, - FuncDecl^% tail_decl - ) { - FuncDeclPtr a, b, c, d, e, f; - SortPtr s = m_ctx->MkListSort(name, elem_sort(), a, b, c, d, e, f); - nil_decl = gcnew FuncDecl(m_ctx, a); - is_nil_decl = gcnew FuncDecl(m_ctx, b); - cons_decl = gcnew FuncDecl(m_ctx, c); - is_cons_decl = gcnew FuncDecl(m_ctx, d); - head_decl = gcnew FuncDecl(m_ctx, e); - tail_decl = gcnew FuncDecl(m_ctx, f); - return gcnew Sort(m_ctx, s); -} - -Constructor^ Context::MkConstructor( - String^ name, - String^ tester, - array^ field_names, - array^ field_sorts, - array^ field_refs - ) { - return m_ctx->MkConstructor(name, tester, field_names, CopyArray(field_sorts), field_refs); -} - - -FuncDecl^ Context::GetConstructor(Constructor^ c) { - return gcnew FuncDecl(m_ctx, m_ctx->GetConstructor(c)); -} - -FuncDecl^ Context::GetTester(Constructor^ c) { - return gcnew FuncDecl(m_ctx, m_ctx->GetTester(c)); -} - -array^ Context::GetAccessors(Constructor^ c) { - array^ result = m_ctx->GetAccessors(c); - return CopyAstArray(result); -} - - -bool Model::TryGetArrayValue(Term^ v, ArrayValue^% av) { - RawArrayValue^ _av = nullptr; - if (m_model->TryGetArrayValue(v(), _av)) { - av = gcnew ArrayValue(); - av->ElseCase = gcnew Term(m_ctx->GetContext, _av->ElseCase); - av->Domain = m_ctx->CopyAstArray(_av->Domain); - av->Range = m_ctx->CopyAstArray(_av->Range); - return true; - } - else { - return false; - } -} - -array^ Context::GetDeclParameters(FuncDecl^ d) { - Z3_context ctx = m_ctx->ctx(); - Z3_func_decl fd = get_func_decl(d()); - unsigned num_params = Z3_get_decl_num_parameters(ctx, fd); - array^ params = gcnew array(num_params); - for (unsigned i = 0; i < num_params; ++i) { - switch(Z3_get_decl_parameter_kind(ctx, fd, i)) { - case Z3_PARAMETER_INT: - params[i] = gcnew IntParameter(Z3_get_decl_int_parameter(ctx, fd, i)); - break; - case Z3_PARAMETER_DOUBLE: - params[i] = gcnew DoubleParameter(Z3_get_decl_double_parameter(ctx, fd, i)); - break; - case Z3_PARAMETER_RATIONAL: { - Z3_string s = Z3_get_decl_rational_parameter(ctx, fd, i); - params[i] = gcnew RationalParameter(gcnew String(s)); - break; - } - case Z3_PARAMETER_SYMBOL: { - Z3_symbol s = Z3_get_decl_symbol_parameter(ctx, fd, i); - params[i] = gcnew SymbolParameter(gcnew Symbol(ctx, s)); - break; - } - case Z3_PARAMETER_SORT: - params[i] = gcnew SortParameter(gcnew Sort(m_ctx,SortPtr(Z3_get_decl_sort_parameter(ctx, fd, i)))); - break; - case Z3_PARAMETER_AST: - params[i] = gcnew TermParameter(gcnew Term(m_ctx,TermPtr(Z3_get_decl_ast_parameter(ctx, fd, i)))); - break; - case Z3_PARAMETER_FUNC_DECL: - params[i] = gcnew FuncDeclParameter(gcnew FuncDecl(m_ctx, FuncDeclPtr(Z3_get_decl_func_decl_parameter(ctx, fd, i)))); - break; - default: - UNREACHABLE(); - break; - } - } - return params; -} - -String^ Context::BenchmarkToSmtlib( - String^ name, - String^ logic, - String^ status, - String^ attributes, - array^ assumptions, - Term^ formula) { - return m_ctx->BenchmarkToSmtlib(name, logic, status, attributes, CopyArray(assumptions), formula()); - } - -void Context::ParseSmtlibString( - String^ string, - [In] array^ types, - [In] array^ old_decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ) { - array^ _assumptions = nullptr; - array^ _formulas = nullptr; - array^ _new_decls = nullptr; - array^ _new_sorts = nullptr; - m_ctx->ParseSmtlibString(string, CopyArray(types), CopyArray(old_decls), - _assumptions, _formulas, _new_decls, _new_sorts, parser_out); - assumptions = CopyTermArray(_assumptions); - formulas = CopyTermArray(_formulas); - new_decls = CopyAstArray(_new_decls); - new_sorts = CopyAstArray(_new_sorts); -} - - -void Context::ParseSmtlibFile( - String^ file, - [In] array^ types, - [In] array^ old_decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ) { - array^ _assumptions = nullptr; - array^ _formulas = nullptr; - array^ _new_decls = nullptr; - array^ _new_sorts = nullptr; - m_ctx->ParseSmtlibFile(file, CopyArray(types), CopyArray(old_decls), - _assumptions, _formulas, _new_decls, _new_sorts, parser_out); - assumptions = CopyAstArray(_assumptions); - formulas = CopyAstArray(_formulas); - new_decls = CopyAstArray(_new_decls); - new_sorts = CopyAstArray(_new_sorts); -} - -// ----------------------------- -// Model - -ArrayValue^ Model::Mk(RawArrayValue^ av) { - ArrayValue^ res = gcnew ArrayValue(); - res->Domain = m_ctx->CopyTermArray(av->Domain); - res->Range = m_ctx->CopyTermArray(av->Range); - res->ElseCase = gcnew Term(m_ctx->GetContext, av->ElseCase); - return res; -} - -FunctionEntry^ Model::Mk(RawFunctionEntry^ fe) { - FunctionEntry^ res = gcnew FunctionEntry(); - res->Arguments = m_ctx->CopyTermArray(fe->Arguments); - res->Result = gcnew Term(m_ctx->GetContext, fe->Result); - return res; -} - -FunctionGraph^ Model::Mk(RawFunctionGraph^ fg) { - FunctionGraph^ res = gcnew FunctionGraph(); - res->Declaration = gcnew FuncDecl(m_ctx->GetContext, fg->Declaration); - res->Entries = gcnew array(fg->Entries->Length); - for (int i = 0; i < fg->Entries->Length; ++i) { - res->Entries[i] = Mk(fg->Entries[i]); - } - res->Else = gcnew Term(m_ctx->GetContext, fg->Else); - return res; -} - -Dictionary^ Model::Mk(Dictionary^ fgs) { - Dictionary^ res = - gcnew Dictionary(); - - Dictionary::Enumerator e = fgs->GetEnumerator(); - while(e.MoveNext()) { - KeyValuePair^ kv = e.Current; - res->Add(gcnew FuncDecl(m_ctx->GetContext, kv->Key), Mk(kv->Value)); - } - return res; -} - -Theory^ Context::MkTheory(String^ name) { - return gcnew Theory(this, name); -} diff --git a/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.h b/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.h deleted file mode 100644 index d457a63f2..000000000 --- a/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.h +++ /dev/null @@ -1,4775 +0,0 @@ -/*++ -Copyright (c) 2007 Microsoft Corporation - -Module Name: - - Microsoft.Z3V3.h - -Abstract: - - Z3 Managed API. - -Author: - - Nikolaj Bjorner (nbjorner) - Leonardo de Moura (leonardo) 2007-06-8 - -Notes: - - This API is deprecated and support for this is discontinued. - It is superseeded by the new Microsoft.Z3 API. - ---*/ - -#ifndef _MICROSOFT_Z3V3_H__ -#define _MICROSOFT_Z3V3_H__ - -struct _Z3_model {}; -struct _Z3_config {}; -struct _Z3_context {}; -struct _Z3_func_decl {}; -struct _Z3_app {}; -struct _Z3_sort {}; -struct _Z3_symbol {}; -struct _Z3_ast {}; -struct _Z3_literals {}; -struct _Z3_pattern {}; -struct _Z3_constructor {}; -struct _Z3_constructor_list {}; -typedef _Z3_literals *Z3_literals; -struct _Z3_theory {}; -struct _Z3_ast_vector {}; -struct _Z3_fixedpoint {}; - -using namespace System; -using namespace System::Collections::Generic; -using namespace System::Runtime::InteropServices; -using namespace System::Numerics; - - -#include "..\lib\z3.h" - -namespace Microsoft { -namespace Z3V3 { - - class ref_context { - unsigned m_count; - bool m_owned; - bool m_scoped; - Z3_context m_ctx; - Z3_fixedpoint m_dl; - ref_context(Z3_context ctx, bool owned, bool scoped): m_count(1), m_owned(owned), m_scoped(scoped), m_ctx(ctx), m_dl(0) {} - public: - static ref_context* mk(Z3_context ctx, bool owned, bool scoped); - void dec_ref(); - void inc_ref(); - Z3_context operator()() { return m_ctx; } - ~ref_context() {} - bool is_ref_counted() const { return !is_scoped(); } - bool is_scoped() const { return m_scoped; } - Z3_fixedpoint dl(); - }; - -/** - \defgroup mapi Managed (.NET) API -*/ -/*@{*/ - - public ref class Z3Log { - static bool m_open = false; - public: - /** - \brief Log assertions to a file. - - \sa Close - - Returns \c true if the open succeeds, otherwise \c false. - */ - static bool Open(String^ filename); - - /** - \brief Return true if the log is open. - */ - static bool IsOpen() { return m_open; } - - /** - \brief Append user comment to log. - - \sa Open - */ - static void Append(String^ string); - - /** - \brief Close file with logged API calls. - - \sa Open - */ - static void Close(); - }; - - /** - \brief Symbol. - - Wrapper class for string or integer symbols. - This class remains unsafe. You cannot access the ToString() - method after the owning context has been deleted. - We don't use dispose pattern here. I believe it would be too - awkward to manage. - */ - public ref class Symbol { - Z3_context m_ctx; - Z3_symbol m_symbol; - internal: - Symbol(Z3_context c, Z3_symbol s) : m_ctx(c), m_symbol(s) { } - Z3_symbol get() { return m_symbol; } - public: - virtual String^ ToString() override; - }; - - /** - \brief Lifted Booleans. - - The result of m_context->Check() is a lifted Boolean. When Z3 is unable to - decide whether the result is satisfiable or unsatisfiable it returns - Undef. - */ - - public enum class LBool - { - True, - False, - Undef - }; - - /** - \brief Z3 error codes. - - - Ok, - - TypeError: User tried to build an invalid (type incorrect) AST. - - IndexOutOfBounds: Index out of bounds - - InvalidArgument:: Invalid argument was provided - - ParserError: An error occurred when parsing a string or file. - - NoParser: Parser output is not available, that is, user didn't invoke ParseSmtlibString or ParseSmtlibFile. - - InvalidPattern: An invalid pattern was used to build a quantifier. - - InternalFatal: An internal fatal error was encountered. - - InvalidUsage: The API was used in an invalid context. - - FileAccessError: File access failed for an inaccessible file. - - NonDisposedConfig A configuration was not disposed explictly. - - NonDisposedContext: A context was not disposed explictly. - - NonDisposedLiterals: A conflict literal set was not disposed explicitly. - - NonDisposedModel: A model was not disposed of explicitly. - - There is no error code for out of memory errors. - Z3 will throw the library exception OutOfMemoryException - if memory allocation fails. Users should call ResetMemory() - to reclaim all allocated resources. - - */ - - public enum class ErrorCode - { - Ok, - TypeError, - IndexOutOfBounds, - InvalidArgument, - ParserError, - NoParser, - InvalidPattern, - InternalFatal, - InvalidUsage, - FileAccessError, - NonDisposedConfig, - NonDisposedContext, - NonDisposedLiterals, - NonDisposedModel - }; - - /** - \brief Z3 pretty printing modes used when pretty printing terms. - - - SmtlibFull: Print AST nodes in SMTLIB verbose format. - - LowLevel: Print AST nodes using a low-level format. - - SmtlibCompliant Print AST in SMTLIB 1.x compliant format. - - Smtlib2Compliant Print AST in SMTLIB 1.x compliant format. - */ - public enum class PrintMode - { - SmtlibFull, - LowLevel, - SmtlibCompliant, - Smtlib2Compliant - }; - - /** - \brief Z3 error exceptions contain an \c ErrorCode. - - A \c Z3Error exception gets raised on errors caused by - malformed calls into the #Context. - */ - public ref class Z3Error : Exception { - public: - Z3Error(ErrorCode c) { Code = c; InternalCode = 0; } - Z3Error(int i) { Code = ErrorCode::Ok; InternalCode = i; } - ErrorCode Code; - int InternalCode; - }; - - - /// @cond 0 - typedef IntPtr AstPtr; - typedef IntPtr SortPtr; - typedef IntPtr FuncDeclPtr; - typedef IntPtr TermPtr; - typedef IntPtr PatternPtr; - typedef IntPtr AppPtr; - - - Z3_func_decl get_func_decl(FuncDeclPtr t) { - if (t == IntPtr::Zero) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return static_cast(t.ToPointer()); - } - Z3_ast get_ast(TermPtr t) { - if (t == IntPtr::Zero) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return static_cast(t.ToPointer()); - } - Z3_sort get_sort(SortPtr t) { - if (t == IntPtr::Zero) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return static_cast(t.ToPointer()); - } - Z3_app get_const_ast(AppPtr c) { - if (c == IntPtr::Zero) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return static_cast(c.ToPointer()); - } - Z3_pattern get_pattern(PatternPtr p) { - if (p == IntPtr::Zero) { - throw gcnew Z3Error(ErrorCode::InvalidArgument); - } - return static_cast(p.ToPointer()); - } - - /// @endcond - - - - /** - \brief In Z3, a symbol can be represented using integers and strings (See #GetSymbolKind). - - \sa MkIntSymbol - \sa MkStringSymbol - */ - public enum class SymbolKind - { - Int, - String - }; - - /** - \brief The different kinds of Z3 sorts (See #GetSortKind). - */ - public enum class SortKind - { - Uninterpreted, - Bool, - Int, - Real, - BitVector, - Array, - Datatype, - Unknown - }; - - /** - \brief Different failure kinds. - - - NoFailure - - Unknown: - - TimeOut: - - MemOut: - - UserCanceled: - - MaxConflicts: - - Theory: - - Quantifiers: - - */ - public enum class SearchFailureExplanation - { - NoFailure, - Unknown, - TimeOut, - MemOut, - UserCanceled, - MaxConflicts, - Theory, - Quantifiers - }; - - /** - \brief The different kinds of Z3 Terms. - - - Numeral: numerals - - App: constant and applications - - Var: bound variables - - Quantifier: quantifiers - - Unknown: internal - */ - public enum class TermKind - { - Numeral, - App, - Var, - Quantifier, - Unknown - }; - - - /** \brief Different kinds of Z3 built-in declarations (See #GetDeclKind) - - */ - public enum class DeclKind - { - // Basic operators - True, - False, - Eq, - Distinct, - Ite, - And, - Or, - Iff, - Xor, - Not, - Implies, - // Arithmetic - ArithNum, - Le, - Ge, - Lt, - Gt, - Add, - Sub, - Uminus, - Mul, - Div, - IDiv, - Rem, - Mod, - ToReal, - ToInt, - IsInt, - // Arrays - Store, - Select, - ConstArray, - DefaultArray, - MapArray, - Union, - Intersect, - Difference, - Complement, - Subset, - AsArray, - // Bit-vectors. - - BitNum, - Bit1, - Bit0, - BNeg, - BAdd, - BSub, - BMul, - BSDiv, - BUDiv, - BSRem, - BURem, - BSMod, - - BSDiv0, - BUDiv0, - BSRem0, - BURem0, - BSMod0, - BULeq, - BSLeq, - BUGeq, - BSGeq, - BULt, - BSLt, - BUGt, - BSGt, - BAnd, - BOr, - BNot, - BXor, - BNand, - BNor, - BXnor, - BConcat, - BSignExt, - BZeroExt, - BExtract, - BRepeat, - BRedOr, - BRedAnd, - BComp, - - BShl, - BLShr, - BAShr, - BRotateLeft, - BRotateRight, - BExtRotateLeft, - BExtRotateRight, - BInt2Bv, - BBv2Int, - BCarry, - BXor3, - - PrAsserted, - PrGoal, - PrModusPonens, - PrReflexivity, - PrTransitivity, - PrTransitivityStar, - PrSymmetry, - PrMonotonicity, - PrQuantIntro, - PrDistributivity, - PrAndElim, - PrNotOrElim, - PrRewrite, - PrRewriteStar, - PrPullQuant, - PrPullQuantStar, - PrPushQuant, - PrElimUnusedVars, - PrDer, - PrQuantInst, - PrHypothesis, - PrLemma, - PrUnitResolution, - PrIffTrue, - PrIffFalse, - PrCommutativity, - PrDefAxiom, - PrDefIntro, - PrApplyDef, - PrIffOeq, - PrNnfPos, - PrNnfNeg, - PrNnfStar, - PrSkolemize, - PrCnfStar, - PrModusPonensOeq, - PrThLemma, - - RaStore, - RaEmpty, - RaIsEmpty, - RaJoin, - RaUnion, - RaWiden, - RaProject, - RaFilter, - RaNegationFilter, - RaRename, - RaComplement, - RaSelect, - RaClone, - - Label, - LabelLit, - Uninterpreted - }; - - - /** - \brief IErrorHandler is an abstract (interface) class for passing - an error handler. - - The \c Handler method takes as argument an \c ErrorCode and processes - it. - */ - public interface class IErrorHandler - { - public: - virtual void Handler(ErrorCode code) = 0; - }; - - /// @cond 0 - LBool ToLBool(Z3_lbool b) { - switch(b) { - case Z3_L_FALSE: return LBool::False; - case Z3_L_TRUE: return LBool::True; - default: return LBool::Undef; - } - } - /// @endcond - - /** - \brief Container for labeled literals. - - A satisfiable state can be queried for a set of labeled literals that are satisfied. - - */ - - public ref class LabeledLiterals { - ref_context& m_context; - Z3_literals m_labels; - internal: - LabeledLiterals(ref_context& ctx, Z3_literals lbls): m_context(ctx), m_labels(lbls) { ctx.inc_ref(); } - Z3_literals Get() { return m_labels; } - TermPtr GetLiteral(unsigned idx) { return TermPtr(Z3_get_literal(m_context(), m_labels, idx)); } - protected: - !LabeledLiterals(); - public: - ~LabeledLiterals() { if (m_labels) { Z3_del_literals(m_context(), m_labels); } m_labels = 0; m_context.dec_ref(); } - unsigned GetNumLabels() { return Z3_get_num_literals(m_context(), m_labels); } - void Disable(unsigned idx) { Z3_disable_literal(m_context(), m_labels, idx); } - Symbol^ GetLabel(unsigned idx) { return gcnew Symbol(m_context(), Z3_get_label_symbol(m_context(), m_labels, idx)); } - }; - - - /** - \brief Container for constructor declarations. - - */ - - public ref class Constructor { - ref_context& m_context; - Z3_constructor m_constructor; - FuncDeclPtr m_constructor_decl; - FuncDeclPtr m_tester; - array^ m_accessors; - - !Constructor(); - - internal: - String^ m_name; - String^ m_tester_name; - array^ m_field_names; - array^ m_field_sorts; - array^ m_field_refs; - - Constructor( - ref_context& context, - String^ name, - String^ tester, - array^ field_names, - array^ field_sorts, - array^ field_refs - ); - - Z3_constructor Query(); - Z3_constructor Get(); - FuncDeclPtr GetConstructor(); - FuncDeclPtr GetTester(); - array^ GetAccessors(); - public: - ~Constructor(); - }; - - - - /** - \brief Configuration - - Configuration can be set prior to creating an instance - of the Z3 Context. - - To set a parameter create an instance of the Params class - and call the SetParamValue() method. - - The set of legal parameters can be found by executing z3.exe /ini? - */ - public ref class Config - { - /// @cond 0 - Z3_config m_config; - /// @endcond - internal: - /// @cond 0 - Z3_config get() { return m_config; } - /// @endcond - - protected: - !Config(); - - public: - /** - \brief Create configuration context. - - Create a configuration context to supply configurations to the - Z3 #Context. Callers must explicitly close the configuration - in order to collect the resources allocated in the configuration. - */ - Config(); - - /// \brief Configuration destructor. - ~Config(); - - /** - \brief Set parameter to specified value. - - The list of all configuration parameters can be obtained using the Z3 executable: - - \verbatim - z3.exe /ini? - \endverbatim - */ - void SetParamValue(String^ name, String^ value); - }; - - - /** - \brief Z3 Parameter values. - */ - public interface class IRawParameter { }; - public interface class IParameter { }; - - public ref class IntParameter : public IRawParameter, public IParameter { - int m_value; - internal: - IntParameter(int i) : m_value(i) {} - public: - property int Int { int get() { return m_value; } } - virtual String^ ToString() override { return m_value.ToString(); } - }; - - public ref class DoubleParameter : public IRawParameter, public IParameter { - double m_value; - internal: - DoubleParameter(double i) : m_value(i) {} - public: - property double Double { double get() { return m_value; } } - virtual String^ ToString() override { return m_value.ToString(); } - }; - - public ref class RationalParameter : public IRawParameter, public IParameter { - String^ m_value; - internal: - RationalParameter(String^ s): m_value(s) {} - public: - property String^ GetRational { String^ get() { return m_value; } } - virtual String^ ToString() override { return m_value; } - }; - - public ref class SymbolParameter : public IRawParameter, public IParameter { - Symbol^ m_value; - internal: - SymbolParameter(Symbol^ s): m_value(s) {} - public: - property Symbol^ GetSymbol { Symbol^ get() { return m_value; } } - }; - - public ref class TermPtrParameter : public IRawParameter { - TermPtr m_value; - internal: - TermPtrParameter(TermPtr t) : m_value(t) {} - public: - property TermPtr GetTerm { TermPtr get() { return m_value; } } - }; - - public ref class SortPtrParameter : public IRawParameter { - SortPtr m_value; - internal: - SortPtrParameter(SortPtr t) : m_value(t) {} - public: - property SortPtr GetSort { SortPtr get() { return m_value; } } - }; - - public ref class FuncDeclPtrParameter : public IRawParameter { - FuncDeclPtr m_value; - internal: - FuncDeclPtrParameter(FuncDeclPtr t) : m_value(t) {} - public: - property FuncDeclPtr GetFuncDecl { FuncDeclPtr get() { return m_value; } } - }; - - - - - /** - \brief Z3 Array Value object. - */ - public ref class RawArrayValue { - public: - array^ Domain; - array^ Range; - TermPtr ElseCase; - }; - - /** - \brief Z3 Function entry object. - - A FunctionEntry object summarizes what a function maps to - based on a given set of argument values. - */ - public ref class RawFunctionEntry { - public: - array^ Arguments; - TermPtr Result; - }; - - /** - \brief Z3 Function graph object. - - The finite function graph of an uninterpreted function - is represented as a list of #FunctionEntry entries, together - with a default value. The domain values not listed in the - #FunctionEntry array map to the default value \c Else. - - \param Declaration contains the function declaration Ast. - \param Entries contains the array of entries where the function - is defined explicitly. - \param Contains the default value of the function; where the function - maps to a default value. - */ - public ref class RawFunctionGraph { - public: - FuncDeclPtr Declaration; - array^ Entries; - TermPtr Else; - }; - - public ref class RawQuantifier { - public: - bool IsForall; - unsigned Weight; - array^ Patterns; - array^ NoPatterns; - array^ Sorts; - array^ Names; - TermPtr Body; - }; - - ref class RawModel; - - public delegate void Action0(); - - generic - public delegate void Action2( - T obj1, - S obj2 - ); - generic - public delegate void Action3( - T obj1, - S obj2, - U obj3 - ); - - - generic - public delegate T Func0(); - - generic - public delegate S Func1( - T obj - ); - - generic - public delegate U Func2( - T obj1, - S obj2 - ); - - - /** - \brief Z3 RawModel object. - */ - public ref class RawModel { - ref_context& m_context; - Z3_model m_model; - Dictionary^ m_graphs; - internal: - RawModel(ref_context& c, Z3_model m) : m_context(c), m_model(m), m_graphs(nullptr) { c.inc_ref(); } - - void Reset(); - protected: - !RawModel(); - public: - ~RawModel(); - - - /** - \brief Return the constants assigned by the given model. - */ - array^ GetModelConstants(); - - /** - \brief Return the function interpretations in the given model. - - A function interpretation is represented as a finite map and an 'else' value. - Each entry in the finite map represents the value of a function given a set of arguments. - */ - Dictionary^ GetFunctionGraphs(); - - /** - \brief Evaluate the AST node \c t in the given model. - - Return the result as a non-zero value. The - returned value is null if the term does not evaluate to a fixed value - in the current model. - term to a value. - - - The evaluation may fail for the following reasons: - - - \c t contains a quantifier or bound variable. - - - the model \c m is partial, that is, it doesn't have a complete interpretation for free functions. - That is, the option PARTIAL_MODELS=true was used. - - - the evaluator doesn't have support for some interpreted operator. - - - \c t is type incorrect (see #TypeCheck). - - - The result of an intepreted operator in \c t is undefined (e.g. division by zero). - */ - TermPtr Eval(TermPtr); - - TermPtr Eval(FuncDeclPtr, array^ args); - - - /** - \brief Return decomposed sequence of stores as an array value. - */ - bool TryGetArrayValue(TermPtr a,[Out] RawArrayValue^% av); - - /** - \brief Convert the given model into a string. - */ - virtual String^ ToString() override; - - /** - \brief Display model to TextWriter - */ - void Display(System::IO::TextWriter^ w); - }; - - public ref class ReferenceCounted {}; - - public ref class TermProofPtr { - TermPtr m_term; - TermPtr m_proof; // proof is optional, use IntPtr::Zero for absence of proofs. - public: - TermProofPtr(TermPtr term, TermPtr proof): m_term(term), m_proof(proof) {} - property TermPtr GetTerm { TermPtr get() { return m_term; } } - property TermPtr Proof { TermPtr get() { return m_proof; } } - }; - - ref class RawTheory; - /** - \brief Z3 API object. - */ - public ref class RawContext : public MarshalByRefObject - { - ref_context* m_context; - bool m_disposed; - static List >^ s_todec; - static IntPtr^ s_monitor; - static bool s_nonempty; - - void Init(); - internal: - static IErrorHandler^ m_error_handler = nullptr; - - Z3_context ctx() { return (*m_context)(); } - Z3_fixedpoint dl() { return m_context->dl(); } - ref_context& ref_context() { return *m_context; } - - /** - \brief Increment and decrement reference counters on - terms, sorts and declarations. - - These methods are required when the context is created - using the ReferenceCounted argument. - */ - void IncRef(AstPtr ast); - - void EnqueueDecRef(AstPtr ast); - - protected: - - !RawContext(); - public: - /** - \brief Create a logical context using the given configuration. - - After a context is created, the configuration cannot be changed. - All main interaction with Z3 happens in the context of a \c Context. - - All contexts that are created must be disposed (call Dispose). - Failure to dispose contexts cause memory leaks. - Garbage collection will not free resources allocated in contexts. - */ - - RawContext(Config^ config); - - /** - \brief Create a logical context using the given configuration. - - This constructor is similar to the default RawContext constructor. - Reference counts to terms, functions, and sorts that are created - over the API have to be handled explicitly by the caller, however. - - Terms (sorts, declarations) created by the context have initially - reference count 0, and the caller has to explicitly manage the reference counts. - This mode is more flexible, but also very error prone. - - Use the metheods AddRef and DecRef on terms, sorts, declarations to - control the reference counts. - - All contexts that are created must be disposed (call Dispose). - Failure to dispose contexts cause memory leaks. - Garbage collection will not free resources allocated in contexts. - */ - RawContext(Config^ config, ReferenceCounted^ rc); - - RawContext(); - - void SetContext(Z3_context ctx); - - void Reset(); - - ~RawContext(); - - /** - @name Tracing and logging - */ - /*@{*/ - - /** - \brief Enable low-level debug tracing. - - This method only works with debug builds. - */ - void EnableDebugTrace(String^ tag); - - /** - \brief Enable or disable warning messages sent to the console out/error. - - Warnings are printed after passing \c true, warning messages are - suppressed after calling this method with \c false. - */ - void ToggleWarningMessages(bool enabled); - - /** - \brief Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - \verbatim - z3.exe -ini? - \endverbatim - - Only a few configuration parameters are mutable once the context is created. - The error handler is invoked when trying to modify an immutable parameter. - - \sa SetParamValue - */ - void UpdateParamValue(String^ param_id, String^ value); - - /** - \brief Get a configuration parameter. - - \sa Z3_mk_config - \sa Z3_set_param_value - */ - String^ GetParamValue(String^ param_id); - - /** - \brief Configure the SMTLIB logic to be used in the given logical context. - */ - - bool SetLogic(String^ logic); - - /*@}*/ - - - /** - @name Symbols - */ - /*@{*/ - /** - \brief Create a Z3 symbol using an intege or a string. - - Symbols are used to name several term and type constructors. - - */ - Symbol^ MkSymbol(int i); - - Symbol^ MkSymbol(String^ s); - /*@}*/ - - /** - @name Types - */ - /*@{*/ - - /** - \brief Create a free (uninterpreted) type using the given name (symbol). - - Two free types are considered the same iff the have the same name. - */ - SortPtr MkSort(Symbol^ s); - - SortPtr MkSort(String^ s); - - SortPtr MkSort(int i); - - - /** - \brief Create the boolean type. - - This type is used to create propositional variables and predicates. - */ - SortPtr MkBoolSort(); - - /** - \brief Create an integer type. - - This type is not the int type found in programming languages. - A machine integer can be represented using bit-vectors. The function - #MkBvType creates a bit-vector type. - - \sa MkBvType - */ - SortPtr MkIntSort(); - - /** - \brief Create a real type. - - This type is not a floating point number. - Z3 does not have support for floating point numbers yet. - */ - SortPtr MkRealSort(); - - - /** - \brief Create a bit-vector type of the given size. - - This type can also be seen as a machine integer. - - \remark The size of the bitvector type must be greater than zero. - */ - SortPtr MkBvSort(unsigned sz); - - /** - \brief Create an array type. - - We usually represent the array type as: [domain -> range]. - Arrays are usually used to model the heap/memory in software verification. - - \sa MkArraySelect - \sa MkArrayStore - \sa MkArrayMap - \sa MkConstArray - */ - - SortPtr MkArraySort(SortPtr domain, SortPtr range); - - /** - \brief Create a named finite domain sort. - - To create constants that belong to the finite domain, - use MkNumeral for creating numerals and pass a numeric - constant together with the sort returned by this call. - */ - SortPtr MkFiniteDomainSort(String^ name, unsigned __int64 domain_size); - - - /** - \brief Create a tuple type. - - - A tuple with \c n fields has a constructor and \c n projections. - This function will also declare the constructor and projection functions. - - \param mk_tuple_name name of the constructor function associated with the tuple type. - \param field_names name of the projection functions. - \param field_types type of the tuple fields. - \param mk_tuple_decl output parameter that will contain the constructor declaration. - \param proj_decl output parameter that will contain the projection function declarations. - This field must be a buffer of size \c num_fields allocated by the user. - */ - SortPtr MkTupleSort( - Symbol^ mk_tuple_name, - array^ field_names, - array^ field_types, - [Out] FuncDeclPtr% mk_tuple_decl, - [In] [Out] array^ proj_decl - ); - - SortPtr MkTupleSort( - String^ mk_tuple_name, - array^ field_names, - array^ field_types, - [Out] FuncDeclPtr% mk_tuple_decl, - [In, Out] array^ proj_decl - ); - - /** - \brief create an enumeration type. - - \param name - name of enumeration sort. - \param enum_names - names of enumerated elements. - \param enum_consts - output function declarations for enumerated elements. - \param enum_testers - output function declarations for enumeration testers. - - */ - SortPtr MkEnumerationSort( - String^ name, - array^ enum_names, - array^ enum_consts, - array^ enum_testers); - - /** - \brief create list sort. - - \param name of resulting list type. - \param elem_sort sort of elements. - \param nil_decl function declaration for nil. - \param is_nil_decl function declaration for nil tester. - \param cons_decl function declaration for cons constructor. - \param is_cons_decl function declaration for cons tester. - \param head_decl function declaration for head accessor. - \param tail_decl function declaration for tail accessor. - - */ - SortPtr MkListSort( - String^ name, - SortPtr elem_sort, - [Out] FuncDeclPtr% nil_decl, - [Out] FuncDeclPtr% is_nil_decl, - [Out] FuncDeclPtr% cons_decl, - [Out] FuncDeclPtr% is_cons_decl, - [Out] FuncDeclPtr% head_decl, - [Out] FuncDeclPtr% tail_decl - ); - - - /** - \brief create constructor object for datatype declarations. - The object must be disposed with manually. - - Use the methods #GetConstructor, #GetTester, and #GetAccessors to - retrieve the function declarations for constructors, tester and accessors - after the datatype has been declared. - - A field_ref is the index of the (mutually) recursive datatype. - For example, if you declare a single recursive datatype, then - a reference to the recursive datatype that is being declared is - the number 0. If you declare two mutually recursive datatypes, then - the reference to the second recursive datatype is 1. - - */ - - Constructor^ MkConstructor( - String^ name, - String^ tester, - array^ field_names, - array^ field_sorts, - array^ field_refs - ); - - /** - \brief retrieve constructor function declaration. - */ - FuncDeclPtr GetConstructor(Constructor^ c) { return c->GetConstructor(); } - - /** - \brief retrieve test function for constructor. - */ - FuncDeclPtr GetTester(Constructor^ c) { return c->GetTester(); } - - /** - \brief retrieve accessors for datatype. - */ - array^ GetAccessors(Constructor^ c) { return c->GetAccessors(); } - - /** - \brief create datatype sort. - */ - SortPtr MkDataType( - String^ name, - array^ constructors - ); - - - /** - \brief create datatype sorts. - - \param names array of names for the recursive datatypes. - \param constructors array of arrays of constructors. - */ - array^ MkDataTypes( - array^ names, - array^>^ constructors - ); - - /*@}*/ - - /** - @name Constants and Applications - */ - - /*@{*/ - - /** - \brief Declare a constant or function. - - \param s name of the constant or function. - \param domain array containing the type of each argument. - The array must contain domain_size elements. It is 0 whe declaring a constant. - \param range type of the constant or the return type of the function. - - After declaring a constant or function, the function - #MkApp can be used to create a constant or function - application. - - \sa MkApp - */ - FuncDeclPtr MkFuncDecl(Symbol^ s, array^ domain, SortPtr range); - - FuncDeclPtr MkFuncDecl(String^ s, array^ domain, SortPtr range); - - FuncDeclPtr MkConstDecl(Symbol^ s, SortPtr ty) { - return MkFuncDecl(s, gcnew array(0), ty); - } - FuncDeclPtr MkFuncDecl(Symbol^ s, SortPtr domain, SortPtr range); - - FuncDeclPtr MkFuncDecl(Symbol^ s, SortPtr d1, SortPtr d2, SortPtr range); - - FuncDeclPtr MkConstDecl(String^ s, SortPtr ty) { - return MkFuncDecl(s, gcnew array(0), ty); - } - FuncDeclPtr MkFuncDecl(String^ s, SortPtr domain, SortPtr range); - - FuncDeclPtr MkFuncDecl(String^ s, SortPtr d1, SortPtr d2, SortPtr range); - - - /** - \brief Create a constant or function application. - - \sa MkFuncDecl - */ - AppPtr MkApp(FuncDeclPtr d, array^ args); - AppPtr MkApp(FuncDeclPtr d, TermPtr arg); - AppPtr MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2); - AppPtr MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2, TermPtr arg3); - - /** - \brief Declare and create a constant. - - \sa MkApp - \sa MkFuncDecl - */ - AppPtr MkConst(FuncDeclPtr d); - AppPtr MkConst(String^ s, SortPtr ty); - AppPtr MkConst(Symbol^ s, SortPtr ty); - - - /** - \brief Declare a fresh constant or function. - - Z3 will generate an unique name for this function declaration. - - \sa MkFuncDecl - */ - FuncDeclPtr MkFreshFuncDecl(String^ prefix, array^ domain, SortPtr range); - - /** - \brief Declare and create a fresh constant. - - \sa MkFuncDecl - \sa MkApp - */ - TermPtr MkFreshConst(String^ prefix, SortPtr ty); - - /** - \brief Create labeled formula. - - */ - TermPtr MkLabel(Symbol^ name, bool pos, TermPtr fml); - - /** - \brief Create an AST node representing \c true. - */ - TermPtr MkTrue() { return TermPtr(Z3_mk_true(ctx())); } - - - /** - \brief Create an AST node representing \c false. - */ - TermPtr MkFalse() { return TermPtr(Z3_mk_false(ctx())); } - - - /** - \brief Create an AST node representing l = r. - - The nodes \c l and \c r must have the same type. - */ - TermPtr MkEq(TermPtr l, TermPtr r); - - - /** - \brief Create an AST node representing distinct(args[0], ..., args[args.Length-1]). - - The \c distinct construct is used for declaring the arguments pairwise distinct. - That is, Forall 0 <= i < j < args.Length. not args[i] = args[j]. - - All arguments must have the same type. - - \remark The number of arguments of a distinct construct must be greater than one. - */ - TermPtr MkDistinct(array^ args); - - - /** - \brief Create an AST node representing not(a). - - The node \c a must have Boolean type. - */ - virtual TermPtr MkNot(TermPtr arg); - - /** - \brief - Create an AST node representing an if-then-else: ite(t1, t2, t3). - - The node \c t1 must have Boolean type, \c t2 and \c t3 must have the same type. - The type of the new node is equal to the type of \c t2 and \c t3. - */ - TermPtr MkIte(TermPtr t1, TermPtr t2, TermPtr t3); - - /** - \brief Create an AST node representing t1 iff t2. - - The nodes \c t1 and \c t2 must have Boolean type. - */ - TermPtr MkIff(TermPtr t1, TermPtr t2); - - /** - \brief Create an AST node representing t1 implies t2. - - The nodes \c t1 and \c t2 must have Boolean type. - */ - TermPtr MkImplies(TermPtr t1, TermPtr t2); - - /** - \brief Create an AST node representing t1 xor t2. - - The nodes \c t1 and \c t2 must have Boolean type. - */ - TermPtr MkXor(TermPtr t1, TermPtr t2); - - /** - \brief Create an AST node representing args[0] and ... and args[args.Length-1]. - - All arguments must have Boolean type. - - \remark The number of arguments must be greater than zero. - */ - TermPtr MkAnd(array^ args); - TermPtr MkAnd(TermPtr arg1, TermPtr arg2); - - /** - \brief Create an AST node representing args[0] or ... or args[args.Length-1]. - - All arguments must have Boolean type. - - \remark The number of arguments must be greater than zero. - */ - TermPtr MkOr(array^ args); - TermPtr MkOr(TermPtr arg1, TermPtr arg2); - - /** - \brief Create an AST node representing args[0] + ... + args[args.Length-1]. - - All arguments must have int or real type. - - \remark The number of arguments must be greater than zero. - */ - TermPtr MkAdd(array^ args); - TermPtr MkAdd(TermPtr arg1, TermPtr arg2); - - /** - \brief Create an AST node representing args[0] * ... * args[args.Length-1]. - - All arguments must have int or real type. - - \remark Z3 has limited support for non-linear arithmetic. - \remark The number of arguments must be greater than zero. - */ - TermPtr MkMul(array^ args); - TermPtr MkMul(TermPtr arg1, TermPtr arg2); - - /** - \brief Create an AST node representing args[0] - ... - args[args.Length - 1]. - - All arguments must have int or real type. - - \remark The number of arguments must be greater than zero. - */ - TermPtr MkSub(array^ args); - TermPtr MkSub(TermPtr arg1, TermPtr arg2); - - /** - \brief Create an AST node representing - arg. - - The argument must have int or real type. - */ - TermPtr MkUnaryMinus(TermPtr arg); - - /** - \brief Create integer or real division. - - The nodes \c arg1 and \c arg2 must have the same type, and must be int or real. - */ - TermPtr MkDiv(TermPtr arg1, TermPtr arg2); - - /** - \brief Create integer modulus - - The nodes \c arg1 and \c arg2 must have integer type. - */ - TermPtr MkMod(TermPtr arg1, TermPtr arg2); - - /** - \brief Create integer remainder - - The nodes \c arg1 and \c arg2 must have integer type. - */ - TermPtr MkRem(TermPtr arg1, TermPtr arg2); - - /** - \brief Create coercion from integer to real - - The node \c arg must have integer type. - */ - TermPtr MkToReal(TermPtr arg); - - /** - \brief Create coercion from real to integer (floor) - - The node \c arg must have real type. - */ - TermPtr MkToInt(TermPtr arg); - - /** - \brief Check if real is an integer value. - - The node \c arg must have real type. - */ - TermPtr MkIsInt(TermPtr arg); - - - - /** - \brief Create less than. - - The nodes \c arg1 and \c arg2 must have the same type, and must be int or real. - */ - TermPtr MkLt(TermPtr arg1, TermPtr arg2); - - /** - \brief Create less than or equal to. - - The nodes \c arg1 and \c arg2 must have the same type, and must be int or real. - */ - TermPtr MkLe(TermPtr arg1, TermPtr arg2); - - /** - \brief Create greater than. - - The nodes \c arg1 and \c arg2 must have the same type, and must be int or real. - */ - TermPtr MkGt(TermPtr arg1, TermPtr arg2); - - /** - \brief Create greater than or equal to. - - The nodes \c arg1 and \c arg2 must have the same type, and must be int or real. - */ - TermPtr MkGe(TermPtr arg1, TermPtr arg2); - - /** - \brief Bitwise negation. - - The node \c arg1 must have a bit-vector type. - */ - TermPtr MkBvNot(TermPtr t1); - - /** - \brief Take conjunction of bits in vector. - - The node \c arg1 must have a bit-vector type. - */ - TermPtr MkBvReduceAnd(TermPtr t1); - - /** - \brief Take disjunction of bits in vector. - - The node \c arg1 must have a bit-vector type. - */ - TermPtr MkBvReduceOr(TermPtr t1); - - /** - \brief Bitwise and. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvAnd(TermPtr t1, TermPtr t2); - - /** - \brief Bitwise or. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvOr(TermPtr t1, TermPtr t2); - - /** - \brief Bitwise exclusive-or. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvXor(TermPtr t1, TermPtr t2); - - /** - \brief Bitwise nand. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvNand(TermPtr t1, TermPtr t2); - - /** - \brief Bitwise nor. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvNor(TermPtr t1, TermPtr t2); - - /** - \brief Bitwise xnor. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvXnor(TermPtr t1, TermPtr t2); - - /** - \brief Standard two's complement unary minus. - - The node \c t1 must have bit-vector type. - */ - TermPtr MkBvNeg(TermPtr t1); - - /** - \brief Standard two's complement addition. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvAdd(TermPtr t1, TermPtr t2); - - /** - \brief Standard two's complement subtraction. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSub(TermPtr t1, TermPtr t2); - - /** - \brief Standard two's complement multiplication. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvMul(TermPtr t1, TermPtr t2); - - /** - \brief Unsigned division. - - It is defined as the \c floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvUdiv(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed division. - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSdiv(TermPtr t1, TermPtr t2); - - /** - \brief Unsigned remainder. - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - - If t2 is zero, then the result is undefined. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvUrem(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed remainder (sign follows dividend). - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - - \sa MkBvSmod - */ - TermPtr MkBvSrem(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed remainder (sign follows divisor). - - If t2 is zero, then the result is undefined. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - - \sa MkBvSrem - */ - TermPtr MkBvSmod(TermPtr t1, TermPtr t2); - - /** - \brief Unsigned less than. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvUlt(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed less than. - - It abbreviates: - \code - (or (and (= (extract[|m-1|:|m-1|] s) bit1) - (= (extract[|m-1|:|m-1|] t) bit0)) - (and (= (extract[|m-1|:|m-1|] s) (extract[|m-1|:|m-1|] t)) - (bvult s t))) - \endcode - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSlt(TermPtr t1, TermPtr t2); - - /** - \brief Unsigned less than or equal to. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvUle(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed less than or equal to. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSle(TermPtr t1, TermPtr t2); - - /** - \brief Unsigned greater than or equal to. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvUge(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed greater than or equal to. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSge(TermPtr t1, TermPtr t2); - - /** - \brief Unsigned greater than. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvUgt(TermPtr t1, TermPtr t2); - - /** - \brief Two's complement signed greater than. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSgt(TermPtr t1, TermPtr t2); - - /** - \brief Concatenate the given bit-vectors. - - The nodes \c t1 and \c t2 must have (possibly different) bit-vector types - - The result is a bit-vector of size n1+n2, where \c n1 (\c n2) is the size - of \c t1 (\c t2). - */ - TermPtr MkBvConcat(TermPtr t1, TermPtr t2); - - /** - \brief Extract the bits \c high down to \c low from a bitvector of - size \c m to yield a new bitvector of size \c n, where n = - high - low + 1. - - The node \c t must have a bit-vector type. - */ - TermPtr MkBvExtract(unsigned high, unsigned low, TermPtr t); - - /** - \brief Sign-extend of the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given - bit-vector. - - The node \c t must have a bit-vector type. - */ - TermPtr MkBvSignExt(unsigned i, TermPtr t); - - /** - \brief Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. - - The node \c t1 must have a bit-vector type. - */ - TermPtr MkBvZeroExt(unsigned i, TermPtr t); - - /** - \brief Repeat the bit-vector i times. - - The node \c t1 must have a bit-vector type. - */ - TermPtr MkBvRepeat(unsigned i, TermPtr t); - - /** - \brief Shift left. - - It is equivalent to multiplication by 2^x where \c x is the value of the - third argument. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvShl(TermPtr t1, TermPtr t2); - - /** - \brief Logical shift right. - - It is equivalent to unsigned division by 2^x where \c x is the - value of the third argument. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvLshr(TermPtr t1, TermPtr t2); - - /** - \brief Arithmetic shift right. - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvAshr(TermPtr t1, TermPtr t2); - - /** - \brief Rotate bits of \c t1 to the left \c i times. - - The node \c t1 must have a bit-vector type. - */ - TermPtr MkBvRotateLeft(unsigned i, TermPtr t1); - - /** - \brief Rotate bits of \c t1 to the right \c i times. - - The node \c t1 must have a bit-vector type. - */ - TermPtr MkBvRotateRight(unsigned i, TermPtr t1); - - /** - \brief Rotate bits of \c t1 to the left \c t2 times. - - The node \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvRotateLeft(TermPtr t1, TermPtr t2); - - /** - \brief Rotate bits of \c t1 to the right \c t2 times. - - The node \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvRotateRight(TermPtr t1, TermPtr t2); - - /** - \brief Convert bit vector to integer. - - The node \c t1 must have a bit-vector type. - */ - TermPtr MkBv2Int(TermPtr t1, bool is_signed); - - /** - \brief Convert integer to bit vector. - - The node \c t1 must have a integer type. - */ - TermPtr MkInt2Bv(unsigned size, TermPtr t1); - - /** - \brief Check that addition does not overflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvAddNoOverflow(TermPtr t1, TermPtr t2, bool is_signed); - - /** - \brief Check that addition does not underflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvAddNoUnderflow(TermPtr t1, TermPtr t2); - - /** - \brief Check that subtraction does not overflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSubNoOverflow(TermPtr t1, TermPtr t2); - - /** - \brief Check that subtraction does not underflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSubNoUnderflow(TermPtr t1, TermPtr t2, bool is_signed); - - /** - \brief Check that division does not overflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvSDivNoOverflow(TermPtr t1, TermPtr t2); - - /** - \brief Check that negation does not overflow. - */ - TermPtr MkBvNegNoOverflow(TermPtr t1); - - /** - \brief Check that multiplication does not overflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvMulNoOverflow(TermPtr t1, TermPtr t2, bool is_signed); - - /** - \brief Check that multiplication does not underflow. - - The nodes \c t1 and \c t2 must have the same bit-vector type. - */ - TermPtr MkBvMulNoUnderflow(TermPtr t1, TermPtr t2); - - /** - \brief Array read. - - The node \c a must have an array type [domain -> range], and \c i must have the type \c domain. - The type of the result is \c range. - - \sa MkArraySort - \sa MkArrayStore - */ - TermPtr MkArraySelect(TermPtr a, TermPtr i); - - /** - \brief Array update. - - The node \c a must have an array type [domain -> range], \c i must have type \c domain, - \c v must have type range. The type of the result is [domain -> range]. - - \sa MkArraySort - \sa MkArraySelect - */ - TermPtr MkArrayStore(TermPtr a, TermPtr i, TermPtr v); - - /** - \brief Array map. - - The \c n nodes \c args must be of array sorts [domain_i -> range_i]. - The function declaration \c f must have type range_1 .. range_n -> range. - \c v must have sort range. The sort of the result is [domain_i -> range]. - - \sa MkArraySort - \sa MkArraySelect - \sa MkArrayStore - */ - TermPtr MkArrayMap(FuncDeclPtr d, array^ args); - - /** - \brief Constant array. - - The node \c a must have an array type [range], \c domain indicates the domain - of the array. - The type of the result is [domain -> range]. - - \sa MkArraySort - \sa MkArraySelect - \sa MkArrayStore - */ - TermPtr MkArrayConst(SortPtr domain, TermPtr v); - - /** - \brief Access the array default. - - The node \c a must have an array type [domain -> range]. - The type of the result is [range]. The result is a term - whose value holds the default array value. That is, models should - ensure that the default for a (ElseCase) evaluates to the - same value as MkArrayDefault(a). - - \sa MkArraySort - \sa MkArraySelect - \sa MkArrayStore - \sa MkArrayconst - */ - TermPtr MkArrayDefault(TermPtr a); - - /*@}*/ - - - /** - @name Sets - */ - /*@{*/ - - /** - \brief Create Set type. - */ - SortPtr MkSetSort(SortPtr ty) { return SortPtr(Z3_mk_set_sort(ctx(), get_sort(ty))); } - - /** - \brief Create the empty set. - */ - TermPtr MkEmptySet(SortPtr ty) { return TermPtr(Z3_mk_empty_set(ctx(), get_sort(ty))); } - - /** - \brief Create the full set. - */ - TermPtr MkFullSet(SortPtr ty) { return TermPtr(Z3_mk_full_set(ctx(), get_sort(ty))); } - - /** - \brief Add an element to a set. - - The first argument must be a set, the second an element. - */ - TermPtr MkSetAdd(TermPtr set, TermPtr elem) { - return TermPtr(Z3_mk_set_add(ctx(), get_ast(set), get_ast(elem))); - } - - /** - \brief Remove an element to a set. - - The first argument must be a set, the second an element. - */ - TermPtr MkSetDel(TermPtr set, TermPtr elem) { - return TermPtr(Z3_mk_set_del(ctx(), get_ast(set), get_ast(elem))); - } - - /** - \brief Take the union of a arrays of sets. - - The arguments must all be of the same type and all be of set types. - */ - TermPtr MkSetUnion(array^ sets); - TermPtr MkSetUnion(TermPtr set1, TermPtr set2); - - /** - \brief Take the intersection of a arrays of sets. - */ - TermPtr MkSetIntersect(array^ sets); - TermPtr MkSetIntersect(TermPtr set1, TermPtr set2); - - /** - \brief Take the set difference between two sets. - */ - TermPtr MkSetDifference(TermPtr arg1, TermPtr arg2) { - return TermPtr(Z3_mk_set_difference(ctx(), get_ast(arg1), get_ast(arg2))); - } - /** - \brief Take the complement of a set. - */ - TermPtr MkSetComplement(TermPtr arg) { - return TermPtr(Z3_mk_set_complement(ctx(), get_ast(arg))); - } - - /** - \brief Check for set membership. - - The first argument should be an element type of the set. - */ - TermPtr MkSetMember(TermPtr elem, TermPtr set) { - return TermPtr(Z3_mk_set_member(ctx(), get_ast(elem), get_ast(set))); - } - - /** - \brief Check for subsetness of sets. - */ - TermPtr MkSetSubset(TermPtr arg1, TermPtr arg2) { - return TermPtr(Z3_mk_set_subset(ctx(), get_ast(arg1), get_ast(arg2))); - } - /*@}*/ - - - /** - @name Injective functions - */ - /*@{*/ - - /** - \brief Create injective function - */ - - FuncDeclPtr MkInjectiveFunction(String^ name, array^ domain, SortPtr range); - - FuncDeclPtr MkInjectiveFunction(Symbol^ name, array^ domain, SortPtr range); - - /*@}*/ - - - - /** - @name Numerals - */ - /*@{*/ - - /** - \brief Create a numeral of a given type. - - \param numeral An integer, or a string representing the numeral value in decimal notation. - If the given type is a real, then the numeral can be a rational, that is, a string of the form [num]* / [num]*. - \param ty The type of the numeral. In the current implementation, the given type can be an int, real, or bit-vectors of arbitrary size. - - */ - TermPtr MkNumeral(String^ numeral, SortPtr ty); - TermPtr MkNumeral(int n, SortPtr ty); - TermPtr MkNumeral(unsigned n, SortPtr ty); - TermPtr MkNumeral(__int64 n, SortPtr ty); - TermPtr MkNumeral(unsigned __int64 n, SortPtr ty); - - /** - \brief Create a numeral of type Int. - */ - TermPtr MkIntNumeral(String^ n) { return MkNumeral(n, MkIntSort()); } - TermPtr MkIntNumeral(int n) { return MkNumeral(n, MkIntSort()); } - TermPtr MkIntNumeral(unsigned n) { return MkNumeral(n, MkIntSort()); } - TermPtr MkIntNumeral(__int64 n) { return MkNumeral(n, MkIntSort()); } - TermPtr MkIntNumeral(unsigned __int64 n) { return MkNumeral(n, MkIntSort()); } - - - /** - \brief Create a numeral of type Real. - */ - TermPtr MkRealNumeral(String^ n) { return MkNumeral(n, MkRealSort()); } - TermPtr MkRealNumeral(int n) { return MkNumeral(n, MkRealSort()); } - TermPtr MkRealNumeral(unsigned n) { return MkNumeral(n, MkRealSort()); } - TermPtr MkRealNumeral(__int64 n) { return MkNumeral(n, MkRealSort()); } - TermPtr MkRealNumeral(unsigned __int64 n) { return MkNumeral(n, MkRealSort()); } - - /*@}*/ - - /** - @name Quantifiers - */ - /*@{*/ - - /** - \brief Create a pattern for quantifier instantiation. - - Z3 uses pattern matching to instantiate quantifiers. If a - pattern is not provided for a quantifier, then Z3 will - automatically compute a set of patterns for it. However, for - optimal performance, the user should provide the patterns. - - Patterns comprise an array of terms. The array of terms - passed to MkPattern should be - non-empty. If the array comprises of more than one term, it is - a called a multi-pattern. - - In general, one can pass in an array of (multi-)patterns in the - quantifier constructor. - - To summarize, each quantifier takes an array of alternative multi-patterns. - The quantifier is instantiated for every multi-pattern that is matched. - Each multi-pattern is an array of terms. All terms must match for the - multi-pattern to trigger instantiation. - Create a multi-pattern using MkPattern. - Create an array of multi-patterns and pass it to the quantifier constructor. - If you just want a multi-pattern with a single term, then pass in the singleton array - - - For example, if you want to create the multi-pattern - consisting of the two terms: \ccode{(store A I V)} - and \ccode{(select A J)} - where A, I, J, V are bound variables, create the pattern - -
-           pattern1 = context.MkPattern(new TermPtr[]{ 
-                             context.MkArrayStore(A,I,V),
-                             context.MkArraySelect(A,J)
-                                      })
-           
- Then form the array -
 
-                 new PatternPtr[]{ pattern1 }
-
-           
- and pass it to the - function \ccode{MkForall} or \ccode{MkExists}. - Suppose you also want to have the quantifier be instantiated if - the pattern \ccode{(select (store A I V) J)} is matched, then create the - pattern: -
-           pattern2 = context.MkPattern(new TermPtr[] {
-                                         context.MkArraySelect(context.MkArrayStore(A,I,V),J) })
-           
- Then form the array: -
-                 new PatternPtr[] { pattern1, pattern2 }
-           
- - \sa MkForall - \sa MkExists - */ - PatternPtr MkPattern(array^ terms); - - /** - \brief Create a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - \verbatim - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - \endverbatim - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper x appears, the higher is its - index. - - \param index de-Bruijn index - \param ty type of the bound variable - - \sa MkForall - \sa MkExists - */ - TermPtr MkBound(unsigned index, SortPtr ty); - - /** - \brief Create a forall formula. - - \param weight quantifiers are associated with weights indicating the importance - of using the quantifier during instantiation. By default, pass the weight 0. - \param patterns array containing the patterns created using #MkPattern. - \param types array containing the types of the bound variables. - \param names array containing the names as symbols of the bound variables. - \param body the body of the quantifier. - - \sa MkPattern - \sa MkBound - \sa MkExists - */ - TermPtr MkForall( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ); - - /** - \brief Create a forall formula. - - \param weight quantifiers are associated with weights indicating the importance - of using the quantifier during instantiation. By default, pass the weight 0. - \param patterns array containing the patterns created using #MkPattern. - \param types array containing the types of the bound variables. - \param names array containing the names as strings of the bound variables. - \param body the body of the quantifier. - - \sa MkPattern - \sa MkBound - \sa MkExists - */ - TermPtr MkForall( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ); - - /** - \brief Create a forall formula. - - This function allows creating a forall without using de-Bruijn indices in the body or patterns. - It is sometimes convenient to create the body of a quantifier without de-Bruijn indices, but - instead use constants. These constants have to be replaced by de-Bruijn indices for the - internal representation. This function allows the caller to hand over the task to Z3 of abstracting - the constants into bound variables, so that each occurrence of the variables in the array - bound gets replaced by a de-Bruijn index. - - \param weight quantifiers are associated with weights indicating the importance - of using the quantifier during instantiation. By default, pass the weight 0. - \param bound array containing the constants to be abstracted as bound variables. - \param patterns array containing the patterns created using #MkPattern. - \param body the body of the quantifier. - - \sa MkPattern - \sa MkExists - */ - TermPtr MkForall( - unsigned weight, - array^ bound, - array^ patterns, - TermPtr body - ); - - /** - \brief Create an exists formula. Similar to #MkForall. - - \sa MkPattern - \sa MkBound - \sa MkForall - */ - TermPtr MkExists( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ); - - TermPtr MkExists( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - TermPtr body - ); - - TermPtr MkExists( - unsigned weight, - array^ bound, - array^ patterns, - TermPtr body - ); - - /** - \brief Create a quantifier with no-pattern directives and symbols. - - Use de-Bruijn indexing. - - \sa MkPattern - \sa MkBound - \sa MkForall - \sa MkExists - */ - - TermPtr MkQuantifier( - bool is_forall, - unsigned weight, - array^ patterns, - array^ no_patterns, - array^ types, - array^ names, - TermPtr body - ) - { - return MkQuantifier(is_forall, weight, nullptr, nullptr, patterns, no_patterns, types, names, body); - } - - - TermPtr MkQuantifier( - bool is_forall, - unsigned weight, - Symbol^ quantifier_id, - Symbol^ skolem_id, - array^ patterns, - array^ no_patterns, - array^ types, - array^ names, - TermPtr body - ); - - - - /** - \brief Create a quantifier with no-pattern directives and symbols. - - Abstract terms as the bound variables. - - \sa MkPattern - \sa MkBound - \sa MkForall - \sa MkExists - */ - - TermPtr MkQuantifier( - bool is_forall, - unsigned weight, - Symbol^ quantifier_id, - Symbol^ skolem_id, - array^ patterns, - array^ no_patterns, - array^ bound, - TermPtr body - ); - - - /*@}*/ - - - /** - @name Accessors - */ - /*@{*/ - - /** - \brief Return a unique identifier for \c t. - */ - - unsigned GetTermId(TermPtr t); - - /** - \brief Return a unique identifier for \c f. - */ - unsigned GetFuncDeclId(FuncDeclPtr f); - - /** - \brief Return a unique identifier for \c s. - */ - unsigned GetSortId(SortPtr s); - - - /** - \brief Return \c SymbolKind.Int if the symbol was constructed - using #MkIntSymbol, and \c SymbolKind.String if the symbol - was constructed using #MkStringSymbol. - */ - SymbolKind GetSymbolKind(Symbol^ s); - - /** - \brief Return the symbol int value. - - \pre GetSymbolKind(s) == SymbolKind.Int - - \sa MkIntSymbol - */ - int GetSymbolInt(Symbol^ s); - - /** - \brief Return the symbol name. - - \pre GetSymbolKind(s) = SymbolKind.String - - \sa MkStringSymbol - */ - String^ GetSymbolString(Symbol^ s); - - /** - \brief Return \c true if the two given AST nodes are equal. - */ - bool IsEq(TermPtr t1, TermPtr t2); - - /** - \brief Return \c true if \c t is well sorted. - */ - bool IsWellSorted(TermPtr t); - - /** - \brief Return the kind of the given AST. - */ - TermKind GetTermKind(TermPtr a); - - /** - \brief Return the kind of the built-in operator. - - \pre GetTermKind(a) == TermKind.App - */ - DeclKind GetDeclKind(FuncDeclPtr d); - - /** - \brief Return auxiliary parameters associated with the built-in operator. - For example, the operator for bit-vector extraction uses - two parameters, the upper and lower bit-index for extraction. - */ - array^ GetDeclParameters(FuncDeclPtr d); - - /** - \brief Return the declaration of a constant or function application. - - \pre GetTermKind(a) == TermKind.App - */ - FuncDeclPtr GetAppDecl(AppPtr a); - - /** - \brief Return the arguments of an application. If \c t - is an constant, then array is empty. - */ - array^ GetAppArgs(AppPtr a); - - /** - \brief Return the number of a numeric ast. - - \pre GetTermKind(a) == TermKind.Numeral - */ - String^ GetNumeralString(TermPtr a); - - /** - \brief Similar to #GetNumeralString, but only succeeds if - the value can fit in a machine int. Throw InvalidArgument if the call fails. - - \pre GetTermKind(v) == TermKind.Numeral && IsInt32(v) - - \sa GetNumeralString - */ - int GetNumeralInt(TermPtr v); - - bool TryGetNumeralInt(TermPtr v, [Out] int% i); - - /** - \brief Similar to #GetNumeralString, but only succeeds if - the value can fit in a machine unsigned int. Throw InvalidArgument if the call fails. - - \pre GetTermKind(v) == TermKind.Numeral - - \sa GetNumeralString - */ - unsigned int GetNumeralUInt(TermPtr v); - - bool TryGetNumeralUInt(TermPtr v, [Out] unsigned int% u); - - - /** - \brief Similar to #GetNumeralString, but only succeeds if - the value can fit in a machine unsigned long long int. Throw InvalidArgument if the call fails. - - \pre GetTermKind(v) == TermKind.Numeral - - \sa GetNumeralString - */ - unsigned __int64 GetNumeralUInt64(TermPtr v); - - bool TryGetNumeralUInt64(TermPtr v, [Out] unsigned __int64% u); - - - /** - \brief Similar to #GetNumeralString, but only succeeds if - the value can fit in a machine long long int. Throw InvalidArgument if the call fails. - - \pre GetTermKind(v) == TermKind.Numeral - - */ - __int64 GetNumeralInt64(TermPtr v); - - bool TryGetNumeralInt64(TermPtr v, [Out] __int64% i); - - /** - \brief Similar to #GetNumeralString, but only succeeds if - the value can fit in a machine long long int. Throw InvalidArgument if the call fails. - - \pre GetTermKind(v) == TermKind.Numeral - - \sa GetNumeralString - */ - - bool TryGetNumeral(TermPtr v, [Out] __int64% num, [Out] __int64% den); - - void GetNumeral(TermPtr v, [Out] System::Numerics::BigInteger% num, [Out] System::Numerics::BigInteger% den); - - /** - \brief Return the Boolean value of a truth constant. Return LBool::Undef if a is not a boolean constant (true or false). - - \pre GetTermKind(a) == TermKind.App - */ - LBool GetBoolValue(TermPtr a); - - - /** - \brief Return the index of a de-Brujin bound variable. - - \pre GetTermKind(a) == TermKind.Var - */ - unsigned GetVarIndex(TermPtr a) { - return Z3_get_index_value(ctx(), get_ast(a)); - } - - /** - \brief Return components of a quantifier. - - \pre GetTermKind(a) = TermKind.Quantifier - */ - RawQuantifier^ GetQuantifier(TermPtr a); - - - /** - \brief Return array of terms in the pattern. - - \pre GetTermKind(a) = TermKind.Pattern - */ - array^ GetPatternTerms(PatternPtr p); - - /** - \brief Return the constant declaration name as a symbol. - */ - Symbol^ GetDeclName(FuncDeclPtr d); - - /** - \brief Return the type name as a symbol. - */ - Symbol^ GetSortName(SortPtr ty); - - /** - \brief Return the type of an AST node. - - The AST node must be a constant, application, numeral, bound variable, or quantifier. - */ - SortPtr GetSort(TermPtr a); - - /** - \brief Return the domain of a function declaration. - - */ - array^ GetDomain(FuncDeclPtr d); - - - /** - \brief Return the range of the given declaration. - - If \c d is a constant (i.e., has zero arguments), then this - function returns the type of the constant. - */ - SortPtr GetRange(FuncDeclPtr d); - - /** - \brief Return the type kind (e.g., array, tuple, int, bool, etc). - - \sa SortKind - */ - SortKind GetSortKind(SortPtr t); - - /** - \brief Return the size of the given bit-vector type. - - \pre GetSortKind(t) = SortKind.Bv - - \sa MkBvSort - \sa GetSortKind - */ - unsigned GetBvSortSize(SortPtr t); - - /** - \brief Return the domain of the given array type. - - \pre GetSortKind(t) == SortKind.Array - - \sa MkArraySort - \sa GetSortKind - */ - SortPtr GetArraySortDomain(SortPtr t); - - /** - \brief Return the range of the given array type. - - \pre GetSortKind(t) == SortKind.Array - - \sa MkArraySort - \sa GetSortKind - */ - SortPtr GetArraySortRange(SortPtr t); - - /** - \brief Return the constructor declaration of the given tuple - type. - - \pre GetSortKind(t) == SortKind.Tuple - - \sa MkTupleSort - \sa GetSortKind - */ - FuncDeclPtr GetTupleConstructor(SortPtr t); - - /** - \brief Return the field declarations of a given tuple type. - - \pre GetSortKind(t) == SortKind.Tuple - - - \sa MkTupleSort - \sa GetSortKind - */ - array^ GetTupleFields(SortPtr t); - - /*@}*/ - - /** - @name Modifiers - */ - /*@{*/ - - /** - \brief Update the arguments of a term or quantifier. - \pre The number of arguments passed in new_args should - be the same as number of arguments to the term t. - */ - TermPtr UpdateTerm(TermPtr t, array^ new_args); - - /*@}*/ - - - /** - @name Constraints - */ - /*@{*/ - - /** - \brief Create a backtracking point. - - The logical context can be viewed as a stack of contexts. The - scope level is the number of elements on this stack. The stack - of contexts is simulated using trail (undo) stacks. - - \sa Pop - \sa PersistTerm - */ - void Push(); - - /** - \brief Backtrack. - - Restores the context from the top of the stack, and pops it off the - stack. Any changes to the logical context (by #AssertCnstr or - other functions) between the matching #Push and \c Pop - operators are flushed, and the context is completely restored to - what it was right before the #Push. - - \param num_scopes number of scopes to pop. Default value is 1. - - \sa Push - \sa PersistTerm - */ - void Pop(unsigned num_scopes); - - void Pop() { Pop(1); } - - unsigned GetNumScopes(); - - - /** - \brief Persist a term during num_scopes of pops. - - Normally, references to terms are no longer valid when - popping scopes beyond the level where the terms are created. - If you want to reference a term below the scope where it - was created, use this method to specify how many pops - the term should survive. - The current scope level is given as the current - total number of calls to push subtracted by the - total number of calls to pop. - If num_scopes is larger or equal to the current - scope level, then the term pointer persists throughout - the life-time of the context. - - Example usage: - - context.Push(); - context.Push(); - Term t = context.MkNumeral(1, context.MkIntSort()); - context.PersistTerm(t, 1); - context.Pop(); - // reference to t is valid. - context.Pop(); - // reference to t is not valid. - */ - void PersistTerm(TermPtr t, unsigned num_scopes); - - - /** - \brief Assert a constraing into the logical context. - - After one assertion, the logical context may become - inconsistent. - - The functions #Check or #CheckAndGetModel should be - used to check whether the logical context is consistent or not. - - \sa Check - \sa CheckAndGetModel - */ - void AssertCnstr(TermPtr a); - - /** - \brief Check whether the given logical context is consistent or not. - - If the logical context is not unsatisfiable (i.e., the return value is different from \c false) - and model construction is enabled (see #Config), then a model is stored in \c m. Otherwise, - the value \c null is stored in \c m. - The caller is responsible for deleting the model using its Dispose method. - - \remark Model construction must be enabled using configuration - parameters (See, #Config). - - \sa Check - */ - LBool CheckAndGetModel([Out] RawModel^% m); - - /** - \brief Check whether the given logical context is consistent or not. - - The function #CheckAndGetModel should be used when models are needed. - - */ - LBool Check(); - - /** - \brief Check whether the given logical context is consistent or - not with respect to auxiliary assumptions. - - If the logical context is not unsatisfiable (i.e., the return value is different from \c false) - and model construction is enabled (see #Config), then a model is stored in \c m. Otherwise, - the value \c null is stored in \c m. - The caller is responsible for deleting the model using its Dispose method. - If the logical context is unsatisfiable, then a proof object is return and stored - in \c proof. - An unsatisfiable core (subset) for the set of supplied assumptions is returned. - - \remark Model construction must be enabled using configuration - parameters (See, #Config). - - \param m returned model. - \param assumptions array of auxiliary assumptions. - \param proof proof object. Proofs must be enabled for this value to be returned. - \param core subset of assumptions that is an unsatisfiable core. - - \sa Check - */ - LBool CheckAssumptions([Out] RawModel^% m, - [In] array^ assumptions, - [Out] TermPtr% proof, - [Out] array^% core); - - /** - \brief Cancel the current search initiated using #Check, #CheckAndGetModel, or #CheckAssumptions. - - \sa Check - \sa CheckAndGetModel - \sa CheckAssumptions - */ - void SoftCheckCancel(); - - - - /** - \brief Retrieve congruence class representatives for terms. - - The function can be used for relying on Z3 to identify equal terms under the current - set of assumptions. The array of terms and array of class identifiers should have - the same length. The class identifiers are numerals that are assigned to the same - value for their corresponding terms if the current context forces the terms to be - equal. You cannot deduce that terms corresponding to different numerals must be different, - (especially when using non-convex theories). - Also note that not necessarily all implied equalities are returned by this call. - Only the set of implied equalities that follow from simple constraint and - equality propagation is discovered. - - A side-effect of the function is a satisfiability check. - The function return LBool.False if the current assertions are not satisfiable. - - \sa Check - */ - - LBool GetImpliedEqualities( - [In] array^ terms, - [Out] array^% class_ids - ); - - - /** - \brief Obtain explanation for search failure. - - \sa Check() - */ - SearchFailureExplanation GetSearchFailureExplanation(); - - - /** - \brief Return conjunction of literals and formulas assigned to true in the current state. - */ - TermPtr GetAssignments(); - - /** - \brief Retrieve set of labels set in current satisfying assignment. - */ - LabeledLiterals^ GetRelevantLabels(); - - /** - \brief Retrieve set of literals satisfying the current assignment. - */ - LabeledLiterals^ GetRelevantLiterals(); - - /** - \brief Retrieve set of guessed literals satisfying the current assignment. - */ - LabeledLiterals^ GetGuessedLiterals(); - - /** - \brief Block the combination of remaining non-disabled labels. - - Subsequent calls to Check will not contain satisfying assignments with the same - combination of labels. - */ - void BlockLiterals(LabeledLiterals^ labels); - - /** - \brief Obtain literal corresponding to index in list of literals. - */ - TermPtr GetLiteral(LabeledLiterals^ labels, unsigned idx) { - return labels->GetLiteral(idx); - } - - /** - \brief Interface to simplifier. - - Provides an interface to the AST simplifier used by Z3. - It allows clients to piggyback on top of the AST simplifier - for their own term manipulation. - */ - TermPtr Simplify(TermPtr a); - - - /*@}*/ - - /** - @name String conversion - */ - /*@{*/ - - - /** - \brief Select mode for the format used for pretty-printing AST nodes. - - The default mode for pretty printing AST nodes is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PrintMode.SmtlibFull. - To print shared common subexpressions only once, use the PrintMode.LowLevel - mode. - */ - - void SetPrintMode(PrintMode mode); - - /** - \brief Convert the given AST node into a string. - */ - String^ ToString(AstPtr a); - - void Display(System::IO::TextWriter^ w, AstPtr a); - - /** - \brief Convert the given logical context into a string. - - This function is mainly used for debugging purposes. It displays - the internal structure of a logical context. - */ - virtual String^ ToString() override; - - void Display(System::IO::TextWriter^ w); - - /** - \brief Convert the given logical context into a string. - - This function is mainly used for debugging purposes. It displays - the internal structure of a logical context. - */ - String^ StatisticsToString() { - return gcnew String(Z3_statistics_to_string(ctx())); - } - - void DisplayStatistics(System::IO::TextWriter^ w) { - w->Write(StatisticsToString()); - } - - /** - \brief Convert the given benchmark into SMT-LIB formatted string. - */ - String^ BenchmarkToSmtlib(String^ name, - String^ logic, - String^ status, - String^ attributes, - array^ assumptions, - TermPtr formula); - - /*@}*/ - - /** - @name Parser interface - */ - /*@{*/ - /** - \brief Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given types and declarations. - The symbols in the arrays \c type_names and \c decl_names don't need to match the names - of the types and declarations in the arrays \c types and \c decls. This is an useful feature - since we can use arbitrary names to reference types and declarations defined using the C API. - - The formulas, assumptions and declarations defined in \c str. - - \param string The string contianing the SMT-LIB benchmark - \param sorts List of auxiliary sorts used in SMT-LIB benchmark. - \param decls List of declarations to be used for parsing the SMT-LIB string. - \param assumptions Returned set of assumptions. - \param formulas Returned set of formulas. - \param new_decls Additional declarations from the SMT-LIB benchmark. - \param new_sorts Additional sorts fromt he SMT-LIB benchmark. - \param parser_out String containing error messages from parsing. - */ - void ParseSmtlibString( - String^ string, - [In] array^ sorts, - [In] array^ decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ); - - /** - \brief Similar to #ParseSmtlibString, but reads the benchmark from a file. - */ - void ParseSmtlibFile( - String^ file, - [In] array^ sorts, - [In] array^ decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ); - - - /** - \brief Parse a string in the native Z3 format. - - Return conjunction of Asserts occurring in the string. - */ - TermPtr ParseZ3String(String^ s); - - /** - \brief Parse a file containing formulas in Z3's native format. - - Return conjunction of Asserts occurring in the file. - */ - TermPtr ParseZ3File(String^ filename); - - /** - \brief Parse a string in the SMT-LIB2 format. - - Return conjunction of Asserts occurring in the string. - */ - TermPtr ParseSmtlib2String(String^ s, array^ sorts, array^ decls); - - /** - \brief Parse a file containing formulas in SMT-LIB2 format. - - Return conjunction of Asserts occurring in the file. - */ - TermPtr ParseSmtlib2File(String^ filename, array^ sorts, array^ decls); - - /** - \brief Execute commands from a string in the SMT-LIB2 format. - - Return conjunction of Asserts modulo push/pop. - */ - TermPtr ExecSmtlib2String(String^ s, array^ sorts, array^ decls); - - /** - \brief Execute commands from a file containing formulas in SMT-LIB2 format. - - Return conjunction of Asserts modulo push/pop. - */ - TermPtr ExecSmtlib2File(String^ filename, array^ sorts, array^ decls); - /*@}*/ - - /** - @name Errors - */ - /*{@*/ - - /** - \brief Register a Z3 error handler. - - A call to a Z3 function throw Z3Error when - it is not used correctly. An error handler can be registered - and will be called in this case prior to throwing Z3Error. - */ - static void SetErrorHandler(IErrorHandler^ h); - - /** - \brief Return a string describing the given error code. - */ - static String^ GetErrorMessage(ErrorCode err); - - /** - \brief Free all resources allocated for Z3. - */ - static void ResetMemory(); - - /*@}*/ - - - /** - @name Miscellaneous - */ - /*@{*/ - - /** - \brief Return Z3 version number information. - */ - void GetVersion( - [Out] unsigned % major, - [Out] unsigned % minor, - [Out] unsigned % build_number, - [Out] unsigned % revision_number); - /*@}*/ - - - /** - \brief Create user theory. - */ - - RawTheory^ MkTheory(String^ name); - - internal: - static Dictionary^ contexts; - - public: - - /** - \brief Register fixed-point rules. - */ - - void RegisterRelation(FuncDeclPtr relation); - - void AddRule(TermPtr rule, Symbol^ name); - - /** - \brief post a query. - The return value is LBool.True if the query is satisfiabl,e - it is LBool.False if it is not satisfiabled, and Undef on - timeouts or approximation. - */ - LBool Query(TermPtr query); - - /** - \brief retrieve details on the search satus. - */ - String^ GetQueryStatus(); - - /** - \brief retrieve formula that satisfies the previous query, - assuming the return value was LBool.True - */ - TermPtr GetQueryAnswer(); - - String^ FixedpointToString(array^ queries); - - array^ SimplifyFixedpointRules(array^ rules, array^ output_predicates); - - // functions for creating custom Fixedpoint relations. - internal: - static void fixedpoint_assign_callback(void*, Z3_func_decl, unsigned, Z3_ast const[], unsigned, Z3_ast const[]); - static void fixedpoint_apply_callback(void*, Z3_func_decl, unsigned, Z3_ast const[], Z3_ast*); - IntPtr m_fixedpoint_gch; - private: - Action3^, array^>^ m_fixedpoint_assign; - Func2^, TermPtr>^ m_fixedpoint_apply; - void init_fixedpoint_callbacks(); - public: - property Action3^, array^>^ FixedpointAssign { - void set(Action3^, array^>^ value) { - m_fixedpoint_assign = value; - init_fixedpoint_callbacks(); - } - } - property Func2^, TermPtr>^ FixedpointApply { - void set(Func2^, TermPtr>^ value) { - m_fixedpoint_apply = value; - init_fixedpoint_callbacks(); - } - } - - }; - - public ref class RawTheory { - typedef GCHandle GCHandle; - typedef GCHandleType GCHandleType; - private: - Z3_theory m_theory; - ref_context& m_context; - String^ m_name; - static Dictionary^ theories; - protected: - !RawTheory() {} - public: - property String^ Name { String^ get() { return m_name; } } - internal: - RawTheory(ref_context& ctx, String^ name); - ~RawTheory(); - - static RawTheory^ GetTheory(Z3_theory th) { - Z3_theory_data td = Z3_theory_get_ext_data(th); - return theories[GCHandle::FromIntPtr(IntPtr(td))]; - } - - - // Delete Handler - private: - Action0^ delete_handler; - internal: - static void static_delete_callback(Z3_theory th); - - public: - property Action0^ DeleteHandler - { - void set(Action0^ value) - { - delete_handler = value; - } - } - - // ReduceEq - internal: - static Z3_bool reduce_eq_callback(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast* r); - private: - Func2^ reduce_eq; - void set_reduce_eq(Func2^ value); - public: - property Func2^ ReduceEq { - void set(Func2^ value) { - set_reduce_eq(value); - } - } - - - // ReduceApp - private: - Func2^, TermPtr>^ reduce_app; - void set_reduce_app(Func2^, TermPtr>^ value); - public: - property Func2^, TermPtr>^ ReduceApp { - void set(Func2^, TermPtr>^ value) { - set_reduce_app(value); - } - } - internal: - static Z3_bool reduce_app_callback(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r); - - // Reduce distinct - private: - Func1^, TermPtr>^ reduce_distinct; - void set_reduce_distinct(Func1^, TermPtr>^ value); - internal: - static Z3_bool reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r); - public: - property Func1^, TermPtr>^ ReduceDistinct { - void set(Func1^, TermPtr>^ value) { - set_reduce_distinct(value); - } - } - - // NewRelevant - internal: - Action^ new_relevant; - private: - void set_new_relevant(Action^ value); - public: - property Action^ NewRelevant { - void set(Action^ value) { - set_new_relevant(value); - } - } - - // NewApp - private: - void set_new_app(Action^ value); - internal: - Action^ new_app; - public: - property Action^ NewApp { - void set(Action^ value) { - set_new_app(value); - } - } - - // NewElem - private: - void set_new_elem(Action^ value); - internal: - Action^ new_elem; - public: - property Action^ NewElem { - void set(Action^ value) { - set_new_elem(value); - } - } - - // InitSearch - private: - void set_init_search(Action0^ value); - internal: - Action0^ init_search; - public: - property Action0^ InitSearch { - void set(Action0^ value) { set_init_search(value); } - } - - // Push - private: - void set_push(Action0^ value); - internal: - Action0^ push; - public: - property Action0^ Push { - void set(Action0^ value) { set_push(value); } - } - - // Pop - private: - void set_pop(Action0^ value); - internal: - Action0^ pop; - public: - property Action0^ Pop { - void set(Action0^ value) { set_pop(value); } - } - - // Restart - private: - void set_restart(Action0^ value); - internal: - Action0^ restart; - public: - property Action0^ Restart { - void set(Action0^ value) { set_restart(value); } - } - - // Reset - private: - void set_reset(Action0^ value); - internal: - Action0^ reset; - public: - property Action0^ Reset { - void set(Action0^ value) { set_reset(value); } - } - - - // FinalCheck - private: - void set_final_check(Func0^ value); - internal: - Func0^ final_check; - public: - property Func0^ FinalCheck { - void set(Func0^ value) { set_final_check(value); } - } - - - // NewEq - private: - void set_new_eq(Action2^ value); - internal: - Action2^ new_eq; - public: - property Action2^ NewEq - { - void set(Action2^ value) { set_new_eq(value); } - } - - - // NewDiseq - private: - void set_new_diseq(Action2^ value); - internal: - Action2^ new_diseq; - public: - property Action2^ NewDiseq - { - void set(Action2^ value) { set_new_diseq(value); } - } - - // NewAssignment - internal: - Action2^ new_assignment; - private: - void set_new_assignment(Action2^ value); - public: - property Action2^ NewAssignment { - void set(Action2^ value) { - set_new_assignment(value); - } - } - - void AssertTheoryAxiom(TermPtr ax) - { - Z3_theory_assert_axiom(m_theory, get_ast(ax)); - } - - void AssumeEq(TermPtr lhs, TermPtr rhs) - { - Z3_theory_assume_eq(m_theory, get_ast(lhs), get_ast(rhs)); - } - - void EnableTheoryAxiomSimplification(bool flag) - { - Z3_theory_enable_axiom_simplification(m_theory, flag); - } - - TermPtr GetEqcRoot(TermPtr n) - { - return TermPtr(Z3_theory_get_eqc_root(m_theory, get_ast(n))); - } - - TermPtr GetEqcNext(TermPtr n) - { - return TermPtr(Z3_theory_get_eqc_next(m_theory, get_ast(n))); - } - - - array^ GetParents(TermPtr n) { - unsigned np = Z3_theory_get_num_parents(m_theory, get_ast(n)); - array^ result = gcnew array(np); - for (unsigned i = 0; i < np; ++i) - { - result[i] = TermPtr(Z3_theory_get_parent(m_theory, get_ast(n), i)); - } - return result; - } - - bool IsTheoryValue(TermPtr a) - { - return 0 != Z3_theory_is_value(m_theory, get_ast(a)); - } - - bool IsTheoryDecl(FuncDeclPtr d) - { - return 0 != Z3_theory_is_decl(m_theory, get_func_decl(d)); - } - - array^ GetElems() - { - unsigned n = Z3_theory_get_num_elems(m_theory); - array^ result = gcnew array(n); - for (unsigned i = 0; i < n; ++i) - { - result[i] = TermPtr(Z3_theory_get_elem(m_theory, i)); - } - return result; - } - - array^ GetApps() - { - unsigned n = Z3_theory_get_num_apps(m_theory); - array^ result = gcnew array(n); - for (unsigned i = 0; i < n; ++i) - { - result[i] = TermPtr(Z3_theory_get_app(m_theory, i)); - } - return result; - } - - SortPtr MkSort(Symbol^ s) - { - return SortPtr(Z3_theory_mk_sort(m_context(), m_theory, s->get())); - } - - TermPtr MkValue(Symbol^ s, SortPtr srt) - { - return TermPtr(Z3_theory_mk_value(m_context(), m_theory, s->get(), get_sort(srt))); - } - - TermPtr MkConstant(Symbol^ s, SortPtr srt) - { - return TermPtr(Z3_theory_mk_constant(m_context(), m_theory, s->get(), get_sort(srt))); - } - - FuncDeclPtr MkFuncDecl(Symbol^ n, array^ domain, SortPtr range); - - SortPtr MkSort(String^ s); - - TermPtr MkValue(String^ s, SortPtr srt); - - TermPtr MkConstant(String^ s, SortPtr srt); - - FuncDeclPtr MkFuncDecl(String^ n, array^ domain, SortPtr range); - - }; - - - ref class Context; - ref class Model; - ref class Theory; - - public ref class Ast : public System::IComparable { - protected: - AstPtr m_ast; - RawContext^ m_ctx; - !Ast(); - internal: - Ast(RawContext^ c, AstPtr a); - AstPtr GetPtr() { return m_ast; } - AstPtr operator()() { return m_ast; } - public: - ~Ast(); - - /** - \brief Test equality of asts. - */ - virtual bool Equals(Object^ obj) override; - - /** - \brief Obtain hash code. - */ - virtual int GetHashCode() override; - - /** - \brief Pretty print term, sort or declaration. - */ - virtual String^ ToString() override; - - /** - \brief Implement IComparable::CompareTo - */ - virtual int CompareTo(Object^ other); - - /** - \brief overload ==, != - */ - // virtual bool operator==(Object^ other); - - // virtual bool operator!=(Object^ other); - - virtual unsigned GetId() { return m_ctx->GetTermId(m_ast); } - }; - - public ref class Sort : public Ast{ - internal: - Sort(RawContext^ c, SortPtr a) : Ast(c,a) {} - public: - String^ GetName(); - virtual unsigned GetId() override { return m_ctx->GetSortId(m_ast); } - }; - - public ref class FuncDecl : public Ast { - internal: - FuncDecl(RawContext^ c, FuncDeclPtr a) : Ast(c,a) {} - public: - String^ GetDeclName(); - DeclKind GetKind(); - virtual unsigned GetId() override { return m_ctx->GetFuncDeclId(m_ast); } - }; - - public ref class Term : public Ast { - internal: - Term(RawContext^ c, TermPtr a) : Ast(c,a) {} - public: - /** - \brief Overloading of Boolean operators. - - \pre Argument type is Boolean. - */ - static Term^ operator!(Term^ t1); - static Term^ operator&(Term^ t1, Term^ t2); - static Term^ operator|(Term^ t1, Term^ t2); - static Term^ operator^(Term^ t1, Term^ t2); - /** - \brief Overloading of common arithmetical operators. - - \pre Argument types are integers or reals. - */ - static Term^ operator+(Term^ t1, Term^ t2); - static Term^ operator*(Term^ t1, Term^ t2); - static Term^ operator/(Term^ t1, Term^ t2); - static Term^ operator-(Term^ t1, Term^ t2); - static Term^ operator>(Term^ t1, Term^ t2); - static Term^ operator<(Term^ t1, Term^ t2); - static Term^ operator>=(Term^ t1, Term^ t2); - static Term^ operator<=(Term^ t1, Term^ t2); - - /** - \brief Overloading of array select. - - \pre Argument is an index, the main term is of array type. - */ - Term^ operator[](Term^ index); - - TermKind GetKind(); - FuncDecl^ GetAppDecl(); - array^ GetAppArgs(); - Sort^ GetSort(); - String^ GetNumeralString(); - unsigned GetVarIndex(); - ref class Quantifier^ GetQuantifier(); - }; - - public ref class Pattern : public Ast { - internal: - Pattern(RawContext^ c, PatternPtr a) : Ast(c,a) {} - }; - - public ref class Quantifier { - public: - bool IsForall; - unsigned Weight; - array^ Patterns; - array^ NoPatterns; - array^ Sorts; - array^ Names; - Term^ Body; - }; - - public ref class ArrayValue { - public: - array^ Domain; - array^ Range; - Term^ ElseCase; - }; - - public ref class TermParameter : public IParameter { - Term^ m_value; - internal: - TermParameter(Term^ t) : m_value(t) {} - public: - virtual String^ ToString() override { return m_value->ToString(); } - property Term^ GetTerm { Term^ get() { return m_value; } } - }; - - public ref class SortParameter : public IParameter { - Sort^ m_value; - internal: - SortParameter(Sort^ s): m_value(s) {} - public: - property Sort^ GetSort { Sort^ get() { return m_value; } } - virtual String^ ToString() override { return m_value->ToString(); } - }; - - public ref class FuncDeclParameter : public IParameter { - FuncDecl^ m_value; - internal: - FuncDeclParameter(FuncDecl^ d): m_value(d) {} - public: - property FuncDecl^ GetFuncDecl { FuncDecl^ get() { return m_value; } } - virtual String^ ToString() override { return m_value->ToString(); } - }; - - /** - \brief Term and optional proof object returned by user-simplifier - */ - public ref class TermProof { - Term^ m_term; - Term^ m_proof; // proof is optional, use null for absence of proofs. - public: - TermProof(Term^ term, Term^ proof): m_term(term), m_proof(proof) {} - property Term^ GetTerm { Term^ get() { return m_term; } } - property Term^ Proof { Term^ get() { return m_proof; } } - }; - - /** - \brief Type safe contexts. - */ - public ref class Context { - - /// @cond 0 - RawContext^ m_ctx; - - - public: - template - array^ CopyArray(array^ a) { - if (!a) { - return gcnew array(0); - } - int len = a->Length; - array^ result = gcnew array(len); - for (int i = 0; i < len; ++i) { - if (a[i]) { - result[i] = a[i](); - } - else { - result[i] = IntPtr(0); - } - } - return result; - } - - array^ CopyArray(array^ a) { - return CopyArray(a); - } - - array^ CopyArray(array^ a) { - return CopyArray(a); - } - - array^ CopyArray(array^ a) { - return CopyArray(a); - } - - array^ CopyArray(array^ a) { - return CopyArray(a); - } - internal: - - template - static array^ CopyAstArray(RawContext^ ctx, array^ a) { - if (!a) return nullptr; - int len = a->Length; - array^ result = gcnew array(len); - - for (int i = 0; i < len; ++i) { - if (a[i] != IntPtr(0)) { - result[i] = gcnew T(ctx,a[i]); - } - else { - result[i] = nullptr; - } - } - return result; - } - - public: - template - array^ CopyAstArray(array^ a) { - return CopyAstArray(m_ctx, a); - } - - - array^ CopySortArray(array^ a) { - return CopyAstArray(a); - } - - array^ CopyTermArray(array^ a) { - return CopyAstArray(a); - } - - array^ CopyFuncDeclArray(array^ a) { - return CopyAstArray(a); - } - internal: - static array^ CopyTermArray(RawContext^ ctx, array^ a) { - return CopyAstArray(ctx, a); - } - - static array^ CopySortArray(RawContext^ ctx, array^ a) { - return CopyAstArray(ctx, a); - } - static Quantifier^ GetQuantifier(RawContext^ ctx, Term^ term); - - internal: - property RawContext^ GetContext { RawContext^ get() { return m_ctx; } } - - /// @endcond - - - public: - /** - \brief Create a type safe version of a context. - - Terms and models created using the type safe context are wrapped within - objects. The object wrappers prevent confusing the \ccode{IntPtr} type used for - terms, sorts and values with arbitrary instances. - - Each method in #Context is paired with a corresponding method in Context. - - \sa Context. - */ - - Context() { m_ctx = gcnew RawContext(); } - - Context(Config^ config) : m_ctx(gcnew RawContext(config)) {} - - Context(Config^ config, ReferenceCounted^ rc) : m_ctx(gcnew RawContext(config, rc)) {} - - /** - \brief Set the context from an externally created context. - */ - void SetContext(Z3_context ctx){ m_ctx->SetContext(ctx); } - - /** - \brief Dispose method for type safe contexts. - */ - ~Context() { m_ctx->Reset(); } - - /** - \brief Enable low-level debug tracing. - - This method only works with debug builds. - */ - - void EnableDebugTrace(String^ tag) { m_ctx->EnableDebugTrace(tag); } - - /** - \brief Enable or disable warning messages sent to the console out/error. - - Warnings are printed after passing \c true, warning messages are - suppressed after calling this method with \c false. - */ - - void ToggleWarningMessages(bool enabled) { m_ctx->ToggleWarningMessages(enabled); } - - void UpdateParamValue(String^ param_id, String^ value) { m_ctx->UpdateParamValue(param_id, value); } - - String^ GetParamValue(String^ param_id) { - return m_ctx->GetParamValue(param_id); - } - - /** - \brief Configure the SMTLIB logic to be used in the given logical context. - */ - - bool SetLogic(String^ logic) { return m_ctx->SetLogic(logic); } - - /** - @name Symbols - */ - /*@{*/ - Symbol^ MkSymbol(int i) { return m_ctx->MkSymbol(i); } - - Symbol^ MkSymbol(String^ s) { return m_ctx->MkSymbol(s); } - /*@}*/ - - /** - @name Modifiers - */ - /*@{*/ - - /** - \brief Update the arguments of a term or quantifier. - \pre The number of arguments passed in new_args should - be the same as number of arguments to the term t. - */ - Term^ UpdateTerm(Term^ t, array^ new_args) { - return gcnew Term(m_ctx, m_ctx->UpdateTerm(t(), CopyArray(new_args))); - } - - /*@}*/ - - /** - @name Constraints - */ - /*@{*/ - void Push() { m_ctx->Push(); } - void Pop(unsigned num_scopes) { m_ctx->Pop(num_scopes); } - void Pop() { Pop(1); } - unsigned GetNumScopes() { return m_ctx->GetNumScopes(); } - void PersistTerm(Term^ t, unsigned num_scopes) { - m_ctx->PersistTerm(t(), num_scopes); - } - LBool Check() { return m_ctx->Check(); } - LBool CheckAndGetModel([Out] Model^% m); - LBool CheckAssumptions([Out] Model^% m, - [In] array^ assumptions, - [Out] Term^% proof, - [Out] array^% core); - void SoftCheckCancel(); - - LBool GetImpliedEqualities( - [In] array^ terms, - [Out] array^% class_ids); - - SearchFailureExplanation GetSearchFailureExplanation() { return m_ctx->GetSearchFailureExplanation(); } - LabeledLiterals^ GetRelevantLabels() { return m_ctx->GetRelevantLabels(); } - LabeledLiterals^ GetRelevantLiterals() { return m_ctx->GetRelevantLiterals(); } - LabeledLiterals^ GetGuessedLiterals() { return m_ctx->GetGuessedLiterals(); } - void BlockLiterals(LabeledLiterals^ lbls) { m_ctx->BlockLiterals(lbls); } - Term^ GetLiteral(LabeledLiterals^ lbls, unsigned idx) { return gcnew Term(m_ctx, m_ctx->GetLiteral(lbls, idx)); } - Term^ Simplify(Term^ a) { return gcnew Term(m_ctx,m_ctx->Simplify(a())); } - void AssertCnstr(Term^ a) { m_ctx->AssertCnstr(a()); } - /*@}*/ - - virtual String^ ToString() override { return m_ctx->ToString(); } - - void Display(System::IO::TextWriter^ w) { m_ctx->Display(w); } - Term^ GetAssignments() { return gcnew Term(m_ctx, m_ctx->GetAssignments()); } - String^ StatisticsToString() { return m_ctx->StatisticsToString(); } - void DisplayStatistics(System::IO::TextWriter^ w) { m_ctx->DisplayStatistics(w); } - - /** - \brief Convert the given benchmark into SMT-LIB formatted string. - */ - String^ BenchmarkToSmtlib(String^ name, - String^ logic, - String^ status, - String^ attributes, - array^ assumptions, - Term^ formula); - - void ParseSmtlibString( - String^ string, - [In] array^ sorts, - [In] array^ decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ); - - - void ParseSmtlibFile( - String^ file, - [In] array^ sorts, - [In] array^ decls, - [Out] array^% assumptions, - [Out] array^% formulas, - [Out] array^% new_decls, - [Out] array^% new_sorts, - [Out] String^% parser_out - ); - - - Term^ ParseZ3String(String^ s) { - return gcnew Term(m_ctx,m_ctx->ParseZ3String(s)); - } - - Term^ ParseZ3File(String^ s) { - return gcnew Term(m_ctx,m_ctx->ParseZ3File(s)); - } - - Term^ ParseSmtlib2String(String^ s, array^ sorts, array^ decls) { - return gcnew Term(m_ctx,m_ctx->ParseSmtlib2String(s, CopyArray(sorts), CopyArray(decls))); - } - - Term^ ParseSmtlib2File(String^ s, array^ sorts, array^ decls) { - return gcnew Term(m_ctx,m_ctx->ParseSmtlib2File(s, CopyArray(sorts), CopyArray(decls))); - } - - Term^ ExecSmtlib2String(String^ s, array^ sorts, array^ decls) { - return gcnew Term(m_ctx,m_ctx->ExecSmtlib2String(s, CopyArray(sorts), CopyArray(decls))); - } - - Term^ ExecSmtlib2File(String^ s, array^ sorts, array^ decls) { - return gcnew Term(m_ctx,m_ctx->ExecSmtlib2File(s, CopyArray(sorts), CopyArray(decls))); - } - - static void SetErrorHandler(IErrorHandler^ h) { - RawContext::SetErrorHandler(h); - } - - static String^ GetErrorMessage(ErrorCode err) { - return RawContext::GetErrorMessage(err); - } - - static void ResetMemory() { - RawContext::ResetMemory(); - } - - - void SetPrintMode(PrintMode mode) { m_ctx->SetPrintMode(mode); } - - String^ ToString(Ast^ a) { return m_ctx->ToString(a()); } - - void Display(System::IO::TextWriter^ w, Ast^ a) { m_ctx->Display(w, a()); } - - - Sort^ MkIntSort() { return gcnew Sort(m_ctx,m_ctx->MkIntSort()); } - Sort^ MkBoolSort() { return gcnew Sort(m_ctx,m_ctx->MkBoolSort()); } - Sort^ MkSort(Symbol^ s) { return gcnew Sort(m_ctx,m_ctx->MkSort(s)); } - Sort^ MkSort(String^ s) { return gcnew Sort(m_ctx,m_ctx->MkSort(s)); } - Sort^ MkSort(int i) { return gcnew Sort(m_ctx,m_ctx->MkSort(i)); } - Sort^ MkFiniteDomainSort(String^ s, unsigned __int64 domain_size) { return gcnew Sort(m_ctx, m_ctx->MkFiniteDomainSort(s, domain_size)); } - Sort^ MkRealSort() { return gcnew Sort(m_ctx,m_ctx->MkRealSort()); } - Sort^ MkBvSort(unsigned sz) { return gcnew Sort(m_ctx,m_ctx->MkBvSort(sz)); } - Sort^ MkArraySort(Sort^ domain, Sort^ range) { return gcnew Sort(m_ctx,m_ctx->MkArraySort(domain(), range())); } - - Sort^ MkTupleSort( - Symbol^ mk_tuple_name, - array^ field_names, - array^ field_types, - [Out] FuncDecl^% mk_tuple_decl, - [In, Out] array^ proj_decl - ); - - Sort^ MkTupleSort( - String^ mk_tuple_name, - array^ field_names, - array^ field_types, - [Out] FuncDecl^% mk_tuple_decl, - [In, Out] array^ proj_decl - ); - - Sort^ MkEnumerationSort( - String^ name, - array^ enum_names, - array^ enum_consts, - array^ enum_testers); - - Sort^ MkListSort( - String^ name, - Sort^ elem_sort, - [Out] FuncDecl^% nil_decl, - [Out] FuncDecl^% is_nil_decl, - [Out] FuncDecl^% cons_decl, - [Out] FuncDecl^% is_cons_decl, - [Out] FuncDecl^% head_decl, - [Out] FuncDecl^% tail_decl - ); - - Constructor^ MkConstructor( - String^ name, - String^ tester, - array^ field_names, - array^ field_sorts, - array^ field_refs - ); - - - FuncDecl^ GetConstructor(Constructor^ c); - - FuncDecl^ GetTester(Constructor^ c); - - array^ GetAccessors(Constructor^ c); - - /** - \brief create datatype sort. - */ - - Sort^ MkDataType( - String^ name, - array^ constructors - ) { - return gcnew Sort(m_ctx, m_ctx->MkDataType(name, constructors)); - } - - /** - \brief create datatype sort. - */ - - array^ MkDataTypes( - array^ names, - array^>^ constructors - ) { - return CopySortArray(m_ctx->MkDataTypes(names, constructors)); - } - - - FuncDecl^ MkFuncDecl(Symbol^ s, array^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, CopyArray(domain), range())); - } - - FuncDecl^ MkFuncDecl(String^ s, array^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, CopyArray(domain), range())); - } - - FuncDecl^ MkConstDecl(Symbol^ s, Sort^ ty) { - return MkFuncDecl(s, gcnew array(0), ty); - } - FuncDecl^ MkFuncDecl(Symbol^ s, Sort^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, domain(), range())); - } - FuncDecl^ MkFuncDecl(Symbol^ s, Sort^ d1, Sort^ d2, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, d1(), d2(), range())); - } - FuncDecl^ MkConstDecl(String^ s, Sort^ ty) { - return MkFuncDecl(s, gcnew array(0), ty); - } - FuncDecl^ MkFuncDecl(String^ s, Sort^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, domain(), range())); - } - FuncDecl^ MkFuncDecl(String^ s, Sort^ d1, Sort^ d2, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, d1(), d2(), range())); - } - Term^ MkApp(FuncDecl^ d, array^ args) { - return gcnew Term(m_ctx,m_ctx->MkApp(d(), CopyArray(args))); - } - Term^ MkApp(FuncDecl^ d, Term^ arg) { - return gcnew Term(m_ctx,m_ctx->MkApp(d(), arg())); - } - Term^ MkApp(FuncDecl^ d, Term^ arg1, Term^ arg2) { - return gcnew Term(m_ctx,m_ctx->MkApp(d(), arg1(), arg2())); - } - Term^ MkApp(FuncDecl^ d, Term^ arg1, Term^ arg2, Term^ arg3) { - return gcnew Term(m_ctx,m_ctx->MkApp(d(), arg1(), arg2(), arg3())); - } - Term^ MkConst(FuncDecl^ d) { - return gcnew Term(m_ctx,m_ctx->MkConst(d())); - } - Term^ MkConst(String^ s, Sort^ ty) { - return gcnew Term(m_ctx,m_ctx->MkConst(s,ty())); - } - Term^ MkConst(Symbol^ s, Sort^ ty) { - return gcnew Term(m_ctx,m_ctx->MkConst(s, ty())); - } - FuncDecl^ MkFreshFuncDecl(String^ prefix, array^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkFreshFuncDecl(prefix, CopyArray(domain), range())); - } - Term^ MkFreshConst(String^ prefix, Sort^ ty) { - return gcnew Term(m_ctx,m_ctx->MkFreshConst(prefix, ty())); - } - Term^ MkTrue() { return gcnew Term(m_ctx,m_ctx->MkTrue()); } - Term^ MkFalse() { return gcnew Term(m_ctx,m_ctx->MkFalse()); } - Term^ MkLabel(Symbol^ name, bool pos, Term^ fml) { return gcnew Term(m_ctx,m_ctx->MkLabel(name, pos, fml())); } - - Term^ MkEq(Term^ l, Term^ r) { return gcnew Term(m_ctx,m_ctx->MkEq(l(), r())); } - Term^ MkDistinct(array^ args) { - return gcnew Term(m_ctx,m_ctx->MkDistinct(CopyArray(args))); - } - Term^ MkNot(Term^ arg) { return gcnew Term(m_ctx,m_ctx->MkNot(arg())); } - Term^ MkIte(Term^ t1, Term^ t2, Term^ t3) { - return gcnew Term(m_ctx,m_ctx->MkIte(t1(), t2(), t3())); - } - Term^ MkIff(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkIff(t1(), t2())); } - Term^ MkImplies(Term^ t1, Term^ t2) {return gcnew Term(m_ctx,m_ctx->MkImplies(t1(), t2()));} - Term^ MkXor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkXor(t1(), t2())); } - Term^ MkAnd(array^ args) { return gcnew Term(m_ctx,m_ctx->MkAnd(CopyArray(args))); } - Term^ MkAnd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkAnd(t1(), t2())); } - Term^ MkOr(array^ args) { return gcnew Term(m_ctx,m_ctx->MkOr(CopyArray(args))); } - Term^ MkOr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkOr(t1(), t2())); } - Term^ MkAdd(array^ args) { return gcnew Term(m_ctx,m_ctx->MkAdd(CopyArray(args))); } - Term^ MkAdd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkAdd(t1(), t2())); } - Term^ MkMul(array^ args) { return gcnew Term(m_ctx,m_ctx->MkMul(CopyArray(args))); } - Term^ MkMul(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkMul(t1(), t2())); } - Term^ MkSub(array^ args) { return gcnew Term(m_ctx,m_ctx->MkSub(CopyArray(args))); } - Term^ MkSub(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkSub(t1(), t2())); } - Term^ MkUnaryMinus(Term^ arg) { return gcnew Term(m_ctx,m_ctx->MkUnaryMinus(arg())); } - Term^ MkDiv(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkDiv(t1(), t2())); } - Term^ MkMod(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkMod(t1(), t2())); } - Term^ MkRem(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkRem(t1(), t2())); } - Term^ MkToReal(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkToReal(t1())); } - Term^ MkToInt(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkToInt(t1())); } - Term^ MkIsInt(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkIsInt(t1())); } - Term^ MkLt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkLt(t1(), t2())); } - Term^ MkLe(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkLe(t1(), t2())); } - Term^ MkGt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkGt(t1(), t2())); } - Term^ MkGe(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkGe(t1(), t2())); } - Term^ MkBvNot(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvNot(t1())); } - Term^ MkBvReduceAnd(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvReduceAnd(t1())); } - Term^ MkBvRedcueOr(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvReduceOr(t1())); } - Term^ MkBvAnd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvAnd(t1(), t2())); } - Term^ MkBvOr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvOr(t1(), t2())); } - Term^ MkBvXor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvXor(t1(), t2())); } - Term^ MkBvNand(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvNand(t1(), t2())); } - Term^ MkBvNor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvNor(t1(), t2())); } - Term^ MkBvXnor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvXnor(t1(), t2())); } - Term^ MkBvNeg(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvNeg(t1())); } - Term^ MkBvAdd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvAdd(t1(), t2())); } - Term^ MkBvSub(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSub(t1(), t2())); } - Term^ MkBvMul(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvMul(t1(), t2())); } - Term^ MkBvUdiv(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUdiv(t1(), t2())); } - Term^ MkBvSdiv(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSdiv(t1(), t2())); } - Term^ MkBvUrem(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUrem(t1(), t2())); } - Term^ MkBvSrem(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSrem(t1(), t2())); } - Term^ MkBvSmod(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSmod(t1(), t2())); } - Term^ MkBvUlt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUlt(t1(), t2())); } - Term^ MkBvSlt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSlt(t1(), t2())); } - Term^ MkBvUle(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUle(t1(), t2())); } - Term^ MkBvSle(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSle(t1(), t2())); } - Term^ MkBvUge(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUge(t1(), t2())); } - Term^ MkBvSge(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSge(t1(), t2())); } - Term^ MkBvUgt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUgt(t1(), t2())); } - Term^ MkBvSgt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSgt(t1(), t2())); } - Term^ MkBvConcat(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvConcat(t1(), t2())); } - Term^ MkBvExtract(unsigned high, unsigned low, Term^ t) { - return gcnew Term(m_ctx,m_ctx->MkBvExtract(high, low, t())); - } - Term^ MkBvSignExt(unsigned i, Term^ t) { - return gcnew Term(m_ctx,m_ctx->MkBvSignExt(i, t())); - } - Term^ MkBvZeroExt(unsigned i, Term^ t) { - return gcnew Term(m_ctx,m_ctx->MkBvZeroExt(i, t())); - } - Term^ MkBvRepeat(unsigned i, Term^ t) { - return gcnew Term(m_ctx,m_ctx->MkBvRepeat(i, t())); - } - Term^ MkBvShl(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvShl(t1(), t2())); } - Term^ MkBvLshr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvLshr(t1(), t2())); } - Term^ MkBvAshr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvAshr(t1(), t2())); } - Term^ MkBvRotateLeft(unsigned i, Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvRotateLeft(i,t1())); } - Term^ MkBvRotateRight(unsigned i, Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvRotateRight(i,t1())); } - Term^ MkBvRotateLeft(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvRotateLeft(t1(), t2())); } - Term^ MkBvRotateRight(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvRotateRight(t1(), t2())); } - Term^ MkBv2Int(Term^ t1, bool is_signed) { return gcnew Term(m_ctx, m_ctx->MkBv2Int(t1(), is_signed)); } - Term^ MkInt2Bv(unsigned n, Term^ t1) { return gcnew Term(m_ctx, m_ctx->MkInt2Bv(n, t1())); } - Term^ MkBvAddNoOverflow(Term^ t1, Term^ t2, bool is_signed) { - return gcnew Term(m_ctx,m_ctx->MkBvAddNoOverflow(t1(), t2(), is_signed)); - } - Term^ MkBvAddNoUnderflow(Term^ t1, Term^ t2) { - return gcnew Term(m_ctx,m_ctx->MkBvAddNoUnderflow(t1(), t2())); - } - Term^ MkBvSubNoOverflow(Term^ t1, Term^ t2) { - return gcnew Term(m_ctx,m_ctx->MkBvSubNoOverflow(t1(), t2())); - } - Term^ MkBvSubNoUnderflow(Term^ t1, Term^ t2, bool is_signed) { - return gcnew Term(m_ctx,m_ctx->MkBvSubNoUnderflow(t1(), t2(), is_signed)); - } - Term^ MkBvSDivNoOverflow(Term^ t1, Term^ t2) { - return gcnew Term(m_ctx,m_ctx->MkBvSDivNoOverflow(t1(), t2())); - } - Term^ MkBvNegNoOverflow(Term^ t1) { - return gcnew Term(m_ctx,m_ctx->MkBvNegNoOverflow(t1())); - } - Term^ MkBvMulNoOverflow(Term^ t1, Term^ t2, bool is_signed) { - return gcnew Term(m_ctx,m_ctx->MkBvMulNoOverflow(t1(), t2(), is_signed)); - } - Term^ MkBvMulNoUnderflow(Term^ t1, Term^ t2) { - return gcnew Term(m_ctx,m_ctx->MkBvMulNoUnderflow(t1(), t2())); - } - Term^ MkArraySelect(Term^ a, Term^ i) { return gcnew Term(m_ctx,m_ctx->MkArraySelect(a(), i())); } - Term^ MkArrayStore(Term^ a, Term^ i, Term^ v) { - return gcnew Term(m_ctx,m_ctx->MkArrayStore(a(), i(), v())); - } - Term^ MkArrayMap(FuncDecl^ f, array^ args) { - return gcnew Term(m_ctx, m_ctx->MkArrayMap(f(), CopyArray(args))); - } - Term^ MkArrayConst(Sort^ domain, Term^ v) { return gcnew Term(m_ctx,m_ctx->MkArrayConst(domain(), v())); } - Term^ MkArrayDefault(Term^ a) { return gcnew Term(m_ctx,m_ctx->MkArrayDefault(a())); } - Sort^ MkSetSort(Sort^ ty) { return gcnew Sort(m_ctx,m_ctx->MkSetSort(ty())); } - Term^ MkEmptySet(Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkEmptySet(ty())); } - Term^ MkFullSet(Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkFullSet(ty())); } - Term^ MkSetAdd(Term^ set, Term^ elem) { return gcnew Term(m_ctx,m_ctx->MkSetAdd(set(), elem())); } - Term^ MkSetDel(Term^ set, Term^ elem) { return gcnew Term(m_ctx,m_ctx->MkSetDel(set(), elem())); } - Term^ MkSetUnion(array^ sets) { - return gcnew Term(m_ctx,m_ctx->MkSetUnion(CopyArray(sets))); - } - Term^ MkSetUnion(Term^ set1, Term^ set2) { - return gcnew Term(m_ctx,m_ctx->MkSetUnion(set1(), set2())); - } - Term^ MkSetIntersect(array^ sets) { - return gcnew Term(m_ctx,m_ctx->MkSetIntersect(CopyArray(sets))); - } - Term^ MkSetIntersect(Term^ set1, Term^ set2) { - return gcnew Term(m_ctx,m_ctx->MkSetIntersect(set1(), set2())); - } - Term^ MkSetDifference(Term^ t1, Term^ t2) { - return gcnew Term(m_ctx,m_ctx->MkSetDifference(t1(), t2())); - } - Term^ MkSetComplement(Term^ arg) { - return gcnew Term(m_ctx,m_ctx->MkSetComplement(arg())); - } - Term^ MkSetMember(Term^ elem, Term^ set) { - return gcnew Term(m_ctx,m_ctx->MkSetMember(elem(), set())); - } - Term^ MkSetSubset(Term^ t1, Term^ t2) { - return gcnew Term(m_ctx,m_ctx->MkSetSubset(t1(), t2())); - } - - FuncDecl^ MkInjectiveFunction(String^ name, array^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkInjectiveFunction(name, CopyArray(domain), range())); - } - FuncDecl^ MkInjectiveFunction(Symbol^ name, array^ domain, Sort^ range) { - return gcnew FuncDecl(m_ctx,m_ctx->MkInjectiveFunction(name, CopyArray(domain), range())); - } - - Term^ MkNumeral(String^ numeral, Sort^ ty) { - return gcnew Term(m_ctx,m_ctx->MkNumeral(numeral, ty())); - } - Term^ MkNumeral(int n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); } - Term^ MkNumeral(unsigned n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); } - Term^ MkNumeral(__int64 n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); } - Term^ MkNumeral(unsigned __int64 n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); } - - Term^ MkIntNumeral(String^ n) { return MkNumeral(n, MkIntSort()); } - Term^ MkIntNumeral(int n) { return MkNumeral(n, MkIntSort()); } - Term^ MkIntNumeral(unsigned n) { return MkNumeral(n, MkIntSort()); } - Term^ MkIntNumeral(__int64 n) { return MkNumeral(n, MkIntSort()); } - Term^ MkIntNumeral(unsigned __int64 n) { return MkNumeral(n, MkIntSort()); } - - Term^ MkRealNumeral(String^ n) { return MkNumeral(n, MkRealSort()); } - Term^ MkRealNumeral(int n) { return MkNumeral(n, MkRealSort()); } - Term^ MkRealNumeral(unsigned n) { return MkNumeral(n, MkRealSort()); } - Term^ MkRealNumeral(__int64 n) { return MkNumeral(n, MkRealSort()); } - Term^ MkRealNumeral(unsigned __int64 n) { return MkNumeral(n, MkRealSort()); } - - Pattern^ MkPattern(array^ terms) { return gcnew Pattern(m_ctx,m_ctx->MkPattern(CopyArray(terms))); } - Term^ MkBound(unsigned index, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkBound(index, ty())); } - - Term^ MkForall( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkForall(weight, CopyArray(patterns), CopyArray(types), names, body())); - } - - Term^ MkForall( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkForall(weight, CopyArray(patterns), CopyArray(types), names, body())); - } - - Term^ MkForall( - unsigned weight, - array^ bound, - array^ patterns, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkForall(weight, CopyArray(bound), CopyArray(patterns), body())); - } - - - Term^ MkExists( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkExists(weight, CopyArray(patterns), CopyArray(types), names, body())); - } - - Term^ MkExists( - unsigned weight, - array^ patterns, - array^ types, - array^ names, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkExists(weight, CopyArray(patterns), CopyArray(types), names, body())); - } - - Term^ MkExists( - unsigned weight, - array^ bound, - array^ patterns, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkExists(weight, CopyArray(bound), CopyArray(patterns), body())); - } - - - - Term^ MkQuantifier( - bool is_forall, - unsigned weight, - array^ patterns, - array^ no_patterns, - array^ types, - array^ names, - Term^ body - ) { - return MkQuantifier(is_forall, weight, nullptr, nullptr, patterns, no_patterns, types, names, body); - } - - Term^ MkQuantifier( - bool is_forall, - unsigned weight, - Symbol^ quantifier_id, - Symbol^ skolem_id, - array^ patterns, - array^ no_patterns, - array^ types, - array^ names, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkQuantifier( - is_forall, weight, - quantifier_id, skolem_id, - CopyArray(patterns), - CopyArray(no_patterns), - CopyArray(types), - names, - body())); - } - - Term^ MkQuantifier( - bool is_forall, - unsigned weight, - Symbol^ quantifier_id, - Symbol^ skolem_id, - array^ patterns, - array^ no_patterns, - array^ bound, - Term^ body - ) { - return gcnew Term(m_ctx,m_ctx->MkQuantifier( - is_forall, weight, - quantifier_id, skolem_id, - CopyArray(patterns), - CopyArray(no_patterns), - CopyArray(bound), - body())); - } - - SymbolKind GetSymbolKind(Symbol^ s) { return m_ctx->GetSymbolKind(s); } - int GetSymbolInt(Symbol^ s) { return m_ctx->GetSymbolInt(s); } - String^ GetSymbolString(Symbol^ s) { return m_ctx->GetSymbolString(s); } - bool IsEq(Term^ t1, Term^ t2) { return m_ctx->IsEq(t1(), t2()); } - bool IsWellSorted(Term^ t) { return m_ctx->IsWellSorted(t()); } - TermKind GetTermKind(Term^ a) { return m_ctx->GetTermKind(a()); } - DeclKind GetDeclKind(FuncDecl^ d) { return m_ctx->GetDeclKind(d()); } - array^ GetDeclParameters(FuncDecl^ d); - FuncDecl^ GetAppDecl(Term^ a) { return gcnew FuncDecl(m_ctx,m_ctx->GetAppDecl(a())); } - array^ GetAppArgs(Term^ a) { return CopyTermArray(m_ctx->GetAppArgs(a())); } - String^ GetNumeralString(Term^ a) { return m_ctx->GetNumeralString(a()); } - int GetNumeralInt(Term^ v) { return m_ctx->GetNumeralInt(v()); } - bool TryGetNumeralInt(Term^ v, [Out] int% i) { return m_ctx->TryGetNumeralInt(v(), i); } - unsigned int GetNumeralUInt(Term^ v) { return m_ctx->GetNumeralUInt(v()); } - bool TryGetNumeralUInt(Term^ v, [Out] unsigned int% u) { return m_ctx->TryGetNumeralUInt(v(), u); } - __int64 GetNumeralInt64(Term^ v) { return m_ctx->GetNumeralInt64(v()); } - bool TryGetNumeralInt64(Term^ v, [Out] __int64% i) { return m_ctx->TryGetNumeralInt64(v(), i); } - unsigned __int64 GetNumeralUInt64(Term^ v) { return m_ctx->GetNumeralUInt64(v()); } - bool TryGetNumeralUInt64(Term^ v, [Out] unsigned __int64% u) { return m_ctx->TryGetNumeralUInt64(v(), u); } - bool TryGetNumeral(Term^ v, [Out] __int64% num, [Out] __int64% den) { return m_ctx->TryGetNumeral(v(), num, den); } - void GetNumeral(Term^ v, [Out] System::Numerics::BigInteger% num, [Out] System::Numerics::BigInteger% den) { - m_ctx->GetNumeral(v(), num, den); - } - - LBool GetBoolValue(Term^ v) { return m_ctx->GetBoolValue(v()); } - - unsigned GetVarIndex(Term^ a) { return m_ctx->GetVarIndex(a()); } - Quantifier^ GetQuantifier(Term^ a) { return GetQuantifier(m_ctx, a); } - - array^ GetPatternTerms(Pattern^ p) { return CopyTermArray(m_ctx->GetPatternTerms(p())); } - Symbol^ GetDeclName(FuncDecl^ d) { return m_ctx->GetDeclName(d()); } - Symbol^ GetSortName(Sort^ ty) { return m_ctx->GetSortName(ty()); } - Sort^ GetSort(Term^ a) { return gcnew Sort(m_ctx,m_ctx->GetSort(a())); } - array^ GetDomain(FuncDecl^ d) { return CopySortArray(m_ctx->GetDomain(d())); } - Sort^ GetRange(FuncDecl^ d) { return gcnew Sort(m_ctx,m_ctx->GetRange(d())); } - SortKind GetSortKind(Sort^ t) { return m_ctx->GetSortKind(t()); } - unsigned GetBvSortSize(Sort^ t) { return m_ctx->GetBvSortSize(t()); } - Sort^ GetArraySortDomain(Sort^ t) { return gcnew Sort(m_ctx,m_ctx->GetArraySortDomain(t())); } - Sort^ GetArraySortRange(Sort^ t) { return gcnew Sort(m_ctx,m_ctx->GetArraySortRange(t())); } - FuncDecl^ GetTupleConstructor(Sort^ t) { return gcnew FuncDecl(m_ctx,m_ctx->GetTupleConstructor(t())); } - array^ GetTupleFields(Sort^ t) { return CopyFuncDeclArray(m_ctx->GetTupleFields(t())); } - - Theory^ MkTheory(String^ name); - - void RegisterRelation(FuncDecl^ r) { m_ctx->RegisterRelation(r()); } - - void AddRule(Term^ rule, Symbol^ name) { m_ctx->AddRule(rule(), name); } - - LBool Query(Term^ query) { return m_ctx->Query(query()); } - - String^ GetQueryStatus() { return m_ctx->GetQueryStatus(); } - - Term^ GetQueryAnswer() { return gcnew Term(m_ctx, m_ctx->GetQueryAnswer()); } - - String^ FixedpointkToString(array^ queries) { - return m_ctx->FixedpointToString(CopyArray(queries)); - } - array^ SimplifyFixedpointRules(array^ rules, array^ output_predicates) { - return CopyTermArray(m_ctx->SimplifyFixedpointRules(CopyArray(rules), CopyArray(output_predicates))); - } - // functions for creating custom Fixedpoint relations. - - private: - Action3^, array^>^ m_assign_callback; - void AssignCallbackAux(FuncDeclPtr f, array^ args, array^ outs) { - m_assign_callback(gcnew FuncDecl(m_ctx, f), CopyAstArray(args), CopyAstArray(outs)); - } - Func2^, Term^>^ m_apply_callback; - TermPtr ApplyCallbackAux(FuncDeclPtr f, array^ args) { - return m_apply_callback(gcnew FuncDecl(m_ctx, f), CopyAstArray(args))(); - } - public: - property Action3^, array^>^ FixedpointAssign { - void set(Action3^, array^>^ value) { - m_assign_callback = value; - m_ctx->FixedpointAssign = gcnew Action3^, array^>(this,&Context::AssignCallbackAux); - } - } - property Func2^, Term^>^ FixedpointApply { - void set(Func2^, Term^>^ value) { - m_apply_callback = value; - m_ctx->FixedpointApply = gcnew Func2^, TermPtr>(this,&Context::ApplyCallbackAux); - } - } - }; - - public ref class FunctionEntry { - public: - array^ Arguments; - Term^ Result; - }; - - public ref class FunctionGraph { - public: - FuncDecl^ Declaration; - array^ Entries; - Term^ Else; - }; - - - public ref class Model { - RawModel^ m_model; - Context^ m_ctx; - - ArrayValue^ Mk(RawArrayValue^ av); - FunctionEntry^ Mk(RawFunctionEntry^ fe); - FunctionGraph^ Mk(RawFunctionGraph^ fg); - Dictionary^ Mk(Dictionary^ fgs); - - internal: - property Context^ GetContext { Context^ get() { return m_ctx; }} - property RawModel^ GetModel { RawModel^ get() { return m_model; }} - - Model(RawModel^ m, Context^ c) : m_model(m), m_ctx(c) {} - - public: - ~Model() { m_model->Reset(); } - - array^ GetModelConstants() { - return m_ctx->CopyFuncDeclArray(m_model->GetModelConstants()); - } - - bool TryGetArrayValue(Term^ a, [Out] ArrayValue^% av); - - Dictionary^ GetFunctionGraphs() { return Mk(m_model->GetFunctionGraphs()); } - - Term^ Eval(Term^ t) { return gcnew Term(m_ctx->GetContext, m_model->Eval(t())); } - - Term^ Eval(FuncDecl^ d, array^ args) { - return gcnew Term(m_ctx->GetContext, m_model->Eval(d(), m_ctx->CopyArray(args))); - } - - void Display(System::IO::TextWriter^ w) { m_model->Display(w); } - - }; - - public ref class Theory - { - Context^ m_context; - RawTheory^ m_theory; - - public: - property String^ Name { String^ get() { return m_theory->Name; } } - - internal: - Theory(Context^ ctx, String^ name) - { - m_context = ctx; - m_theory = gcnew RawTheory(ctx->GetContext->ref_context(), name); - } - - private: - array^ MkTerms(array^ ts) - { - return m_context->CopyAstArray(ts); - } - Term^ MkTerm(TermPtr t) { return gcnew Term(m_context->GetContext, t); } - FuncDecl^ MkFuncDecl(FuncDeclPtr f) { return gcnew FuncDecl(m_context->GetContext, f); } - - TermPtr GetTermPtr(Term^ t) - { - if (t) return t(); - return IntPtr::Zero; - } - - public: - property Action0^ DeleteHandler - { - void set(Action0^ value) - { - m_theory->DeleteHandler = value; - } - } - private: - Func2^ reduce_eq; - TermPtr ReduceEqAux(TermPtr a, TermPtr b) { - return GetTermPtr(reduce_eq(MkTerm(a), MkTerm(b))); - } - public: - property Func2^ ReduceEq - { - void set(Func2^ value) - { - reduce_eq = value; - m_theory->ReduceEq = gcnew Func2(this,&Theory::ReduceEqAux); - } - } - private: - Func2^, Term^>^ reduce_app; - TermPtr ReduceAppAux(FuncDeclPtr a, array^ b) { - return GetTermPtr(reduce_app(MkFuncDecl(a), MkTerms(b))); - } - public: - property Func2^, Term^>^ ReduceApp - { - void set(Func2^, Term^>^ value) - { - reduce_app = value; - m_theory->ReduceApp = gcnew Func2^,TermPtr>(this,&Theory::ReduceAppAux); - } - } - private: - Func1^, Term^>^ reduce_distinct; - TermPtr ReduceDistinctAux(array^ args) { - return GetTermPtr(reduce_distinct(MkTerms(args))); - } - - public: - property Func1^, Term^>^ ReduceDistinct - { - void set(Func1^, Term^>^ value) - { - reduce_distinct = value; - m_theory->ReduceDistinct = gcnew Func1^,TermPtr>(this, &Theory::ReduceDistinctAux); - } - } - private: - Action^ new_app; - void NewAppAux(TermPtr a) { return new_app(MkTerm(a)); } - public: - property Action^ NewApp - { - void set(Action^ value) - { - new_app = value; - m_theory->NewApp = gcnew Action(this, &Theory::NewAppAux); - } - } - private: - Action^ new_elem; - void NewElemAux(TermPtr a) { return new_elem(MkTerm(a)); } - public: - property Action^ NewElem - { - void set(Action^ value) - { - new_elem = value; - m_theory->NewElem = gcnew Action(this, &Theory::NewElemAux); - } - } - property Action0^ InitSearch - { - void set(Action0^ value) - { - m_theory->InitSearch = value; - } - } - property Action0^ Push - { - void set(Action0^ value) - { - m_theory->Push = value; - } - } - property Action0^ Pop - { - void set(Action0^ value) - { - m_theory->Pop = value; - } - } - property Action0^ Reset - { - void set(Action0^ value) - { - m_theory->Reset = value; - } - } - property Action0^ Restart - { - void set(Action0^ value) - { - m_theory->Restart = value; - } - } - - property Func0^ FinalCheck - { - void set(Func0^ value) - { - m_theory->FinalCheck = value; - } - } - private: - Action2^ new_eq; - void NewEqAux(TermPtr a, TermPtr b) { - new_eq(MkTerm(a), MkTerm(b)); - } - public: - property Action2^ NewEq - { - void set(Action2^ value) - { - new_eq = value; - m_theory->NewEq = gcnew Action2(this, &Theory::NewEqAux); - } - } - private: - Action2^ new_diseq; - void NewDiseqAux(TermPtr a, TermPtr b) { - new_diseq(MkTerm(a), MkTerm(b)); - } - public: - property Action2^ NewDiseq - { - void set(Action2^ value) - { - new_diseq = value; - m_theory->NewDiseq = gcnew Action2(this, &Theory::NewDiseqAux); - } - } - private: - Action2^ new_assignment; - void NewAssignmentAux(TermPtr a, bool b) { - new_assignment(MkTerm(a), b); - } - public: - property Action2^ NewAssignment - { - void set(Action2^ value) - { - new_assignment = value; - m_theory->NewAssignment = gcnew Action2(this, &Theory::NewAssignmentAux); - } - } - private: - Action^ new_relevant; - void NewRelevantAux(TermPtr a) { new_relevant(MkTerm(a)); } - public: - property Action^ NewRelevant - { - void set(Action^ value) { - new_relevant = value; - m_theory->NewRelevant = gcnew Action(this, &Theory::NewRelevantAux); - } - } - - void AssertTheoryAxiom(Term^ ax) - { - m_theory->AssertTheoryAxiom(ax()); - } - - void AssumeEq(Term^ lhs, Term^ rhs) - { - m_theory->AssumeEq(lhs(), rhs()); - } - - - void EnableTheoryAxiomSimplification(bool flag) - { - m_theory->EnableTheoryAxiomSimplification(flag); - } - - Term^ GetEqcRoot(Term^ n) - { - return MkTerm(m_theory->GetEqcRoot(n())); - } - - Term^ GetEqcNext(Term^ n) - { - return MkTerm(m_theory->GetEqcNext(n())); - } - - array^ GetParents(Term^ n) - { - return MkTerms(m_theory->GetParents(n())); - } - - bool IsTheoryValue(Term^ a) - { - return m_theory->IsTheoryValue(a()); - } - - bool IsTheoryDecl(FuncDecl^ d) - { - return m_theory->IsTheoryDecl(d()); - } - - array^ GetElems() - { - return MkTerms(m_theory->GetElems()); - } - - array^ GetApps() - { - return MkTerms(m_theory->GetApps()); - } - - - Sort^ MkSort(Symbol^ s) - { - return gcnew Sort(m_context->GetContext,m_theory->MkSort(s)); - } - - Term^ MkValue(Symbol^ s, Sort^ srt) - { - return MkTerm(m_theory->MkValue(s, srt())); - } - - Term^ MkConstant(Symbol^ s, Sort^ srt) - { - return MkTerm(m_theory->MkConstant(s, srt())); - } - - FuncDecl^ MkFuncDecl(Symbol^ n, array^ domain, Sort^ range) - { - array^ dom = gcnew array(domain->Length); - for (int i = 0; i < domain->Length; ++i) dom[i] = domain[i](); - return gcnew FuncDecl(m_context->GetContext, m_theory->MkFuncDecl(n, dom, range())); - } - - Sort^ MkSort(String^ s) - { - return gcnew Sort(m_context->GetContext,m_theory->MkSort(s)); - } - - Term^ MkValue(String^ s, Sort^ srt) - { - return MkTerm(m_theory->MkValue(s, srt())); - } - - Term^ MkConstant(String^ s, Sort^ srt) - { - return MkTerm(m_theory->MkConstant(s, srt())); - } - - FuncDecl^ MkFuncDecl(String^ n, array^ domain, Sort^ range) - { - return this->MkFuncDecl(m_context->MkSymbol(n), domain, range); - } - - - }; - - -/*@}*/ - -}; -}; - -#endif diff --git a/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.vcxproj b/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.vcxproj deleted file mode 100644 index 506e0e17d..000000000 --- a/src/api/dotnet/dead/Microsoft.Z3V3/Microsoft.Z3V3.vcxproj +++ /dev/null @@ -1,555 +0,0 @@ - - - - - commercial - Win32 - - - commercial - x64 - - - Debug - Win32 - - - Debug - x64 - - - external - Win32 - - - external - x64 - - - release_mt - Win32 - - - release_mt - x64 - - - Release - Win32 - - - Release - x64 - - - Trace - Win32 - - - Trace - x64 - - - - {F008F2C4-D652-4A58-8DEF-DB83E2355454} - Microsoft.Z3V3 - ManagedCProj - Microsoft.Z3V3 - - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - true - - - Application - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - true - - - DynamicLibrary - Unicode - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false - false - AllRules.ruleset - - - AllRules.ruleset - - - - AllRules.ruleset - AllRules.ruleset - - - - - AllRules.ruleset - AllRules.ruleset - - - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - WIN32;_DEBUG;Z3DEBUG;_WINDOWS;_TRACE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - - - Level3 - ProgramDatabase - - - $(OutDir)Microsoft.Z3V3.dll - true - true - false - - - MachineX86 - - - - - - - - - X64 - - - Disabled - WIN32;_DEBUG;_WINDOWS;_TRACE;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - - - Level3 - ProgramDatabase - - - $(OutDir)Microsoft.Z3V3.dll - true - true - MachineX64 - - - - - - - - - false - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - false - - - MachineX86 - - - - - - - - - X64 - - - false - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - MachineX64 - - - - - - - - - false - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - false - - - MachineX86 - - - - - - - - - X64 - - - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - MachineX64 - - - - - - - - - false - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - false - - - MachineX86 - - - - - - - - - false - WIN32;NDEBUG;_WINDOWS;_EXTERNAL_RELEASE;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - false - - - MachineX86 - true - - - - - - - - - false - WIN32;NDEBUG;_WINDOWS;_Z3_COMMERCIAL;_EXTERNAL_RELEASE;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - false - - - MachineX86 - - - - - - - - - X64 - - - false - WIN32;NDEBUG;_WINDOWS;_EXTERNAL_RELEASE;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - MachineX64 - true - - - - - - - - - X64 - - - false - WIN32;NDEBUG;_WINDOWS;_Z3_COMMERCIAL;_AMD64_;_EXTERNAL_RELEASE;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - - - $(OutDir)Microsoft.Z3V3.dll - true - MachineX64 - - - - - - - - - - - - - - - - - true - true - - - true - true - - - - true - true - - - - - - - - - - - - {4a7e5a93-19d8-4382-8950-fb2edec7a76e} - false - - - - - - \ No newline at end of file diff --git a/src/api/python/z3poly.py b/src/api/python/z3poly.py deleted file mode 100644 index f8e6eb1f7..000000000 --- a/src/api/python/z3poly.py +++ /dev/null @@ -1,67 +0,0 @@ -############################################ -# Copyright (c) 2012 Microsoft Corporation -# -# Z3 Polynomial interface -# -# Author: Leonardo de Moura (leonardo) -############################################ -from z3 import * - -class PolynomialManager: - """Polynomial Manager. - """ - def __init__(self, ctx=None): - self.ctx = z3._get_ctx(ctx) - self.manager = Z3_mk_polynomial_manager(self.ctx_ref()) - - def __del__(self): - Z3_del_polynomial_manager(self.ctx_ref(), self.manager) - - def ctx_ref(self): - return self.ctx.ref() - - def m(self): - return self.manager - -_main_pmanager = None -def main_pmanager(): - """Return a reference to the global Polynomial manager. - """ - global _main_pmanager - if _main_pmanager == None: - _main_pmanager = PolynomialManager() - return _main_pmanager - -def _get_pmanager(ctx): - if ctx == None: - return main_pmanager() - else: - return ctx - -class Polynomial: - """Multivariate polynomials. - """ - def __init__(self, poly=None, m=None): - self.pmanager = _get_pmanager(m) - if poly == None: - self.poly = Z3_mk_zero_polynomial(self.ctx_ref(), self.m()) - else: - self.poly = poly - Z3_polynomial_inc_ref(self.ctx_ref(), self.m(), self.poly) - - def __del__(self): - Z3_polynomial_dec_ref(self.ctx_ref(), self.m(), self.poly) - - def m(self): - return self.pmanager.m() - - def ctx_ref(self): - return self.pmanager.ctx_ref() - - def __repr__(self): - return Z3_polynomial_to_string(self.ctx_ref(), self.m(), self.poly) - -# test -p = Polynomial() -print p - diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 879f8f4d3..c6fa7718c 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -27,6 +27,7 @@ Notes: #include"cmd_util.h" #include"simplify_cmd.h" #include"eval_cmd.h" +#include"front_end_params.h" class help_cmd : public cmd { svector m_cmds; diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index e9a613d4e..c56066827 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -348,6 +348,18 @@ cmd_context::~cmd_context() { } } +bool cmd_context::is_smtlib2_compliant() const { + return params().m_smtlib2_compliant; +} + +bool cmd_context::produce_models() const { + return params().m_model; +} + +bool cmd_context::produce_proofs() const { + return params().m_proof_mode != PGM_DISABLED; +} + cmd_context::check_sat_state cmd_context::cs_state() const { if (m_check_sat_result.get() == 0) return css_clear; diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index efbfbfb75..9296f0735 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -249,7 +249,7 @@ protected: public: cmd_context(front_end_params * params = 0, bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null); ~cmd_context(); - bool is_smtlib2_compliant() const { return params().m_smtlib2_compliant; } + bool is_smtlib2_compliant() const; void set_logic(symbol const & s); bool has_logic() const { return m_logic != symbol::null; } symbol const & get_logic() const { return m_logic; } @@ -269,8 +269,8 @@ public: void set_global_decls(bool flag) { SASSERT(!has_manager()); m_global_decls = flag; } unsigned random_seed() const { return m_random_seed; } void set_random_seed(unsigned s) { m_random_seed = s; } - bool produce_models() const { return params().m_model; } - bool produce_proofs() const { return params().m_proof_mode != PGM_DISABLED; } + bool produce_models() const; + bool produce_proofs() const; bool produce_unsat_cores() const { return m_produce_unsat_cores; } void set_produce_unsat_cores(bool flag) { m_produce_unsat_cores = flag; } bool produce_assignments() const { return m_produce_assignments; } diff --git a/src/cmd_context/solver.h b/src/cmd_context/solver.h deleted file mode 100644 index 373f878bb..000000000 --- a/src/cmd_context/solver.h +++ /dev/null @@ -1,61 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - solver.h - -Abstract: - - abstract solver interface - -Author: - - Leonardo (leonardo) 2011-03-19 - -Notes: - ---*/ -#ifndef _SOLVER_H_ -#define _SOLVER_H_ - -#include"check_sat_result.h" -#include"front_end_params.h" -#include"progress_callback.h" -#include"params.h" - -class solver : public check_sat_result { -public: - virtual ~solver() {} - - // for backward compatibility - virtual void set_front_end_params(front_end_params & p) {} - - virtual void updt_params(params_ref const & p) {} - virtual void collect_param_descrs(param_descrs & r) {} - - virtual void set_produce_proofs(bool f) {} - virtual void set_produce_models(bool f) {} - virtual void set_produce_unsat_cores(bool f) {} - - virtual void init(ast_manager & m, symbol const & logic) = 0; - virtual void reset() = 0; - virtual void assert_expr(expr * t) = 0; - virtual void push() = 0; - virtual void pop(unsigned n) = 0; - virtual unsigned get_scope_level() const = 0; - virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) = 0; - - virtual void set_cancel(bool f) {} - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - virtual void set_progress_callback(progress_callback * callback) = 0; - - virtual unsigned get_num_assertions() const; - virtual expr * get_assertion(unsigned idx) const; - - virtual void display(std::ostream & out) const; -}; - -#endif diff --git a/src/cmd_context/strategic_solver_cmd.cpp b/src/cmd_context/strategic_solver_cmd.cpp new file mode 100644 index 000000000..3bb820e0d --- /dev/null +++ b/src/cmd_context/strategic_solver_cmd.cpp @@ -0,0 +1,34 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + strategic_solver_cmd.h + +Abstract: + + Specialization of the strategic solver that + used cmd_context to access the assertion set. + +Author: + + Leonardo (leonardo) 2012-11-01 + +Notes: + +--*/ +#include"strategic_solver_cmd.h" +#include"cmd_context.h" + +strategic_solver_cmd::strategic_solver_cmd(cmd_context & ctx): + m_ctx(ctx) { +} + +unsigned strategic_solver_cmd::get_num_assertions() const { + return static_cast(m_ctx.end_assertions() - m_ctx.begin_assertions()); +} + +expr * strategic_solver_cmd::get_assertion(unsigned idx) const { + SASSERT(idx < get_num_assertions()); + return m_ctx.begin_assertions()[idx]; +} diff --git a/src/cmd_context/strategic_solver_cmd.h b/src/cmd_context/strategic_solver_cmd.h new file mode 100644 index 000000000..014d2dee6 --- /dev/null +++ b/src/cmd_context/strategic_solver_cmd.h @@ -0,0 +1,40 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + strategic_solver_cmd.h + +Abstract: + + Specialization of the strategic solver that + used cmd_context to access the assertion set. + +Author: + + Leonardo (leonardo) 2012-11-01 + +Notes: + +--*/ +#ifndef _STRATEGIC_SOLVER_CMD_H_ +#define _STRATEGIC_SOLVER_CMD_H_ + +#include"strategic_solver.h" + +class cmd_context; + +/** + Specialization for the SMT 2.0 command language frontend. + + The strategic solver does not have to maintain a copy of the assertion set in the cmd_context. +*/ +class strategic_solver_cmd : public strategic_solver_core { + cmd_context & m_ctx; +public: + strategic_solver_cmd(cmd_context & ctx); + virtual unsigned get_num_assertions() const; + virtual expr * get_assertion(unsigned idx) const; +}; + +#endif diff --git a/src/dead/array_property/array_property_expander.cpp b/src/dead/array_property/array_property_expander.cpp deleted file mode 100644 index 4b1d8b002..000000000 --- a/src/dead/array_property/array_property_expander.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - array_property_expander.cpp - -Abstract: - - Expand array operations for the array property fragment formulas. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-16-12 - -Revision History: - ---*/ - -#include"array_property_expander.h" -#include"obj_hashtable.h" -#include"var_subst.h" -#include"array_decl_plugin.h" -#include"for_each_expr.h" - -array_property_expander::array_property_expander(ast_manager& m): - m_manager(m) { -} - -namespace array_property_exp { - class proc { - ast_manager& m_manager; - unsigned& m_offset; - expr_ref_vector m_trail; - family_id m_fid; - array_util m_util; - obj_map m_mem; - - - void insert(expr* a, expr* b) { - m_trail.push_back(b); - m_mem.insert(a, b); - } - - - public: - proc(ast_manager& m, unsigned& offset) : - m_manager(m), - m_offset(offset), - m_trail(m), - m_fid(m.get_family_id("array")), - m_util(m) - {} - - expr* find(expr* e) { - expr* result = 0; - VERIFY(m_mem.find(e, result)); - return result; - } - - void operator()(var* n) { insert(n, n); } - - void operator()(quantifier* q) { - expr* e = find(q->get_expr()); - quantifier* q2 = m_manager.update_quantifier(q, e); - insert(q, q2); - } - - void operator()(app* n) { - ast_manager& m = m_manager; - unsigned num_args = n->get_num_args(); - ptr_buffer args; - for (unsigned i = 0; i < num_args; ++i) { - args.push_back(find(n->get_arg(i))); - } - if (m_manager.is_eq(n) && m_util.is_array(args[0])) { - visit_eq(n); - return; - } - if (m_manager.is_distinct(n) && num_args > 0 && m_util.is_array(args[0])) { - ptr_buffer eqs; - for (unsigned i = 0; i < num_args; ++i) { - for (unsigned j = i + 1; j < num_args; ++j) { - eqs.push_back(m.mk_not(m.mk_eq(args[i], args[j]))); - } - } - insert(n, m.mk_and(eqs.size(), eqs.c_ptr())); - return; - } - - if (m_util.is_select(n)) { - SASSERT(num_args > 0); - - // select(store(A,i,v),j) -> ite(i = j, v, select(A,j)) - if (m_util.is_store(args[0])) { - app* a = to_app(args[0]); - expr* b = find(a->get_arg(0)); - expr* v = find(a->get_arg(a->get_num_args()-1)); - ptr_buffer eqs; - SASSERT(num_args + 1 == a->get_num_args()); - for (unsigned i = 1; i < num_args; ++i) { - eqs.push_back(m.mk_eq(args[i], find(a->get_arg(i)))); - } - expr* r = m.mk_ite(m.mk_and(eqs.size(), eqs.c_ptr()), v, mk_select(b, num_args-1, args.c_ptr()+1)); - insert(n, r); - return; - } - - // select(ite(a,b,c),i) -> ite(a, select(b,i), select(c, i)) - if (m.is_ite(args[0])) { - app* k = to_app(args[0]); - expr* a = k->get_arg(0); - expr* b = mk_select(k->get_arg(1), args.size()-1, args.c_ptr()+1); - expr* c = mk_select(k->get_arg(2), args.size()-1, args.c_ptr()+1); - expr* r = m.mk_ite(a, b, c); - insert(n, r); - return; - } - - // select(map_f(A,B),i) -> f(select(A,i), select(B,i)) - if (m_util.is_map(args[0])) { - app* a = to_app(args[0]); - func_decl* f = a->get_decl(); - SASSERT(f->get_num_parameters() == 1); - SASSERT(f->get_parameter(0).is_ast()); - SASSERT(is_func_decl(f->get_parameter(0).get_ast())); - parameter p = f->get_parameter(0); - func_decl* d = to_func_decl(p.get_ast()); - ptr_buffer args2; - for (unsigned i = 0; i < a->get_num_args(); ++i) { - args2.push_back(mk_select(find(a->get_arg(i)), args.size()-1, args.c_ptr()+1)); - } - expr* r = m.mk_app(d, args2.size(), args2.c_ptr()); - insert(n, r); - return; - } - - // select(const v, i) -> v - if (m_util.is_const(args[0])) { - insert(n, to_app(args[0])->get_arg(0)); - return; - } - } - expr* r = m_manager.mk_app(n->get_decl(), args.size(), args.c_ptr()); - insert(n, r); - } - - private: - void visit_eq(app* eq) { - ast_manager& m = m_manager; - SASSERT(m.is_eq(eq)); - sort* s = m.get_sort(eq->get_arg(0)); - SASSERT(is_sort_of(s, m_fid, ARRAY_SORT)); - // sort* rng = get_array_range(s); - unsigned arity = get_array_arity(s); - shift_vars sh(m); - expr_ref e1(m), e2(m); - sh(find(eq->get_arg(0)), arity, e1); - sh(find(eq->get_arg(1)), arity, e2); - expr_ref_vector args(m); - buffer names; - ptr_buffer sorts; - args.push_back(e1); - for (unsigned i = 0; i < arity; ++i) { - args.push_back(m.mk_var(i, get_array_domain(s, i))); - sorts.push_back(get_array_domain(s, arity - i - 1)); - names.push_back(symbol(m_offset++)); - } - e1 = mk_select(args.size(), args.c_ptr()); - args[0] = e2; - e2 = mk_select(args.size(), args.c_ptr()); - e1 = m.mk_eq(e1, e2); - - e1 = m.mk_quantifier(true, arity, sorts.c_ptr(), names.c_ptr(), e1, 1); - insert(eq, e1); - } - - app* mk_select(unsigned n, expr* const* args) { - return m_manager.mk_app(m_fid, OP_SELECT, 0, 0, n, args); - } - - app* mk_select(expr* a, unsigned n, expr* const* args) { - ptr_buffer args2; - args2.push_back(a); - args2.append(n, args); - return mk_select(n+1, args2.c_ptr()); - } - }; -}; - -void array_property_expander::operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result) { - ast_manager& m = m_manager; - unsigned offset = 0; - for (unsigned i = 0; i < num_fmls; ++i) { - bool change = false; - expr_ref e(m); - result.push_back(fmls[i]); - do { - array_property_exp::proc p(m, offset); - e = result[i].get(); - for_each_expr(p, e); - result[i] = p.find(e); - change = e != result[i].get(); - } - while (change); - } -} - diff --git a/src/dead/array_property/array_property_expander.h b/src/dead/array_property/array_property_expander.h deleted file mode 100644 index 69b2d2ecd..000000000 --- a/src/dead/array_property/array_property_expander.h +++ /dev/null @@ -1,33 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - array_property_expander.h - -Abstract: - - Expand array operations for the array property fragment formulas. - -Author: - - Nikolaj Bjorner (nbjorner) 2010-16-12 - -Revision History: - ---*/ -#ifndef _ARRAY_PROPERTY_EXPANDER_H_ -#define _ARRAY_PROPERTY_EXPANDER_H_ - -#include"ast.h" - -class array_property_expander { - ast_manager& m_manager; -public: - array_property_expander(ast_manager& m); - void operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result); -}; - - -#endif /* _ARRAY_PROPERTY_EXPANDER_H_ */ - diff --git a/src/dead/array_property/array_property_recognizer.cpp b/src/dead/array_property/array_property_recognizer.cpp deleted file mode 100644 index 402e29b07..000000000 --- a/src/dead/array_property/array_property_recognizer.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - array_property_recognizer.cpp - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-16-12 - -Revision History: - ---*/ - -#include"array_decl_plugin.h" -#include"array_property_recognizer.h" -#include"for_each_expr.h" - - -array_property_recognizer::array_property_recognizer(ast_manager& m): - m_manager(m) {} - -namespace is_array_property_ns { - struct bad {}; - class proc { - ast_manager& m_manager; - family_id m_fid; - bool m_has_quantifier; - - void check_array_sort(expr* n) { - if (is_sort_of(m_manager.get_sort(n), m_fid, ARRAY_SORT)) { - throw bad(); - } - } - - public: - proc(ast_manager& m) : - m_manager(m), - m_fid(m.get_family_id("array")), - m_has_quantifier(false) {} - - bool has_quantifier() const { return m_has_quantifier; } - - void operator()(var* n) { - check_array_sort(n); - } - - void operator()(quantifier * ) { - m_has_quantifier = true; - } - - void operator()(app* n) { - unsigned num_args = n->get_num_args(); - if (m_manager.is_eq(n) || m_manager.is_distinct(n)) { - return; - } - family_id fid = n->get_family_id(); - if (fid == m_fid) { - switch(n->get_decl_kind()) { - case OP_STORE: - for (unsigned i = 1; i + 1 < num_args; ++i) { - check_array_sort(n->get_arg(i)); - } - return; - case OP_SELECT: - for (unsigned i = 1; i < num_args; ++i) { - check_array_sort(n->get_arg(i)); - } - return; - case OP_CONST_ARRAY: - case OP_ARRAY_MAP: - return; - default: - throw bad(); - } - } - // arrays cannot be arguments of other functions. - for (unsigned i = 0; i < num_args; ++i) { - check_array_sort(n->get_arg(i)); - } - } - }; -}; - -bool array_property_recognizer::operator()(unsigned num_fmls, expr* const* fmls) { - is_array_property_ns::proc p(m_manager); - try { - for (unsigned i = 0; i < num_fmls; ++i) { - for_each_expr(p, fmls[i]); - } - } - catch (is_array_property_ns::bad) { - return false; - } - return p.has_quantifier(); -} - - diff --git a/src/dead/array_property/array_property_recognizer.h b/src/dead/array_property/array_property_recognizer.h deleted file mode 100644 index 5c20f17da..000000000 --- a/src/dead/array_property/array_property_recognizer.h +++ /dev/null @@ -1,33 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - array_property_recognizer.h - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-16-12 - -Revision History: - ---*/ -#ifndef _ARRAY_PROPERTY_RECOGNIZER_H_ -#define _ARRAY_PROPERTY_RECOGNIZER_H_ - -#include"ast.h" - -class array_property_recognizer { - ast_manager& m_manager; -public: - array_property_recognizer(ast_manager& m); - bool operator()(unsigned num_fmls, expr* const* fmls); -}; - - -#endif /* _ARRAY_PROPERTY_RECOGNIZER_H_ */ - diff --git a/src/dead/assertion_stack.cpp b/src/dead/assertion_stack.cpp deleted file mode 100644 index 85bfb057c..000000000 --- a/src/dead/assertion_stack.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - assertion_stack.cpp - -Abstract: - - Assertion stacks - -Author: - - Leonardo de Moura (leonardo) 2012-02-17 - -Revision History: - ---*/ -#include"assertion_stack.h" -#include"well_sorted.h" -#include"ast_smt2_pp.h" -#include"ref_util.h" - -assertion_stack::assertion_stack(ast_manager & m, bool models_enabled, bool core_enabled): - m_manager(m), - m_forbidden(m), - m_csubst(m, core_enabled), - m_fsubst(m, core_enabled) { - init(m.proofs_enabled(), models_enabled, core_enabled); -} - -assertion_stack::assertion_stack(ast_manager & m, bool proofs_enabled, bool models_enabled, bool core_enabled): - m_manager(m), - m_forbidden(m), - m_csubst(m, core_enabled, proofs_enabled), - m_fsubst(m, core_enabled, proofs_enabled) { - init(proofs_enabled, models_enabled, core_enabled); -} - -void assertion_stack::init(bool proofs_enabled, bool models_enabled, bool core_enabled) { - m_ref_count = 0; - m_models_enabled = models_enabled; - m_proofs_enabled = proofs_enabled; - m_core_enabled = core_enabled; - m_inconsistent = false; - m_form_qhead = 0; -} - -assertion_stack::~assertion_stack() { - reset(); -} - -void assertion_stack::reset() { - m_inconsistent = false; - m_form_qhead = 0; - m_mc_qhead = 0; - dec_ref_collection_values(m_manager, m_forms); - dec_ref_collection_values(m_manager, m_proofs); - dec_ref_collection_values(m_manager, m_deps); - m_forbidden_set.reset(); - m_forbidden.reset(); - m_csubst.reset(); - m_fsubst.reset(); - m_mc.reset(); - m_scopes.reset(); -} - -void assertion_stack::expand(expr * f, proof * pr, expr_dependency * dep, expr_ref & new_f, proof_ref & new_pr, expr_dependency_ref & new_dep) { - // TODO: expand definitions - new_f = f; - new_pr = pr; - new_dep = dep; -} - -void assertion_stack::push_back(expr * f, proof * pr, expr_dependency * d) { - if (m().is_true(f)) - return; - if (m().is_false(f)) { - m_inconsistent = true; - } - else { - SASSERT(!m_inconsistent); - } - m().inc_ref(f); - m_forms.push_back(f); - if (proofs_enabled()) { - m().inc_ref(pr); - m_proofs.push_back(pr); - } - if (unsat_core_enabled()) { - m().inc_ref(d); - m_deps.push_back(d); - } -} - -void assertion_stack::quick_process(bool save_first, expr * & f, expr_dependency * d) { - if (!m().is_and(f) && !(m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))) { - if (!save_first) { - push_back(f, 0, d); - } - return; - } - typedef std::pair expr_pol; - sbuffer todo; - todo.push_back(expr_pol(f, true)); - while (!todo.empty()) { - if (m_inconsistent) - return; - expr_pol p = todo.back(); - expr * curr = p.first; - bool pol = p.second; - todo.pop_back(); - if (pol && m().is_and(curr)) { - app * t = to_app(curr); - unsigned i = t->get_num_args(); - while (i > 0) { - --i; - todo.push_back(expr_pol(t->get_arg(i), true)); - } - } - else if (!pol && m().is_or(curr)) { - app * t = to_app(curr); - unsigned i = t->get_num_args(); - while (i > 0) { - --i; - todo.push_back(expr_pol(t->get_arg(i), false)); - } - } - else if (m().is_not(curr)) { - todo.push_back(expr_pol(to_app(curr)->get_arg(0), !pol)); - } - else { - if (!pol) - curr = m().mk_not(curr); - if (save_first) { - f = curr; - save_first = false; - } - else { - push_back(curr, 0, d); - } - } - } -} - -void assertion_stack::process_and(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) { - unsigned num = f->get_num_args(); - for (unsigned i = 0; i < num; i++) { - if (m_inconsistent) - return; - slow_process(save_first && i == 0, f->get_arg(i), m().mk_and_elim(pr, i), d, out_f, out_pr); - } -} - -void assertion_stack::process_not_or(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) { - unsigned num = f->get_num_args(); - for (unsigned i = 0; i < num; i++) { - if (m_inconsistent) - return; - expr * child = f->get_arg(i); - if (m().is_not(child)) { - expr * not_child = to_app(child)->get_arg(0); - slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), d, out_f, out_pr); - } - else { - expr_ref not_child(m()); - not_child = m().mk_not(child); - slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), d, out_f, out_pr); - } - } -} - -void assertion_stack::slow_process(bool save_first, expr * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) { - if (m().is_and(f)) - process_and(save_first, to_app(f), pr, d, out_f, out_pr); - else if (m().is_not(f) && m().is_or(to_app(f)->get_arg(0))) - process_not_or(save_first, to_app(to_app(f)->get_arg(0)), pr, d, out_f, out_pr); - else if (save_first) { - out_f = f; - out_pr = pr; - } - else { - push_back(f, pr, d); - } -} - -void assertion_stack::slow_process(expr * f, proof * pr, expr_dependency * d) { - expr_ref out_f(m()); - proof_ref out_pr(m()); - slow_process(false, f, pr, d, out_f, out_pr); -} - - -void assertion_stack::assert_expr(expr * f, proof * pr, expr_dependency * d) { - SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr))); - if (m_inconsistent) - return; - expr_ref new_f(m()); proof_ref new_pr(m()); expr_dependency_ref new_d(m()); - expand(f, pr, d, new_f, new_pr, new_d); - if (proofs_enabled()) - slow_process(f, pr, d); - else - quick_process(false, f, d); -} - -#ifdef Z3DEBUG -// bool assertion_stack::is_expanded(expr * f) { -// } -#endif - -void assertion_stack::update(unsigned i, expr * f, proof * pr, expr_dependency * d) { - SASSERT(i >= m_form_qhead); - SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr))); - if (m_inconsistent) - return; - if (proofs_enabled()) { - expr_ref out_f(m()); - proof_ref out_pr(m()); - slow_process(true, f, pr, d, out_f, out_pr); - if (!m_inconsistent) { - if (m().is_false(out_f)) { - push_back(out_f, out_pr, d); - } - else { - m().inc_ref(out_f); - m().dec_ref(m_forms[i]); - m_forms[i] = out_f; - - m().inc_ref(out_pr); - m().dec_ref(m_proofs[i]); - m_proofs[i] = out_pr; - - if (unsat_core_enabled()) { - m().inc_ref(d); - m().dec_ref(m_deps[i]); - m_deps[i] = d; - } - } - } - } - else { - quick_process(true, f, d); - if (!m_inconsistent) { - if (m().is_false(f)) { - push_back(f, 0, d); - } - else { - m().inc_ref(f); - m().dec_ref(m_forms[i]); - m_forms[i] = f; - - if (unsat_core_enabled()) { - m().inc_ref(d); - m().dec_ref(m_deps[i]); - m_deps[i] = d; - } - } - } - } -} - -void assertion_stack::expand_and_update(unsigned i, expr * f, proof * pr, expr_dependency * d) { - SASSERT(i >= m_form_qhead); - SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr))); - if (m_inconsistent) - return; - expr_ref new_f(m()); proof_ref new_pr(m()); expr_dependency_ref new_d(m()); - expand(f, pr, d, new_f, new_pr, new_d); - update(i, new_f, new_pr, new_d); -} - -void assertion_stack::push() { -} - -void assertion_stack::pop(unsigned num_scopes) { -} - -void assertion_stack::commit() { -} - -void assertion_stack::add_filter(func_decl * f) const { -} - -void assertion_stack::add_definition(app * c, expr * def, proof * pr, expr_dependency * dep) { - -} - -void assertion_stack::add_definition(func_decl * f, quantifier * q, proof * pr, expr_dependency * dep) { -} - -void assertion_stack::convert(model_ref & m) { -} - -void assertion_stack::display(std::ostream & out) const { - out << "(assertion-stack"; - unsigned sz = size(); - for (unsigned i = 0; i < sz; i++) { - out << "\n "; - if (i == m_form_qhead) - out << "==>\n"; - out << mk_ismt2_pp(form(i), m(), 2); - } - out << ")" << std::endl; -} - -bool assertion_stack::is_well_sorted() const { - unsigned sz = size(); - for (unsigned i = 0; i < sz; i++) { - expr * t = form(i); - if (!::is_well_sorted(m(), t)) - return false; - } - return true; -} diff --git a/src/dead/assertion_stack.h b/src/dead/assertion_stack.h deleted file mode 100644 index ca08ed2f6..000000000 --- a/src/dead/assertion_stack.h +++ /dev/null @@ -1,141 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - assertion_stack.h - -Abstract: - - It should be viewed as the "goal" object for incremental solvers. - The main difference is the support of push/pop operations. Like a - goal, an assertion_stack contains expressions, their proofs (if - proof generation is enabled), and dependencies (if unsat core - generation is enabled). - - The assertions on the stack are grouped by scope levels. Scoped - levels are created using push, and removed using pop. - - Assertions may be "committed". Whenever a push is executed, all - "uncommitted" assertions are automatically committed. - Only uncommitted assertions can be simplified/reduced. - - An assertion set has a limited model converter that only supports - definitions (for variable/function elimination) and filters (for fresh - symbols introduced by tactics). - - Some tactics support assertion_stacks and can be applied to them. - However, a tactic can only access the assertions on the top level. - The assertion stack also informs the tactic which declarations - can't be eliminated since they occur in the already committed part. - -Author: - - Leonardo de Moura (leonardo) 2012-02-17 - -Revision History: - ---*/ -#ifndef _ASSERTION_STACK_H_ -#define _ASSERTION_STACK_H_ - -#include"ast.h" -#include"model.h" -#include"expr_substitution.h" -#include"macro_substitution.h" - -class assertion_stack { - ast_manager & m_manager; - unsigned m_ref_count; - bool m_models_enabled; // model generation is enabled. - bool m_proofs_enabled; // proof production is enabled. m_manager.proofs_enabled() must be true if m_proofs_enabled == true - bool m_core_enabled; // unsat core extraction is enabled. - bool m_inconsistent; - ptr_vector m_forms; - ptr_vector m_proofs; - ptr_vector m_deps; - unsigned m_form_qhead; // position of first uncommitted assertion - unsigned m_mc_qhead; - - // Set of declarations that can't be eliminated - obj_hashtable m_forbidden_set; - func_decl_ref_vector m_forbidden; - - // Limited model converter support, it supports only extensions - // and filters. - // It should be viewed as combination of extension_model_converter and - // filter_model_converter for goals. - expr_substitution m_csubst; // substitution for eliminated constants - macro_substitution m_fsubst; // substitution for eliminated functions - - // Model converter is just a sequence of tagged pointers. - // Tag 0 (extension) func_decl was eliminated, and its definition is in m_vsubst or m_fsubst. - // Tag 1 (filter) func_decl was introduced by tactic, and must be removed from model. - ptr_vector m_mc; - - struct scope { - unsigned m_forms_lim; - unsigned m_forbidden_vars_lim; - unsigned m_mc_lim; - bool m_inconsistent_old; - }; - - svector m_scopes; - - void init(bool proofs_enabled, bool models_enabled, bool core_enabled); - void expand(expr * f, proof * pr, expr_dependency * dep, expr_ref & new_f, proof_ref & new_pr, expr_dependency_ref & new_dep); - void push_back(expr * f, proof * pr, expr_dependency * d); - void quick_process(bool save_first, expr * & f, expr_dependency * d); - void process_and(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr); - void process_not_or(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr); - void slow_process(bool save_first, expr * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr); - void slow_process(expr * f, proof * pr, expr_dependency * d); - -public: - assertion_stack(ast_manager & m, bool models_enabled = true, bool core_enabled = true); - assertion_stack(ast_manager & m, bool proofs_enabled, bool models_enabled, bool core_enabled); - ~assertion_stack(); - - void reset(); - - void inc_ref() { ++m_ref_count; } - void dec_ref() { --m_ref_count; if (m_ref_count == 0) dealloc(this); } - - ast_manager & m() const { return m_manager; } - - bool models_enabled() const { return m_models_enabled; } - bool proofs_enabled() const { return m_proofs_enabled; } - bool unsat_core_enabled() const { return m_core_enabled; } - bool inconsistent() const { return m_inconsistent; } - - unsigned size() const { return m_forms.size(); } - unsigned qhead() const { return m_form_qhead; } - expr * form(unsigned i) const { return m_forms[i]; } - proof * pr(unsigned i) const { return proofs_enabled() ? static_cast(m_proofs[i]) : 0; } - expr_dependency * dep(unsigned i) const { return unsat_core_enabled() ? m_deps[i] : 0; } - - void assert_expr(expr * f, proof * pr, expr_dependency * d); - void assert_expr(expr * f) { - assert_expr(f, proofs_enabled() ? m().mk_asserted(f) : 0, 0); - } - void update(unsigned i, expr * f, proof * pr = 0, expr_dependency * dep = 0); - void expand_and_update(unsigned i, expr * f, proof * pr = 0, expr_dependency * d = 0); - - void commit(); - void push(); - void pop(unsigned num_scopes); - unsigned scope_lvl() const { return m_scopes.size(); } - - bool is_well_sorted() const; - - bool is_forbidden(func_decl * f) const { return m_forbidden_set.contains(f); } - void add_filter(func_decl * f) const; - void add_definition(app * c, expr * def, proof * pr, expr_dependency * dep); - void add_definition(func_decl * f, quantifier * q, proof * pr, expr_dependency * dep); - - void convert(model_ref & m); - - void display(std::ostream & out) const; -}; - -#endif diff --git a/src/dead/big_rational.h b/src/dead/big_rational.h deleted file mode 100644 index 753260ced..000000000 --- a/src/dead/big_rational.h +++ /dev/null @@ -1,33 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - big_rational.h - -Abstract: - - Big rational numbers - -Author: - - Leonardo de Moura (leonardo) 2006-09-18. - -Revision History: - ---*/ -#ifndef _BIG_RATIONAL_H_ -#define _BIG_RATIONAL_H_ - -#ifdef _WINDOWS -#include"..\msbig_rational\msbig_rational.h" -#else -#ifdef NO_GMP -#include"dummy_big_rational.h" -#else -#include"gmp_big_rational.h" -#endif -#endif - -#endif /* _BIG_RATIONAL_H_ */ - diff --git a/src/dead/configure.in b/src/dead/configure.in deleted file mode 100644 index 46b9593f3..000000000 --- a/src/dead/configure.in +++ /dev/null @@ -1,168 +0,0 @@ -AC_PREREQ(2.50) -AC_INIT(lib/util.h) - -ARITH="internal" -AC_ARG_WITH([gmp], [AS_HELP_STRING([--with-gmp], [Use GMP for multi-precision naturals (default=no)])], [use_gmp=yes], [use_gmp=no]) -AS_IF([test "$use_gmp" = "yes"],[ - ARITH="gmp" - CPPFLAGS="$CPPFLAGS -D_MP_GMP" -],[ - CPPFLAGS="$CPPFLAGS -D_MP_INTERNAL" -]) -AC_SUBST(EXTRA_LIB_SRCS) - -AC_ARG_WITH(python, -[AS_HELP_STRING([--with-python=PYTHON_PATH], - [specify the location of the python 2.x executable.])]) - -PYTHON="python" -if test "x$with_python" != x; then - PYTHON="$with_python" -fi - -AC_SUBST(PYTHON) - -AC_PATH_PROG([D2U], [dos2unix], [no], [~/bin$PATH_SEPARATOR$PATH]) -AS_IF([test "$D2U" = "no"], [AC_MSG_ERROR(dos2unix not found)]) -AC_SUBST(D2U) - -AC_PROG_CXX(g++) -AC_PROG_MAKE_SET - -AC_LANG_CPLUSPLUS - -host_os=`uname -s` - -AS_IF([test "$host_os" = "Darwin"], [ - PLATFORM=osx - SO_EXT=dylib - SLIBFLAGS="-dynamiclib -fopenmp" - COMP_VERSIONS="-compatibility_version \$(Z3_VERSION) -current_version \$(Z3_VERSION)" - STATIC_FLAGS= - CPPFLAGS+="" -], [test "$host_os" = "Linux"], [ - PLATFORM=linux - SO_EXT=so - LDFLAGS=-lrt - SLIBFLAGS="-shared -fopenmp" - COMP_VERSIONS= - STATIC_FLAGS=-static -], [test "${host_os:0:6}" = "CYGWIN"], [ - PLATFORM=win - SO_EXT=dll - LDFLAGS= - SLIBFLAGS="-shared -fopenmp" - COMP_VERSIONS= - STATIC_FLAGS=-static - CPPFLAGS+=" -D_CYGWIN" -], -[ - AC_MSG_ERROR([Unknown host platform: $host_os]) -]) -AC_SUBST(PLATFORM) -AC_SUBST(SO_EXT) -AC_SUBST(SLIBFLAGS) -AC_SUBST(COMP_VERSIONS) -AC_SUBST(STATIC_FLAGS) - -cat > tst_python.py <= "3": - exit(1) -exit(0) -EOF - -if $PYTHON tst_python.py; then - HAS_PYTHON="1" - HAS_PYTHON_MSG="yes" -cat > get_py_dir.py << EOF -import distutils.sysconfig -print distutils.sysconfig.get_python_lib() -EOF - if $PYTHON get_py_dir.py > dir.txt; then - PYTHON_PACKAGE_DIR=`cat dir.txt` - else - HAS_PYTHON="0" - HAS_PYTHON_MSG="no" - fi - rm -f dir.txt - rm -f get_py_dir.py -else - HAS_PYTHON="0" - HAS_PYTHON_MSG="no" -fi -AC_SUBST(PYTHON_PACKAGE_DIR) -AC_SUBST(HAS_PYTHON) -rm -f tst_python.py - -cat > tst64.c < tmp.sh - dnl mv tmp.sh test_capi/build-external-linux.sh - dnl sed 's|lz3-gmp|lz3|' test_user_theory/build-external-linux.sh > tmp.sh - dnl mv tmp.sh test_user_theory/build-external-linux.sh -else - CXXFLAGS="" - dnl In 64-bit systems it is not possible to build a dynamic library using static gmp. - dnl EXTRA_LIBS="\$(BIN_DIR)/lib\$(Z3)-gmp.so" -fi -rm -f tst64.c -rm -f tst64 - -AC_SUBST(GMP_STATIC_LIB) -GMP_STATIC_LIB="" - -if test "$ARITH" = "gmp"; then - AC_CHECK_HEADER([gmp.h], GMP='gmp', AC_MSG_ERROR([GMP include file not found])) - AC_SUBST(LIBS) - AC_CHECK_LIB(gmp, __gmpz_cmp, LIBS="-lgmp $LIBS", AC_MSG_ERROR([GMP library not found])) - dnl Look for libgmp.a at /usr/local/lib and /usr/lib - dnl TODO: make the following test more robust... - if test -e /usr/local/lib/libgmp.a; then - GMP_STATIC_LIB="/usr/local/lib/libgmp.a" - else if test -e /usr/lib/libgmp.a; then - GMP_STATIC_LIB="/usr/lib/libgmp.a" - else if test -e /usr/lib/libgmp.dll.a; then - GMP_STATIC_LIB="/usr/lib/libgmp.dll.a" - else - AC_MSG_ERROR([Failed to find libgmp.a]) - fi fi fi -fi - -AC_PROG_CXXCPP - -AC_OUTPUT(Makefile) - -cat < - -Author: - - Leonardo de Moura (leonardo) 2007-06-12. - -Revision History: - ---*/ -#ifndef _CONTAINS_VAR_H_ -#define _CONTAINS_VAR_H_ - -class ast; - -bool contains_var(ast * n); - -#endif /* _CONTAINS_VAR_H_ */ - diff --git a/src/dead/dl_simplifier_plugin.cpp b/src/dead/dl_simplifier_plugin.cpp deleted file mode 100644 index b357b39f8..000000000 --- a/src/dead/dl_simplifier_plugin.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_simplifier_plugin.cpp - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-08-10 - -Revision History: - ---*/ - -#include"dl_simplifier_plugin.h" - -namespace datalog { - - dl_simplifier_plugin::dl_simplifier_plugin(ast_manager& m) - : simplifier_plugin(symbol("datalog_relation"), m), - m_util(m) - {} - - bool dl_simplifier_plugin::reduce( - func_decl * f, unsigned num_args, expr* const* args, expr_ref& result) { - uint64 v1, v2; - switch(f->get_decl_kind()) { - case OP_DL_LT: - if (m_util.try_get_constant(args[0], v1) && - m_util.try_get_constant(args[1], v2)) { - result = (v1 < v2)?m_manager.mk_true():m_manager.mk_false(); - return true; - } - // x < x <=> false - if (args[0] == args[1]) { - result = m_manager.mk_false(); - return true; - } - // x < 0 <=> false - if (m_util.try_get_constant(args[1], v2) && v2 == 0) { - result = m_manager.mk_false(); - return true; - } - // 0 < x <=> 0 != x - if (m_util.try_get_constant(args[1], v1) && v1 == 0) { - result = m_manager.mk_not(m_manager.mk_eq(args[0], args[1])); - return true; - } - break; - - default: - break; - } - return false; - } - -}; - - diff --git a/src/dead/dl_simplifier_plugin.h b/src/dead/dl_simplifier_plugin.h deleted file mode 100644 index 8633b7144..000000000 --- a/src/dead/dl_simplifier_plugin.h +++ /dev/null @@ -1,38 +0,0 @@ -/*++ -Copyright (c) 2010 Microsoft Corporation - -Module Name: - - dl_simplifier_plugin.h - -Abstract: - - - -Author: - - Nikolaj Bjorner (nbjorner) 2010-08-10 - -Revision History: - ---*/ -#ifndef _DL_SIMPLIFIER_PLUGIN_H_ -#define _DL_SIMPLIFIER_PLUGIN_H_ - -#include"dl_decl_plugin.h" -#include "simplifier_plugin.h" - -namespace datalog { - - class dl_simplifier_plugin : public simplifier_plugin { - dl_decl_util m_util; - public: - dl_simplifier_plugin(ast_manager& m); - - virtual bool reduce(func_decl * f, unsigned num_args, expr* const* args, expr_ref& result); - - }; - -}; -#endif /* _DL_SIMPLIFIER_PLUGIN_H_ */ - diff --git a/src/dead/dummy_big_rational.h b/src/dead/dummy_big_rational.h deleted file mode 100644 index 350e06140..000000000 --- a/src/dead/dummy_big_rational.h +++ /dev/null @@ -1,54 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - dummy_big_rational.h - -Abstract: - - Dummy big rational - -Author: - - Leonardo de Moura (leonardo) 2006-09-26. - -Revision History: - ---*/ - -#ifndef _DUMMY_BIG_RATIONAL_H_ -#define _DUMMY_BIG_RATIONAL_H_ - -#include -#include"debug.h" - -class big_rational { -public: - big_rational() { } - big_rational(int n) {} - ~big_rational() {} - void reset() {} - unsigned hash() const { return 0; } - void set(int num, int den) { UNREACHABLE(); } - void set(const char * str) { UNREACHABLE(); } - bool is_int() const { UNREACHABLE(); return false; } - long get_int() const { UNREACHABLE(); return 0; } - void neg() { UNREACHABLE(); } - big_rational & operator=(const big_rational & r) { UNREACHABLE(); return *this; } - bool operator==(const big_rational & r) const { UNREACHABLE(); return false; } - bool operator<(const big_rational & r) const { UNREACHABLE(); return false; } - big_rational & operator+=(const big_rational & r) { UNREACHABLE(); return *this; } - big_rational & operator-=(const big_rational & r) { UNREACHABLE(); return *this; } - big_rational & operator*=(const big_rational & r) { UNREACHABLE(); return *this; } - big_rational & operator/=(const big_rational & r) { UNREACHABLE(); return *this; } - big_rational & operator%=(const big_rational & r) { UNREACHABLE(); return *this; } - friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) { UNREACHABLE(); } - void get_numerator(big_rational & result) { UNREACHABLE(); } - void get_denominator(big_rational & result) { UNREACHABLE(); } - void get_floor(big_rational & result) { UNREACHABLE(); } - std::string to_string() const { UNREACHABLE(); return std::string(""); } -}; - -#endif /* _DUMMY_BIG_RATIONAL_H_ */ - diff --git a/src/dead/expr_weight.cpp b/src/dead/expr_weight.cpp deleted file mode 100644 index 60d64b70b..000000000 --- a/src/dead/expr_weight.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/*++ -Copyright (c) 2007 Microsoft Corporation - -Module Name: - - expr_weight.cpp - -Abstract: - - Functor for computing the weight of an expression. - -Author: - - Leonardo (leonardo) 2008-01-11 - -Notes: - ---*/ -#include"expr_weight.h" -#include"recurse_expr_def.h" - -template class recurse_expr; - -weight expr_weight_visitor::visit(app const * n, weight const * args) { - weight r(1); - unsigned j = n->get_num_args(); - while (j > 0) { - --j; - r += args[j]; - } - return r; -} diff --git a/src/dead/expr_weight.h b/src/dead/expr_weight.h deleted file mode 100644 index 9c371484f..000000000 --- a/src/dead/expr_weight.h +++ /dev/null @@ -1,35 +0,0 @@ -/*++ -Copyright (c) 2007 Microsoft Corporation - -Module Name: - - expr_weight.h - -Abstract: - - Functor for computing the weight of an expression. - -Author: - - Leonardo (leonardo) 2008-01-11 - -Notes: - ---*/ -#ifndef _EXPR_WEIGHT_H_ -#define _EXPR_WEIGHT_H_ - -#include"recurse_expr.h" -#include"approx_nat.h" - -typedef approx_nat weight; - -struct expr_weight_visitor { - weight visit(var * n) { return weight(1); } - weight visit(app const * n, weight const * args); - weight visit(quantifier * n, weight body, weight *, weight *) { body += 1; return body; } -}; - -typedef recurse_expr expr_weight; - -#endif /* _EXPR_WEIGHT_H_ */ diff --git a/src/dead/gl_tactic.cpp b/src/dead/gl_tactic.cpp deleted file mode 100644 index e5d219b06..000000000 --- a/src/dead/gl_tactic.cpp +++ /dev/null @@ -1,1047 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - gl_tactic.cpp - -Abstract: - - A T-function - and perhaps Goldreich Levin-based heuristic. - -Author: - - Nikolaj (nbjorner) 2011-12-18 - -Notes: - - This module experiments with T-function bit-vector operations. - - TBD: - 1. convert to tactic. - 2. implement using fewer y bits based on satisfying assignment. - 3. try out code-generation. - 4. better lemma learning? - 5. Incremental refinement into SAT. - - - ---*/ - -#include"gl_tactic.h" -#include"assertion_set_strategy.h" -#include"bv_decl_plugin.h" -#include"shallow_context_simplifier.h" -#include"elim_uncnstr_vars.h" -#include"max_bv_sharing.h" -#include"max_bool_sharing.h" -#include"bv_size_reduction.h" -#include"context_simplifier.h" -#include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"elim_var_model_converter.h" -#include"smt_context.h" -#include"ast_pp.h" - -using namespace gl; - - -typedef svector assignment; - -static void gl_unsupported(ast_manager& m, expr* e) { - TRACE("gl_st", if (e) tout << "unsupported: " << mk_ismt2_pp(e, m) << "\n";); - throw gl_exception(""); -} - -class expr_evaluator { - typedef unsigned char uint8; - typedef unsigned short uint16; - typedef unsigned uint32; - typedef signed char int8; - typedef signed short int16; - typedef signed int int32; - - enum code { - ADD, - SUB, - MUL, - ITE, - BAND, - BOR, - BXOR, - BNOT, - ULT, - SLT, - SHL, - ASHR, - LSHR, - LOADC, - LOADV, - EQ, - UREM, - SREM, - SMOD, - UDIV, - SDIV - }; - - struct oper { - code m_code; - unsigned dst; - unsigned src1; - unsigned src2; - unsigned src3; - uint64 data; - unsigned bw; - - static oper mk_binary(code c, unsigned bw, unsigned dst, unsigned src1, unsigned src2) { - return oper(c, bw, dst, src1, src2, 0, 0); - } - static oper mk_ite(unsigned bw, unsigned dst, unsigned src1, unsigned src2, unsigned src3) { - return oper(ITE, bw, dst, src1, src2, src3, 0); - } - static oper mk_loadc(unsigned bw, unsigned dst, uint64 data) { - return oper(LOADC, bw, dst, 0, 0, 0, data); - } - - private: - oper(code c, unsigned bw, unsigned dst, unsigned src1, unsigned src2, unsigned src3, uint64 data): - m_code(c), bw(bw), dst(dst), src1(src1), src2(src2), src3(src3), data(data) { } - }; - - ast_manager& m; - bv_util m_bv; - svector m_regs; - svector m_ops; - unsigned m_dst; - obj_map m_cache; - assignment const* m_vals_tmp; - obj_map* m_vars_tmp; - - unsigned mk_oper(code c, expr* e, unsigned src1, unsigned src2) { - return mk_oper(c, get_bitwidth(e), src1, src2); - } - - unsigned get_bitwidth(expr* e) { - unsigned bw = 0; - if (m.is_bool(e)) { - bw = 1; - } - else if (m_bv.is_bv(e)) { - bw= m_bv.get_bv_size(e); - if (bw > 64) { - unsupported(e); - } - } - else { - unsupported(e); - } - return bw; - } - - unsigned mk_oper(code c, unsigned bw, unsigned src1, unsigned src2) { - unsigned dst = m_regs.size(); - m_regs.push_back(0); - m_ops.push_back(oper::mk_binary(c, bw, dst, src1, src2)); - return dst; - } - - unsigned mk_const(expr* e, uint64 c) { - return mk_const(get_bitwidth(e), c); - } - - unsigned mk_const(unsigned bw, uint64 c) { - unsigned dst = m_regs.size(); - m_regs.push_back(0); - m_ops.push_back(oper::mk_loadc(bw, dst, c)); - return dst; - } - - - unsigned mk_ite(expr* e, unsigned src1, unsigned src2, unsigned src3) { - unsigned dst = m_regs.size(); - unsigned bw = get_bitwidth(e); - m_regs.push_back(0); - m_ops.push_back(oper::mk_ite(bw, dst, src1, src2, src3)); - return dst; - } - - unsigned mk_oper(code c, unsigned num_args, expr* const* args, uint64 def) { - if (num_args == 0) { - unsupported(0); - return mk_const(static_cast(0), def); - } - unsigned dst = compile(args[0]); - for (unsigned i = 1; i < num_args; ++i) { - dst = mk_oper(c, args[i], dst, compile(args[i])); - } - return dst; - } - - unsigned compile(app* a) { - unsigned src1 = 0, src2 = 0, src3 = 0, dst = 0; - uint64 src0 = 0; - unsigned num_args = a->get_num_args(); - expr* const* args = a->get_args(); - unsigned var_id = 0; - - if (num_args >= 1) { - src1 = compile(a->get_arg(0)); - } - if (num_args >= 2) { - src2 = compile(a->get_arg(1)); - } - if (num_args >= 3) { - src3 = compile(a->get_arg(2)); - } - if (m_bv.is_bv(a) && m_bv.get_bv_size(a) > 64) { - unsupported(a); - } - if (m_vars_tmp->find(a, var_id)) { - return mk_oper(LOADV, a, var_id, 0); - } - if (a->get_family_id() == m.get_basic_family_id()) { - switch(a->get_decl_kind()) { - case OP_AND: - return mk_oper(BAND, num_args, args, 1); - case OP_OR: - return mk_oper(BOR, num_args, args, 0); - case OP_NOT: - return mk_oper(BNOT, a, src1, 0); - case OP_EQ: - return mk_oper(EQ, a, src1, src2); - case OP_ITE: - return mk_ite(a, src1, src2, src3); - case OP_DISTINCT: - unsupported(a); - case OP_TRUE: - return mk_const(a, 1); - case OP_FALSE: - return mk_const(a, 0); - case OP_XOR: - return mk_oper(BNOT, a, mk_oper(EQ, a, src1, src2), 0); - case OP_IFF: - return mk_oper(EQ, a, src1, src2); // mask? - default: - UNREACHABLE(); - } - } - if (a->get_family_id() == m_bv.get_family_id()) { - unsigned bv_size; - rational val; - switch(a->get_decl_kind()) { - case OP_BV_NUM: - VERIFY(m_bv.is_numeral(a, val, bv_size)); - if (bv_size > 64) { - unsupported(a); - } - src0 = val.get_uint64(); - return mk_const(a, src0); - case OP_BIT1: - return mk_const(a, 1); - case OP_BIT0: - return mk_const(a, 0); - case OP_BNEG: - SASSERT(num_args == 1); - return mk_oper(SUB, a, 0, src1); - case OP_BADD: - return mk_oper(ADD, num_args, args, 0); - case OP_BSUB: - SASSERT(num_args == 2); - return mk_oper(SUB, a, src1, src2); - case OP_BMUL: - return mk_oper(MUL, num_args, args, 1); - case OP_BSDIV: - case OP_BSDIV0: - case OP_BSDIV_I: - return mk_oper(SDIV, a, src1, src2); - case OP_BUDIV: - case OP_BUDIV0: - case OP_BUDIV_I: - return mk_oper(UDIV, a, src1, src2); - case OP_BSREM: - case OP_BSREM0: - case OP_BSREM_I: - return mk_oper(SREM, a, src1, src2); - case OP_BUREM: - case OP_BUREM0: - case OP_BUREM_I: - return mk_oper(UREM, a, src1, src2); - case OP_BSMOD: - case OP_BSMOD0: - case OP_BSMOD_I: - return mk_oper(SMOD, a, src1, src2); - case OP_ULEQ: - return mk_oper(BOR, a, mk_oper(ULT, a, src1, src2), mk_oper(EQ, a, src1, src2)); - case OP_SLEQ: - return mk_oper(BOR, a, mk_oper(SLT, a, src1, src2), mk_oper(EQ, a, src1, src2)); - case OP_UGEQ: - return mk_oper(BOR, a, mk_oper(ULT, a, src2, src1), mk_oper(EQ, a, src1, src2)); - case OP_SGEQ: - return mk_oper(BOR, a, mk_oper(SLT, a, src2, src1), mk_oper(EQ, a, src1, src2)); - case OP_ULT: - return mk_oper(ULT, a, src1, src2); - case OP_SLT: - return mk_oper(SLT, a, src1, src2); - case OP_UGT: - return mk_oper(ULT, a, src2, src1); - case OP_SGT: - return mk_oper(SLT, a, src2, src1); - case OP_BAND: - return mk_oper(BAND, num_args, args, ~((uint64)0)); - case OP_BOR: - return mk_oper(BOR, num_args, args, 0); - case OP_BNOT: - return mk_oper(BNOT, a, src1, 0); - case OP_BXOR: - SASSERT(num_args == 2); - return mk_oper(BXOR, a, src1, src2); - case OP_BNAND: - return mk_oper(BNOT, a, mk_oper(BAND, num_args, args, ~((uint64)0)), 0); - case OP_BNOR: - return mk_oper(BNOT, a, mk_oper(BOR, num_args, args, 0), 0); - case OP_BXNOR: - SASSERT(num_args == 2); - return mk_oper(BNOT, a, mk_oper(BXOR, a, src1, src2), 0); - case OP_CONCAT: { - SASSERT(num_args > 0); - expr* last = args[num_args-1]; - src1 = compile(last); - unsigned offset = m_bv.get_bv_size(last); - for (unsigned i = num_args-1; i > 0; ) { - --i; - unsigned bv_size = m_bv.get_bv_size(args[i]); - uint64 mask = (1ull << offset)-1; - offset += bv_size; - src2 = compile(args[i]); - src2 = mk_oper(SHL, args[i], src2, offset); - src1 = mk_oper(BAND, offset, src1, mk_const(offset, mask)); - src1 = mk_oper(BOR, offset, src1, src2); - - } - return src1; - } - case OP_SIGN_EXT: - unsupported(a); - case OP_ZERO_EXT: - unsupported(a); - case OP_EXTRACT: { - unsigned lo = m_bv.get_extract_low(a); - unsigned hi = m_bv.get_extract_high(a); - if (lo > 0) { - dst = mk_oper(SHL, a, src1, lo); - } - else { - dst = src1; - } - return dst; - } - case OP_REPEAT: - case OP_BREDOR: - case OP_BREDAND: - case OP_BCOMP: - unsupported(a); - case OP_BSHL: - SASSERT(num_args == 2); - return mk_oper(SHL, a, src1, src2); - case OP_BLSHR: - SASSERT(num_args == 2); - return mk_oper(LSHR, a, src1, src2); - case OP_BASHR: - SASSERT(num_args == 2); - return mk_oper(ASHR, a, src1, src2); - case OP_ROTATE_LEFT: - case OP_ROTATE_RIGHT: - case OP_EXT_ROTATE_LEFT: - case OP_EXT_ROTATE_RIGHT: - case OP_BUMUL_NO_OVFL: // no unsigned multiplication overflow predicate - case OP_BSMUL_NO_OVFL: // no signed multiplication overflow predicate - case OP_BSMUL_NO_UDFL: // no signed multiplication underflow predicate - case OP_BIT2BOOL: // predicate - unsupported(a); - case OP_MKBV: // bools to bv - return src1; - case OP_INT2BV: - case OP_BV2INT: - case OP_CARRY: - case OP_XOR3: - unsupported(a); - } - } - unsupported(a); - UNREACHABLE(); - return 0; - } - - uint64 to_bool(bool b) { return b?0x1:0x0; } - - void interpret(oper oper) { - unsigned mask = 0; - switch(oper.m_code) { - case LOADC: - m_regs[oper.dst] = oper.data; - break; - case LOADV: - m_regs[oper.dst] = (*m_vals_tmp)[oper.src1]; - break; - case ADD: - m_regs[oper.dst] = m_regs[oper.src1] + m_regs[oper.src2]; - break; - case SUB: - switch(oper.bw) - { - case 8: m_regs[oper.dst] = (uint8)m_regs[oper.src1] - (uint8)m_regs[oper.src2]; break; - case 16: m_regs[oper.dst] = (uint16)m_regs[oper.src1] - (uint16)m_regs[oper.src2]; break; - case 32: m_regs[oper.dst] = (uint32)m_regs[oper.src1] - (uint32)m_regs[oper.src2]; break; - case 64: m_regs[oper.dst] = m_regs[oper.src1] - m_regs[oper.src2]; break; - default: unsupported(0); - } - break; - case MUL: - m_regs[oper.dst] = m_regs[oper.src1] * m_regs[oper.src2]; - break; - case SDIV: - switch(oper.bw) - { - case 8: m_regs[oper.dst] = (int8)m_regs[oper.src1] / (int8)m_regs[oper.src2]; break; - case 16: m_regs[oper.dst] = (int16)m_regs[oper.src1] / (int16)m_regs[oper.src2]; break; - case 32: m_regs[oper.dst] = (int32)m_regs[oper.src1] / (int32)m_regs[oper.src2]; break; - case 64: m_regs[oper.dst] = (int64)m_regs[oper.src1] / (int64)m_regs[oper.src2]; break; - default: unsupported(0); - } - break; - case UDIV: - switch(oper.bw) - { - case 8: m_regs[oper.dst] = (uint8)m_regs[oper.src1] / (uint8)m_regs[oper.src2]; break; - case 16: m_regs[oper.dst] = (uint16)m_regs[oper.src1] / (uint16)m_regs[oper.src2]; break; - case 32: m_regs[oper.dst] = (uint32)m_regs[oper.src1] / (uint32)m_regs[oper.src2]; break; - case 64: m_regs[oper.dst] = m_regs[oper.src1] / m_regs[oper.src2]; break; - default: unsupported(0); - } - break; - case SMOD: - case SREM: - case UREM: - unsupported(0); - case BAND: - m_regs[oper.dst] = m_regs[oper.src1] & m_regs[oper.src2]; - break; - case BOR: - m_regs[oper.dst] = m_regs[oper.src1] | m_regs[oper.src2]; - break; - case BXOR: - m_regs[oper.dst] = m_regs[oper.src1] ^ m_regs[oper.src2]; - break; - case BNOT: - m_regs[oper.dst] = ~m_regs[oper.src1]; - break; - case SHL: - mask = (1ull << oper.bw) - 1; - m_regs[oper.dst] = m_regs[oper.src1] << (mask & m_regs[oper.src2]); - break; - case LSHR: - m_regs[oper.dst] = m_regs[oper.src1] >> (mask & m_regs[oper.src2]); - break; - case ASHR: - switch(oper.bw) - { - case 8: m_regs[oper.dst] = (int8)m_regs[oper.src1] >> (int8)m_regs[oper.src2]; break; - case 16: m_regs[oper.dst] = (int16)m_regs[oper.src1] >> (int16)m_regs[oper.src2]; break; - case 32: m_regs[oper.dst] = (int32)m_regs[oper.src1] >> (int32)m_regs[oper.src2]; break; - case 64: m_regs[oper.dst] = (int64)m_regs[oper.src1] >> (int64)m_regs[oper.src2]; break; - default: unsupported(0); - } - break; - case ULT: - switch(oper.bw) - { - case 8: m_regs[oper.dst] = to_bool((uint8)m_regs[oper.src1] < (uint8)m_regs[oper.src2]); break; - case 16: m_regs[oper.dst] = to_bool((uint16)m_regs[oper.src1] < (uint16)m_regs[oper.src2]); break; - case 32: m_regs[oper.dst] = to_bool((uint32)m_regs[oper.src1] < (uint32)m_regs[oper.src2]); break; - case 64: m_regs[oper.dst] = to_bool(m_regs[oper.src1] < m_regs[oper.src2]); break; - default: unsupported(0); - } - break; - case SLT: - switch(oper.bw) - { - case 8: m_regs[oper.dst] = to_bool((int8)m_regs[oper.src1] < (int8)m_regs[oper.src2]); break; - case 16: m_regs[oper.dst] = to_bool((int16)m_regs[oper.src1] < (int16)m_regs[oper.src2]); break; - case 32: m_regs[oper.dst] = to_bool((int32)m_regs[oper.src1] < (int32)m_regs[oper.src2]); break; - case 64: m_regs[oper.dst] = to_bool((int64)m_regs[oper.src1] < (int64)m_regs[oper.src2]); break; - default: unsupported(0); - } - break; - case ITE: - m_regs[oper.dst] = (0x1&m_regs[oper.src1])?m_regs[oper.src2]:m_regs[oper.src3]; - break; - case EQ: - mask = (1ull << oper.bw) - 1; - m_regs[oper.dst] = to_bool((mask & m_regs[oper.src1]) == (mask & m_regs[oper.src2])); - break; - default: - UNREACHABLE(); - break; - } - } - - unsigned compile(expr* e) { - unsigned val; - TRACE("gl_st", tout << mk_ismt2_pp(e, m) << "\n";); - if (!is_app(e)) { - unsupported(e); - } - app* a = to_app(e); - if (!m_cache.find(a, val)) { - val = compile(a); - m_cache.insert(a, val); - } - return val; - } - - void interpret() { - for (unsigned i = 0; i < m_ops.size(); ++i) { - interpret(m_ops[i]); - } - } - - void unsupported(expr* e) { - gl_unsupported(m, e); - } - -public: - - expr_evaluator(ast_manager& m): m(m), m_bv(m), m_vals_tmp(0) - {} - - void compile(obj_map& vars, expr* e) { - m_vars_tmp = &vars; - m_dst = compile(e); - } - - uint64 evaluate(assignment const& assign) { - m_vals_tmp = &assign; - interpret(); - return m_regs[m_dst]; - } - -}; - -// compile a formula by abstracting T-functions (of certain size) -// to propositional abstrations. -class t_function_abstractor { - ast_manager& m; - bv_util m_bv; - family_id m_bv_fid; - app_ref_vector* m_t_funs, *m_t_proxies; - obj_map* m_t_vars; - obj_map m_cache; - - void unsupported(expr* e) { gl_unsupported(m, e); } - - void unsupported() { gl_unsupported(m, 0); } - - bool is_bv(app* t) const { - return m_bv_fid == t->get_family_id(); - } - - // t is a T function. Extract constraints on inputs. - void absT(expr* _t, app_ref& result) { - app* c; - if (!is_app(_t)) { - unsupported(_t); - } - app* t = to_app(_t); - if (m_cache.find(t, c)) { - result = c; - } - else { - absT(t, result); - m_cache.insert(t, result); - } - } - - void absT(app* t, app_ref& result) { - if (is_bv(t)) { - absTBv(t, result); - } - else { - absTVar(t, result); - } - } - - void absT(unsigned num_args, expr* const* args, expr_ref_vector& rs) { - app_ref result(m); - for (unsigned i = 0; i < num_args; ++i) { - absT(args[i], result); - rs.push_back(result); - } - } - - void absTVar(app* t, app_ref& result) { - absF(t, result); - m_t_vars->insert(result, m_t_vars->size()); - } - - void absTBv(app* t, app_ref& result) { - SASSERT(is_bv(t)); - expr_ref_vector results(m); - switch(t->get_decl_kind()) { - case OP_BV_NUM: - case OP_BIT1: - case OP_BIT0: - case OP_BADD: - case OP_BSUB: - case OP_BNEG: - case OP_BMUL: - case OP_BAND: - case OP_BOR: - case OP_BNOT: - case OP_BXOR: - case OP_BNAND: - case OP_BNOR: - case OP_BXNOR: - case OP_CONCAT: - case OP_SIGN_EXT: - case OP_ZERO_EXT: - case OP_EXTRACT: - case OP_BSHL: - absT(t->get_num_args(), t->get_args(), results); - result = m.mk_app(t->get_decl(), results.size(), results.c_ptr()); - break; - default: - absTVar(t, result); - break; - } - } - - // f is a formula/non-T function. Extract T functions. - void absF(expr* _f, app_ref& result) { - app* c; - if (!is_app(_f)) { - unsupported(_f); - } - app* f = to_app(_f); - if (m_cache.find(f, c)) { - result = c; - } - else { - absF(f, result); - m_cache.insert(f, result); - } - } - - void absF(app* a, app_ref& result) { - if (a->get_family_id() == m.get_basic_family_id()) { - absFBasic(a, result); - } - else if (is_bv(a)) { - absFBv(a, result); - } - else { - expr_ref_vector rs(m); - absF(a->get_num_args(), a->get_args(), rs); - result = m.mk_app(a->get_decl(), rs.size(), rs.c_ptr()); - } - } - - void absF(unsigned num_args, expr*const* args, expr_ref_vector& rs) { - app_ref result(m); - for (unsigned i = 0; i < num_args; ++i) { - absF(args[i], result); - rs.push_back(result); - } - } - - void absFBasic(app* f, app_ref& result) { - expr_ref_vector results(m); - expr* e1, *e2; - if (m.is_eq(f, e1, e2) && m_bv.is_bv(e1)) { - app_ref r1(m), r2(m); - r1 = to_app(m_bv.mk_bv_xor(2, f->get_args())); - absFBv(r1, r2); - e1 = m_bv.mk_numeral(rational(0), m_bv.get_bv_size(e1)); - result = m.mk_eq(e1, r2); - } - else { - absF(f->get_num_args(), f->get_args(), results); - result = m.mk_app(f->get_decl(), results.size(), results.c_ptr()); - } - } - - void absFBv(app* a, app_ref& result) { - expr_ref_vector results(m); - switch(a->get_decl_kind()) { - case OP_BADD: - case OP_BSUB: - case OP_BNEG: - case OP_BMUL: - case OP_BAND: - case OP_BOR: - case OP_BNOT: - case OP_BXOR: - case OP_BNAND: - case OP_BNOR: - case OP_BXNOR: - case OP_CONCAT: - case OP_SIGN_EXT: - case OP_ZERO_EXT: - case OP_EXTRACT: - case OP_BSHL: { - app_ref tmp(m); - absT(a, tmp); - result = m.mk_fresh_const("T",m.get_sort(a)); - m_t_funs->push_back(tmp); - m_t_proxies->push_back(result); - return; - } - default: - absF(a->get_num_args(), a->get_args(), results); - result = m.mk_app(a->get_decl(), results.size(), results.c_ptr()); - return; - } - } - -public: - t_function_abstractor(ast_manager& m): m(m), m_bv(m), m_bv_fid(m.get_family_id("bv")) {} - - void operator()(expr* e, app_ref& result, app_ref_vector& t_funs, app_ref_vector& t_proxies, obj_map& t_vars) { - m_cache.reset(); - m_t_funs = &t_funs; - m_t_proxies = &t_proxies; - m_t_vars = &t_vars; - absF(e, result); - } - -}; - -class gl_eval { - ast_manager& m; - expr_evaluator m_eval; - app_ref m_proxy; - expr_ref m_proxy_val; - uint64 m_expected; - bool m_expected_valid; -public: - gl_eval(ast_manager& m): m(m), m_eval(m), m_proxy(m), m_proxy_val(m), m_expected(0) {} - - void set_model(model_ref& mdl) { - m_proxy_val = 0; - if (mdl->eval(m_proxy, m_proxy_val, false) && m_proxy_val.get()) { - rational r; - bv_util bv(m); - unsigned bv_size; - m_expected_valid = true; - VERIFY(bv.is_numeral(m_proxy_val, r, bv_size)); - m_expected = r.get_uint64(); - TRACE("gl_st", tout << mk_pp(m_proxy, m) << " |-> " << r << "\n";); - } - else { - m_expected_valid = false; - } - } - - void set_proxy(app* e) { m_proxy = e; } - - expr* get_proxy() { return m_proxy; } - - expr* get_proxy_val() { return m_proxy_val; } - - bool operator()(assignment const& assign, unsigned num_bits) { - if (!m_expected_valid) { - TRACE("gl_st", tout << mk_pp(m_proxy, m) << " not valid\n";); - return true; - } - else { - uint64 val = m_eval.evaluate(assign); - uint64 mask = (1ULL << num_bits) - 1ULL; - TRACE("gl_st", tout << mk_pp(m_proxy, m) << " " << val << " expected: " << m_expected << " num_bits: " << num_bits << "\n";); - return (val & mask) == (m_expected & mask); - } - } - - void compile(obj_map& var2index, expr* e) { - m_eval.compile(var2index, e); - } -}; - - -class gl_st : public assertion_set_strategy { - - ast_manager& m; - front_end_params m_params; - - // variables and their assignments. obj_map m_var2index; - ptr_vector m_index2var; - svector m_vals; - - // t-functions - vector m_evals; - - // external search state. - smt::context m_ctx; - - // internal search state. - unsigned_vector m_search_stack; - unsigned m_max_bitwidth; - unsigned m_max_search_depth; - - - bv_util m_bv; - volatile bool m_cancel; - -public: - - gl_st(ast_manager& m, params_ref const& p): - m(m), m_ctx(m, m_params), - m_bv(m), m_cancel(false), - m_max_search_depth(0) { - m_params.m_model = true; - } - - virtual ~gl_st() { - for (unsigned i = 0; i < m_evals.size(); ++i) dealloc(m_evals[i]); - } - - struct nonsat_by_gl { }; - - struct unsupported_by_gl { }; - - virtual void operator()(assertion_set & s, model_converter_ref & mc) { - ptr_vector conjs; - for (unsigned i = 0; i < s.size(); ++i) { - conjs.push_back(s.form(i)); - } - app_ref fml1(m.mk_and(conjs.size(), conjs.c_ptr()), m); - app_ref fml2(m); - t_function_abstractor TAbs(m); - app_ref_vector t_funs(m), t_proxies(m); - TAbs(fml1, fml2, t_funs, t_proxies, m_var2index); - TRACE("gl_st", - tout << mk_pp(fml1, m) << "\n"; - tout << mk_pp(fml2, m) << "\n";); - - m_index2var.resize(m_var2index.size()); - m_vals.resize(m_var2index.size()); - obj_map::iterator it = m_var2index.begin(), end = m_var2index.end(); - for (; it != end; ++it) { - m_index2var[it->m_value] = it->m_key; - } - - m_max_bitwidth = 0; - - for (unsigned i = 0; i < t_funs.size(); ++i) { - gl_eval* eval = alloc(gl_eval, m); - eval->compile(m_var2index, t_funs[i].get()); - eval->set_proxy(t_proxies[i].get()); - m_evals.push_back(eval); - m_max_bitwidth = std::max(m_max_bitwidth, m_bv.get_bv_size(t_proxies[i].get())); - } - - m_ctx.assert_expr(fml2); - - if (search()) { - elim_var_model_converter* emc = alloc(elim_var_model_converter, m); - mc = emc; - for (unsigned i = 0; i < m_index2var.size(); ++i) { - expr_ref vl(m); - if (m.is_bool(m_index2var[i])) { - vl = m_vals[i]? m.mk_true():m.mk_false(); - } - else if (m_bv.is_bv(m_index2var[i])) { - vl = m_bv.mk_numeral(m_vals[i], m_bv.get_bv_size(m_index2var[i])); - } - emc->insert(m_index2var[i]->get_decl(), vl); - } - // TBD: other variables. - s.reset(); - } - else { - throw nonsat_by_gl(); - } - } - - virtual void cleanup() { - - } - - virtual void collect_statistics(statistics & st) const { - - } - - virtual void reset_statistics() { - - } -protected: - virtual void set_cancel(bool f) { - } -private: - - void checkpoint() { - if (m_cancel) - throw gl_exception(STE_CANCELED_MSG); - cooperate("gl"); - } - - bool search() { - while (true) { - lbool res = m_ctx.check(); - if (res == l_false) { - return false; - } - model_ref mdl; - m_ctx.get_model(mdl); - for (unsigned i = 0; i < m_evals.size(); ++i) { - m_evals[i]->set_model(mdl); - } - m_max_search_depth = 0; - if (t_search()) { - return true; - } - expr_ref_vector eqs(m); - for (unsigned i = 0; i < m_evals.size(); ++i) { - expr* v = m_evals[i]->get_proxy_val(); - expr* p = m_evals[i]->get_proxy(); - if (v && p) { - if (m_bv.is_bv(v) && m_bv.get_bv_size(v) > m_max_search_depth) { - v = m_bv.mk_extract(m_max_search_depth-1,0,v); - p = m_bv.mk_extract(m_max_search_depth-1,0,p); - } - eqs.push_back(m.mk_eq(v, p)); - } - } - expr_ref fml(m); - fml = m.mk_and(eqs.size(), eqs.c_ptr()); - TRACE("gl_st", tout << "block " << mk_pp(fml, m) << "\n";); - m_ctx.assert_expr(m.mk_not(fml)); - } - return false; - } - - - bool t_search() { - if (!decide()) { - return false; - } - while (true) { - while (!propagate()) { - if (!backtrack()) { - return false; - } - } - if (!decide()) { - return true; - } - } - } - - bool propagate() { - // update the assignment. - for (unsigned i = 0; i < m_index2var.size(); ++i) { - m_vals[i] = 0; - for (unsigned j = 0; j < m_search_stack.size(); ++j) { - if (m_search_stack[j] & (1 << i)) { - m_vals[i] |= (1ULL << j); - } - } - } - // evaluate under assignment - for (unsigned i = 0; i < m_evals.size(); ++i) { - if (!(*m_evals[i])(m_vals, m_search_stack.size())) { - return false; - } - } - return true; - } - - // backtrack to previous level. - bool backtrack() { - while (!next()) { - TRACE("gl_st", tout << "level: " << m_search_stack.size() << "\n";); - m_search_stack.pop_back(); - if (m_search_stack.empty()) { - return false; - } - } - return true; - } - - bool next() { - SASSERT(!m_search_stack.empty()); - m_search_stack.back()++; - TRACE("gl_st", tout << "next " << m_search_stack.back() << "\n";); - return !(m_search_stack.back() & (1 << m_index2var.size())); - } - - // choose the next assignment. - bool decide() { - if (m_search_stack.size() == m_max_bitwidth) { - return false; - } - else { - m_search_stack.push_back(0); - m_max_search_depth = std::max(m_max_search_depth, m_search_stack.size()); - return true; - } - } - - std::ostream& display(std::ostream& out) { - out << "gl"; - return out; - } - -}; - -MK_FAIL_IF(fail_if_not_bv, !is_qfbv(s), "failed: GL supports only pure QF_BV for now."); - -static as_st * mk_gl_preamble(ast_manager & m, params_ref const & p) { - params_ref main_p; - main_p.set_bool(":elim-and", true); - main_p.set_bool(":push-ite-bv", true); - main_p.set_bool(":blast-distinct", true); - main_p.set_bool(":hi-div0", true); - - params_ref simp2_p = p; - simp2_p.set_bool(":som", true); - simp2_p.set_bool(":pull-cheap-ite", true); - simp2_p.set_bool(":push-ite-bv", false); - simp2_p.set_bool(":local-ctx", true); - simp2_p.set_uint(":local-ctx-limit", 10000000); - - params_ref hoist_p; - hoist_p.set_bool(":hoist-mul", true); - hoist_p.set_bool(":som", false); - - params_ref gaussian_p; - // conservative guassian elimination. - gaussian_p.set_uint(":gaussian-max-occs", 2); - - return and_then(and_then(mk_simplifier(m), - mk_shallow_simplifier(m), - using_params(mk_gaussian(m), gaussian_p), - mk_elim_uncnstr_vars(m), - mk_bv_size_reduction(m), - using_params(mk_simplifier(m), simp2_p)), - using_params(mk_simplifier(m), hoist_p), - mk_max_bv_sharing(m), - mk_nnf(p)); -} - -as_st * mk_gl(ast_manager & m, params_ref const& p) { - return alloc(gl_st, m, p); -} - -as_st * mk_qfbv_gl_strategy(ast_manager & m, params_ref const & p) { - params_ref gl_p(p); - - as_st * st = and_then(mk_gl_preamble(m, p), - fail_if_not_bv(), - mk_gl(m, gl_p)); - - st->updt_params(p); - return st; -} - diff --git a/src/dead/gl_tactic.h b/src/dead/gl_tactic.h deleted file mode 100644 index 63a88c98d..000000000 --- a/src/dead/gl_tactic.h +++ /dev/null @@ -1,29 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - gl_tactic.h - -Abstract: - - A T-function/Goldreich Levin-based heuristic. - -Author: - - Nikolaj (nbjorner) 2011-12-18 - -Notes: - ---*/ - -#ifndef _GL_TACTIC_H_ -#define _GL_TACTIC_H_ - -#include"tactic.h" - -namespace gl { - tactic * mk_tactic(ast_manager& m, params_ref const& p); -}; - -#endif diff --git a/src/dead/gmp_big_rational.cpp b/src/dead/gmp_big_rational.cpp deleted file mode 100644 index 3b2948607..000000000 --- a/src/dead/gmp_big_rational.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - gmp_big_rational.cpp - -Abstract: - - Big rationals using GMP - -Author: - - Leonardo de Moura (leonardo) 2006-09-26. - -Revision History: - ---*/ -#include - -#include"gmp_big_rational.h" -#include"trace.h" -#include"buffer.h" - -#ifndef NO_GMP -mpz_t big_rational::m_tmp; -bool big_rational::m_tmp_initialized = false; -mpz_t big_rational::m_int_min; -mpz_t big_rational::m_int_max; -mpz_t big_rational::m_uint_max; -mpz_t big_rational::m_two32; -mpz_t big_rational::m_int64_min; -mpz_t big_rational::m_int64_max; -mpz_t big_rational::m_uint64_max; -bool big_rational::m_has_limits = false; - -void big_rational::init_limits() { - mpz_init(m_int_min); - mpz_init(m_int_max); - mpz_init(m_uint_max); - mpz_init(m_two32); - mpz_init(m_int64_min); - mpz_init(m_int64_max); - mpz_init(m_uint64_max); - mpz_set_si(m_int_min, INT_MIN); - mpz_set_si(m_int_max, INT_MAX); - mpz_set_ui(m_uint_max, UINT_MAX); - mpz_set_ui(m_two32, UINT_MAX); - mpz_t & tmp = get_tmp(); - mpz_set_si(tmp, 1); - mpz_add(m_two32, m_two32, tmp); - unsigned max_l = static_cast(INT64_MAX % static_cast(UINT_MAX)); - unsigned max_h = static_cast(INT64_MAX / static_cast(UINT_MAX)); - mpz_set_ui(m_int64_max, max_h); - mpz_mul(m_int64_max, m_uint_max, m_int64_max); - mpz_set_ui(tmp, max_l); - mpz_add(m_int64_max, tmp, m_int64_max); - mpz_neg(m_int64_min, m_int64_max); - mpz_set_si(tmp, -1); - mpz_add(m_int64_min, m_int64_min, tmp); - mpz_set(m_uint64_max, m_int64_max); - mpz_set_si(tmp, 2); - mpz_mul(m_uint64_max, m_uint64_max, tmp); - mpz_set_si(tmp, 1); - mpz_add(m_uint64_max, m_uint64_max, tmp); - m_has_limits = true; -} - -std::string big_rational::to_string() const { - size_t sz = mpz_sizeinbase(mpq_numref(m_data), 10) + mpz_sizeinbase(mpq_numref(m_data), 10) + 3; - buffer b(sz, 0); - mpq_get_str(b.c_ptr(), 10, m_data); - std::string result(b.c_ptr()); - return result; -} - -int64 big_rational::get_int64() const { - if (!m_has_limits) { - init_limits(); - } - SASSERT(is_int64()); - mpz_t & tmp = get_tmp(); - mpq_get_num(tmp, m_data); - if (sizeof(int64) == sizeof(long) || mpz_fits_slong_p(tmp)) { - return mpz_get_si(tmp); - } - else { - mpz_mod(tmp, tmp, two32()); - int64 r = static_cast(mpz_get_ui(tmp)); - mpq_get_num(tmp, m_data); - mpz_div(tmp, tmp, two32()); - r += static_cast(mpz_get_si(tmp)) << static_cast(32); - return r; - } -} - -uint64 big_rational::get_uint64() const { - if (!m_has_limits) { - init_limits(); - } - SASSERT(is_uint64()); - mpz_t & tmp = get_tmp(); - mpq_get_num(tmp, m_data); - if (sizeof(uint64) == sizeof(unsigned long) || mpz_fits_ulong_p(tmp)) { - return mpz_get_ui(tmp); - } - else { - mpz_mod(tmp, tmp, two32()); - uint64 r = static_cast(mpz_get_ui(tmp)); - mpq_get_num(tmp, m_data); - mpz_div(tmp, tmp, two32()); - r += static_cast(mpz_get_ui(tmp)) << static_cast(32); - return r; - } -} - -#endif diff --git a/src/dead/gmp_big_rational.h b/src/dead/gmp_big_rational.h deleted file mode 100644 index bffb069b7..000000000 --- a/src/dead/gmp_big_rational.h +++ /dev/null @@ -1,193 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - gmp_big_rational.h - -Abstract: - - Big rationals using gmp - -Author: - - Leonardo de Moura (leonardo) 2006-09-26. - -Revision History: - ---*/ -#ifndef _GMP_BIG_RATIONAL_H_ -#define _GMP_BIG_RATIONAL_H_ - -#ifndef NO_GMP - -#include -#include -#include"util.h" -#include"debug.h" -#include"trace.h" - -class big_rational { - mpq_t m_data; - static mpz_t m_tmp; - static bool m_tmp_initialized; - static mpz_t & get_tmp() { - if (!m_tmp_initialized) { - mpz_init(m_tmp); - m_tmp_initialized = true; - } - return m_tmp; - } - static mpz_t m_int_min; - static mpz_t m_int_max; - static mpz_t m_uint_max; - static mpz_t m_two32; - static mpz_t m_int64_min; - static mpz_t m_int64_max; - static mpz_t m_uint64_max; - static bool m_has_limits; - static void init_limits(); - - static mpz_t & int64_min() { - if (!m_has_limits) { - init_limits(); - } - return m_int64_min; - } - - static mpz_t & int64_max() { - if (!m_has_limits) { - init_limits(); - } - return m_int64_max; - } - - static mpz_t & uint64_max() { - if (!m_has_limits) { - init_limits(); - } - return m_uint64_max; - } - - static mpz_t & uint_max() { - if (!m_has_limits) { - init_limits(); - } - return m_uint_max; - } - - static mpz_t & two32() { - if (!m_has_limits) { - init_limits(); - } - return m_two32; - } - -public: - big_rational() { mpq_init(m_data); reset(); } - big_rational(int n) { mpq_init(m_data); mpq_set_si(m_data, n, 1); } - ~big_rational() { mpq_clear(m_data); } - void reset() { mpq_set_si(m_data, 0, 1); } - unsigned hash() const { return mpz_get_si(mpq_numref(m_data)); } - void set(int num, int den) { - mpq_set_si(m_data, num, den); - mpq_canonicalize(m_data); - } - void setu(unsigned num) { - mpq_set_ui(m_data, num, 1); - mpq_canonicalize(m_data); - } - void set(const char * str) { - mpq_set_str(m_data, str, 10); - } - bool is_int() const { - return mpz_cmp_ui(mpq_denref(m_data), 1) == 0; - } - bool is_even() const { - if (!is_int()) { - return false; - } - mpz_t & tmp = get_tmp(); - mpq_get_num(tmp, m_data); - return mpz_even_p(tmp) != 0; - } - bool is_int64() const { - if (!is_int()) { - return false; - } - mpz_t & tmp = get_tmp(); - mpq_get_num(tmp, m_data); - return mpz_fits_slong_p(tmp) || - (mpz_cmp(tmp, int64_min()) >= 0 && mpz_cmp(tmp, int64_max()) <= 0); - } - bool is_uint64() const { - if (!is_int()) { - return false; - } - mpz_t & tmp = get_tmp(); - mpq_get_num(tmp, m_data); - return mpz_sgn(tmp) >= 0 && (mpz_fits_ulong_p(tmp) || mpz_cmp(tmp, uint64_max()) <= 0); - } - int64 get_int64() const; - uint64 get_uint64() const; - void neg() { mpq_neg(m_data, m_data); } - big_rational & operator=(const big_rational & r) { - mpq_set(m_data, r.m_data); - return *this; - } - bool operator==(const big_rational & r) const { return mpq_equal(m_data, r.m_data) != 0; } - bool operator<(const big_rational & r) const { return mpq_cmp(m_data, r.m_data) < 0; } - big_rational & operator+=(const big_rational & r) { - mpq_add(m_data, m_data, r.m_data); - return *this; - } - big_rational & operator-=(const big_rational & r) { - mpq_sub(m_data, m_data, r.m_data); - return *this; - } - big_rational & operator*=(const big_rational & r) { - mpq_mul(m_data, m_data, r.m_data); - return *this; - } - big_rational & operator/=(const big_rational & r) { - mpq_div(m_data, m_data, r.m_data); - return *this; - } - big_rational & operator%=(const big_rational & r) { - mpz_t & tmp = get_tmp(); - mpz_tdiv_r(tmp, mpq_numref(m_data), mpq_numref(r.m_data)); - mpq_set_z(m_data, tmp); - return *this; - } - friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) { - mpz_t & tmp = get_tmp(); - mpz_tdiv_q(tmp, mpq_numref(r1.m_data), mpq_numref(r2.m_data)); - mpq_set_z(result.m_data, tmp); - } - void get_numerator(big_rational & result) { - mpz_t & tmp = get_tmp(); - mpq_get_num(tmp, m_data); - mpq_set_z(result.m_data, tmp); - } - void get_denominator(big_rational & result) { - mpz_t & tmp = get_tmp(); - mpq_get_den(tmp, m_data); - mpq_set_z(result.m_data, tmp); - } - void get_floor(big_rational & result) { - mpz_t & tmp = get_tmp(); - mpz_fdiv_q(tmp, mpq_numref(m_data), mpq_denref(m_data)); - mpq_set_z(result.m_data, tmp); - } - std::string to_string() const; -#ifdef Z3DEBUG - static void test() { - init_limits(); - } -#endif -}; - -#endif - -#endif /* _GMP_BIG_RATIONAL_H_ */ - diff --git a/src/dead/lru_cache.cpp b/src/dead/lru_cache.cpp deleted file mode 100644 index cb61410b7..000000000 --- a/src/dead/lru_cache.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - lru_cache.cpp - -Abstract: - - expr -> expr LRU cache - -Author: - - Leonardo (leonardo) 2011-04-12 - -Notes: - ---*/ -#include"lru_cache.h" -#include"ast_ll_pp.h" - -#define MIN_MAX_SIZE 1024 -#define INITIAL_CAPACITY 128 - -lru_cache::cell * lru_cache::allocate(unsigned capacity) { - cell * mem = static_cast(memory::allocate(sizeof(cell) * capacity)); - memset(mem, 0, sizeof(cell)*capacity); - return mem; -} - -void lru_cache::deallocate(cell * table) { - memory::deallocate(table); -} - -lru_cache::cell * lru_cache::copy_table(cell * old_head, cell * new_table, unsigned new_capacity) { - SASSERT(old_head); - cell * it = old_head; - cell * new_head = 0; - cell * prev = 0; - do { - expr * k = it->m_key; - unsigned h = k->hash(); - unsigned mask = new_capacity - 1; - unsigned idx = h & mask; - - cell * begin = new_table + idx; - cell * end = new_table + new_capacity; - cell * curr = begin; - - for (; curr != end; ++curr) { - if (curr->m_key == 0) { - curr->m_key = k; - curr->m_value = it->m_value; - LCS_CODE(curr->m_hits = it->m_hits;); - LCS_CODE(curr->m_birthday = it->m_birthday;); - if (prev == 0) { - new_head = curr; - } - else { - prev->m_next = curr; - curr->m_prev = prev; - } - goto end; - } - } - for (curr = new_table; curr != begin; ++curr) { - if (curr->m_key == 0) { - curr->m_key = k; - curr->m_value = it->m_value; - SASSERT(prev != 0); - prev->m_next = curr; - curr->m_prev = prev; - } - goto end; - } - UNREACHABLE(); - end: - prev = curr; - it = it->m_next; - } - while (it != old_head); - prev->m_next = new_head; - new_head->m_prev = prev; - return new_head; -} - -void lru_cache::expand_table() { - SASSERT(m_head); - unsigned new_capacity = m_capacity * 2; - TRACE("lru_cache", tout << "expanding table new_capacity: " << new_capacity << "\n";); - cell * new_table = allocate(new_capacity); - m_head = copy_table(m_head, new_table, new_capacity); - deallocate(m_table); - m_table = new_table; - m_capacity = new_capacity; - m_num_deleted = 0; - SASSERT(check_invariant()); -} - -void lru_cache::remove_deleted() { - SASSERT(m_head); - TRACE("lru_cache", tout << "removing deleted entries\n";); - cell * new_table = allocate(m_capacity); - m_head = copy_table(m_head, new_table, m_capacity); - deallocate(m_table); - m_table = new_table; - m_num_deleted = 0; - SASSERT(check_invariant()); -} - -void lru_cache::init() { - if (m_max_size < MIN_MAX_SIZE) - m_max_size = MIN_MAX_SIZE; - m_size = 0; - m_capacity = INITIAL_CAPACITY; - m_table = allocate(m_capacity); - m_head = 0; - m_num_deleted = 0; -} - -lru_cache::lru_cache(ast_manager & m): - m_manager(m), - m_max_size(m.get_num_asts() * 100) { - init(); - TRACE("lru_cache", tout << "new lru cache, max-size: " << m_max_size << "\n";); -} - -lru_cache::lru_cache(ast_manager & m, unsigned max_size): - m_manager(m), - m_max_size(max_size) { - init(); -} - -void lru_cache::dec_refs() { - if (m_head) { - cell * curr = m_head; -#ifdef Z3DEBUG - unsigned sz = 0; -#endif - do { - m_manager.dec_ref(curr->m_key); - m_manager.dec_ref(curr->m_value); - curr = curr->m_next; - DEBUG_CODE(sz++;); - } - while (curr != m_head); - SASSERT(sz == m_size); - } -} - -lru_cache::~lru_cache() { - TRACE("lru_cache", tout << "destructor invoked size: " << m_size << ", m_head: " << m_head << "\n";); - LCS_CODE({ - if (m_head) { - unsigned used = 0; - cell * curr = m_head; - do { - if (curr->m_hits > 0) - used++; - curr = curr->m_next; - } - while (curr != m_head); - verbose_stream() << "[lru_cache] num-used: " << used << " size: " << m_size << "\n"; - } - }); - SASSERT(check_invariant()); - dec_refs(); - deallocate(m_table); -} - -void lru_cache::del_least_used() { - SASSERT(m_head); - SASSERT(m_size >= 2); - cell * c = m_head->m_prev; - TRACE("lru_cache", tout << "del least used: " << mk_bounded_pp(c->m_key, m_manager, 3) << "\n";); - LCS_CODE({ - static unsigned non_zero = 0; - static unsigned long long total_hits; - static unsigned counter = 0; - if (c->m_hits > 0) { - counter++; - total_hits += c->m_hits; - non_zero++; - if (non_zero % 1000 == 0) - verbose_stream() << "[lru_cache] cell with non-zero hits was deleted: " << non_zero << " avg: " << ((double)total_hits/(double) counter) << std::endl; - } - }); - SASSERT(c->m_prev != c); - SASSERT(c->m_next != c); - m_manager.dec_ref(c->m_key); - m_manager.dec_ref(c->m_value); - c->m_prev->m_next = c->m_next; - c->m_next->m_prev = c->m_prev; - SASSERT(m_head->m_prev == c->m_prev); - c->m_key = reinterpret_cast(1); - c->m_prev = 0; - c->m_next = 0; - m_size--; - m_num_deleted++; - CASSERT("lru_cache", check_invariant()); - if (m_num_deleted * 3 > m_capacity) - remove_deleted(); -} - -void lru_cache::add_front(cell * c) { - SASSERT(c->m_next == 0); - SASSERT(c->m_prev == 0); - if (m_head == 0) { - c->m_next = c; - c->m_prev = c; - m_head = c; - } - else { - c->m_prev = m_head->m_prev; - c->m_next = m_head; - m_head->m_prev->m_next = c; - m_head->m_prev = c; - m_head = c; - } - CASSERT("lru_cache", check_invariant()); - SASSERT(m_head == c); -} - -void lru_cache::move_front(cell * c) { - SASSERT(m_head); - SASSERT(c->m_next); - SASSERT(c->m_prev); - if (m_head != c) { - c->m_prev->m_next = c->m_next; - c->m_next->m_prev = c->m_prev; - - c->m_prev = m_head->m_prev; - c->m_next = m_head; - - m_head->m_prev->m_next = c; - m_head->m_prev = c; - - m_head = c; - } - CASSERT("lru_cache", check_invariant()); - SASSERT(m_head == c); -} - -void lru_cache::insert(expr * k, expr * v) { - LCS_CODE(m_time++;); - if (m_size == m_max_size) - del_least_used(); - else if (m_size * 2 > m_capacity) - expand_table(); - SASSERT(m_size < m_max_size); - unsigned h = k->hash(); - unsigned mask = m_capacity - 1; - unsigned idx = h & mask; - - cell * begin = m_table + idx; - cell * end = m_table + m_capacity; - cell * curr = begin; - cell * del_cell = 0; - -#define INSERT_LOOP() \ - if (curr->m_key == 0) { \ - cell * new_cell; \ - if (del_cell) { \ - new_cell = del_cell; \ - m_num_deleted--; \ - } \ - else { \ - new_cell = curr; \ - } \ - m_manager.inc_ref(k); \ - m_manager.inc_ref(v); \ - new_cell->m_key = k; \ - new_cell->m_value = v; \ - LCS_CODE(new_cell->m_hits = 0;); \ - LCS_CODE(new_cell->m_birthday = m_time;); \ - m_size++; \ - add_front(new_cell); \ - return; \ - } \ - if (curr->m_key == reinterpret_cast(1)) { \ - del_cell = curr; \ - continue; \ - } \ - if (curr->m_key == k) { \ - m_manager.inc_ref(v); \ - m_manager.dec_ref(curr->m_value); \ - curr->m_value = v; \ - LCS_CODE(curr->m_hits = 0;); \ - LCS_CODE(curr->m_birthday = m_time;); \ - move_front(curr); \ - return; \ - } - - for (; curr != end; ++curr) { - INSERT_LOOP(); - } - for (curr = m_table; curr != begin; ++curr) { - INSERT_LOOP(); - } - UNREACHABLE(); -} - -expr * lru_cache::find(expr * k) { - unsigned h = k->hash(); - unsigned mask = m_capacity - 1; - unsigned idx = h & mask; - -#ifdef LRU_CACHE_STATISTICS - static unsigned long long total_age = 0; - static unsigned long long max_time = 0; - static unsigned counter = 0; -#define COLLECT() \ - if (curr->m_hits == 0) { \ - counter ++; \ - unsigned age = m_time - curr->m_birthday; \ - if (age > max_time) \ - max_time = age; \ - total_age += age; \ - if (counter % 1000 == 0) \ - verbose_stream() << "[lru_cache] avg time for first hit: " << ((double) total_age / (double) counter) << " max time: " << max_time << "\n"; \ - } -#endif - - cell * begin = m_table + idx; - cell * end = m_table + m_capacity; - cell * curr = begin; - for (; curr != end; ++curr) { - if (curr->m_key == k) { - // LCS_CODE(COLLECT()); - LCS_CODE(if (curr->m_hits == 0 && m_time - curr->m_birthday >= 5000) return 0;) - LCS_CODE(curr->m_hits++;); - move_front(curr); - return curr->m_value; - } - if (curr->m_key == 0) - return 0; - } - for (curr = m_table; curr != begin; ++curr) { - if (curr->m_key == k) { - // LCS_CODE(COLLECT()); - LCS_CODE(curr->m_hits++;); - LCS_CODE(if (curr->m_hits == 0 && m_time - curr->m_birthday >= 5000) return 0;); - move_front(curr); - return curr->m_value; - } - if (curr->m_key == 0) - return 0; - } - return 0; -} - -void lru_cache::reset() { - TRACE("lru_cache", tout << "reset... m_size: " << m_size << "\n";); - LCS_CODE(m_time = 0;); - if (m_head) { - cell * curr = m_head; -#ifdef Z3DEBUG - unsigned sz = 0; -#endif - do { - m_manager.dec_ref(curr->m_key); - m_manager.dec_ref(curr->m_value); - cell * next = curr->m_next; - curr->m_key = 0; - curr->m_value = 0; - curr->m_next = 0; - curr->m_prev = 0; - LCS_CODE(curr->m_hits = 0;); - LCS_CODE(curr->m_birthday = 0;); - curr = next; - DEBUG_CODE(sz++;); - } - while (curr != m_head); - SASSERT(sz == m_size); - m_head = 0; - m_size = 0; - SASSERT(check_invariant()); - } -} - -void lru_cache::cleanup() { - dec_refs(); - deallocate(m_table); - m_capacity = INITIAL_CAPACITY; - m_table = allocate(m_capacity); - m_head = 0; - m_size = 0; - m_num_deleted = 0; -} - -bool lru_cache::check_invariant() const { - SASSERT(m_size <= m_max_size); - cell * begin = m_table; - cell * end = m_table + m_capacity; - unsigned sz = 0; - if (m_head) { - cell * curr = m_head; - do { - sz++; - SASSERT(curr->m_key != 0 && curr->m_key != reinterpret_cast(1)); - SASSERT(curr->m_next->m_prev == curr); - SASSERT(curr->m_prev->m_next == curr); - SASSERT(curr < end); - SASSERT(curr >= begin); - curr = curr->m_next; - } - while (curr != m_head); - } - SASSERT(m_size == sz); - sz = 0; - unsigned num_deleted = 0; - for (cell * it = begin; it != end; it++) { - if (it->m_key == reinterpret_cast(1)) { - num_deleted++; - continue; - } - if (it->m_key != 0) { - sz++; - } - } - SASSERT(m_size == sz); - SASSERT(m_num_deleted == num_deleted); - return true; -} diff --git a/src/dead/lru_cache.h b/src/dead/lru_cache.h deleted file mode 100644 index b9c72a01c..000000000 --- a/src/dead/lru_cache.h +++ /dev/null @@ -1,80 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - lru_cache.h - -Abstract: - - expr -> expr LRU cache - -Author: - - Leonardo (leonardo) 2011-04-12 - -Notes: - ---*/ -#ifndef _LRU_CACHE_H_ -#define _LRU_CACHE_H_ - -#include"ast.h" - -// #define LRU_CACHE_STATISTICS - -#ifdef LRU_CACHE_STATISTICS -#define LCS_CODE(CODE) { CODE } -#else -#define LCS_CODE(CODE) -#endif - -class lru_cache { - struct cell { - expr * m_key; - expr * m_value; - cell * m_prev; - cell * m_next; -#ifdef LRU_CACHE_STATISTICS - unsigned m_hits; - unsigned m_birthday; -#endif - }; - - ast_manager & m_manager; - cell * m_table; - cell * m_head; - unsigned m_size; - unsigned m_max_size; - unsigned m_capacity; - unsigned m_num_deleted; -#ifdef LRU_CACHE_STATISTICS - unsigned m_time; -#endif - - static cell * allocate(unsigned capacity); - static void deallocate(cell * table); - static cell * copy_table(cell * old_head, cell * new_table, unsigned new_capacity); - - void del_least_used(); - void add_front(cell * c); - void move_front(cell * c); - void expand_table(); - void remove_deleted(); - void init(); - void dec_refs(); -public: - lru_cache(ast_manager & m); - lru_cache(ast_manager & m, unsigned max_size); - ~lru_cache(); - void insert(expr * k, expr * v); - expr * find(expr * k); - void reset(); - void cleanup(); - unsigned size() const { return m_size; } - unsigned capacity() const { return m_capacity; } - bool empty() const { return m_size == 0; } - bool check_invariant() const; -}; - -#endif diff --git a/src/dead/parameters.h b/src/dead/parameters.h deleted file mode 100644 index 80c0d52d6..000000000 --- a/src/dead/parameters.h +++ /dev/null @@ -1,32 +0,0 @@ -/*++ -Copyright (c) 2007 Microsoft Corporation - -Module Name: - - parameters.h - -Abstract: - - Settings and parameters supplied to pre-processing and solver - modules. - -Author: - - Leonardo de Moura (leonardo) 2006-10-18. - Nikolaj Bjorner (nbjorner) 2007-02-15 - -Revision History: - 2007-02-15, nbjorner. - Hoisted out from simplify_parser.h and core_theory_types.h - in order to share functionality with SMTLIB and other - front-ends without bringing in the simplifier and core_theory. - ---*/ -#ifndef _PARAMETERS_H_ -#define _PARAMETERS_H_ - -#include"sat_params.h" -#include"core_theory_params.h" -#include"front_end_params.h" - -#endif diff --git a/src/dead/simple_sat.cpp b/src/dead/simple_sat.cpp deleted file mode 100644 index d949198fe..000000000 --- a/src/dead/simple_sat.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - simple_sat.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2006-10-10. - -Revision History: - ---*/ -#include -#include -#include"front_end_params.h" -#include"sat_def.h" -#include"dimacs_parser.h" -#include"timeit.h" -#include"mem_stat.h" - -class simple_sat_solver : public no_extension { - const front_end_params & m_params; - sat_solver * m_sat; - unsigned m_num_vars; - svector m_model; -public: - simple_sat_solver(const front_end_params & p): - m_params(p), - m_sat(new sat_solver(*this, p)), - m_num_vars(0) { - } - - ~simple_sat_solver() { - delete m_sat; - } - - static bool enable_ref_counters() { - return false; - } - - void mk_var() { - m_sat->mk_var(); - m_num_vars++; - } - - void mk_clause(const literal_vector & lits) { - m_sat->mk_main_clause(lits); - } - - unsigned get_num_vars() const { - return m_num_vars; - } - - lbool check() { - return m_sat->check(); - } - - void mk_model() { - if (m_params.m_build_model) { - m_sat->save_assignment(m_model); - } - } - - void display_model(std::ostream & out) const { - int sz = m_model.size(); - for (int i = 1; i < sz; i++) { - if (m_model[i] == l_true) { - out << i << " "; - } - else if (m_model[i] == l_false) { - out << -i << " "; - } - } - out << "\n"; - } - - void display_statistics(std::ostream & out) const { - m_sat->display_statistics(out); - } -}; - -extern bool g_display_statistics; -extern front_end_params g_front_end_params; - -void solve_cnf(const char * file) { - clock_t start_time = clock(); - simple_sat_solver solver(g_front_end_params); - std::ifstream in(file); - parse_dimacs(in, solver); - lbool r = solver.check(); - clock_t end_time = clock(); - switch(r) { - case l_false: - std::cout << "unsat\n"; - break; - case l_undef: - std::cout << "unknown\n"; - break; - case l_true: - std::cout << "sat\n"; - if (g_front_end_params.m_build_model) { - solver.display_model(std::cout); - } - break; - } - if (g_display_statistics) { - solver.display_statistics(std::cerr); - memory::display_max_usage(std::cerr); - std::cerr << "time: " << ((static_cast(end_time) - static_cast(start_time)) / CLOCKS_PER_SEC) << "\n"; - } -} - diff --git a/src/dead/simple_sat.h b/src/dead/simple_sat.h deleted file mode 100644 index 260e9d65e..000000000 --- a/src/dead/simple_sat.h +++ /dev/null @@ -1,26 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - simple_sat.h - -Abstract: - - Simple SAT solver using the Z3 SAT template. - -Author: - - Leonardo de Moura (leonardo) 2006-10-10. - -Revision History: - ---*/ - -#ifndef _SIMPLE_SAT_H_ -#define _SIMPLE_SAT_H_ - -void solve_cnf(const char * file); - -#endif /* _SIMPLE_SAT_H_ */ - diff --git a/src/dead/smt_classifier.h b/src/dead/smt_classifier.h deleted file mode 100644 index 1ce27f3eb..000000000 --- a/src/dead/smt_classifier.h +++ /dev/null @@ -1,46 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - smt_classifier.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-06-24. - -Revision History: - ---*/ -#ifndef _SMT_CLASSIFIER_H_ -#define _SMT_CLASSIFIER_H_ - -#include"static_features.h" - -namespace smt { - - class classifier { - context & m_context; - ast_manager & m_manager; - static_features m_static_features; - symbol m_logic; - public: - classifier(context & c); - /** - \brief Give a hint by specifying the logic used to describe a problem. - */ - void set_logic(symbol & s); - /** - \brief Setup the logical context for solving the following formulas. - */ - void setup(unsigned num_formulas, expr * const * fs); - }; - -}; - -#endif /* _SMT_CLASSIFIER_H_ */ - diff --git a/src/dead/smt_euf.cpp b/src/dead/smt_euf.cpp deleted file mode 100644 index e6c393f69..000000000 --- a/src/dead/smt_euf.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - smt_euf.cpp - -Abstract: - - Equality and uninterpreted functions - -Author: - - Leonardo de Moura (leonardo) 2012-02-14. - -Revision History: - ---*/ -#include"smt_euf.h" -#include"smt_context.h" -#include"ast_smt2_pp.h" - -namespace smt { - - struct euf_manager::imp { - context & m_context; - ast_manager & m_manager; - region & m_region; - expr_ref_vector m_e_internalized_stack; // stack of the expressions already internalized as enodes. - ptr_vector m_app2enode; // app -> enode - ptr_vector m_enodes; - vector m_decl2enodes; // decl -> enode (for decls with arity > 0) - cg_table m_cg_table; - dyn_ack_manager m_dyn_ack_manager; - struct new_eq { - enode * m_lhs; - enode * m_rhs; - eq_justification m_justification; - new_eq() {} - new_eq(enode * lhs, enode * rhs, eq_justification const & js): - m_lhs(lhs), m_rhs(rhs), m_justification(js) {} - }; - svector m_eq_propagation_queue; - struct new_th_eq { - theory_id m_th_id; - theory_var m_lhs; - theory_var m_rhs; - new_th_eq():m_th_id(null_theory_id), m_lhs(null_theory_var), m_rhs(null_theory_var) {} - new_th_eq(theory_id id, theory_var l, theory_var r):m_th_id(id), m_lhs(l), m_rhs(r) {} - }; - svector m_th_eq_propagation_queue; - svector m_th_diseq_propagation_queue; - enode * m_is_diseq_tmp; // auxiliary enode used to find congruent equality atoms. - tmp_enode m_tmp_enode; - ptr_vector m_almost_cg_tables; // temporary field for is_ext_diseq - obj_map m_cached_generation; - obj_hashtable m_cache_generation_visited; - friend class mk_enode_trail; - class mk_enode_trail : public trail { - imp & m_owner; - public: - mk_enode_trail(imp & o):m_owner(o) {} - virtual void undo(context & ctx) { m_owner.undo_mk_enode(); } - }; - mk_enode_trail m_mk_enode_trail; - volatile bool m_cancel_flag; - - // Statistics - unsigned m_num_mk_enode; - unsigned m_num_del_enode; - - void push_eq(enode * lhs, enode * rhs, eq_justification const & js) { - SASSERT(lhs != rhs); - m_eq_propagation_queue.push_back(new_eq(lhs, rhs, js)); - } - - void push_new_congruence(enode * n1, enode * n2, bool used_commutativity) { - SASSERT(n1->m_cg == n2); - push_eq(n1, n2, eq_justification::mk_cg(used_commutativity)); - } - - bool e_internalized(expr const * n) const { - return m_app2enode.get(n->get_id(), 0) != 0; - } - - void set_app2enode(expr const * n, enode * e) { - m_app2enode.setx(n->get_id(), e, 0); - } - - enode * mk_enode(app * n, bool suppress_args, bool merge_tf, bool cgc_enabled, unsigned generation) { - TRACE("mk_enode_detail", - tout << mk_ismt2_pp(n, m_manager) << "\n"; - tout <<"suppress_args: " << suppress_args << ", merge_tf: " << merge_tf << ", cgc_enabled: " << cgc_enabled << "\n";); - SASSERT(!e_internalized(n)); - unsigned scope_lvl = m_context.get_scope_level(); - unsigned id = n->get_id(); - unsigned _generation = 0; - if (!m_cached_generation.empty() && m_cached_generation.find(n, _generation)) { - generation = _generation; - } - enode * e = enode::mk(m_manager, m_region, m_app2enode, n, generation, suppress_args, merge_tf, scope_lvl, cgc_enabled, true); - TRACE("mk_enode_detail", tout << "e.get_num_args() = " << e->get_num_args() << "\n";); - if (n->get_num_args() == 0 && m_manager.is_value(n)) - e->mark_as_interpreted(); - TRACE("mk_var_bug", tout << "mk_enode: " << id << "\n";); - TRACE("generation", tout << "mk_enode: " << id << " " << generation << "\n";); - set_app2enode(n, e); - m_e_internalized_stack.push_back(n); - m_context.push_trail_ptr(&m_mk_enode_trail); - m_enodes.push_back(e); - if (e->get_num_args() > 0) { - if (e->is_true_eq()) { - /* - bool_var v = enode2bool_var(e); - assign(literal(v), mk_justification(eq_propagation_justification(e->get_arg(0), e->get_arg(1)))); - e->m_cg = e; - */ - } - else { - if (cgc_enabled) { - enode_bool_pair pair = m_cg_table.insert(e); - enode * e_prime = pair.first; - if (e != e_prime) { - e->m_cg = e_prime; - bool used_commutativity = pair.second; - push_new_congruence(e, e_prime, used_commutativity); - } - else { - e->m_cg = e; - } - } - else { - e->m_cg = e; - } - } - if (!e->is_eq()) { - unsigned decl_id = n->get_decl()->get_decl_id(); - if (decl_id >= m_decl2enodes.size()) - m_decl2enodes.resize(decl_id+1); - m_decl2enodes[decl_id].push_back(e); - } - } - SASSERT(e_internalized(n)); - m_num_mk_enode++; - - // #ifndef SMTCOMP - // if (m_params.m_trace_stream != NULL) - // *m_params.m_trace_stream << "[attach-enode] #" << n->get_id() << " " << m_generation << "\n"; - // #endif - - return e; - } - - void undo_mk_enode() { - SASSERT(!m_e_internalized_stack.empty()); - m_num_del_enode++; - expr * n = m_e_internalized_stack.back(); - TRACE("undo_mk_enode", tout << "undo_enode: #" << n->get_id() << "\n" << mk_ismt2_pp(n, m_manager) << "\n";); - TRACE("mk_var_bug", tout << "undo_mk_enode: " << n->get_id() << "\n";); - unsigned n_id = n->get_id(); - SASSERT(is_app(n)); - enode * e = m_app2enode[n_id]; - m_app2enode[n_id] = 0; - if (e->is_cgr() && !e->is_true_eq() && e->is_cgc_enabled()) { - SASSERT(m_cg_table.contains_ptr(e)); - m_cg_table.erase(e); - } - if (e->get_num_args() > 0 && !e->is_eq()) { - unsigned decl_id = to_app(n)->get_decl()->get_decl_id(); - SASSERT(decl_id < m_decl2enodes.size()); - SASSERT(m_decl2enodes[decl_id].back() == e); - m_decl2enodes[decl_id].pop_back(); - } - e->del_eh(m_manager); - SASSERT(m_e_internalized_stack.size() == m_enodes.size()); - m_enodes.pop_back(); - m_e_internalized_stack.pop_back(); - } - - }; - - euf_manager::euf_manager(context & ctx) { - } - - euf_manager::~euf_manager() { - } -}; diff --git a/src/dead/smt_euf.h b/src/dead/smt_euf.h deleted file mode 100644 index b21205a5e..000000000 --- a/src/dead/smt_euf.h +++ /dev/null @@ -1,55 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - smt_euf.h - -Abstract: - - Equality and uninterpreted functions - -Author: - - Leonardo de Moura (leonardo) 2012-02-14. - -Revision History: - ---*/ -#ifndef _SMT_EUF_H_ -#define _SMT_EUF_H_ - -#include"ast.h" -#include"smt_enode.h" -#include"smt_eq_justification.h" - -namespace smt { - class context; - - class euf_manager { - struct imp; - imp * m_imp; - public: - euf_manager(context & ctx); - ~euf_manager(); - - enode * mk_enode(app * n, bool suppress_args, bool merge_tf, bool cgc_enabled); - - void add_eq(enode * n1, enode * n2, eq_justification js); - bool assume_eq(enode * lhs, enode * rhs); - void reset(); - - static bool is_eq(enode const * n1, enode const * n2) { return n1->get_root() == n2->get_root(); } - bool is_diseq(enode * n1, enode * n2) const; - bool is_ext_diseq(enode * n1, enode * n2, unsigned depth); - enode * get_enode_eq_to(func_decl * f, unsigned num_args, enode * const * args); - bool is_shared(enode * n) const; - - unsigned get_num_enodes_of(func_decl const * decl) const; - enode_vector::const_iterator begin_enodes_of(func_decl const * decl) const; - enode_vector::const_iterator end_enodes_of(func_decl const * decl) const; - }; -}; - - -#endif diff --git a/src/dead/smt_trail.h b/src/dead/smt_trail.h deleted file mode 100644 index 0ac45ea18..000000000 --- a/src/dead/smt_trail.h +++ /dev/null @@ -1,131 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - smt_trail.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-19. - -Revision History: - ---*/ -#ifndef _SMT_TRAIL_H_ -#define _SMT_TRAIL_H_ - -namespace smt { - - class context; - - class trail { - public: - virtual ~trail() { - } - virtual void undo(context & ctx) = 0; - }; - - template - class value_trail : public trail { - T & m_value; - T m_old_value; - - public: - value_trail(T & value): - m_value(value), - m_old_value(value) { - } - - virtual ~value_trail() { - } - - virtual void undo(context & ctx) { - m_value = m_old_value; - } - }; - - template - class set_ptr_trail : public trail { - T * & m_ptr; - public: - set_ptr_trail(T * & ptr): - m_ptr(ptr) { - SASSERT(m_ptr == 0); - } - - virtual void undo(context & ctx) { - m_ptr = 0; - } - }; - - template - class vector_value_trail : public trail { - vector & m_vector; - unsigned m_idx; - T m_old_value; - public: - vector_value_trail(vector & v, unsigned idx): - m_vector(v), - m_idx(idx), - m_old_value(v[idx]) { - } - - virtual ~vector_value_trail() { - } - - virtual void undo(context & ctx) { - m_vector[m_idx] = m_old_value; - } - }; - - template - class push_back_trail : public trail { - vector & m_vector; - public: - push_back_trail(vector & v): - m_vector(v) { - } - - virtual void undo(context & ctx) { - m_vector.pop_back(); - } - }; - - class set_bitvector_trail : public trail { - svector & m_vector; - unsigned m_idx; - public: - set_bitvector_trail(svector & v, unsigned idx): - m_vector(v), - m_idx(idx) { - SASSERT(m_vector[m_idx] == false); - m_vector[m_idx] = true; - } - - virtual void undo(context & ctx) { - m_vector[m_idx] = false; - } - }; - - template - class new_obj_trail : public trail { - T * m_obj; - public: - new_obj_trail(T * obj): - m_obj(obj) { - } - - virtual void undo(context & ctx) { - dealloc(m_obj); - } - }; - -}; - -#endif /* _SMT_TRAIL_H_ */ - diff --git a/src/dead/spc/README b/src/dead/spc/README deleted file mode 100644 index 67ccf0e3c..000000000 --- a/src/dead/spc/README +++ /dev/null @@ -1,2 +0,0 @@ -Superposition Calculus. -This module is currently disabled. \ No newline at end of file diff --git a/src/dead/spc/fvi.h b/src/dead/spc/fvi.h deleted file mode 100644 index fffec2ce3..000000000 --- a/src/dead/spc/fvi.h +++ /dev/null @@ -1,214 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - fvi.h - -Abstract: - - Feature Vector Indexing. - -Author: - - Leonardo de Moura (leonardo) 2008-02-01. - -Revision History: - ---*/ -#ifndef _FVI_H_ -#define _FVI_H_ - -#include"splay_tree_map.h" -#include"hashtable.h" -#include"vector.h" - -/** - \brief A feature vector indexing for objects of type T *. - - ToVector is a functor for converting T into a vector of natural numbers. - It should provide a method: - - void operator(T * d, unsigned * f); - This method should fill the vector f with the features of d. - - Hash: functor for computing the hashcode of T *. - - Eq : functor for comparing T pointers. -*/ -template > -class fvi : private ToVector { -public: - struct statistics { - unsigned m_size; - unsigned m_num_nodes; - unsigned m_num_leaves; - unsigned m_min_leaf_size; - unsigned m_avg_leaf_size; - unsigned m_max_leaf_size; - statistics() { reset(); } - - void reset() { - m_size = m_num_nodes = m_num_leaves = m_avg_leaf_size = m_max_leaf_size = 0; - m_min_leaf_size = UINT_MAX; - } - }; - -private: - struct ucompare { - int operator()(unsigned i1, unsigned i2) const { - if (i1 < i2) return -1; - if (i1 > i2) return 1; - return 0; - } - }; - - struct node { - node() {} - virtual ~node() {} - virtual bool is_leaf() const = 0; - }; - - typedef splay_tree_map children; - - struct non_leaf : public node { - children m_children; - non_leaf() {} - - struct delete_children { - void operator()(unsigned k, node * n) const { - dealloc(n); - } - }; - - virtual ~non_leaf() { - delete_children visitor; - m_children.visit(visitor); - m_children.reset(); - } - - virtual bool is_leaf() const { return false; } - }; - - typedef ptr_hashtable set; - - struct leaf : public node { - set m_set; - leaf() {} - virtual ~leaf() {} - virtual bool is_leaf() const { return true; } - }; - - unsigned m_num_features; - svector m_tmp_buffer; - non_leaf * m_root; - - struct stop {}; - - template - void visit_leaf(leaf * n, Visitor & v, bool le) const { - typename set::iterator it = n->m_set.begin(); - typename set::iterator end = n->m_set.end(); - for (; it != end; ++it) - if (!v(*it)) - throw stop(); - } - - template - struct non_leaf_visitor { - fvi const & m_owner; - unsigned m_fidx; - Visitor & m_visitor; - bool m_le; - - non_leaf_visitor(fvi const & o, unsigned fidx, Visitor & v, bool le): - m_owner(o), m_fidx(fidx), m_visitor(v), m_le(le) {} - - void operator()(unsigned k, node * n) { - if (n->is_leaf()) - m_owner.visit_leaf(static_cast(n), m_visitor, m_le); - else - m_owner.visit_non_leaf(static_cast(n), m_fidx + 1, m_visitor, m_le); - } - }; - - template - void visit_non_leaf(non_leaf * n, unsigned fidx, Visitor & v, bool le) const { - // Remark: this function is recursive, but there is no risk - // of stack overflow since the number of features is small. - non_leaf_visitor v2(*this, fidx, v, le); - if (le) - n->m_children.visit_le(v2, m_tmp_buffer[fidx]); - else - n->m_children.visit_ge(v2, m_tmp_buffer[fidx]); - } - -#ifdef Z3DEBUG - bool m_visiting; -#endif - - void to_fvector(T * d) const { - fvi * _this = const_cast(this); - _this->ToVector::operator()(d, _this->m_tmp_buffer.c_ptr()); - } - - struct non_leaf_stat_visitor { - fvi const & m_owner; - statistics & m_stats; - non_leaf_stat_visitor(fvi const & o, statistics & st):m_owner(o), m_stats(st) {} - void operator()(unsigned k, node * n); - }; - - void stats(leaf * n, statistics & result) const; - void stats(non_leaf * n, statistics & result) const; - - struct non_leaf_collect_visitor { - fvi const & m_owner; - ptr_vector & m_elems; - non_leaf_collect_visitor(fvi const & o, ptr_vector & elems):m_owner(o), m_elems(elems) {} - void operator()(unsigned k, node * n); - }; - - void collect(leaf * n, ptr_vector & result) const; - void collect(non_leaf * n, ptr_vector & result) const; - -public: - fvi(unsigned num_features, ToVector const & t = ToVector()); - ~fvi() { reset(); dealloc(m_root); } - - void insert(T * d); - bool contains(T * d) const; - void erase(T * d); - void reset(); - - /** - \brief Traverse the elements that have features smaller (greater) or equal than the one of the given element. - - For each visited element the following method of v is executed: - - - bool operator()(T * d) - - If false is returned, the traversal is aborted. - - \warning The object cannot be updated during the traversal. - */ - template - void visit(T * d, Visitor & v, bool le = true) const { - DEBUG_CODE(const_cast(this)->m_visiting = true;); - to_fvector(d); - try { - visit_non_leaf(m_root, 0, v, le); - } - catch (stop) { - } - DEBUG_CODE(const_cast(this)->m_visiting = false;); - } - - void stats(statistics & result) const; - - /** - \brief Copy to result the set of elements stored in the index. - */ - void collect(ptr_vector & result) const; -}; - -#endif /* _FVI_H_ */ diff --git a/src/dead/spc/fvi_def.h b/src/dead/spc/fvi_def.h deleted file mode 100644 index 8fcbda89b..000000000 --- a/src/dead/spc/fvi_def.h +++ /dev/null @@ -1,199 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - fvi_def.h - -Abstract: - - Feature Vector Indexing. - -Author: - - Leonardo de Moura (leonardo) 2008-02-01. - -Revision History: - ---*/ -#ifndef _FVI_DEF_H_ -#define _FVI_DEF_H_ - -#include"fvi.h" -#include"splay_tree_def.h" -#include"buffer.h" - -template -fvi::fvi(unsigned num_features, ToVector const & t): - ToVector(t), - m_num_features(num_features), - m_root(0) { - m_tmp_buffer.resize(num_features, 0); - m_root = alloc(non_leaf); - SASSERT(num_features >= 2); - DEBUG_CODE(m_visiting = false;); -} - -template -void fvi::reset() { - SASSERT(!m_visiting); - dealloc(m_root); - m_root = alloc(non_leaf); -} - -template -void fvi::insert(T * d) { - SASSERT(!m_visiting); - to_fvector(d); - non_leaf * n = m_root; - unsigned i = 0; - for (; i < m_num_features - 1; i++) { - node * child = 0; - if (!n->m_children.find(m_tmp_buffer[i], child)) { - child = alloc(non_leaf); - n->m_children.insert(m_tmp_buffer[i], child); - } - SASSERT(child); - SASSERT(!child->is_leaf()); - n = static_cast(child); - } - node * l = 0; - SASSERT(i == m_num_features - 1); - if (!n->m_children.find(m_tmp_buffer[i], l)) { - l = alloc(leaf); - n->m_children.insert(m_tmp_buffer[i], l); - } - SASSERT(l); - SASSERT(l->is_leaf()); - static_cast(l)->m_set.insert(d); -} - -template -bool fvi::contains(T * d) const { - to_fvector(d); - non_leaf * n = m_root; - node * child; - unsigned i = 0; - for (; i < m_num_features - 1; i++) { - if (!n->m_children.find(m_tmp_buffer[i], child)) - return false; - SASSERT(child); - SASSERT(!child->is_leaf()); - n = static_cast(child); - } - SASSERT(i == m_num_features - 1); - return - n->m_children.find(m_tmp_buffer[i], child) && - static_cast(child)->m_set.contains(d); -} - -template -void fvi::erase(T * d) { - SASSERT(!m_visiting); - SASSERT(contains(d)); - ptr_buffer path; - to_fvector(d); - non_leaf * n = m_root; - node * child; - unsigned i = 0; - for (; i < m_num_features - 1; i++) { - path.push_back(n); - if (!n->m_children.find(m_tmp_buffer[i], child)) { - UNREACHABLE(); - } - SASSERT(child); - SASSERT(!child->is_leaf()); - n = static_cast(child); - } - path.push_back(n); - SASSERT(i == m_num_features - 1); - if (!n->m_children.find(m_tmp_buffer[i], child)) { - UNREACHABLE(); - } - SASSERT(child); - SASSERT(child->is_leaf()); - leaf * l = static_cast(child); - l->m_set.erase(d); - if (l->m_set.empty()) { - dealloc(l); - while (true) { - non_leaf * n = path.back(); - n->m_children.erase(m_tmp_buffer[i]); - path.pop_back(); - i--; - if (!n->m_children.empty() || n == m_root) - break; - dealloc(n); - } - } -} - -template -void fvi::non_leaf_stat_visitor::operator()(unsigned k, node * n) { - if (n->is_leaf()) - m_owner.stats(static_cast(n), m_stats); - else - m_owner.stats(static_cast(n), m_stats); -} - -template -void fvi::stats(leaf * n, statistics & result) const { - unsigned sz = n->m_set.size(); - result.m_size += sz; - if (sz > result.m_max_leaf_size) - result.m_max_leaf_size = sz; - if (sz < result.m_min_leaf_size) - result.m_min_leaf_size = sz; - result.m_num_leaves ++; - result.m_num_nodes ++; -} - -template -void fvi::stats(non_leaf * n, statistics & result) const { - result.m_num_nodes++; - // Remark: this function is recursive, but there is no risk - // of stack overflow since the number of features is small. - non_leaf_stat_visitor v(*this, result); - n->m_children.visit(v); -} - -template -void fvi::stats(statistics & result) const { - result.reset(); - stats(m_root, result); - if (m_root->m_children.empty()) - result.m_min_leaf_size = 0; - if (result.m_num_leaves > 0) - result.m_avg_leaf_size = result.m_size / result.m_num_leaves; -} - -template -void fvi::non_leaf_collect_visitor::operator()(unsigned k, node * n) { - if (n->is_leaf()) - m_owner.collect(static_cast(n), m_elems); - else - m_owner.collect(static_cast(n), m_elems); -} - -template -void fvi::collect(leaf * n, ptr_vector & result) const { - typename set::iterator it = n->m_set.begin(); - typename set::iterator end = n->m_set.end(); - for (; it != end; ++it) - result.push_back(*it); -} - -template -void fvi::collect(non_leaf * n, ptr_vector & result) const { - // Remark: this function is recursive, but there is no risk - // of stack overflow since the number of features is small. - non_leaf_collect_visitor v(*this, result); - n->m_children.visit(v); -} - -template -void fvi::collect(ptr_vector & result) const { - collect(m_root, result); -} - -#endif /* _FVI_DEF_H_ */ diff --git a/src/dead/spc/kbo.cpp b/src/dead/spc/kbo.cpp deleted file mode 100644 index e35bdbda8..000000000 --- a/src/dead/spc/kbo.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - kbo.cpp - -Abstract: - - Knuth-Bendix ordering. - -Author: - - Leonardo de Moura (leonardo) 2008-01-28. - -Revision History: - ---*/ -#include"kbo.h" -#include"ast_pp.h" - -inline unsigned kbo::f_weight(func_decl * f) const { - // TODO - return 1; -} - -inline unsigned kbo::var_weight() const { - return m_var_weight; -} - -inline void kbo::reset() { - m_weight_balance = 0; - m_deltas.reset(); - m_num_pos = 0; - m_num_neg = 0; -} - -/** - \brief Increase the balance of the given variable. -*/ -inline void kbo::inc(expr_offset v) { - SASSERT(is_var(v.get_expr())); - int val; - unsigned v_idx = to_var(v.get_expr())->get_idx(); - unsigned offset = v.get_offset(); - if (m_deltas.find(v_idx, offset, val)) { - if (val == -1) - m_num_neg--; - else if (val == 0) - m_num_pos++; - m_deltas.insert(v_idx, offset, val + 1); - } - else { - m_deltas.insert(v_idx, offset, 1); - m_num_pos ++; - } -} - -/** - \brief Decreate the balance of the given variable. -*/ -inline void kbo::dec(expr_offset v) { - int val; - unsigned v_idx = to_var(v.get_expr())->get_idx(); - unsigned offset = v.get_offset(); - if (m_deltas.find(v_idx, offset, val)) { - if (val == 0) - m_num_neg++; - else if (val == 1) - m_num_pos--; - m_deltas.insert(v_idx, offset, val - 1); - } - else { - m_deltas.insert(v_idx, offset, -1); - m_num_neg ++; - } -} - -/** - \brief Accumulate the variables and weight balance of t. Return - true if t contains target_var. -*/ -template -bool kbo::VWBc(expr_offset t, expr_offset target_var) { - SASSERT(target_var.get_expr() == 0 || is_var(target_var.get_expr())); - svector & todo = m_vwbc_todo; - expr_offset s; - bool found = false; - unsigned j; - SASSERT(todo.empty()); - todo.push_back(t); - while (!todo.empty()) { - t = todo.back(); - if (t == target_var) - found = true; - expr * n = t.get_expr(); - unsigned offset = t.get_offset(); - todo.pop_back(); - switch (n->get_kind()) { - case AST_VAR: - if (m_subst && m_subst->find(to_var(n), offset, s)) - todo.push_back(s); - else if (pos) { - inc(t); - m_weight_balance += var_weight(); - } - else { - dec(t); - m_weight_balance -= var_weight(); - } - break; - case AST_APP: - if (pos) - m_weight_balance += f_weight(to_app(n)->get_decl()); - else - m_weight_balance -= f_weight(to_app(n)->get_decl()); - j = to_app(n)->get_num_args(); - while (j > 0) { - --j; - todo.push_back(expr_offset(to_app(n)->get_arg(j), offset)); - } - break; - default: - UNREACHABLE(); - break; - } - } - return found; -} - -template -inline void kbo::VWB(expr_offset t, unsigned idx) { - expr_offset null(0, 0); - app * n = to_app(t.get_expr()); - unsigned num = n->get_num_args(); - for (; idx < num; idx++) - VWBc(expr_offset(n->get_arg(idx), t.get_offset()), null); -} - -inline bool is_unary_app(expr * n) { - return is_app(n) && to_app(n)->get_num_args() == 1; -} - -inline kbo::result kbo::no_neg() const { - return m_num_neg == 0 ? GREATER : UNCOMPARABLE; -} - -inline kbo::result kbo::no_pos() const { - return m_num_pos == 0 ? LESSER : UNCOMPARABLE; -} - -order::result kbo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) { - reset(); - m_subst = s; - - if (t1 == t2) - return EQUAL; - - expr * n1 = t1.get_expr(); - expr * n2 = t2.get_expr(); - - // f(s) >_{kbo} f(t) iff s >_{kbo} t - while (is_unary_app(n1) && is_unary_app(n2) && to_app(n1)->get_decl() == to_app(n2)->get_decl()) { - n1 = to_app(n1)->get_arg(0); - n2 = to_app(n2)->get_arg(0); - } - - svector & todo = m_compare_todo; - SASSERT(todo.empty()); - todo.push_back(entry(find(expr_offset(n1, t1.get_offset())), - find(expr_offset(n2, t2.get_offset())), - 0)); - - result res = UNKNOWN; - - while (!todo.empty()) { - entry & e = todo.back(); - expr_offset t1 = e.m_t1; - expr_offset t2 = e.m_t2; - expr * n1 = t1.get_expr(); - expr * n2 = t2.get_expr(); - TRACE("kbo", tout << "processing with idx: " << e.m_idx << "\n" << - mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n"; - tout << "wb : " << m_weight_balance << "\n";); - SASSERT(!is_quantifier(n1) && !is_quantifier(n2)); - bool v1 = is_var(n1); - bool v2 = is_var(n2); - if (v1 && v2) { - todo.pop_back(); - inc(t1); - dec(t2); - res = t1 == t2 ? EQUAL : UNCOMPARABLE; - } - else if (v1) { - todo.pop_back(); - res = VWBc(t2, t1) ? LESSER : UNCOMPARABLE; - inc(t1); - m_weight_balance += var_weight(); - } - else if (v2) { - todo.pop_back(); - res = VWBc(t1, t2) ? GREATER : UNCOMPARABLE; - dec(t2); - m_weight_balance -= var_weight(); - } - else { - func_decl * f = to_app(n1)->get_decl(); - func_decl * g = to_app(n2)->get_decl(); - result lex; - if (f != g || to_app(n1)->get_num_args() != to_app(n2)->get_num_args()) { - VWB(t1, 0); - VWB(t2, 0); - lex = UNCOMPARABLE; - } - else { - unsigned & idx = e.m_idx; - // when idx > 0, res contains the result for child (idx - 1) - if (idx > 0 && res != EQUAL) { - VWB(t1, idx); - VWB(t2, idx); - lex = res; - } - else if (idx == to_app(n1)->get_num_args()) { - // all children were visited - lex = EQUAL; - } - else if (idx < to_app(n1)->get_num_args()) { - expr_offset c1 = find(expr_offset(to_app(n1)->get_arg(idx), t1.get_offset())); - expr_offset c2 = find(expr_offset(to_app(n2)->get_arg(idx), t2.get_offset())); - idx++; // move curr entry child idx - entry new_entry(c1, c2, 0); - todo.push_back(new_entry); - continue; // process child before continuing - } - } - - todo.pop_back(); - m_weight_balance += f_weight(f); - m_weight_balance -= f_weight(g); - - if (m_weight_balance > 0) - res = no_neg(); - else if (m_weight_balance < 0) - res = no_pos(); - else if (f_greater(f, g)) - res = no_neg(); - else if (f_greater(g, f)) - res = no_pos(); - else if (f != g) - res = UNCOMPARABLE; - else if (lex == EQUAL) - res = EQUAL; - else if (lex == GREATER) - res = no_neg(); - else if (lex == LESSER) - res = no_pos(); - else - res = UNCOMPARABLE; - } - TRACE("kbo", tout << "result: " << res << "\n";); - } - - return res; -} - -bool kbo::greater(expr_offset const & t1, expr_offset const & t2, substitution * s) { - return compare(t1, t2, s) == GREATER; -} - -int kbo::compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) { - switch (compare(t1, t2, s)) { - case GREATER: return 1; - case EQUAL: return 0; - default: return -1; - } -} diff --git a/src/dead/spc/kbo.h b/src/dead/spc/kbo.h deleted file mode 100644 index eed4709bd..000000000 --- a/src/dead/spc/kbo.h +++ /dev/null @@ -1,70 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - kbo.h - -Abstract: - - Knuth-Bendix ordering. - -Author: - - Leonardo de Moura (leonardo) 2008-01-28. - -Revision History: - ---*/ -#ifndef _KBO_H_ -#define _KBO_H_ - -#include"order.h" - -class kbo : public order { - struct entry { - expr_offset m_t1; - expr_offset m_t2; - unsigned m_idx; - entry():m_idx(UINT_MAX) {} - entry(expr_offset const & t1, expr_offset const & t2, unsigned idx): - m_t1(t1), m_t2(t2), m_idx(idx) {} - }; - - unsigned m_var_weight; - int m_weight_balance; - var_offset_map m_deltas; - unsigned m_num_pos; - unsigned m_num_neg; - svector m_vwbc_todo; - svector m_compare_todo; - - unsigned f_weight(func_decl * f) const; - unsigned var_weight() const; - - void reset(); - void inc(expr_offset v); - void dec(expr_offset v); - - template - bool VWBc(expr_offset t, expr_offset target_var); - - template - void VWB(expr_offset t, unsigned idx); - - result no_neg() const; - result no_pos() const; - -public: - kbo(ast_manager & m, precedence * p, unsigned var_weight = 1):order(m, p), m_var_weight(var_weight) {} - virtual ~kbo() {} - virtual void reserve(unsigned num_offsets, unsigned num_vars) { m_deltas.reserve(num_offsets, num_vars); } - virtual void reserve_offsets(unsigned num_offsets) { m_deltas.reserve_offsets(num_offsets); } - virtual void reserve_vars(unsigned num_vars) { m_deltas.reserve_vars(num_vars); } - virtual result compare(expr_offset const & t1, expr_offset const & t2, substitution * s); - result compare(expr * t1, expr * t2) { return compare(expr_offset(t1, 0), expr_offset(t2, 0), 0); } - virtual bool greater(expr_offset const & t1, expr_offset const & t2, substitution * s); - virtual int compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s); -}; - -#endif /* _KBO_H_ */ diff --git a/src/dead/spc/lpo.cpp b/src/dead/spc/lpo.cpp deleted file mode 100644 index d7af7aec5..000000000 --- a/src/dead/spc/lpo.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - lpo.h - -Abstract: - - Lexicographical Path Ordering - -Author: - - Leonardo de Moura (leonardo) 2008-02-01. - -Revision History: - ---*/ -#include"lpo.h" - -/** - \brief Check whether the variable in t1 occurs in t2. -*/ -bool lpo::occurs(expr_offset const & t1, expr_offset const & t2) { - SASSERT(is_var(t1.get_expr())); - if (is_ground(t2.get_expr())) - return false; - m_todo.reset(); - m_todo.push_back(t2); - while (!m_todo.empty()) { - expr_offset t = m_todo.back(); - m_todo.pop_back(); - t = find(t); - expr * n = t.get_expr(); - if (is_ground(n)) - continue; - unsigned offset = t.get_offset(); - unsigned j; - switch (n->get_kind()) { - case AST_VAR: - if (t == t1) - return true; - break; - case AST_APP: - j = to_app(n)->get_num_args(); - while (j > 0) { - --j; - expr * arg = to_app(n)->get_arg(j); - if (!is_ground(arg)) - m_todo.push_back(expr_offset(arg, offset)); - } - break; - default: - UNREACHABLE(); - } - } - return false; -} - -inline bool lpo::greater(expr_offset s, expr_offset t, unsigned depth) { - return lpo::compare(s, t, depth) == GREATER; -} - -/** - \brief Return true if s >_{lpo} t_i forall children t_i of t. -*/ -bool lpo::dominates_args(expr_offset s, expr_offset t, unsigned depth) { - SASSERT(is_app(t.get_expr())); - unsigned num_args = to_app(t.get_expr())->get_num_args(); - unsigned off = t.get_offset(); - for (unsigned i = 0; i < num_args; i++) { - expr * t_i = to_app(t.get_expr())->get_arg(i); - if (!greater(s, expr_offset(t_i, off), depth+1)) - return false; - } - return true; -} - -/** - \brief Return true if s_i >=_{lpo} t for some arg s_i of s. - */ -bool lpo::arg_dominates_expr(expr_offset s, expr_offset t, unsigned depth) { - SASSERT(is_app(s.get_expr())); - unsigned num_args = to_app(s.get_expr())->get_num_args(); - unsigned off = s.get_offset(); - for (unsigned i = 0; i < num_args; i++) { - expr * s_i = to_app(s.get_expr())->get_arg(i); - result r = compare(expr_offset(s_i, off), t, depth+1); - if (r == EQUAL || r == GREATER) - return true; - } - return false; -} - -order::result lpo::lex_compare(expr_offset s, expr_offset t, unsigned depth) { - SASSERT(is_app(s.get_expr())); - SASSERT(is_app(t.get_expr())); - app * _s = to_app(s.get_expr()); - app * _t = to_app(t.get_expr()); - unsigned num_args1 = _s->get_num_args(); - unsigned num_args2 = _t->get_num_args(); - unsigned num_args = std::min(num_args1, num_args2); - unsigned off1 = s.get_offset(); - unsigned off2 = t.get_offset(); - result r = EQUAL; - for (unsigned i = 0; i < num_args; i++) { - r = compare(expr_offset(_s->get_arg(i), off1), expr_offset(_t->get_arg(i), off2), depth+1); - if (r != EQUAL) - break; - } - if (r == EQUAL) { - if (num_args1 > num_args2) - return GREATER; - if (num_args1 < num_args2) - return NOT_GTEQ; - } - return r; -} - -inline order::result lpo::compare_core(expr_offset s, expr_offset t, unsigned depth) { - s = find(s); - t = find(t); - - if (max_depth(depth)) - return UNKNOWN; - - if (is_var(s.get_expr())) - return s == t ? EQUAL : UNCOMPARABLE; - else if (is_var(t.get_expr())) - return occurs(t, s) ? GREATER : UNCOMPARABLE; - else { - func_decl * f = to_app(s.get_expr())->get_decl(); - func_decl * g = to_app(t.get_expr())->get_decl(); - if (f_greater(f, g)) - return dominates_args(s, t, depth) ? GREATER : NOT_GTEQ; - else if (f != g) - return arg_dominates_expr(s, t, depth) ? GREATER : NOT_GTEQ; - else { - result r = lex_compare(s, t, depth); - if (r == GREATER) { - if (dominates_args(s, t, depth)) - return GREATER; - } - else if (r == EQUAL) - return EQUAL; - return to_app(s.get_expr())->get_num_args() > 1 && arg_dominates_expr(s, t, depth) ? GREATER : NOT_GTEQ; - } - } -} - -order::result lpo::compare(expr_offset s, expr_offset t, unsigned depth) { - TRACE("lpo", tout << "comparing:\n" << mk_pp(s.get_expr(), m_manager) << "\n" << mk_pp(t.get_expr(), m_manager) << "\n";); - result r = compare_core(s, t, depth); - TRACE("lpo", tout << "result of comparing:\n" << mk_pp(s.get_expr(), m_manager) << "\n" << mk_pp(t.get_expr(), m_manager) << "\nresult: " << r << "\n";); - return r; -} - -bool lpo::greater(expr_offset const & t1, expr_offset const & t2, substitution * s) { - m_subst = s; - return greater(t1, t2, static_cast(0)); -} - -order::result lpo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) { - m_subst = s; - result r = compare(t1, t2, static_cast(0)); - if (r != NOT_GTEQ) - return r; - r = compare(t2, t1, static_cast(0)); - if (r == GREATER) - return LESSER; - if (r == UNKNOWN) - return UNKNOWN; - return UNCOMPARABLE; -} - -int lpo::compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) { - m_subst = s; - result r = compare(t1, t2, static_cast(0)); - switch (r) { - case GREATER: return 1; - case EQUAL: return 0; - default: return -1; - } -} diff --git a/src/dead/spc/lpo.h b/src/dead/spc/lpo.h deleted file mode 100644 index df18e78e1..000000000 --- a/src/dead/spc/lpo.h +++ /dev/null @@ -1,49 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - lpo.h - -Abstract: - - Lexicographical Path Ordering - -Author: - - Leonardo de Moura (leonardo) 2008-02-01. - -Revision History: - ---*/ -#ifndef _LPO_H_ -#define _LPO_H_ - -#include"order.h" -#include"vector.h" -#include"map.h" - -class lpo : public order { - svector m_todo; - - bool occurs(expr_offset const & t1, expr_offset const & t2); - bool greater(expr_offset s, expr_offset t, unsigned depth); - bool dominates_args(expr_offset s, expr_offset t, unsigned depth); - bool arg_dominates_expr(expr_offset s, expr_offset t, unsigned depth); - result lex_compare(expr_offset s, expr_offset t, unsigned depth); - result compare_core(expr_offset s, expr_offset t, unsigned depth); - result compare(expr_offset s, expr_offset t, unsigned depth); - bool max_depth(unsigned d) { /* TODO */ return false; } -public: - lpo(ast_manager & m, precedence * p):order(m, p) {} - virtual ~lpo() {} - - virtual result compare(expr_offset const & t1, expr_offset const & t2, substitution * s); - result compare(expr * t1, expr * t2) { return compare(expr_offset(t1, 0), expr_offset(t2, 0), static_cast(0)); } - - virtual bool greater(expr_offset const & t1, expr_offset const & t2, substitution * s); - bool greater(expr_offset const & t1, expr_offset const & t2) { return greater(t1, t2); } - virtual int compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s); -}; - -#endif /* _LPO_H_ */ diff --git a/src/dead/spc/marker.h b/src/dead/spc/marker.h deleted file mode 100644 index 277f2816d..000000000 --- a/src/dead/spc/marker.h +++ /dev/null @@ -1,56 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - marker.h - -Abstract: - - Auxiliary object for managing markings - -Author: - - Leonardo de Moura (leonardo) 2008-02-07. - -Revision History: - ---*/ -#ifndef _MARKER_H_ -#define _MARKER_H_ - -#include"vector.h" - -/** - \brief Keep track of all marked objects. Unmark them when the method - unmark or destructor is invoked. -*/ -template -class marker { - ptr_vector m_to_unmark; -public: - ~marker() { - unmark(); - } - - void mark(T * obj) { - obj->set_mark(true); - m_to_unmark.push_back(obj); - } - - bool is_marked(T * obj) const { - return obj->is_marked(); - } - - void unmark() { - typename ptr_vector::iterator it = m_to_unmark.begin(); - typename ptr_vector::iterator end = m_to_unmark.end(); - for (; it != end; ++it) { - T * obj = *it; - obj->set_mark(false); - } - m_to_unmark.reset(); - } -}; - -#endif /* _MARKER_H_ */ diff --git a/src/dead/spc/normalize_vars.cpp b/src/dead/spc/normalize_vars.cpp deleted file mode 100644 index 9f25b71de..000000000 --- a/src/dead/spc/normalize_vars.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - normalize_vars.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-16. - -Revision History: - ---*/ -#include"normalize_vars.h" - -expr * normalize_vars::operator()(expr * n) { - SASSERT(m_todo.empty()); - m_todo.push_back(n); - while (!m_todo.empty()) { - n = m_todo.back(); - if (m_cache.contains(n)) { - m_todo.pop_back(); - continue; - } - if (is_var(n)) { - m_todo.pop_back(); - unsigned idx = to_var(n)->get_idx(); - var * new_var = m_map.get(idx, 0); - if (new_var == 0) { - new_var = m_manager.mk_var(m_next_var, to_var(n)->get_sort()); - m_next_var++; - m_new_vars.push_back(new_var); - m_map.setx(idx, new_var, 0); - } - SASSERT(new_var->get_sort() == to_var(n)->get_sort()); - m_cache.insert(n, new_var); - } - else { - SASSERT(is_app(n)); - bool visited = true; - unsigned num_args = to_app(n)->get_num_args(); - unsigned j = num_args; - while (j > 0) { - --j; - expr * child = to_app(n)->get_arg(j); - if (!m_cache.contains(child)) { - m_todo.push_back(child); - visited = false; - } - } - if (visited) { - m_todo.pop_back(); - m_new_children.reset(); - bool modified = false; - for (unsigned i = 0; i < num_args; i++) { - expr * child = to_app(n)->get_arg(i); - expr * new_child = 0; - m_cache.find(child, new_child); - SASSERT(new_child); - if (child != new_child) - modified = true; - m_new_children.push_back(new_child); - } - if (!modified) - m_cache.insert(n, n); - else - m_cache.insert(n, m_manager.mk_app(to_app(n)->get_decl(), m_new_children.size(), m_new_children.c_ptr())); - } - } - } - expr * r = 0; - m_cache.find(n, r); - SASSERT(r); - return r; -} - -void normalize_vars::reset() { - m_cache.reset(); - m_map.reset(); - m_new_vars.reset(); - m_next_var = 0; -} - diff --git a/src/dead/spc/normalize_vars.h b/src/dead/spc/normalize_vars.h deleted file mode 100644 index 7d2768a54..000000000 --- a/src/dead/spc/normalize_vars.h +++ /dev/null @@ -1,47 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - normalize_vars.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-16. - -Revision History: - ---*/ -#ifndef _NORMALIZE_VARS_H_ -#define _NORMALIZE_VARS_H_ - -#include"ast.h" -#include"obj_hashtable.h" - -class normalize_vars { - ast_manager & m_manager; - var_ref_vector m_new_vars; - unsigned m_next_var; - ptr_vector m_map; - typedef obj_map cache; - cache m_cache; - ptr_vector m_todo; - ptr_vector m_new_children; -public: - normalize_vars(ast_manager & m): - m_manager(m), - m_new_vars(m) { - } - - expr * operator()(expr * n); - void reset(); - unsigned get_num_vars() const { return m_new_vars.size(); } - var * const * get_vars() const { return m_new_vars.c_ptr(); } -}; - -#endif /* _NORMALIZE_VARS_H_ */ - diff --git a/src/dead/spc/order.cpp b/src/dead/spc/order.cpp deleted file mode 100644 index ebf9cdca1..000000000 --- a/src/dead/spc/order.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - order.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-15. - -Revision History: - ---*/ - -#include"order.h" - -bool order::equal(expr_offset const & _t1, expr_offset const & _t2, substitution * s) { - if (_t1 == _t2) - return true; - if (s == 0) - return false; - m_eq_todo.reset(); - m_eq_todo.push_back(expr_offset_pair(_t1, _t2)); - while (!m_eq_todo.empty()) { - expr_offset_pair const & p = m_eq_todo.back(); - expr_offset t1 = find(p.first); - expr_offset t2 = find(p.second); - m_eq_todo.pop_back(); - if (t1 == t2) - continue; - expr * n1 = t1.get_expr(); - expr * n2 = t2.get_expr(); - if (!is_app(n1) || !is_app(n2)) - return false; - if (to_app(n1)->get_decl() != to_app(n2)->get_decl()) - return false; - if (to_app(n1)->get_num_args() != to_app(n2)->get_num_args()) - return false; - unsigned num = to_app(n1)->get_num_args(); - for (unsigned i = 0; i < num; i++) - m_eq_todo.push_back(expr_offset_pair(expr_offset(to_app(n1)->get_arg(i), t1.get_offset()), - expr_offset(to_app(n2)->get_arg(i), t2.get_offset()))); - } - return true; -} - diff --git a/src/dead/spc/order.h b/src/dead/spc/order.h deleted file mode 100644 index 93d8a9eb0..000000000 --- a/src/dead/spc/order.h +++ /dev/null @@ -1,87 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - order.h - -Abstract: - - Abstract class for term orderings. - -Author: - - Leonardo de Moura (leonardo) 2008-01-28. - -Revision History: - ---*/ -#ifndef _ORDER_H_ -#define _ORDER_H_ - -#include"substitution.h" -#include"precedence.h" -#include"trace.h" - -class order { -protected: - ast_manager & m_manager; - precedence * m_precedence; - substitution * m_subst; - - typedef std::pair expr_offset_pair; - svector m_eq_todo; - - expr_offset find(expr_offset t) { - while (m_subst && is_var(t.get_expr()) && m_subst->find(to_var(t.get_expr()), t.get_offset(), t)) - ; - return t; - } - - bool f_greater(func_decl * f, func_decl * g) const { - bool r = m_precedence->compare(f, g) > 0; - TRACE("order", tout << f->get_name() << " greater than " << g->get_name() << " == " << r << "\n";); - return r; - } -public: - enum result { - UNKNOWN, - UNCOMPARABLE, - EQUAL, - GREATER, - LESSER, - NOT_GTEQ - }; - static bool ok(result r) { return r == EQUAL || r == GREATER || r == LESSER; } - order(ast_manager & m, precedence * p):m_manager(m), m_precedence(p) { SASSERT(p); } - virtual ~order() { dealloc(m_precedence); } - virtual void reserve(unsigned num_offsets, unsigned num_vars) {} - virtual void reserve_offsets(unsigned num_offsets) {} - virtual void reserve_vars(unsigned num_vars) {} - ast_manager & get_manager() { return m_manager; } - - virtual result compare(expr_offset const & t1, expr_offset const & t2, substitution * s) = 0; - result compare(expr * t1, expr * t2, unsigned offset, substitution * s) { return compare(expr_offset(t1, offset), expr_offset(t2, offset), s); } - result compare(expr * t1, expr * t2) { return compare(expr_offset(t1, 0), expr_offset(t2, 0), 0); } - virtual bool greater(expr_offset const & t1, expr_offset const & t2, substitution * s) = 0; - bool greater(expr * t1, expr * t2) { return greater(expr_offset(t1,0), expr_offset(t2,0), 0); } - bool greater(expr * t1, expr * t2, substitution * s) { return greater(expr_offset(t1,0), expr_offset(t2,0), s); } - bool greater(expr * t1, expr * t2, unsigned offset, substitution * s) { - return greater(expr_offset(t1, offset), expr_offset(t2, offset), s); - } - /** - \brief Return a value > 0 if t1 is greater than t2, 0 if t1 == t2, and < 0 otherwise (uncomparable, unknown, lesser). - */ - virtual int compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) = 0; - - /** - \brief Return true if the given terms are equal modulo the given substitution - */ - bool equal(expr_offset const & t1, expr_offset const & t2, substitution * s); - - bool equal(expr * t1, expr * t2, unsigned offset = 0, substitution * s = 0) { - return equal(expr_offset(t1, offset), expr_offset(t2, offset), s); - } -}; - -#endif /* _ORDER_H_ */ diff --git a/src/dead/spc/precedence.cpp b/src/dead/spc/precedence.cpp deleted file mode 100644 index 797a723d9..000000000 --- a/src/dead/spc/precedence.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - precedence.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-08. - -Revision History: - ---*/ -#include"precedence.h" -#include"warning.h" - -lex_precedence::lex_precedence(unsigned n, precedence ** ps): - m_precedences(n, ps) { -} - -lex_precedence::~lex_precedence() { - std::for_each(m_precedences.begin(), m_precedences.end(), delete_proc()); -} - -int lex_precedence::compare(func_decl * f, func_decl * g) { - int r = 0; - ptr_vector::iterator it = m_precedences.begin(); - ptr_vector::iterator end = m_precedences.end(); - for (; it != end; ++it) { - r = (*it)->compare(f, g); - if (r != 0) - return r; - } - return r; -} - -inv_precedence::inv_precedence(precedence * p): - m_precedence(p) { - SASSERT(p); -} - -inv_precedence::~inv_precedence() { - dealloc(m_precedence); -} - -int inv_precedence::compare(func_decl * f, func_decl * g) { - return m_precedence->compare(g, f); -} - -int arbitrary_precedence::compare(func_decl * f, func_decl * g) { - return static_cast(f->get_decl_id()) - static_cast(g->get_decl_id()); -} - -int arity_precedence::compare(func_decl * f, func_decl * g) { - return static_cast(f->get_arity()) - static_cast(g->get_arity()); -} - -int interpreted_precedence::compare(func_decl * f, func_decl * g) { - return static_cast(f->get_family_id() == null_family_id) - static_cast(g->get_family_id() == null_family_id); -} - -inline int ext_precedence::get_func_pos(func_decl * f) { - unsigned id = f->get_decl_id(); - return m_cached.get(id, m_undefined); -} - -int ext_precedence::compare(func_decl * f, func_decl * g) { - return get_func_pos(f) - get_func_pos(g); -} - -ext_precedence::ext_precedence(ast_manager & m, unsigned num_decls, func_decl ** decls): - m_undefined(num_decls), - m_cached_domain(m) { - for (unsigned i = 0; i < num_decls; i++) { - m_cached.setx(decls[i]->get_decl_id(), i, m_undefined); - m_cached_domain.push_back(decls[i]); - } -} - -ext_precedence::~ext_precedence() { -} - -int abstract_user_precedence::get_decl_pos(decl * d) { - unsigned id = d->get_decl_id(); - int pos = m_cached.get(id, -1); - if (pos == -1) { - if (!m_symbol2pos.find(d->get_name(), pos)) - pos = m_undefined; - m_cached.setx(id, pos, -1); - SASSERT(pos != -1); - } - return pos; -} - -abstract_user_precedence::abstract_user_precedence(ast_manager & m, unsigned num_syms, symbol * syms): - m_undefined(num_syms), - m_cached_domain(m) { - for (unsigned i = 0; i < num_syms; i++) - m_symbol2pos.insert(syms[i], i); -} - -abstract_user_precedence::~abstract_user_precedence() { -} - -int user_precedence::compare(func_decl * f, func_decl * g) { - return get_decl_pos(f) - get_decl_pos(g); -} - -int user_sort_precedence::compare(func_decl * f, func_decl * g) { - return get_decl_pos(f->get_range()) - get_decl_pos(g->get_range()); -} - -static precedence * mk_default_precedence(ast_manager & m, order_params const & params) { - ptr_buffer ps; - if (!params.m_order_precedence.empty()) - ps.push_back(alloc(user_precedence, m, params.m_order_precedence.size(), params.m_order_precedence.c_ptr())); - ps.push_back(alloc(interpreted_precedence)); - ps.push_back(alloc(arity_precedence)); - ps.push_back(alloc(arbitrary_precedence)); - return alloc(lex_precedence, ps.size(), ps.c_ptr()); -} - -static precedence * mk_inv_precedence(bool inv, precedence * p) { - return inv ? alloc(inv_precedence,p) : p; -} - -static precedence * mk_lex_precedence(ptr_buffer const & ps) { - unsigned sz = ps.size(); - if (sz == 0) - return alloc(arbitrary_precedence); - else if (sz == 1) - return ps[0]; - else - return alloc(lex_precedence, sz, ps.c_ptr()); -} - -precedence * mk_precedence(ast_manager & m, order_params const & params) { - if (params.m_order_precedence_gen.empty()) - return mk_default_precedence(m, params); - - symbol user("user"); - symbol definition("definition"); - symbol interpreted("interpreted"); - symbol frequency("frequency"); - symbol arity("arity"); - symbol arbitrary("arbitrary"); - symbol inv("-"); - - ptr_buffer ps; - - svector::const_iterator it = params.m_order_precedence_gen.begin(); - svector::const_iterator end = params.m_order_precedence_gen.end(); - bool prev_inv = false; - for (; it != end; ++it) { - symbol curr = *it; - if (curr == user) { - if (params.m_order_precedence.empty()) - ps.push_back(mk_inv_precedence(prev_inv, alloc(user_precedence, m, params.m_order_precedence.size(), params.m_order_precedence.c_ptr()))); - } - else if (curr == definition) { - warning_msg("definition precedence was not implement yet."); - } - else if (curr == interpreted) { - ps.push_back(mk_inv_precedence(prev_inv, alloc(interpreted_precedence))); - } - else if (curr == frequency) { - warning_msg("frequency precedence was not implement yet."); - } - else if (curr == arity) { - ps.push_back(mk_inv_precedence(prev_inv, alloc(arity_precedence))); - } - else if (curr == arbitrary) { - ps.push_back(mk_inv_precedence(prev_inv, alloc(arbitrary_precedence))); - // it is pointless to continue, arbitrary_precedence is a total order - return mk_lex_precedence(ps); - } - else if (curr == inv) { - prev_inv = true; - } - else { - warning_msg("invalid precedence generator: ignoring atom '%s'.", curr.bare_str()); - } - } - - return mk_lex_precedence(ps); -} diff --git a/src/dead/spc/precedence.h b/src/dead/spc/precedence.h deleted file mode 100644 index 82cf81be1..000000000 --- a/src/dead/spc/precedence.h +++ /dev/null @@ -1,142 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - precedence.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-08. - -Revision History: - ---*/ -#ifndef _PRECEDENCE_H_ -#define _PRECEDENCE_H_ - -#include"ast.h" -#include"order_params.h" - -/** - \brief Abstract functor used to implement an order on function symbols. -*/ -class precedence { -public: - virtual ~precedence() {} - virtual int compare(func_decl * f, func_decl * g) = 0; - bool operator()(func_decl * f, func_decl * g) { return compare(f, g) < 0; } -}; - -/** - \brief Compose different precedence functors using lexicographical order. -*/ -class lex_precedence : public precedence { - ptr_vector m_precedences; -public: - lex_precedence(unsigned n, precedence ** ps); - virtual ~lex_precedence(); - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief Invert functor - */ -class inv_precedence : public precedence { - precedence * m_precedence; -public: - inv_precedence(precedence * p); - virtual ~inv_precedence(); - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief An arbitrary total order based on the func_decl ids. -*/ -class arbitrary_precedence : public precedence { -public: - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief Precedence based on the arity. - - \remark This is not a total order, so it must be combined - with other precedence functors (e.g., arbitrary_precedence). -*/ -class arity_precedence : public precedence { -public: - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief Interpreted function symbols are smaller. - */ -class interpreted_precedence : public precedence { -public: - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief A precedence given as a sequence of func_decls. - This functor is used to encapsulate automatically/externally generated - precedences. -*/ -class ext_precedence : public precedence { - unsigned m_undefined; // position for func_decl's not specified by the user. - int_vector m_cached; // mapping: decl -> int - decl_ref_vector m_cached_domain; - - int get_func_pos(func_decl * f); -public: - ext_precedence(ast_manager & m, unsigned num_decls, func_decl ** decls); - virtual ~ext_precedence(); - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief Abstract class for user precedences based on - function or sort symbols. -*/ -class abstract_user_precedence : public precedence { -protected: - symbol_table m_symbol2pos; - unsigned m_undefined; // position for symbols not specified by the user. - int_vector m_cached; // mapping: decl -> int - decl_ref_vector m_cached_domain; - - int get_decl_pos(decl * d); -public: - abstract_user_precedence(ast_manager & m, unsigned num_syms, symbol * syms); - virtual ~abstract_user_precedence(); -}; - -/** - \brief A user defined precedence given as a sequence of symbols. - - \remark User provided precedences are usually not total. -*/ -class user_precedence : public abstract_user_precedence { -public: - user_precedence(ast_manager & m, unsigned num_syms, symbol * syms):abstract_user_precedence(m, num_syms, syms) {} - virtual int compare(func_decl * f, func_decl * g); -}; - -/** - \brief A user defined precedence given as a sequence of sort symbols. - The functions are ordered based on their range sort. -*/ -class user_sort_precedence : public abstract_user_precedence { -public: - user_sort_precedence(ast_manager & m, unsigned num_syms, symbol * syms):abstract_user_precedence(m, num_syms, syms) {} - virtual int compare(func_decl * f, func_decl * g); -}; - -precedence * mk_precedence(ast_manager & m, order_params const & params); - -#endif /* _PRECEDENCE_H_ */ - diff --git a/src/dead/spc/preprocessor.cpp b/src/dead/spc/preprocessor.cpp deleted file mode 100644 index 703fecc0f..000000000 --- a/src/dead/spc/preprocessor.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - preprocessor.cpp - -Abstract: - - Preprocessor - -Author: - - Leonardo de Moura (leonardo) 2008-01-17. - -Revision History: - ---*/ -#include"ast_pp.h" -#include"ast_ll_pp.h" -#include"preprocessor.h" -#include"for_each_expr.h" -#include"num_occurs.h" - -preprocessor::preprocessor(ast_manager & m, defined_names & d, simplifier & s, preprocessor_params & p): - m_params(p), - m_manager(m), - m_simp(s), - m_nnf(m, d, p), - m_cnf(m, d, p), - m_der(m), - m_push_app_ite(s, p.m_lift_ite == LI_CONSERVATIVE), - m_cnf_todo(m), - m_cnf_todo_prs(m), - m_push_todo(m), - m_push_todo_prs(m) { - switch (m_params.m_cnf_mode) { - case CNF_QUANT: - if (m_params.m_nnf_mode == NNF_SKOLEM) - m_params.m_nnf_mode = NNF_QUANT; - break; - case CNF_OPPORTUNISTIC: - if (m_params.m_nnf_mode == NNF_SKOLEM) - m_params.m_nnf_mode = NNF_QUANT; - break; - case CNF_FULL: - m_params.m_nnf_mode = NNF_FULL; - break; - default: - break; - } -} - -#ifdef _TRACE -struct num_occurs_pp { - - ast_manager & m_manager; - std::ostream & m_out; - num_occurs m_occurs; - - num_occurs_pp(ast_manager & m, std::ostream & out, expr * root): - m_manager(m), - m_out(out) { - m_occurs(root); - } - void operator()(var * n) {} - void operator()(app * n) { - unsigned val = m_occurs.get_num_occs(n); - if (val > 1 && m_manager.is_bool(n)) - m_out << "#" << n->get_id() << " -> " << val << " " << n->get_ref_count() << "\n"; - } - void operator()(quantifier * n) {} -}; -#endif - -void preprocessor::operator()(expr * e, proof * in_pr, expr_ref_vector & result, proof_ref_vector & result_prs) { - m_cnf_todo.reset(); - m_cnf_todo_prs.reset(); - - expr_ref r1(m_manager); - proof_ref pr1(m_manager); - m_simp(e, r1, pr1); - in_pr = m_manager.mk_modus_ponens(in_pr, pr1); - - expr_ref r2(m_manager); - proof_ref pr2(m_manager); - m_nnf(r1, m_cnf_todo, m_cnf_todo_prs, r2, pr2); - in_pr = m_manager.mk_modus_ponens(in_pr, pr2); - - TRACE("preprocessor", tout << mk_ll_pp(r2, m_manager); - num_occurs_pp proc(m_manager, tout, r2); - for_each_expr(proc, r2);); - - m_cnf_todo.push_back(r2); - m_cnf_todo_prs.push_back(in_pr); - - unsigned sz = m_cnf_todo.size(); - for (unsigned i = 0; i < sz; i++) { - m_push_todo.reset(); - m_push_todo_prs.reset(); - - expr * e = m_cnf_todo.get(i); - if (m_params.m_lift_ite != LI_NONE) { - m_push_app_ite(e, r1, pr1); - } - else { - r1 = e; - pr1 = 0; - } - - TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager);); - - expr_ref aux(r1, m_manager); - m_simp(aux, r1, pr2); - pr1 = m_manager.mk_transitivity(pr1, pr2); - - TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager);); - - aux = r1; - m_der(aux, r1, pr2); - pr1 = m_manager.mk_transitivity(pr1, pr2); - - TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager);); - - if (m_manager.proofs_enabled()) - in_pr = m_manager.mk_modus_ponens(m_cnf_todo_prs.get(i), pr1); - else - in_pr = 0; - - aux = r1; - m_cnf(aux, m_push_todo, m_push_todo_prs, r1, pr1); - m_push_todo.push_back(r1); - - TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager);); - - if (m_manager.proofs_enabled()) { - in_pr = m_manager.mk_modus_ponens(in_pr, pr1); - m_push_todo_prs.push_back(in_pr); - } - - unsigned sz2 = m_push_todo.size(); - for (unsigned j = 0; j < sz2; j++) { - expr * e = m_push_todo.get(j); - m_simp(e, r1, pr1); - - TRACE("preprocessor", tout << mk_ll_pp(r1, m_manager);); - - if (m_manager.proofs_enabled()) - in_pr = m_manager.mk_modus_ponens(m_push_todo_prs.get(j), pr1); - else - in_pr = 0; - push_assertion(m_manager, r1, in_pr, result, result_prs); - } - } -} diff --git a/src/dead/spc/preprocessor.h b/src/dead/spc/preprocessor.h deleted file mode 100644 index c7ce9e847..000000000 --- a/src/dead/spc/preprocessor.h +++ /dev/null @@ -1,51 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - preprocessor.h - -Abstract: - - Preprocess AST before adding them to the logical context - -Author: - - Leonardo de Moura (leonardo) 2008-01-17. - -Revision History: - ---*/ -#ifndef _PREPROCESSOR_H_ -#define _PREPROCESSOR_H_ - -#include"preprocessor_params.h" -#include"simplifier.h" -#include"pattern_inference.h" -#include"nnf.h" -#include"cnf.h" -#include"der.h" -#include"push_app_ite.h" - -/** - \brief Functor used to preprocess expressions before adding them to - the logical context. -*/ -class preprocessor { - preprocessor_params & m_params; - ast_manager & m_manager; - simplifier & m_simp; - nnf m_nnf; - cnf m_cnf; - der_star m_der; - push_app_ite m_push_app_ite; - expr_ref_vector m_cnf_todo; - proof_ref_vector m_cnf_todo_prs; - expr_ref_vector m_push_todo; - proof_ref_vector m_push_todo_prs; -public: - preprocessor(ast_manager & m, defined_names & d, simplifier & s, preprocessor_params & p); - void operator()(expr * e, proof * in_pr, expr_ref_vector & result, proof_ref_vector & result_prs); -}; - -#endif /* _PREPROCESSOR_H_ */ diff --git a/src/dead/spc/sparse_use_list.h b/src/dead/spc/sparse_use_list.h deleted file mode 100644 index d50d48fee..000000000 --- a/src/dead/spc/sparse_use_list.h +++ /dev/null @@ -1,107 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - sparse_use_list.h - -Abstract: - - Sparse use list index. - -Author: - - Leonardo de Moura (leonardo) 2008-02-13. - -Revision History: - ---*/ -#ifndef _SPARSE_USE_LIST_H_ -#define _SPARSE_USE_LIST_H_ - -#include"ast.h" -#include"obj_hashtable.h" - -/** - \brief (Generic sparse) use-list data-structure. -*/ -template -class sparse_use_list { - typedef obj_map use_list; - use_list m_use_list; - -public: - typedef typename Set::iterator iterator; - sparse_use_list() {} - ~sparse_use_list() { - reset(); - } - - void insert(typename Set::data const & parent, T * child) { - Set * parents = 0; - if (!m_use_list.find(child, parents)) { - parents = alloc(Set); - m_use_list.insert(child, parents); - } - SASSERT(parents); - parents->insert(parent); - } - - /** - \brief Return 0 if child did not contain any parents. - Return 1, if child does not have more parents after - removing parent. - Return 2 otherwise. - */ - unsigned erase(typename Set::data const & parent, T * child) { - Set * parents = 0; - if (m_use_list.find(child, parents)) { - parents->erase(parent); - if (parents->empty()) { - dealloc(parents); - m_use_list.erase(child); - return 1; - } - return 2; - } - return 0; - } - - void reset() { - typename use_list::iterator it = m_use_list.begin(); - typename use_list::iterator end = m_use_list.end(); - for (; it != end; ++it) - dealloc(it->m_value); - m_use_list.reset(); - } - - Set * get_parents(T * e) { - Set * parents = 0; - m_use_list.find(e, parents); - return parents; - } - - iterator begin(T * e) { - Set * parents = 0; - m_use_list.find(e, parents); - SASSERT(parents); - return parents->begin(); - } - - iterator end(T * e) { - Set * parents = 0; - m_use_list.find(e, parents); - SASSERT(parents); - return parents->end(); - } - - bool empty(T * e) const { - Set * parents = 0; - if (m_use_list.find(e, parents)) - return parents->empty(); - return true; - } -}; - -#endif /* _SPARSE_USE_LIST_H_ */ - diff --git a/src/dead/spc/spc_asserted_literals.cpp b/src/dead/spc/spc_asserted_literals.cpp deleted file mode 100644 index d4ade5a03..000000000 --- a/src/dead/spc/spc_asserted_literals.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_asserted_literals.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ - -#include"spc_asserted_literals.h" -#include"ast_pp.h" - -namespace spc { - - asserted_literals::asserted_literals(ast_manager & m): - m_manager(m), - m_subst(m), - m_tmp_eq1(2), - m_tmp_eq2(2) { - for (unsigned i = 0; i < 2; i++) { - m_st[i] = alloc(substitution_tree, m_manager); - m_expr2clause[i] = alloc(expr2clause); - } - m_subst.reserve_offsets(3); - } - - asserted_literals::~asserted_literals() { - for (unsigned i = 0; i < 2; i++) { - dealloc(m_st[i]); - dealloc(m_expr2clause[i]); - } - } - - void asserted_literals::insert(clause * cls) { - if (cls->get_num_literals() == 1) { - TRACE("asserted_literals", tout << "inserting clause into asserted_literals index:\n"; - cls->display(tout, m_manager); tout << "\n";); - literal const & l = cls->get_literal(0); - unsigned neg = static_cast(l.sign()); - expr * atom = l.atom(); - m_st[neg]->insert(to_app(atom)); - m_expr2clause[neg]->insert(atom, cls); - m_subst.reserve_vars(m_st[neg]->get_approx_num_regs()); - } - } - - void asserted_literals::erase(clause * cls) { - if (cls->get_num_literals() == 1) { - literal const & l = cls->get_literal(0); - unsigned neg = static_cast(l.sign()); - expr * atom = l.atom(); - m_expr2clause[neg]->erase(atom); - m_st[neg]->erase(to_app(atom)); - } - } - - void asserted_literals::reset() { - for (unsigned i = 0; i < 2; i++) { - m_st[i]->reset(); - m_expr2clause[i]->reset(); - } - } - - struct asserted_literals_visitor : public st_visitor { - expr * m_target; - asserted_literals_visitor(substitution & s):st_visitor(s), m_target(0) {} - virtual bool operator()(expr * e) { - m_target = e; - return false; // stop - } - }; - - /** - \brief Return an unit clause that is a generalization - of the given literal. - Return 0 if such clause does not exist. - */ - clause * asserted_literals::gen(expr * atom, bool n) { - if (is_app(atom)) { - TRACE("asserted_literals", tout << "checking if there is generalizer for: " << n << "\n" << - mk_pp(atom, m_manager) << "\n";); - unsigned neg = static_cast(n); - m_subst.reset_subst(); - asserted_literals_visitor visitor(m_subst); - TRACE("asserted_literals_bug", tout << "query: " << mk_pp(atom, m_manager) << "\n"; m_st[neg]->display(tout); - m_subst.display(tout);); - m_st[neg]->gen(to_app(atom), visitor); - if (visitor.m_target != 0) { - clause * cls = 0; - m_expr2clause[neg]->find(visitor.m_target, cls); - SASSERT(cls); - return cls; - } - if (m_manager.is_eq(atom)) { - m_subst.reset(); - m_tmp_eq1.copy_swapping_args(to_app(atom)); - m_st[neg]->gen(m_tmp_eq1.get_app(), visitor); - if (visitor.m_target != 0) { - clause * cls = 0; - m_expr2clause[neg]->find(visitor.m_target, cls); - SASSERT(cls); - return cls; - } - } - } - return 0; - } - - /** - \brief Return an unit clause that is a generalization - of the equality (= lhs rhs) - Return 0 if such clause does not exist. - */ - clause * asserted_literals::gen_eq(expr * lhs, expr * rhs) { - expr * args[2] = { lhs, rhs }; - func_decl_ref eq_decl(m_manager.mk_func_decl(m_manager.get_basic_family_id(), OP_EQ, 0, 0, 2, args), m_manager); - m_tmp_eq2.set_decl(eq_decl); - m_tmp_eq2.set_arg(0, lhs); - m_tmp_eq2.set_arg(1, rhs); - return gen(m_tmp_eq2.get_app(), false); - } - - /** - \brief Return a unit equality clause (= s t) that (eq) subsumes (= lhs rhs). - That is, lhs and rhs have the form u[s'] and u[t'] and there is - a substitution sigma s.t. sigma(s) = s' and sigma(t) = t'. - Return 0 if such clause does not exist. - */ - clause * asserted_literals::subsumes(expr * lhs, expr * rhs) { - while (true) { - TRACE("eq_subsumption", tout << "eq_subsumption loop:\n" << mk_pp(lhs, m_manager) << "\n" << - mk_pp(rhs, m_manager) << "\n";); - clause * subsumer = gen_eq(lhs, rhs); - if (subsumer) - return subsumer; - if (!is_app(lhs) || !is_app(rhs) || - to_app(lhs)->get_decl() != to_app(rhs)->get_decl() || - to_app(lhs)->get_num_args() != to_app(rhs)->get_num_args()) - return 0; - expr * d1 = 0; - expr * d2 = 0; - unsigned num_args = to_app(lhs)->get_num_args(); - for (unsigned i = 0; i < num_args; i++) { - expr * c1 = to_app(lhs)->get_arg(i); - expr * c2 = to_app(rhs)->get_arg(i); - if (c1 != c2) { - if (d1) - return 0; - d1 = c1; - d2 = c2; - } - } - SASSERT(d1); - lhs = d1; - rhs = d2; - } - return 0; - } - -}; diff --git a/src/dead/spc/spc_asserted_literals.h b/src/dead/spc/spc_asserted_literals.h deleted file mode 100644 index 969f5b452..000000000 --- a/src/dead/spc/spc_asserted_literals.h +++ /dev/null @@ -1,69 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_asserted_literals.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#ifndef _SPC_ASSERTED_LITERALS_H_ -#define _SPC_ASSERTED_LITERALS_H_ - -#include"spc_clause.h" -#include"substitution_tree.h" -#include"obj_hashtable.h" - -namespace spc { - - /** - \brief Index for the asserted literals in the logical context. - - This index is used to implement forward unit subsumption, - equality subsumption, positive simplify-reflect, and - negative simplify-reflect. - */ - class asserted_literals { - protected: - typedef obj_map expr2clause; - ast_manager & m_manager; - substitution_tree * m_st[2]; - expr2clause * m_expr2clause[2]; - substitution m_subst; - tmp_app m_tmp_eq1; - tmp_app m_tmp_eq2; - public: - asserted_literals(ast_manager & m); - ~asserted_literals(); - - void insert(clause * cls); - void erase(clause * cls); - void reset(); - void reserve_vars(unsigned num_vars) { m_subst.reserve_vars(num_vars); } - - clause * gen(literal const & l) { - return gen(l.atom(), l.sign()); - } - - clause * gen(expr * atom, bool neg); - clause * gen_eq(expr * lhs, expr * rhs); - clause * subsumes(expr * lhs, expr * rhs); - - bool has_pos_literals() const { return !m_st[0]->empty(); } - bool has_neg_literals() const { return !m_st[1]->empty(); } - bool has_literals() const { return has_pos_literals() || has_neg_literals(); } - }; - -}; - -#endif /* _SPC_ASSERTED_LITERALS_H_ */ - diff --git a/src/dead/spc/spc_clause.cpp b/src/dead/spc/spc_clause.cpp deleted file mode 100644 index 4a2ce7bbf..000000000 --- a/src/dead/spc/spc_clause.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_clause.cpp - -Abstract: - - Superposition Calculus Clause - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#include"spc_clause.h" -#include"splay_tree_def.h" - -template class splay_tree; - -namespace spc { - - clause::clause(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl): - m_id(UINT_MAX), - m_time(UINT_MAX), - m_scope_lvl(scope_lvl), - m_bidx(UINT_MAX), - m_processed(false), - m_indexed(false), - m_has_sel_lit(false), - m_justification(p) { - - set_fields(num_lits, lits); - - m_num_lits_capacity = m_num_lits[0] + m_num_lits[1]; - - memcpy(m_lits, lits, sizeof(literal) * get_num_literals()); - - for (unsigned i = 0; i < num_lits; i++) - m.inc_ref(m_lits[i].atom()); - m_justification->inc_ref(); - m_justification->set_owner(this); - - sort_literals(); - } - - clause * clause::mk(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl) { - void * mem = m.get_allocator().allocate(sizeof(clause) + num_lits * sizeof(literal)); - return new (mem) clause(m, num_lits, lits, p, scope_lvl); - } - - void clause::init(unsigned id, unsigned time) { - SASSERT(m_id == UINT_MAX); - SASSERT(m_time == UINT_MAX); - - m_id = id; - m_time = time; - m_proof_depth = 0; - - justification_stat j_stat; - get_justification_stat(m_justification, j_stat); - - m_proof_depth = j_stat.m_proof_depth; - - if (j_stat.m_max_scope_lvl > m_scope_lvl) - m_scope_lvl = j_stat.m_max_scope_lvl; - - update_parents(j_stat.m_parent_clauses); - } - - void clause::update_parents(ptr_buffer & parents) { - ptr_buffer::iterator it = parents.begin(); - ptr_buffer::iterator end = parents.end(); - for (; it != end; ++it) { - clause * parent = *it; - parent->add_child(this); - } - } - - void clause::deallocate(ast_manager & m) { - - justification_stat j_stat; - get_justification_stat(get_justification(), j_stat); - - ptr_buffer::iterator it = j_stat.m_parent_clauses.begin(); - ptr_buffer::iterator end = j_stat.m_parent_clauses.end(); - for (; it != end; ++it) { - clause * parent = *it; - parent->del_child(this); - } - - dec_ref(get_justification(), m); - - unsigned num_lits = get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) - m.dec_ref(get_literal(i).atom()); - - unsigned capacity = get_num_literals_capacity(); - this->~clause(); - m.get_allocator().deallocate(sizeof(clause) + capacity * sizeof(literal), this); - } - - void clause::select_literal(unsigned idx) { - SASSERT(idx < get_num_literals()); - m_lits[idx].set_selected(true); - m_has_sel_lit = true; - } - - /** - \brief Return true if l is maximal in the clause, given a substitution s. - - s(l) is considered maximal if there is no literal l' in the clause such s(l') is greater - than s(l). - */ - bool clause::is_maximal(order & o, literal const & l, unsigned offset, substitution * s) const { - unsigned num_lits = get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l_prime = m_lits[i]; - if (l != l_prime && greater(o, l_prime, l, offset, s)) - return false; - } - return true; - } - - /** - \brief Return true if l is a maximal selected literal in the clause, given a substitution s. - - s(l) is considered maximal selected literal if there is no - selected literal l' in the clause such s(l') is greater than s(l). - */ - bool clause::is_sel_maximal(order & o, literal const & l, unsigned offset, substitution * s) const { - if (!l.is_selected()) - return false; - unsigned num_lits = get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l_prime = m_lits[i]; - if (l != l_prime && l_prime.is_selected() && greater(o, l_prime, l, offset, s)) - return false; - } - return true; - } - - /** - \brief Return true if l is eligible for resolution. - */ - bool clause::is_eligible_for_resolution(order & o, literal const & l, unsigned offset, substitution * s) const { - if (has_sel_lit()) - return is_sel_maximal(o, l, offset, s); - else - return is_maximal(o, l, offset, s); - } - - /** - \brief Return true if l is eligible for paramodulation. - */ - bool clause::is_eligible_for_paramodulation(order & o, literal const & l, unsigned offset, substitution * s) const { - return !has_sel_lit() && is_maximal(o, l, offset, s); - } - - /** - \brief Try to orient literals. - */ - void clause::try_to_orient_literals(order & o) { - o.reserve_vars(get_num_vars()); - unsigned num_lits = get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal & l = m_lits[i]; - l.try_to_orient(o); - } - } - - void clause::set_fields(unsigned num_lits, literal * lits) { - clause_stat c_stat; - get_clause_stat(num_lits, lits, c_stat); - - m_num_vars = c_stat.m_max_var_idx + 1; - m_sym_count = c_stat.m_sym_count; - m_const_count = c_stat.m_const_count; - m_depth = c_stat.m_depth; - m_num_lits[0] = c_stat.m_num_lits[0]; - m_num_lits[1] = c_stat.m_num_lits[1]; - m_ground = c_stat.m_ground; - } - - struct lit_lt { - bool operator()(literal const & l1, literal const & l2) const { - if (l1.is_ground() > l2.is_ground()) - return true; - if (l1.is_ground() != l2.is_ground()) - return false; - if (l1.get_approx_depth() > l2.get_approx_depth()) - return true; - if (l1.get_approx_depth() != l2.get_approx_depth()) - return false; - if (l1.get_approx_sym_count() > l2.get_approx_sym_count()) - return true; - if (l1.get_approx_sym_count() != l2.get_approx_sym_count()) - return false; - if (l1.get_approx_const_count() > l2.get_approx_const_count()) - return true; - if (l1.get_approx_const_count() != l2.get_approx_const_count()) - return false; - return l1.get_id() < l2.get_id(); - } - }; - - /** - \brief Sort literals to improve the performance of subsumption tests. - */ - void clause::sort_literals() { - DEBUG_CODE({ - unsigned num_lits = get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - SASSERT(m_lits[i].has_stats()); - } - }); - std::sort(m_lits, m_lits + get_num_literals(), lit_lt()); - } - - /** - \brief Replace clause literal with the given literals. - Use the given justification to justify the new clause. - */ - void clause::update_lits(ast_manager & m, unsigned num_lits, literal * lits, justification * j) { - unsigned old_num_lits = get_num_literals(); - SASSERT(num_lits <= old_num_lits); - - for (unsigned i = 0; i < num_lits; i++) - m.inc_ref(lits[i].atom()); - - for (unsigned i = 0; i < old_num_lits; i++) - m.dec_ref(m_lits[i].atom()); - - for (unsigned i = 0; i < num_lits; i++) - m_lits[i] = lits[i]; - - set_fields(num_lits, m_lits); - - SASSERT(get_num_literals() == num_lits); - - j->inc_ref(); - m_justification->set_owner(0); // release ownership - dec_ref(m_justification, m); - m_justification = j; - m_justification->set_owner(this); - - sort_literals(); - - justification_stat j_stat; - get_justification_stat(m_justification, j_stat); - - m_proof_depth = j_stat.m_proof_depth; - - SASSERT(m_scope_lvl == j_stat.m_max_scope_lvl); - - update_parents(j_stat.m_parent_clauses); - } - - void clause::display(std::ostream & out, ast_manager & m, bool detailed) { - if (get_num_literals() == 0) { - out << "empty-clause"; - return; - } - out << "#" << m_id << ": (clause "; - spc::display(out, get_num_literals(), m_lits, m, detailed); - out << ")"; - if (m_processed) - out << "*"; - } - - void get_clause_stat(unsigned num_lits, literal * lits, clause_stat & stat) { - for (unsigned i = 0; i < num_lits; i++) { - literal_stat c; - lits[i].get_stat(c); - stat.m_sym_count += c.m_sym_count; - stat.m_depth = std::max(stat.m_depth, c.m_depth); - stat.m_max_var_idx = std::max(stat.m_max_var_idx, c.m_max_var_idx); - stat.m_const_count += c.m_const_count; - stat.m_ground &= c.m_ground; - stat.m_num_lits[static_cast(lits[i].sign())]++; - } - } - -}; diff --git a/src/dead/spc/spc_clause.h b/src/dead/spc/spc_clause.h deleted file mode 100644 index 171248732..000000000 --- a/src/dead/spc/spc_clause.h +++ /dev/null @@ -1,152 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_clause.h - -Abstract: - - Superposition Calculus Clause - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#ifndef _SPC_CLAUSE_H_ -#define _SPC_CLAUSE_H_ - -#include"ast.h" -#include"splay_tree.h" -#include"use_list.h" -#include"spc_literal.h" -#include"spc_justification.h" -#include"use_list.h" - -namespace spc { - - class context; - - /** - \brief Superposition Calculus clause. - */ - class clause { - struct compare { - // ignoring potential overflow/underflow - int operator()(clause * c1, clause * c2) const { - return static_cast(c1->get_id()) - static_cast(c2->get_id()); - } - }; - public: - typedef splay_tree set; - private: - unsigned m_id; // clause unique id - unsigned m_time; // how old is the clause. - unsigned m_num_vars; // approx. number of variables (i.e., max_var_id + 1) - unsigned m_sym_count; // number of symbols - unsigned m_const_count; // number of constants - unsigned m_depth; // depth (i.e., max depth of a literal) - unsigned m_proof_depth; - unsigned m_scope_lvl; // which scope level owns the clause - unsigned m_num_lits[2]; // number of positive [0] and negative [1] literals. - unsigned m_num_lits_capacity; // some of the clause literals can be simplified and removed, this field contains the original number of literals (used for GC). - unsigned m_bidx; // position on the backtracking stack - bool m_ground:1; - bool m_processed:1; - bool m_indexed:1; - bool m_has_sel_lit:1; - justification * m_justification; - set m_children; - literal m_lits[0]; - friend class context; - - void set_fields(unsigned num_lits, literal * lits); - unsigned get_bidx() const { return m_bidx; } - void init(unsigned idx, unsigned time); - void update_parents(ptr_buffer & parents); - void set_bidx(unsigned idx) { SASSERT(m_bidx == UINT_MAX); m_bidx = idx; } - void add_child(clause * c) { m_children.insert(c); } - void del_child(clause * c) { m_children.erase(c); } - void set_processed(bool f) { m_processed = f; } - void set_indexed(bool f) { m_indexed = f; } - void sort_literals(); - /** - \brief Release ownership of the justification. - */ - justification * release_justification() { justification * r = m_justification; m_justification = 0; return r; } - - clause(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl); - - public: - static clause * mk(ast_manager & m, unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl); - void deallocate(ast_manager & m); - - unsigned get_id() const { SASSERT(m_id != UINT_MAX); return m_id; } - unsigned get_time() const { return m_time; } - unsigned get_symbol_count() const { return m_sym_count; } - unsigned get_proof_depth() const { return m_proof_depth; } - unsigned get_num_literals() const { return m_num_lits[0] + m_num_lits[1]; } - unsigned get_num_literals_capacity() const { return m_num_lits_capacity; } - unsigned get_num_pos_literals() const { return m_num_lits[0]; } - unsigned get_num_neg_literals() const { return m_num_lits[1]; } - unsigned get_depth() const { return m_depth; } - unsigned get_const_count() const { return m_const_count; } - unsigned get_scope_lvl() const { return m_scope_lvl; } - unsigned get_num_vars() const { return m_num_vars; } - bool empty() const { return m_num_lits[0] == 0 && m_num_lits[1] == 0; } - literal const & get_literal(unsigned idx) const { return m_lits[idx]; } - literal & get_literal(unsigned idx) { return m_lits[idx]; } - literal * get_literals() const { return const_cast(m_lits); } - justification * get_justification() const { return m_justification; } - bool is_processed() const { return m_processed; } - bool is_indexed() const { return m_indexed; } - bool is_ground() const { return m_ground; } - void select_literal(unsigned idx); - bool is_maximal(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const; - bool is_sel_maximal(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const ; - bool is_eligible_for_resolution(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const; - bool is_eligible_for_paramodulation(order & o, literal const & l, unsigned offset = 0, substitution * s = 0) const; - bool has_sel_lit() const { return m_has_sel_lit; } - void try_to_orient_literals(order & o); - void update_lits(ast_manager & m, unsigned num_lits, literal * lits, justification * j); - - void display(std::ostream & out, ast_manager & m, bool detailed = false); - unsigned hash() const { return m_id; } - }; - - typedef ptr_vector clause_vector; - - /** - \brief Clause Statistics (used to build clauses, subsumption, etc). - */ - struct clause_stat : public expr_stat { - unsigned m_num_lits[2]; - clause_stat() { - m_num_lits[0] = 0; - m_num_lits[1] = 0; - } - }; - - /** - \brief Compute the statistics for a clause with num_lits - literals lits, and store the results in stat. - */ - void get_clause_stat(unsigned num_lits, literal * lits, clause_stat & stat); - - /** - \brief A mapping from clause-id's to clauses - */ - class id2clause { - ptr_vector m_clauses; - public: - void insert(clause * c) { return m_clauses.setx(c->get_id(), c, 0); } - void erase(clause * c) { unsigned id = c->get_id(); if (id < m_clauses.size()) m_clauses[id] = 0; } - clause * operator()(unsigned id) const { return m_clauses.get(id, 0); } - }; -}; - -#endif /* _SPC_CLAUSE_H_ */ - diff --git a/src/dead/spc/spc_clause_pos_set.h b/src/dead/spc/spc_clause_pos_set.h deleted file mode 100644 index 47fec1d7e..000000000 --- a/src/dead/spc/spc_clause_pos_set.h +++ /dev/null @@ -1,58 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_clause_pos_set.h - -Abstract: - - A set of pairs (clause, index). - -Author: - - Leonardo de Moura (leonardo) 2008-02-16. - -Revision History: - ---*/ -#ifndef _SPC_CLAUSE_POS_SET_H_ -#define _SPC_CLAUSE_POS_SET_H_ - -#include"hashtable.h" - -namespace spc { - - typedef std::pair clause_pos_pair; - - class clause_pos_entry { - clause_pos_pair m_data; - public: - typedef clause_pos_pair data; - clause_pos_entry() { m_data.first = 0; } - unsigned get_hash() const { return m_data.first->get_id(); } - bool is_free() const { return m_data.first == 0; } - bool is_deleted() const { return m_data.first == reinterpret_cast(1); } - bool is_used() const { - return m_data.first != reinterpret_cast(0) && m_data.first != reinterpret_cast(1); - } - clause_pos_pair const & get_data() const { return m_data; } - clause_pos_pair & get_data() { return m_data; } - void set_data(clause_pos_pair const & d) { - SASSERT(d.first != 0 && d.first != reinterpret_cast(1)); - m_data = d; - } - void set_hash(unsigned h) { SASSERT(m_data.first->get_id() == h); } - void mark_as_deleted() { m_data.first = reinterpret_cast(1); } - void mark_as_free() { m_data.first = 0; } - }; - - struct clause_pos_pair_hash { - unsigned operator()(clause_pos_pair const & p) const { return p.first->get_id(); } - }; - - typedef core_hashtable > clause_pos_set; -}; - -#endif /* _SPC_CLAUSE_POS_SET_H_ */ - diff --git a/src/dead/spc/spc_clause_selection.cpp b/src/dead/spc/spc_clause_selection.cpp deleted file mode 100644 index df11a01b2..000000000 --- a/src/dead/spc/spc_clause_selection.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_clause_selection.cpp - -Abstract: - - Superposition Calculus Clause Selection - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#include"spc_clause_selection.h" - -namespace spc { - - const unsigned default_heap_size = 1024; - - clause_selection::clause_selection(unsigned num_heaps, clause_eval * const * fs, unsigned * slot_size): - m_curr_slot(0), - m_counter(0), - m_fs(num_heaps, fs) { - SASSERT(num_heaps > 0); - for (unsigned i = 0; i < num_heaps; i++) { - m_heaps.push_back(alloc(heap, default_heap_size, lt(m_id2clause, *(fs[i])))); - SASSERT(slot_size[i] > 0); - m_slot_size.push_back(slot_size[i]); - } - } - - clause_selection::~clause_selection() { - std::for_each(m_heaps.begin(), m_heaps.end(), delete_proc >()); - std::for_each(m_fs.begin(), m_fs.end(), delete_proc()); - } - - void clause_selection::reserve(unsigned cid) { - unsigned capacity = m_heaps[0]->get_bounds(); - if (cid >= capacity) { - unsigned new_capacity = 2 * cid + 1; - SASSERT(cid < new_capacity); - ptr_vector >::iterator it = m_heaps.begin(); - ptr_vector >::iterator end = m_heaps.end(); - for (; it != end; ++it) { - heap * h = *it; - h->reserve(new_capacity);; - } - } - } - - void clause_selection::reset() { - ptr_vector >::iterator it = m_heaps.begin(); - ptr_vector >::iterator end = m_heaps.end(); - for (; it != end; ++it) { - heap * h = *it; - h->reset(); - } - } - - void clause_selection::insert(clause * c) { - reserve(c->get_id()); - m_id2clause.insert(c); - ptr_vector >::iterator it = m_heaps.begin(); - ptr_vector >::iterator end = m_heaps.end(); - for (; it != end; ++it) { - heap * h = *it; - h->insert(c->get_id()); - } - } - - void clause_selection::erase(clause * c) { - // remark: it is not necessary to remove c from m_id2clause - ptr_vector >::iterator it = m_heaps.begin(); - ptr_vector >::iterator end = m_heaps.end(); - SASSERT(it != end); - if (!(*it)->contains(c->get_id())) - return; - for (; it != end; ++it) { - heap * h = *it; - h->erase(c->get_id()); - } - } - - bool clause_selection::empty() const { - ptr_vector >::const_iterator it = m_heaps.begin(); - ptr_vector >::const_iterator end = m_heaps.end(); - for (; it != end; ++it) - if (!(*it)->empty()) - return false; - return true; - } - - clause * clause_selection::get_best() { - heap * h = m_heaps[m_curr_slot]; - if (h->empty()) - return 0; - unsigned cid = m_heaps[m_curr_slot]->erase_min(); - clause * c = m_id2clause(cid); - SASSERT(c); - // remove clause from the other heaps - unsigned num_heaps = m_heaps.size(); - for (unsigned i = 0; i < num_heaps; i++) { - if (m_curr_slot != i) - m_heaps[i]->erase(cid); - } - // remark: it is not necessary to remove c from m_id2clause - m_counter++; - if (m_counter >= m_slot_size[m_curr_slot]) { - m_counter = 0; - m_curr_slot++; - if (m_curr_slot >= m_slot_size.size()) - m_curr_slot = 0; - } - return c; - } -}; diff --git a/src/dead/spc/spc_clause_selection.h b/src/dead/spc/spc_clause_selection.h deleted file mode 100644 index 34fcc2e8f..000000000 --- a/src/dead/spc/spc_clause_selection.h +++ /dev/null @@ -1,85 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_clause_selection.h - -Abstract: - - Superposition Calculus Clause Selection - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#ifndef _SPC_CLAUSE_SELECTION_H_ -#define _SPC_CLAUSE_SELECTION_H_ - -#include"spc_clause.h" -#include"heap.h" - -namespace spc { - - /** - \brief Abstract functor for evaluating how 'good' a clause is. - Smaller values mean better clauses. - */ - struct clause_eval { - virtual ~clause_eval() {} - virtual unsigned operator()(clause * c) const = 0; - }; - - /** - \brief Clause selection heuristic. It supports different priority queues. - */ - class clause_selection { - class lt { - id2clause & m_id2clause; - clause_eval & m_func; - public: - lt(id2clause & m, clause_eval & f): - m_id2clause(m), m_func(f) {} - bool operator()(int cidx1, int cidx2) const { - return m_func(m_id2clause(cidx1)) < m_func(m_id2clause(cidx2)); - } - }; - - id2clause m_id2clause; - ptr_vector > m_heaps; - unsigned_vector m_slot_size; - unsigned m_curr_slot; - unsigned m_counter; - ptr_vector m_fs; - void reserve(unsigned cid); - public: - clause_selection(unsigned num_heaps, clause_eval * const * fs, unsigned * slots); - ~clause_selection(); - void insert(clause * c); - void erase(clause * c); - bool empty() const; - void reset(); - clause * get_best(); - }; - - struct symbol_count_clause_eval : public clause_eval { - virtual ~symbol_count_clause_eval() {} - virtual unsigned operator()(clause * c) const { return c->get_symbol_count(); } - }; - - struct time_clause_eval : public clause_eval { - virtual ~time_clause_eval() {} - virtual unsigned operator()(clause * c) const { return c->get_time(); } - }; - - struct proof_depth_clause_eval : public clause_eval { - virtual ~proof_depth_clause_eval() {} - virtual unsigned operator()(clause * c) const { return c->get_proof_depth(); } - }; -}; - -#endif /* _SPC_CLAUSE_SELECTION_H_ */ - diff --git a/src/dead/spc/spc_context.cpp b/src/dead/spc/spc_context.cpp deleted file mode 100644 index b1ff0a18f..000000000 --- a/src/dead/spc/spc_context.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_context.cpp - -Abstract: - - Superposition Calculus Engine - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#include"spc_context.h" -#include"buffer.h" -#include"ast_pp.h" -#include"ast_ll_pp.h" -#include"ast_smt2_pp.h" -#include"warning.h" - -namespace spc { - - context::context(ast_manager & m, order & o, clause_selection & cs, literal_selection & ls, simplifier & s, spc_params & params): - m_manager(m), - m_params(params), - m_alloc(m.get_allocator()), - m_order(o), - m_cls_sel(cs), - m_lit_sel(ls), - m_simplifier(s), - m_time(0), - m_scope_lvl(0), - m_sem_taut(m), - m_asserted_literals(m), - m_rewriter(m, s, m_order, m_asserted_literals), - m_der(m), - m_subsumption(m, m_asserted_literals, params), - m_eq_resolution(m, m_order, m_stats), - m_factoring(m, m_order, m_stats), - m_superposition(m, m_order, m_stats), - m_unsat(0) { - m_order.reserve_offsets(3); - } - - context::~context() { - reset(); - } - - void context::reset() { - m_cls_sel.reset(); - m_time = 0; - m_scope_lvl = 0; - - if (m_unsat) - m_unsat = 0; - for (unsigned i = 0; i <= m_scope_lvl; i++) { - del_clauses(i); - if (i < m_clauses_to_unfreeze.size()) - m_clauses_to_unfreeze[i].reset(); - } - - m_asserted_literals.reset(); - m_rewriter.reset(); - m_subsumption.reset(); - m_superposition.reset(); - } - - /** - \brief Insert the given clause into the indexes of processed clauses. - */ - void context::insert_index(clause * cls) { - TRACE("insert_index", tout << "indexing clause, num_vars: " << cls->get_num_vars() << "\n"; - cls->display(tout, m_manager); tout << "\n";); - m_order.reserve_vars(cls->get_num_vars()); - m_lit_sel(cls); - m_asserted_literals.insert(cls); - m_rewriter.insert(cls); - m_subsumption.insert(cls); - m_superposition.insert(cls); - cls->set_indexed(true); - } - - void context::erase_index(clause * cls) { - if (cls->is_indexed()) { - m_asserted_literals.erase(cls); - m_rewriter.erase(cls); - m_subsumption.erase(cls); - m_superposition.erase(cls); - cls->set_indexed(false); - } - } - - void context::set_conflict(clause * cls) { - SASSERT(cls->get_num_literals() == 0); - m_unsat = cls; - if (m_params.m_spc_trace) { - cls->display(std::cout, m_manager); std::cout << " "; - cls->get_justification()->display(std::cout); - std::cout << "\n"; - std::cout.flush(); - } - } - - void context::del_clause(clause * cls) { - TRACE("context", tout << "deleting clause:\n"; cls->display(tout, m_manager); tout << "\n";); - m_stats.m_num_del_clause++; - - erase_index(cls); - if (!cls->is_processed()) - m_cls_sel.erase(cls); - - unsigned scope_lvl = cls->get_scope_lvl(); - unsigned bidx = cls->get_bidx(); - m_clauses_to_delete[scope_lvl][bidx] = 0; - - cls->deallocate(m_manager); - } - - void context::freeze_clause_until(clause * cls, unsigned scope_lvl) { - if (cls->get_scope_lvl() >= scope_lvl) { - del_clause(cls); - return; - } - TRACE("context", tout << "freezing clause until: " << scope_lvl << ":\n"; cls->display(tout, m_manager); tout << "\n";); - if (scope_lvl >= m_clauses_to_unfreeze.size()) - m_clauses_to_unfreeze.resize(scope_lvl+1, clause_vector()); - - erase_index(cls); - cls->set_processed(false); - - m_clauses_to_unfreeze[scope_lvl].push_back(cls); - } - - void context::unfreeze_clause(clause * cls) { - TRACE("context", tout << "unfreezing clausel: "; cls->display(tout, m_manager); tout << "\n";); - SASSERT(!cls->is_processed()); - m_cls_sel.insert(cls); - } - - void context::init_clause(clause * cls) { - m_stats.m_num_mk_clause++; - - cls->init(m_cls_id_gen.mk(), m_time); - m_time++; - unsigned scope_lvl = cls->get_scope_lvl(); - - if (scope_lvl >= m_clauses_to_delete.size()) - m_clauses_to_delete.resize(scope_lvl+1, clause_vector()); - - clause_vector & cv = m_clauses_to_delete[scope_lvl]; - unsigned bidx = cv.size(); - cv.push_back(cls); - cls->set_bidx(bidx); - } - - clause * context::mk_clause(unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl) { - clause * cls = clause::mk(m_manager, num_lits, lits, p, scope_lvl); - init_clause(cls); - return cls; - } - - void context::assert_expr(expr * n, proof * p, unsigned scope_lvl) { - TRACE("spc_assert_expr", tout << mk_ismt2_pp(n, m_manager) << "\n";); - SASSERT(scope_lvl <= m_scope_lvl); - justification_ref ref(m_manager); - ref = justification_proof_wrapper::mk(p, m_manager); - assert_expr(n, ref, scope_lvl); - } - - void invalid_clause(expr * n) { - warning_msg("ignoring formula containing an universally quantified boolean variable."); - } - - void context::assert_expr(expr * n, justification * p, unsigned scope_lvl) { - SASSERT(scope_lvl <= m_scope_lvl); - buffer lits; - if (is_forall(n)) - n = to_quantifier(n)->get_expr(); - if (m_manager.is_or(n)) { - unsigned num = to_app(n)->get_num_args(); - for (unsigned i = 0; i < num; i++) { - expr * c = to_app(n)->get_arg(i); - bool is_neg = m_manager.is_not(c); - if (is_var(c) || (is_neg && is_var(to_app(c)->get_arg(0)))) { - invalid_clause(n); - return; - } - if (is_neg) - lits.push_back(literal(to_app(c)->get_arg(0), true)); - else - lits.push_back(literal(c, false)); - } - } - else if (m_manager.is_false(n)) { - // skip - } - else if (m_manager.is_not(n)) { - if (is_var(to_app(n)->get_arg(0))) { - invalid_clause(n); - return; - } - lits.push_back(literal(to_app(n)->get_arg(0), true)); - } - else { - if (is_var(n)) { - invalid_clause(n); - return; - } - lits.push_back(literal(n, false)); - } - - if (trivial(lits.size(), lits.c_ptr())) - return; - - clause * cls = mk_clause(lits.size(), lits.c_ptr(), p, scope_lvl); - m_cls_sel.insert(cls); - if (cls->get_num_literals() == 0) - set_conflict(cls); - } - - /** - \brief Return true if the given clause (set of literals) is trivial. - That is, it contains the literal s = s or complementary literals. - */ - bool context::trivial(unsigned num_lits, literal * lits) { - SASSERT(m_found_literals.empty()); - for (unsigned i = 0; i < num_lits; i++) { - literal l = lits[i]; - if (m_found_literals.contains_neg(l) || l.is_true(m_manager)) { - m_found_literals.reset(); - m_stats.m_num_trivial++; - return true; - } - m_found_literals.insert(l); - } - m_found_literals.reset(); - return false; - } - - bool context::trivial(clause * cls) { - return trivial(cls->get_num_literals(), cls->get_literals()); - } - - /** - \brief Simplify the given clause using the set of processed clauses. - Return the simplified clause. - */ - clause * context::simplify(clause * cls) { - clause * old_cls = cls; - m_der(cls); - cls = m_rewriter(old_cls); - if (cls != old_cls) { - // freeze old clause until simplified clause is deleted. - freeze_clause_until(old_cls, cls->get_scope_lvl()); - init_clause(cls); - m_stats.m_num_simplified++; - } - m_der(cls); - return cls; - } - - /** - \brief Use the given clause to simplify the set of processed clauses. - - \remark: processed clauses that can be simplified, are moved to the - set of unprocessed clauses. - */ - void context::simplify_processed(clause * cls) { - // TODO - } - - /** - \brief Return true if the clause is redundant. - */ - bool context::redundant(clause * cls) { - int r_scope_lvl = -1; - if (trivial(cls)) { - TRACE("redundant", tout << "clause is trivial:\n"; cls->display(tout, m_manager); tout << "\n";); - r_scope_lvl = 0; - } - else if (m_sem_taut(cls->get_num_literals(), cls->get_literals())) { - TRACE("redundant", tout << "clause is a semantic tautology:\n"; cls->display(tout, m_manager); tout << "\n";); - r_scope_lvl = 0; - } - else { - clause * subsumer = m_subsumption.forward(cls); - if (subsumer != 0) { - TRACE("redundant", tout << "clause was subsumed: "; cls->display(tout, m_manager); - tout << "\nsubsumer:\n"; subsumer->display(tout, m_manager); tout << "\n";); - r_scope_lvl = subsumer->get_scope_lvl(); - m_stats.m_num_subsumed++; - } - } - - if (r_scope_lvl >= 0) { - m_stats.m_num_redundant++; - TRACE("spc_saturate", tout << "clause is redundant until level: " << r_scope_lvl << " ...\n";); - freeze_clause_until(cls, r_scope_lvl); - return true; - } - - return false; - } - - /** - \brief Process a newly generated clause. - */ - void context::process_new_clause(clause * cls) { - if (cls) { - SASSERT(cls->get_justification() != 0); - init_clause(cls); - if (trivial(cls)) { - del_clause(cls); - return; - } - cls = simplify(cls); - if (trivial(cls)) { - del_clause(cls); - return; - } - // if (!redundant(cls)) { - m_cls_sel.insert(cls); - if (cls->get_num_literals() == 0) - set_conflict(cls); - // } - } - } - - /** - \brief Apply superposition (left&right), resolution, (equality) factoring, and equality resolution - with the given clause and the set of processed clauses. - */ - void context::generate(clause * cls) { - m_new_clauses.reset(); - m_eq_resolution(cls, m_new_clauses); - m_factoring(cls, m_new_clauses); - m_superposition(cls, m_new_clauses); - - ptr_vector::iterator it = m_new_clauses.begin(); - ptr_vector::iterator end = m_new_clauses.end(); - for (; it != end; ++it) { - TRACE("spc_generate", tout << "new generated clause:\n"; (*it)->display(tout, m_manager); tout << "\n";); - process_new_clause(*it); - } - } - - void context::saturate(unsigned threshold) { - if (inconsistent()) - return; - TRACE("spc_saturate", tout << "initial state:\n"; display(tout);); - unsigned i = 0; - ptr_buffer to_simplify; - while (i < threshold && !processed_all()) { - i++; - m_stats.m_num_processed++; - clause * cls = m_cls_sel.get_best(); - if (m_params.m_spc_trace) { - cls->display(std::cout, m_manager); std::cout << " "; - cls->get_justification()->display(std::cout); - std::cout << "\n"; - std::cout.flush(); - } - cls->set_processed(true); - TRACE("spc_saturate", tout << "get best: "; cls->display(tout, m_manager); tout << "\n";); - cls = simplify(cls); - - TRACE("spc_saturate", tout << "clause after simplification: "; cls->display(tout, m_manager); tout << "\n";); - if (redundant(cls)) - continue; - if (cls->empty()) { - set_conflict(cls); - break; - } - cls->try_to_orient_literals(m_order); - simplify_processed(cls); - insert_index(cls); - generate(cls); - if (inconsistent()) - break; - } - - TRACE("spc_saturate", tout << "final state:\n"; display(tout);); - -#if 0 - IF_VERBOSE(10000, - display(std::cout);); - display_statistics(std::cout); - if (m_unsat && m_manager.fine_grain_proofs()) { - std::cout << mk_ll_pp(m_unsat->get_justification()->get_proof(), m_manager); - } -#endif - } - - void context::push_scope() { - m_scope_lvl++; - m_time_trail.push_back(m_time); - } - - void context::del_clauses(unsigned scope_lvl) { - if (scope_lvl < m_clauses_to_delete.size()) { - clause_vector & cv = m_clauses_to_delete[m_scope_lvl]; - clause_vector::iterator it = cv.begin(); - clause_vector::iterator end = cv.end(); - for (; it != end; ++it) { - clause * cls = *it; - if (cls) - del_clause(cls); - } - cv.reset(); - } - } - - void context::unfreeze_clauses(unsigned scope_lvl) { - if (scope_lvl < m_clauses_to_unfreeze.size()) { - clause_vector & cv = m_clauses_to_unfreeze[m_scope_lvl]; - clause_vector::iterator it = cv.begin(); - clause_vector::iterator end = cv.end(); - for (; it != end; ++it) - unfreeze_clause(*it); - cv.reset(); - } - } - - void context::pop_scope(unsigned num_scopes) { - SASSERT(num_scopes >= m_scope_lvl); - unsigned new_lvl = m_scope_lvl - num_scopes; - m_time = m_time_trail[new_lvl]; - m_time_trail.shrink(new_lvl); - - if (m_unsat && new_lvl < m_unsat->get_scope_lvl()) - m_unsat = 0; - - while (m_scope_lvl > new_lvl) { - del_clauses(m_scope_lvl); - unfreeze_clauses(m_scope_lvl); - m_scope_lvl --; - } - } - - void context::display(std::ostream & out, vector const & cvs, unsigned scope_lvl, bool frozen) const { - if (scope_lvl < cvs.size()) { - bool first = true; - clause_vector const & cv = cvs[scope_lvl]; - clause_vector::const_iterator it = cv.begin(); - clause_vector::const_iterator end = cv.end(); - for (; it != end; ++it) { - clause * cls = *it; - if (cls) { - if (first) { - out << "level " << scope_lvl << ":\n"; - first = false; - } - cls->display(out, m_manager); - if (frozen) - out << " [frozen]"; - out << "\n"; - } - } - } - } - - void context::display(std::ostream & out) const { - for (unsigned i = 0; i <= m_scope_lvl; i++) { - display(out, m_clauses_to_delete, i, false); - display(out, m_clauses_to_unfreeze, i, true); - } - } - - void context::display_statistics(std::ostream & out) const { - m_stats.display(out); - } - - -/** - Generate new clauses - - 5) Object equality resolution 1 - - (R or X = i) - ==> - sigma(R) - - sigma = { X -> j } - where i and j are distinct objects - sigma(X = i) is not smaller or equal than any other literal in the clause - - 6) Object equality resolution 2 - - (R or X = Y) - ==> - sigma(R) - - sigma = { X -> i, Y -> j } - For every pair of distinct objects i and j - sigma(X = Y) is not smaller or equal than any other literal in the clause - -*/ - -}; diff --git a/src/dead/spc/spc_context.h b/src/dead/spc/spc_context.h deleted file mode 100644 index b0c0cbd45..000000000 --- a/src/dead/spc/spc_context.h +++ /dev/null @@ -1,122 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_context.h - -Abstract: - - Superposition Calculus Engine - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#ifndef _SPC_CONTEXT_H_ -#define _SPC_CONTEXT_H_ - -#include"spc_params.h" -#include"spc_clause.h" -#include"spc_clause_selection.h" -#include"spc_literal_selection.h" -#include"spc_semantic_tautology.h" -#include"spc_rewriter.h" -#include"spc_asserted_literals.h" -#include"spc_subsumption.h" -#include"spc_eq_resolution.h" -#include"spc_factoring.h" -#include"spc_superposition.h" -#include"spc_statistics.h" -#include"spc_der.h" -#include"substitution_tree.h" -#include"order.h" - -namespace spc { - - /** - \brief Logical context of the superposition calculus engine. - */ - class context { - public: - statistics m_stats; - protected: - typedef clause::set clause_set; - - ast_manager & m_manager; - spc_params & m_params; - small_object_allocator & m_alloc; - order & m_order; - clause_selection & m_cls_sel; - literal_selection & m_lit_sel; - simplifier & m_simplifier; - unsigned m_time; - unsigned m_scope_lvl; - id_gen m_cls_id_gen; - found_literals m_found_literals; - semantic_tautology m_sem_taut; - asserted_literals m_asserted_literals; - rewriter m_rewriter; - der m_der; - subsumption m_subsumption; - eq_resolution m_eq_resolution; - factoring m_factoring; - superposition m_superposition; - vector m_clauses_to_unfreeze; - vector m_clauses_to_delete; - unsigned_vector m_time_trail; - clause * m_unsat; - ptr_vector m_new_clauses; - - void insert_index(clause * cls); - void erase_index(clause * cls); - - void init_clause(clause * cls); - clause * mk_clause(unsigned num_lits, literal * lits, justification * p, unsigned scope_lvl); - - void del_clause(clause * cls); - void del_clauses(unsigned scope_lvl); - - void freeze_clause_until(clause * cls, unsigned scope_lvl); - void unfreeze_clause(clause * cls); - void unfreeze_clauses(unsigned scope_lvl); - - bool trivial(unsigned num_lits, literal * lits); - bool trivial(clause * cls); - clause * simplify(clause * cls); - void simplify_processed(clause * cls); - bool redundant(clause * cls); - void generate(clause * cls); - void process_new_clause(clause * cls); - - void display(std::ostream & out, vector const & cvs, unsigned scope_lvl, bool frozen) const; - - void set_conflict(clause * cls); - - public: - context(ast_manager & m, order & o, clause_selection & cs, literal_selection & ls, simplifier & s, spc_params & params); - ~context(); - - simplifier & get_simplifier() { return m_simplifier; } - order & get_order() { return m_order; } - ast_manager & get_manager() { return m_manager; } - - unsigned get_scope_lvl() const { return m_scope_lvl; } - - void assert_expr(expr * n, proof * p, unsigned scope_lvl = 0); - void assert_expr(expr * n, justification * p, unsigned scope_lvl = 0); - void saturate(unsigned threshold); - bool inconsistent() const { return m_unsat != 0; } - bool processed_all() const { return m_cls_sel.empty(); } - void push_scope(); - void pop_scope(unsigned num_scopes); - void reset(); - void display(std::ostream & out) const; - void display_statistics(std::ostream & out) const; - }; -}; - -#endif /* _SPC_CONTEXT_H_ */ diff --git a/src/dead/spc/spc_decl_plugin.cpp b/src/dead/spc/spc_decl_plugin.cpp deleted file mode 100644 index 3ffb0c64d..000000000 --- a/src/dead/spc/spc_decl_plugin.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_decl_plugin.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-12. - -Revision History: - ---*/ -#include"spc_decl_plugin.h" - -std::ostream & operator<<(std::ostream & out, spc_op_kind k) { - switch (k) { - case PR_DEMODULATION: out << "demod"; break; - case PR_SPC_REWRITE: out << "rewrite"; break; - case PR_SPC_RESOLUTION: out << "res"; break; - case PR_SUPERPOSITION: out << "sup"; break; - case PR_EQUALITY_RESOLUTION: out << "eq_res"; break; - case PR_FACTORING: out << "fact"; break; - case PR_SPC_DER: out << "der"; break; - case PR_SPC_ASSERTED: out << "asserted"; break; - default: out << "unknown"; break; - } - return out; -} - -spc_decl_plugin::spc_decl_plugin() : - m_demodulation("demod"), - m_spc_rewrite("sp-rw"), - m_spc_resolution("sp-res"), - m_superposition("sp"), - m_equality_resolution("eq-res"), - m_factoring("fact"), - m_spc_der("spc-der") { -} - -spc_decl_plugin::~spc_decl_plugin() { -} - -sort * spc_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const* parameters) { - UNREACHABLE(); - return 0; -} - -func_decl * spc_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - -#define MK_PROOF(SYM) m_manager->mk_func_decl(SYM, arity, domain, m_manager->mk_proof_sort(), func_decl_info(m_family_id, k)) - - SASSERT(num_parameters == 0); - switch (k) { - /* - #1: (forall (x) (= t[x] s[x])) - [demod #1] (= t[a] s[a]) - */ - case PR_DEMODULATION: return MK_PROOF(m_demodulation); - /* - Justifies a rewriting (simplification step) in the superposition engine. - It has n+1 antecedents. The first antecedent is the clause being simplified. - The other antecedents are demodulators. - The consequent is the simplied clause. - */ - case PR_SPC_REWRITE: return MK_PROOF(m_spc_rewrite); - /* - Resolution proof: - - #1: (or C l) - #2: (or D (not l')) - [sp-res #1 #2]: sigma(or C D) - - where sigma is the mgu of l and l' - - */ - case PR_SPC_RESOLUTION: return MK_PROOF(m_spc_resolution); - /* - Superposition proof: - - #1: (or (= s t) R) - #2: D[u] - [sp #1 #2]: sigma(or R D[t]) - - where sigma is the mgu(u, s) - */ - case PR_SUPERPOSITION: return MK_PROOF(m_superposition); - /* - Equality resolution proof: - - #1: (or (not (= s t)) R) - [eq-res #1]: sigma R - - where sigma is the mgu of s and t. - */ - case PR_EQUALITY_RESOLUTION: return MK_PROOF(m_equality_resolution); - /* - Proof object for factoring and equality-factoring: - - #1: (or P[t] P[s] R) - [fact #1]: sigma(or P[t] R) - - where sigma is the mgu(t,s) - - #1: (or (= s t) (= u v) R) - [fact #1]: sigma(or (not (= t v)) (= u v) R) - - where sigma = mgu(s, u) - */ - case PR_FACTORING: return MK_PROOF(m_factoring); - /* - Proof object for destructive equality resolution: - - #1: (or (not (= x t)) C[x]) - [spc-der #1]: C[t] - - t does not contain x. - - Several variables may be eliminated simultaneously. - */ - case PR_SPC_DER: return MK_PROOF(m_spc_der); - default: - UNREACHABLE(); - return 0; - } - -} - - diff --git a/src/dead/spc/spc_decl_plugin.h b/src/dead/spc/spc_decl_plugin.h deleted file mode 100644 index ce98233b4..000000000 --- a/src/dead/spc/spc_decl_plugin.h +++ /dev/null @@ -1,61 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_decl_plugin.h - -Abstract: - - Proof declarations for Superposition Calculus Engine. - -Author: - - Leonardo de Moura (leonardo) 2008-02-12. - -Revision History: - ---*/ -#ifndef _SPC_DECL_PLUGIN_H_ -#define _SPC_DECL_PLUGIN_H_ - -#include"ast.h" - -enum spc_op_kind { - PR_DEMODULATION, - PR_SPC_REWRITE, - PR_SPC_RESOLUTION, - PR_SUPERPOSITION, - PR_EQUALITY_RESOLUTION, - PR_FACTORING, - PR_SPC_DER, - PR_SPC_ASSERTED, - PR_SPC_LAST_ID -}; - -std::ostream & operator<<(std::ostream & out, spc_op_kind k); - -class spc_decl_plugin : public decl_plugin { - symbol m_demodulation; - symbol m_spc_rewrite; - symbol m_spc_resolution; - symbol m_superposition; - symbol m_equality_resolution; - symbol m_factoring; - symbol m_spc_der; - -public: - spc_decl_plugin(); - - virtual ~spc_decl_plugin(); - - virtual decl_plugin * mk_fresh() { return alloc(spc_decl_plugin); } - - virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const* parameters); - - virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); -}; - -#endif /* _SPC_DECL_PLUGIN_H_ */ - diff --git a/src/dead/spc/spc_der.cpp b/src/dead/spc/spc_der.cpp deleted file mode 100644 index dbd125ffc..000000000 --- a/src/dead/spc/spc_der.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_der.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-17. - -Revision History: - ---*/ -#include"spc_der.h" -#include"occurs.h" - -namespace spc { - - der::der(ast_manager & m): - m_manager(m), - m_subst(m), - m_spc_fid(m.get_family_id("spc")) { - m_subst.reserve_offsets(1); - } - - void der::apply(clause * cls, unsigned j, expr * lhs, expr * rhs) { - TRACE("der", tout << "applying der at: " << j << "\n"; cls->display(tout, m_manager); tout << "\n";); - m_subst.reserve_vars(cls->get_num_vars()); - m_subst.reset(); - m_subst.insert(expr_offset(lhs, 0), expr_offset(rhs, 0)); - literal_buffer new_lits(m_manager); - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - if (i != j) { - literal const & l = cls->get_literal(i); - expr_ref new_atom(m_manager); - m_subst.apply(l.atom(), new_atom); - new_lits.push_back(literal(new_atom, l.sign())); - } - } - justification * js = mk_der_justification(m_manager, m_spc_fid, cls->get_justification(), new_lits.size(), new_lits.c_ptr()); - cls->update_lits(m_manager, new_lits.size(), new_lits.c_ptr(), js); - } - - bool der::apply(clause * cls) { - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = cls->get_literal(i); - if (l.sign() && m_manager.is_eq(l.atom())) { - expr * lhs = l.lhs(); - expr * rhs = l.rhs(); - if (is_var(lhs) && !occurs(lhs, rhs)) { - apply(cls, i, lhs, rhs); - return true; - } - else if (is_var(rhs) && !occurs(rhs, lhs)) { - apply(cls, i, rhs, lhs); - return true; - } - } - } - return false; - } - - /** - \brief Clause cls is destructively updated. - */ - void der::operator()(clause * cls) { - while(apply(cls)) - ; - } - - -}; - diff --git a/src/dead/spc/spc_der.h b/src/dead/spc/spc_der.h deleted file mode 100644 index eb434d915..000000000 --- a/src/dead/spc/spc_der.h +++ /dev/null @@ -1,52 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_der.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-17. - -Revision History: - ---*/ -#ifndef _SPC_DER_H_ -#define _SPC_DER_H_ - -#include"spc_clause.h" - -namespace spc { - - /** - \brief Functor for applying destructive equality resolution. - This is similar to the Functor in der.h, but this one applies - the simplification on clauses instead of ast's. - - x != s or R - ==> - sigma(R) - - where - sigma = mgu(x, s) - */ - class der { - ast_manager & m_manager; - substitution m_subst; - unsigned_vector m_to_keep; - family_id m_spc_fid; - void apply(clause * cls, unsigned j, expr * lhs, expr * rhs); - bool apply(clause * cls); - public: - der(ast_manager & m); - void operator()(clause * cls); - }; -}; - -#endif /* _SPC_DER_H_ */ - diff --git a/src/dead/spc/spc_eq_resolution.cpp b/src/dead/spc/spc_eq_resolution.cpp deleted file mode 100644 index df1e0ca69..000000000 --- a/src/dead/spc/spc_eq_resolution.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_eq_resolution.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#include"spc_eq_resolution.h" - -namespace spc { - - /** - \brief Apply equality resolution rule on the given clause. - Store the produced clauses in new_clauses. - */ - void eq_resolution::operator()(clause * cls, ptr_vector & new_clauses) { - m_subst.reserve_vars(cls->get_num_vars()); - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - literal const & l = cls->get_literal(i); - expr * atom = l.atom(); - if (l.sign() && m_manager.is_eq(atom)) { - expr * lhs = to_app(atom)->get_arg(0); - expr * rhs = to_app(atom)->get_arg(1); - m_subst.reset(); - if (m_unifier(lhs, rhs, m_subst, false) && cls->is_eligible_for_resolution(m_order, l, 0, &m_subst)) { - m_stats.m_num_eq_resolution++; - new_clauses.push_back(mk_result(cls, i)); - } - } - } - } -}; diff --git a/src/dead/spc/spc_eq_resolution.h b/src/dead/spc/spc_eq_resolution.h deleted file mode 100644 index a73987559..000000000 --- a/src/dead/spc/spc_eq_resolution.h +++ /dev/null @@ -1,50 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_eq_resolution.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#ifndef _SPC_EQ_RESOLUTION_H_ -#define _SPC_EQ_RESOLUTION_H_ - -#include"spc_unary_inference.h" -#include"spc_statistics.h" - -namespace spc { - - /** - \brief Functor for applying equality resolution. - - s != t or R - ==> - sigma(R) - */ - class eq_resolution : public unary_inference { - protected: - statistics & m_stats; - family_id m_spc_fid; - virtual justification * mk_justification(justification * parent, unsigned num_lits, literal * new_lits) { - return mk_eq_res_justification(m_manager, m_spc_fid, parent, num_lits, new_lits); - } - public: - eq_resolution(ast_manager & m, order & ord, statistics & stats):unary_inference(m, ord), m_stats(stats), m_spc_fid(m.get_family_id("spc")) {} - virtual ~eq_resolution() {} - void operator()(clause * cls, ptr_vector & new_clauses); - }; -}; - - -#endif /* _SPC_EQ_RESOLUTION_H_ */ - diff --git a/src/dead/spc/spc_factoring.cpp b/src/dead/spc/spc_factoring.cpp deleted file mode 100644 index 9f2a4ab9f..000000000 --- a/src/dead/spc/spc_factoring.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_factoring.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#include"spc_factoring.h" - -namespace spc { - - /** - \brief Create a new clause by removing literal at position j, apply substitution m_subst, - and adding a disequality lhs != rhs. - */ - clause * factoring::mk_eq_fact_result(clause * cls, unsigned j, expr * lhs, expr * rhs) { - sbuffer new_literals; - - expr_ref new_eq(m_manager.mk_eq(lhs, rhs), m_manager); - expr_ref new_eq_after_subst(m_manager); - m_subst.apply(new_eq, new_eq_after_subst); - new_literals.push_back(literal(new_eq_after_subst, true)); - - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - if (i != j) { - literal const & l = cls->get_literal(i); - expr_ref new_atom(m_manager); - m_subst.apply(l.atom(), new_atom); - new_literals.push_back(literal(new_atom, l.sign())); - } - } - - justification * js = mk_factoring_justification(m_manager, m_spc_fid, cls->get_justification(), new_literals.size(), - new_literals.c_ptr()); - clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, cls->get_scope_lvl()); - m_stats.m_num_eq_factoring++; - return new_cls; - } - - /** - \brief Try to apply equality factoring using the eq literal stored at position j. - Assume lhs and rhs are the left hand side of this equality (they may be swapped). - */ - void factoring::try_eq_factoring(clause * cls, unsigned j, expr * lhs, expr * rhs, ptr_vector & new_clauses) { - literal const & l1 = cls->get_literal(j); - sort * s = m_manager.get_sort(lhs); - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l2 = cls->get_literal(i); - if (i == j) - continue; - if (l2.sign()) - continue; - expr * atom = l2.atom(); - if (!m_manager.is_eq(atom)) - continue; - expr * lhs2 = to_app(atom)->get_arg(0); - if (m_manager.get_sort(lhs2) != s) - continue; - expr * rhs2 = to_app(atom)->get_arg(1); - m_subst.reset(); - if (m_unifier(lhs, lhs2, m_subst, false) && - (l1.is_oriented() || !m_order.greater(rhs, lhs, &m_subst)) && - cls->is_eligible_for_paramodulation(m_order, l1, 0, &m_subst)) { - new_clauses.push_back(mk_eq_fact_result(cls, j, rhs, rhs2)); - } - m_subst.reset(); - if (m_unifier(lhs, rhs2, m_subst, false) && - (l1.is_oriented() || !m_order.greater(rhs, lhs, &m_subst)) && - cls->is_eligible_for_paramodulation(m_order, l1, 0, &m_subst)) { - new_clauses.push_back(mk_eq_fact_result(cls, j, rhs, lhs2)); - } - } - } - - /** - \brief Try to apply equality factoring using the eq literal stored at position i. - */ - void factoring::try_eq_factoring(clause * cls, unsigned i, ptr_vector & new_clauses) { - if (cls->get_num_pos_literals() <= 1) - return; - literal const & l = cls->get_literal(i); - app * eq = to_app(l.atom()); - expr * lhs = eq->get_arg(0); - expr * rhs = eq->get_arg(1); - if (l.is_oriented()) { - if (!l.is_left()) - std::swap(lhs, rhs); - try_eq_factoring(cls, i, lhs, rhs, new_clauses); - } - else { - try_eq_factoring(cls, i, lhs, rhs, new_clauses); - try_eq_factoring(cls, i, rhs, lhs, new_clauses); - } - } - - /** - \brief Try to apply (ordering) factoring rule. - */ - void factoring::try_factoring(clause * cls, unsigned j, ptr_vector & new_clauses) { - literal const & l1 = cls->get_literal(j); - if (l1.sign() && cls->get_num_neg_literals() <= 1) - return; - if (!l1.sign() && cls->get_num_pos_literals() <= 1) - return; - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - if (i == j) - continue; - literal const & l2 = cls->get_literal(i); - if (l1.sign() != l2.sign()) - continue; - m_subst.reset(); - if (m_unifier(l1.atom(), l2.atom(), m_subst, false) && - cls->is_eligible_for_resolution(m_order, l1, 0, &m_subst)) { - new_clauses.push_back(mk_result(cls, i)); - m_stats.m_num_factoring++; - } - } - } - - /** - \brief Apply factoring rule on the given clause. - Store the produced clauses into new_clauses. - */ - void factoring::operator()(clause * cls, ptr_vector & new_clauses) { - if (cls->get_num_pos_literals() <= 1 && cls->get_num_neg_literals() <= 1) - return; - - m_subst.reserve_vars(cls->get_num_vars()); - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - literal const & l = cls->get_literal(i); - expr * atom = l.atom(); - // remark: if the clause has selected literals then the literal will not be eligible - // for paramodulation and eq_resolution will not be applied. - if (!l.sign() && m_manager.is_eq(atom) && !cls->has_sel_lit()) - try_eq_factoring(cls, i, new_clauses); - if (l.is_selected() || !cls->has_sel_lit()) - try_factoring(cls, i, new_clauses); - } - } - -}; diff --git a/src/dead/spc/spc_factoring.h b/src/dead/spc/spc_factoring.h deleted file mode 100644 index 09e944f6d..000000000 --- a/src/dead/spc/spc_factoring.h +++ /dev/null @@ -1,66 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_factoring.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#ifndef _SPC_FACTORING_H_ -#define _SPC_FACTORING_H_ - -#include"spc_unary_inference.h" -#include"spc_statistics.h" - -namespace spc { - - /** - \brief Functor for applying factoring. - - - Equality Factoring - s = t or u = v or R - ==> - sigma(t != v or u = v or R) - - sigma = mgu(s, u) - sigma(s) not greater than sigma(t) - sigma(s = t) is eligible for paramodulation. - - - Factoring - P(t) or P(s) or R - ==> - sigma(P(t) or R) - - sigma = mgu(t,s) - sigma(P(t)) is eligible for resolution. - */ - class factoring : public unary_inference { - protected: - statistics & m_stats; - family_id m_spc_fid; - virtual justification * mk_justification(justification * parent, unsigned num_lits, literal * new_lits) { - return mk_factoring_justification(m_manager, m_spc_fid, parent, num_lits, new_lits); - } - clause * mk_eq_fact_result(clause * cls, unsigned j, expr * lhs, expr * rhs); - void try_eq_factoring(clause * cls, unsigned j, expr * lhs, expr * rhs, ptr_vector & new_clauses); - void try_eq_factoring(clause * cls, unsigned i, ptr_vector & new_clauses); - void try_factoring(clause * cls, unsigned j, ptr_vector & new_clauses); - public: - factoring(ast_manager & m, order & ord, statistics & stats):unary_inference(m, ord), m_stats(stats), m_spc_fid(m.get_family_id("spc")) {} - virtual ~factoring() {} - void operator()(clause * cls, ptr_vector & new_clauses); - }; -}; - -#endif /* _SPC_FACTORING_H_ */ - diff --git a/src/dead/spc/spc_justification.cpp b/src/dead/spc/spc_justification.cpp deleted file mode 100644 index 7e83a7fc3..000000000 --- a/src/dead/spc/spc_justification.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_justification.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-08. - -Revision History: - ---*/ -#include"spc_justification.h" -#include"spc_clause.h" -#include"marker.h" - -namespace spc { - - void get_justification_stat(justification * p, justification_stat & stat) { - // Remark: justification objects that are not associated - // with clauses may be shared. That is, they may be parent of - // several different justification objects. - marker m; - ptr_buffer todo; - todo.push_back(p); - while (!todo.empty()) { - justification * p = todo.back(); - todo.pop_back(); - if (!m.is_marked(p)) { - m.mark(p); - clause * cls = p->get_clause(); - if (cls) { - if (cls->get_proof_depth() > stat.m_proof_depth) - stat.m_proof_depth = cls->get_proof_depth(); - if (cls->get_scope_lvl() > stat.m_max_scope_lvl) - stat.m_max_scope_lvl = cls->get_scope_lvl(); - stat.m_parent_clauses.push_back(cls); - } - else { - p->get_parents(todo); - } - } - } - } - - void justification::display(std::ostream & out) { - out << "[" << get_rule_id(); - ptr_buffer ps; - get_parents(ps); - unsigned sz = ps.size(); - for (unsigned i = 0; i < sz; i++) { - out << " "; - justification * js = ps[i]; - clause * cls = js->get_clause(); - if (cls) - out << "#" << cls->get_id(); - else - js->display(out); - } - out << "]"; - } - - justification * justification_proof_wrapper::mk(proof * p, ast_manager & m) { - void * mem = m.get_allocator().allocate(sizeof(justification_proof_wrapper)); - return new (mem) justification_proof_wrapper(p, m); - } - - proof * justification_proof_wrapper::get_proof() const { - return m_proof; - } - - unsigned justification_proof_wrapper::del_eh(ast_manager & m) { - m.dec_ref(m_proof); - return sizeof(justification_proof_wrapper); - } - - void dec_ref(justification * p, ast_manager & m) { - if (p->dec_ref()) { - ptr_buffer to_delete; - ptr_buffer parents; - to_delete.push_back(p); - while (!to_delete.empty()) { - justification * p = to_delete.back(); - to_delete.pop_back(); - SASSERT(p->get_ref_count() == 0); - parents.reset(); - p->get_parents(parents); - ptr_buffer::iterator it = parents.begin(); - ptr_buffer::iterator end = parents.end(); - for (; it != end; ++it) { - justification * parent = *it; - if (parent->dec_ref()) - to_delete.push_back(parent); - } - unsigned sz = p->del_eh(m); - p->~justification(); - m.get_allocator().deallocate(sz, p); - } - } - } - - /** - \brief Return a proof for a new clause formed by the literals lits[0] ... lits[num_lits - 1]. - This clause was produced using a main clause C, where the proof of C is \c main_pr, - and the auxiliary proofs auxs[0] ... aux[num_auxs-1]. - - \remark If fine_grain_proofs() is false, then 0 is returned. - */ - proof * mk_proof(ast_manager & m, family_id spc_fid, spc_op_kind pid, unsigned num_lits, literal * lits, proof * main_pr, - unsigned num_auxs, proof * const * auxs) { - if (m.fine_grain_proofs()) { - expr * new_fact_body = mk_or(m, num_lits, lits); - - SASSERT(main_pr); - SASSERT(m.has_fact(main_pr)); - expr * fact = m.get_fact(main_pr); - expr * new_fact = 0; - if (is_quantifier(fact)) - new_fact = m.update_quantifier(to_quantifier(fact), new_fact_body); - else - new_fact = new_fact_body; - - ptr_buffer args; - args.push_back(main_pr); - args.append(num_auxs, (expr**) auxs); - args.push_back(new_fact); - - return m.mk_app(spc_fid, pid, args.size(), args.c_ptr()); - } - return 0; - } - - justification * rewrite_justification::mk(ast_manager & m, justification * head, - unsigned num_demodulators, justification * const * demodulators, proof * pr) { - void * mem = m.get_allocator().allocate(get_obj_size(num_demodulators, m.fine_grain_proofs())); - return new (mem) rewrite_justification(m, head, num_demodulators, demodulators, pr); - } - - rewrite_justification::rewrite_justification(ast_manager & m, justification * head, - unsigned num_demodulators, justification * const * demodulators, proof * pr): - m_num_demodulators(num_demodulators) { - SASSERT(m.fine_grain_proofs() == (pr != 0)); - m_fields[0] = head; - head->inc_ref(); - for (unsigned i = 0; i < num_demodulators; i++) { - m_fields[i+1] = demodulators[i]; - demodulators[i]->inc_ref(); - } - if (m.fine_grain_proofs()) { - SASSERT(pr); - m_fields[num_demodulators+1] = pr; - m.inc_ref(pr); - } - } - - void rewrite_justification::get_parents(ptr_buffer & parents) { - unsigned num_parents = m_num_demodulators+1; - for (unsigned i = 0; i < num_parents; i++) - parents.push_back(reinterpret_cast(m_fields[i])); - } - - proof * rewrite_justification::get_proof() const { - return reinterpret_cast(m_fields[m_num_demodulators+1]); - } - - unsigned rewrite_justification::del_eh(ast_manager & m) { - if (m.fine_grain_proofs()) { - m.dec_ref(reinterpret_cast(m_fields[m_num_demodulators+1])); - return get_obj_size(m_num_demodulators, true); - } - return get_obj_size(m_num_demodulators, false); - } - - proof * mk_rewrite_proof(ast_manager & m, family_id spc_fid, unsigned num_lits, literal * lits, proof * main_pr, - unsigned num_auxs, proof * const * auxs) { - return mk_proof(m, spc_fid, PR_SPC_REWRITE, num_lits, lits, main_pr, num_auxs, auxs); - } -}; diff --git a/src/dead/spc/spc_justification.h b/src/dead/spc/spc_justification.h deleted file mode 100644 index ba8827822..000000000 --- a/src/dead/spc/spc_justification.h +++ /dev/null @@ -1,337 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_justification.h - -Abstract: - - Proof-like objects for tracking dependencies in the superposition - calculus engine, and generating proofs. - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#ifndef _SPC_JUSTIFICATION_H_ -#define _SPC_JUSTIFICATION_H_ - -#include"ast.h" -#include"spc_literal.h" -#include"spc_decl_plugin.h" - -namespace spc { - - class clause; - - /** - \brief Proof-like object use to track dependencies and produce - proofs. - - \remark All justification objects must be allocated using the - small_object_allocator in ast_manager. - */ - class justification { - clause * m_owner; - unsigned m_ref_count:30; - unsigned m_mark:1; - unsigned m_assumption:1; - - friend class clause; - void set_owner(clause * cls) { m_owner = cls; } - - public: - justification(bool assumption = false): - m_owner(0), - m_ref_count(0), - m_mark(false), - m_assumption(assumption) { - } - - virtual ~justification() {} - - void inc_ref() { - m_ref_count++; - } - - bool dec_ref() { - SASSERT(m_ref_count > 0); - m_ref_count--; - return m_ref_count == 0; - } - - unsigned get_ref_count() { - return m_ref_count; - } - - void set_mark(bool f) { m_mark = f; } - - bool is_marked() const { return m_mark; } - - /** - \brief Return the clause justified by this object. - - \remark for some justification objects that clause is - supressed. Example: intermediate steps. - */ - clause * get_clause() { return m_owner; } - - /** - \brief Return the expr justified by this object. - This method returns a non null value only when - proof generation is enabled. - */ - virtual expr * get_expr(ast_manager & m) { return 0; } - - /** - \brief Return a non-zero value if the justification - is wrapping a proof object. - */ - virtual proof * get_proof() const { return 0; } - - /** - \brief Return the parent justifications. - */ - virtual void get_parents(ptr_buffer & parents) {} - - /** - \brief Return the name of the rule used. - */ - virtual spc_op_kind get_rule_id() = 0; - - /** - \brief Return true if the justification is an external assumption. - */ - bool assumption() const { return m_assumption; } - - void display(std::ostream & out); - - /** - \brief This method is invoked before the object is deleted. - Return the amount of memory consumed by this object. - */ - virtual unsigned del_eh(ast_manager & m) = 0; - }; - - struct justification_stat { - unsigned m_proof_depth; - unsigned m_max_scope_lvl; - ptr_buffer m_parent_clauses; - justification_stat(): - m_proof_depth(0), - m_max_scope_lvl(0) { - } - }; - - void get_justification_stat(justification * p, justification_stat & stat); - - void dec_ref(justification * p, ast_manager & m); - - /** - \brief Smart pointer for justification objects. - */ - class justification_ref { - justification * m_obj; - ast_manager & m_manager; - void inc_ref() { if (m_obj) m_obj->inc_ref(); } - void dec_ref() { if (m_obj) spc::dec_ref(m_obj, m_manager); } - public: - justification_ref(ast_manager & m):m_obj(0), m_manager(m) {} - justification_ref(justification * j, ast_manager & m): - m_obj(j), m_manager(m) { - inc_ref(); - } - ~justification_ref() { - dec_ref(); - } - operator justification*() const { return m_obj; } - operator bool() const { return m_obj != 0; } - bool operator!() const { return m_obj == 0; } - justification * operator->() const { return m_obj; } - justification const & operator*() const { return *m_obj; } - justification_ref & operator=(justification * n) { - if (n) - n->inc_ref(); - dec_ref(); - m_obj = n; - return *this; - } - justification_ref & operator=(justification_ref & n) { - SASSERT(&m_manager == &n.m_manager); - n.inc_ref(); - dec_ref(); - m_obj = n.m_obj; - return *this; - } - }; - - class justification_proof_wrapper : public justification { - proof * m_proof; - justification_proof_wrapper(proof * p, ast_manager & m):m_proof(p) { m.inc_ref(m_proof); } - public: - static justification * mk(proof * p, ast_manager & m); - virtual ~justification_proof_wrapper() {} - virtual proof * get_proof() const; - virtual spc_op_kind get_rule_id() { return PR_SPC_ASSERTED; }; - virtual unsigned del_eh(ast_manager & m); - }; - - proof * mk_proof(ast_manager & m, family_id spc_fid, spc_op_kind pid, unsigned num_lits, literal * lits, proof * main_pr, unsigned num_auxs, - proof * const * auxs); - - /** - \brief Justification for rewriting steps: demodulation, duplicate literal deletion, resolved literal deletion. - */ - class rewrite_justification : public justification { - unsigned m_num_demodulators; - void * m_fields[0]; - static unsigned get_obj_size(unsigned num_demodulators, bool fine_grain) { - return sizeof(rewrite_justification) + (num_demodulators + (fine_grain ? 2 : 1)) * sizeof(void *); - } - rewrite_justification(ast_manager & m, justification * head, - unsigned num_demodulators, justification * const * demodulators, proof * pr); - public: - static justification * mk(ast_manager & m, justification * head, - unsigned num_demodulators, justification * const * demodulators, proof * pr = 0); - virtual ~rewrite_justification() {} - virtual proof * get_proof() const; - virtual spc_op_kind get_rule_id() { return PR_SPC_REWRITE; } - virtual void get_parents(ptr_buffer & parents); - virtual unsigned del_eh(ast_manager & m); - }; - - proof * mk_rewrite_proof(ast_manager & m, family_id spc_fid, unsigned num_lits, literal * lits, proof * main_pr, unsigned num_auxs, - proof * const * auxs); - - template - class unary_justification : public justification { - protected: - justification * m_parent; - proof * m_proof; - - unary_justification(ast_manager & m, justification * p, proof * pr): - m_parent(p), - m_proof(pr) { - p->inc_ref(); - SASSERT(m.fine_grain_proofs() == (pr != 0)); - if (m.fine_grain_proofs()) - m.inc_ref(pr); - } - - public: - virtual proof * get_proof() const { - return m_proof; - } - - virtual void get_parents(ptr_buffer & parents) { - parents.push_back(m_parent); - } - - virtual unsigned del_eh(ast_manager & m) { - if (m.fine_grain_proofs()) - m.dec_ref(m_proof); - return sizeof(unary_justification); - } - - virtual spc_op_kind get_rule_id() { - return Kind; - } - - static justification * mk(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) { - proof * pr = 0; - if (m.fine_grain_proofs()) - pr = mk_proof(m, spc_fid, Kind, num_lits, lits, p->get_proof(), 0, 0); - void * mem = m.get_allocator().allocate(sizeof(unary_justification)); - return new (mem) unary_justification(m, p, pr); - } - }; - - inline justification * mk_eq_res_justification(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) { - return unary_justification::mk(m, spc_fid, p, num_lits, lits); - } - - inline justification * mk_factoring_justification(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) { - return unary_justification::mk(m, spc_fid, p, num_lits, lits); - } - - inline justification * mk_der_justification(ast_manager & m, family_id spc_fid, justification * p, unsigned num_lits, literal * lits) { - return unary_justification::mk(m, spc_fid, p, num_lits, lits); - } - - template - class binary_justification : public justification { - protected: - justification * m_parent1; - justification * m_parent2; - proof * m_proof; - - binary_justification(ast_manager & m, justification * p1, justification * p2, proof * pr): - m_parent1(p1), - m_parent2(p2), - m_proof(pr) { - p1->inc_ref(); - p2->inc_ref(); - SASSERT(m.fine_grain_proofs() == (pr != 0)); - if (m.fine_grain_proofs()) - m.inc_ref(pr); - } - - public: - virtual proof * get_proof() const { - return m_proof; - } - - virtual void get_parents(ptr_buffer & parents) { - parents.push_back(m_parent1); - parents.push_back(m_parent2); - } - - virtual unsigned del_eh(ast_manager & m) { - if (m.fine_grain_proofs()) - m.dec_ref(m_proof); - return sizeof(binary_justification); - } - - virtual spc_op_kind get_rule_id() { - return Kind; - } - - static justification * mk(ast_manager & m, family_id spc_fid, justification * p1, justification * p2, unsigned num_lits, literal * lits, - unsigned num_vars, var * const * vars) { - proof * pr = 0; - if (m.fine_grain_proofs()) { - ptr_buffer sorts; - sbuffer names; - for (unsigned i = 0; i < num_vars; i++) { - sorts.push_back(vars[num_vars - i - 1]->get_sort()); - names.push_back(symbol(num_vars - i - 1)); - } - expr * body = mk_or(m, num_lits, lits); - expr * new_fact = 0; - if (num_vars == 0) - new_fact = body; - else - new_fact = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), body); - pr = m.mk_app(spc_fid, Kind, p1->get_proof(), p2->get_proof(), new_fact); - } - void * mem = m.get_allocator().allocate(sizeof(binary_justification)); - return new (mem) binary_justification(m, p1, p2, pr); - } - }; - - inline justification * mk_superposition_justification(ast_manager & m, family_id spc_fid, justification * p1, justification * p2, - unsigned num_lits, literal * lits, unsigned num_vars, var * const * vars) { - return binary_justification::mk(m, spc_fid, p1, p2, num_lits, lits, num_vars, vars); - } - - inline justification * mk_resolution_justification(ast_manager & m, family_id spc_fid, justification * p1, justification * p2, - unsigned num_lits, literal * lits, unsigned num_vars, var * const * vars) { - return binary_justification::mk(m, spc_fid, p1, p2, num_lits, lits, num_vars, vars); - } -}; - -#endif /* _SPC_JUSTIFICATION_H_ */ diff --git a/src/dead/spc/spc_literal.cpp b/src/dead/spc/spc_literal.cpp deleted file mode 100644 index f2bdd0e9e..000000000 --- a/src/dead/spc/spc_literal.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_literal.cpp - -Abstract: - - Superposition Calculus literal - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#include"spc_literal.h" -#include"ast_pp.h" - -namespace spc { - - void literal::try_to_orient(order & o) { - ast_manager & m = o.get_manager(); - if (!m_sign && m.is_eq(m_atom)) { - expr * lhs = to_app(m_atom)->get_arg(0); - expr * rhs = to_app(m_atom)->get_arg(1); - TRACE("spc_orient", tout << "trying to orient:\n" << mk_pp(lhs, m) << "\n" << mk_pp(rhs, m) << "\n";); - switch (o.compare(lhs, rhs)) { - case order::GREATER: - m_oriented = true; - m_left = true; - TRACE("spc_orient", tout << "greater\n";); - return; - case order::LESSER: - m_oriented = true; - m_left = false; - TRACE("spc_orient", tout << "smaller\n";); - return; - default: - return; - } - } - } - - void literal::get_stat(literal_stat & stat) { - get_expr_stat(m_atom, stat); - m_stats = true; - m_ground = stat.m_ground; - m_sym_count = stat.m_sym_count > SYM_COUNT_MAX ? SYM_COUNT_MAX : stat.m_sym_count; - m_depth = stat.m_depth > DEPTH_MAX ? DEPTH_MAX : stat.m_depth; - m_const_count = stat.m_const_count > CONST_COUNT_MAX ? CONST_COUNT_MAX : stat.m_const_count; - } - - expr * literal::to_expr(ast_manager & m) const { - if (is_true(m)) - return m.mk_true(); - else if (is_false(m)) - return m.mk_false(); - else if (m_sign) - return m.mk_not(m_atom); - else - return m_atom; - } - - void literal::display(std::ostream & out, ast_manager & m, bool detailed) const { - pp_params p; - p.m_pp_single_line = true; - - if (m_sign) - out << "(not "; - - if (m_oriented) { - expr * lhs = to_app(m_atom)->get_arg(0); - expr * rhs = to_app(m_atom)->get_arg(1); - if (!m_left) - std::swap(lhs, rhs); - out << "(-> "; - ast_pp(out, lhs, m, p); - out << " "; - ast_pp(out, rhs, m, p); - out << ")"; - } - else { - ast_pp(out, m_atom, m, p); - } - - if (m_sign) - out << ")"; - - if (detailed && m_stats) { - out << "[" << m_ground << ", " << m_depth << ", " << m_sym_count << ", " << m_const_count << "]"; - } - - if (m_selected) - out << "$"; - if (m_p_indexed) - out << "!"; - if (m_r_indexed) - out << "@"; - } - - void display(std::ostream & out, unsigned num_lists, literal * lits, ast_manager & m, bool detailed) { - for (unsigned i = 0; i < num_lists; i++) { - if (i > 0) out << " "; - lits[i].display(out, m, detailed); - } - } - - /** - \brief Given an eq literal store in lhs and rhs the left and right hand sides. If they can be oriented - given the substitution s, then return true, and make lhs the maximal one. - */ - bool can_orient(order & o, literal const & l, unsigned offset, substitution * s, expr * & lhs, expr * & rhs) { - SASSERT(o.get_manager().is_eq(l.atom())); - lhs = l.lhs(); - rhs = l.rhs(); - if (l.is_oriented()) { - if (!l.is_left()) - std::swap(lhs, rhs); - return true; - } - else { - order::result comp = o.compare(lhs, rhs, offset, s); - if (comp == order::GREATER) - return true; - else if (comp == order::LESSER) { - std::swap(lhs, rhs); - return true; - } - return false; - } - } - - /** - \brief Compare literal signs. Negative sign is bigger than the positive one. - */ - inline order::result compare_signs(bool sign1, bool sign2) { - if (sign1 && !sign2) - return order::GREATER; - else if (!sign1 && sign2) - return order::LESSER; - else - return order::EQUAL; - } - - /** - \brief Compare two literals (modulo a substitution) using the given term ordering. - */ - order::result compare(order & o, literal const & l1, literal const & l2, unsigned offset, substitution * s) { - ast_manager & m = o.get_manager(); - expr * n1 = l1.atom(); - expr * n2 = l2.atom(); - bool is_eq1 = m.is_eq(n1); - bool is_eq2 = m.is_eq(n2); - if (is_eq1 && is_eq2) { - expr * lhs1 = 0; - expr * rhs1 = 0; - expr * lhs2 = 0; - expr * rhs2 = 0; - bool oriented1 = can_orient(o, l1, offset, s, lhs1, rhs1); - bool oriented2 = can_orient(o, l2, offset, s, lhs2, rhs2); - if (oriented1) { - // equation 1 can be oriented - if (oriented2) { - // equation 2 can be oriented - // both equations are oriented - SASSERT(oriented1); - SASSERT(oriented2); - order::result r = o.compare(lhs1, lhs2, offset, s); - if (r == order::EQUAL) { - if (l1.pos()) { - if (l2.pos()) - return o.compare(rhs1, rhs2, offset, s); - else - return order::LESSER; - } - else { - if (l2.pos()) - return order::GREATER; - else - return o.compare(rhs1, rhs2, offset, s); - } - } - return r; - } - else { - // equation 2 cannot be oriented - SASSERT(oriented1); - SASSERT(!oriented2); - SASSERT(o.compare(lhs1, rhs1, offset, s) == order::GREATER); - if (o.equal(lhs1, lhs2, offset, s)) { - order::result r = o.compare(rhs1, rhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - if (o.equal(lhs1, rhs2, offset, s)) { - order::result r = o.compare(rhs1, lhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - order::result lhs1_lhs2 = o.compare(lhs1, lhs2, offset, s); - order::result lhs1_rhs2 = o.compare(lhs1, rhs2, offset, s); - if (lhs1_lhs2 == lhs1_rhs2) - return lhs1_lhs2; - order::result rhs1_rhs2 = o.compare(rhs1, rhs2, offset, s); - if (lhs1_lhs2 == rhs1_rhs2) - return lhs1_lhs2; - if (lhs1_rhs2 == order::LESSER && rhs1_rhs2 == order::LESSER) - return order::LESSER; - order::result rhs1_lhs2 = o.compare(rhs1, lhs2, offset, s); - if (lhs1_lhs2 == order::LESSER && rhs1_lhs2 == order::LESSER) - return order::LESSER; - return order::UNCOMPARABLE; - } - } - else { - // equation 1 cannot be oriented - if (oriented2) { - SASSERT(!oriented1); - SASSERT(oriented2); - // equation 2 can be oriented - if (o.equal(lhs1, lhs2, offset, s)) { - order::result r = o.compare(rhs1, rhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - if (o.equal(rhs1, lhs2, offset, s)) { - order::result r = o.compare(lhs1, rhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - order::result lhs1_lhs2 = o.compare(lhs1, lhs2, offset, s); - order::result rhs1_lhs2 = o.compare(rhs1, lhs2, offset, s); - if (lhs1_lhs2 == rhs1_lhs2) - return lhs1_lhs2; - order::result rhs1_rhs2 = o.compare(rhs1, rhs2, offset, s); - if (lhs1_lhs2 == rhs1_rhs2) - return lhs1_lhs2; - if (rhs1_lhs2 == order::GREATER && rhs1_rhs2 == order::GREATER) - return order::GREATER; - order::result lhs1_rhs2 = o.compare(lhs1, rhs2, offset, s); - if (lhs1_lhs2 == order::GREATER && lhs1_rhs2 == order::GREATER) - return order::GREATER; - return order::UNCOMPARABLE; - } - else { - SASSERT(!oriented1); - SASSERT(!oriented2); - if (o.equal(lhs1, lhs2, offset, s)) { - order::result r = o.compare(rhs1, rhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - if (o.equal(rhs1, lhs2, offset, s)) { - order::result r = o.compare(lhs1, rhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - if (o.equal(lhs1, rhs2, offset, s)) { - order::result r = o.compare(rhs1, lhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - if (o.equal(rhs1, rhs2, offset, s)) { - order::result r = o.compare(lhs1, lhs2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - - order::result r; - order::result aux; - switch (o.compare(lhs1, lhs2, offset, s)) { - case order::GREATER: - r = o.compare(lhs1, rhs2, offset, s); - if (r == order::GREATER) - return order::GREATER; - aux = o.compare(rhs1, rhs2, offset, s); - if (aux == order::GREATER) - return order::GREATER; - if (r == order::LESSER && aux == order::LESSER) - return order::LESSER; - SASSERT(r != order::EQUAL); - SASSERT(aux != order::EQUAL); - return order::UNCOMPARABLE; - case order::LESSER: - r = o.compare(rhs1, lhs2, offset, s); - if (r == order::LESSER) - return order::LESSER; - aux = o.compare(rhs1, rhs2, offset, s); - if (aux == order::LESSER) - return order::LESSER; - if (r == order::GREATER && aux == order::GREATER) - return order::GREATER; - SASSERT(r != order::EQUAL); - SASSERT(aux != order::EQUAL); - return order::UNCOMPARABLE; - case order::EQUAL: - UNREACHABLE(); - return order::UNKNOWN; - default: - switch (o.compare(lhs1, rhs2, offset, s)) { - case order::GREATER: - if (o.compare(rhs1, lhs2, offset, s) == order::GREATER) - return order::GREATER; - return order::UNCOMPARABLE; - case order::LESSER: - if (o.compare(rhs1, lhs2, offset, s) == order::LESSER || - o.compare(rhs1, rhs2, offset, s) == order::LESSER) - return order::LESSER; - return order::UNCOMPARABLE; - case order::EQUAL: - UNREACHABLE(); - return order::UNKNOWN; - default: - if (o.compare(rhs1, lhs2, offset, s) == order::GREATER && - o.compare(rhs1, rhs2, offset, s) == order::GREATER) - return order::GREATER; - return order::UNCOMPARABLE; - } - } - } - } - } - else if (is_eq1) { - expr * lhs1 = l1.lhs(); - expr * rhs1 = l1.rhs(); - if (l1.is_oriented() && !l1.is_left()) - std::swap(lhs1, rhs1); - order::result r = o.compare(lhs1, n2, offset, s); - if (!l1.is_oriented() || r != order::GREATER) { - order::result r2 = o.compare(rhs1, n2, offset, s); - if (r2 == order::GREATER) - return order::GREATER; - else if (r != r2) - return order::UNCOMPARABLE; - } - return r; - } - else if (is_eq2) { - expr * lhs2 = l2.lhs(); - expr * rhs2 = l2.rhs(); - if (l2.is_oriented() && !l2.is_left()) - std::swap(lhs2, rhs2); - order::result r = o.compare(n1, lhs2, offset, s); - if (!l1.is_oriented() || r != order::LESSER) { - order::result r2 = o.compare(n1, rhs2, offset, s); - if (r2 == order::LESSER) - return order::LESSER; - else if (r != r2) - return order::UNCOMPARABLE; - } - return r; - } - else { - order::result r = o.compare(n1, n2, offset, s); - if (r == order::EQUAL) - return compare_signs(l1.sign(), l2.sign()); - return r; - } - } - - bool greater(order & o, literal const & l1, literal const & l2, unsigned offset, substitution * s) { - order::result r = compare(o, l1, l2, offset, s); - TRACE("literal_order", ast_manager & m = o.get_manager(); - tout << "comparing "; - l1.display(tout, m); - tout << " "; - l2.display(tout, m); - tout << " : " << r << "\n";); - return r == order::GREATER; - } - - void found_literals::insert(literal const & l) { - unsigned id = l.get_id(); - m_marks.reserve(id+1); - if (!m_marks.get(id)) { - m_marks.set(id); - m_lit_ids.push_back(id); - } - } - - bool found_literals::contains(literal const & l) const { - unsigned id = l.get_id(); - return id < m_marks.size() && m_marks.get(id); - } - - bool found_literals::contains_neg(literal const & l) const { - unsigned id = l.get_neg_id(); - return id < m_marks.size() && m_marks.get(id); - } - - void found_literals::reset() { - unsigned_vector::iterator it = m_lit_ids.begin(); - unsigned_vector::iterator end = m_lit_ids.end(); - for (; it != end; ++it) - m_marks.unset(*it); - m_lit_ids.reset(); - } - - void literal_buffer::reset() { - buffer::iterator it = m_lits.begin(); - buffer::iterator end = m_lits.end(); - for (; it != end; ++it) - m_manager.dec_ref(it->atom()); - m_lits.reset(); - } - - - expr * mk_or(ast_manager & m, unsigned num_lists, literal * lits) { - if (num_lists == 0) - return m.mk_false(); - else if (num_lists == 1) - return lits[0].to_expr(m); - else { - ptr_buffer new_exprs; - for (unsigned i = 0; i < num_lists; i++) - new_exprs.push_back(lits[i].to_expr(m)); - return m.mk_or(new_exprs.size(), new_exprs.c_ptr()); - } - } - -}; diff --git a/src/dead/spc/spc_literal.h b/src/dead/spc/spc_literal.h deleted file mode 100644 index 8b5322e4d..000000000 --- a/src/dead/spc/spc_literal.h +++ /dev/null @@ -1,212 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_literal.h - -Abstract: - - Superposition Calculus literal - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#ifndef _SPC_LITERAL_H_ -#define _SPC_LITERAL_H_ - -#include"ast.h" -#include"order.h" -#include"expr_stat.h" - -namespace spc { - typedef expr_stat literal_stat; - -#define DEPTH_NUM_BITS 4 -#define DEPTH_MAX ((1 << DEPTH_NUM_BITS) - 1) -#define CONST_COUNT_NUM_BITS 4 -#define CONST_COUNT_MAX ((1 << CONST_COUNT_NUM_BITS) - 1) -#define SYM_COUNT_NUM_BITS 16 -#define SYM_COUNT_MAX ((1 << SYM_COUNT_NUM_BITS) - 1) - - /** - \brief Superposition Calculus literal. - */ - class literal { - expr * m_atom; - unsigned m_sign:1; // true if a negative literal. - unsigned m_oriented:1; // true if it is an oriented equality. - unsigned m_left:1; // true if the largest term is on the left-hand-side of the equality (only meaningful if m_oriented == true). - unsigned m_selected:1; // true if it is a selected literal. - unsigned m_stats:1; // true if the following fields were initialized. - unsigned m_ground:1; // true if it is a ground literal - unsigned m_p_indexed:1; // true if the literal was inserted into the p (paramodulation) superposition index. - unsigned m_r_indexed:1; // true if the literal was inserted into the r (resolution) superposition index. - unsigned m_depth:DEPTH_NUM_BITS; // approx. depth - unsigned m_const_count:CONST_COUNT_NUM_BITS; // approx. number of constants - unsigned m_sym_count:SYM_COUNT_NUM_BITS; // approx. size - - friend class clause; - - void set_selected(bool f) { - m_selected = f; - } - - public: - literal(): - m_atom(0), - m_sign(false), - m_oriented(false), - m_left(false), - m_selected(false), - m_stats(false), - m_ground(false), - m_p_indexed(false), - m_r_indexed(false), - m_depth(0), - m_const_count(0), - m_sym_count(0) { - } - - literal(expr * atom, bool sign = false): - m_atom(atom), - m_sign(sign), - m_oriented(false), - m_left(false), - m_selected(false), - m_stats(false), - m_ground(false), - m_p_indexed(false), - m_r_indexed(false), - m_depth(0), - m_const_count(0), - m_sym_count(0) { - } - - bool sign() const { return m_sign; } - bool pos() const { return !m_sign; } - bool neg() const { return m_sign; } - bool is_oriented() const { return m_oriented; } - bool is_left() const { return m_left; } - bool is_selected() const { return m_selected; } - expr * atom() const { return m_atom; } - expr * lhs() const { return to_app(m_atom)->get_arg(0); } - expr * rhs() const { return to_app(m_atom)->get_arg(1); } - unsigned get_id() const { return m_sign ? (to_app(m_atom)->get_id() << 1) + 1 : (to_app(m_atom)->get_id() << 1); } - unsigned get_neg_id() const { return m_sign ? (to_app(m_atom)->get_id() << 1) : (to_app(m_atom)->get_id() << 1) + 1; } - - bool operator==(literal const & other) const { return m_atom == other.m_atom && m_sign == other.m_sign; } - bool operator!=(literal const & other) const { return !operator==(other); } - - void set_p_indexed(bool f) { m_p_indexed = f; } - void set_r_indexed(bool f) { m_r_indexed = f; } - bool is_p_indexed() const { return m_p_indexed; } - bool is_r_indexed() const { return m_r_indexed; } - - void try_to_orient(order & o); - bool is_true(ast_manager & m) const { - return - (!m_sign && m.is_true(m_atom)) || - (!m_sign && m.is_eq(m_atom) && to_app(m_atom)->get_arg(0) == to_app(m_atom)->get_arg(1)) || - (m_sign && m.is_false(m_atom)); - } - bool is_false(ast_manager & m) const { - return - (m_sign && m.is_true(m_atom)) || - (m_sign && m.is_eq(m_atom) && to_app(m_atom)->get_arg(0) == to_app(m_atom)->get_arg(1)) || - (!m_sign && m.is_false(m_atom)); - } - expr * to_expr(ast_manager & m) const; - - /** - \brief Collect literal statistics - */ - void get_stat(literal_stat & stat); - void init_stat() { literal_stat st; get_stat(st); } - bool has_stats() const { return m_stats; } - bool is_ground() const { SASSERT(m_stats); return m_ground; } - unsigned get_approx_depth() const { SASSERT(m_stats); return m_depth; } - unsigned get_approx_const_count() const { SASSERT(m_stats); return m_const_count; } - unsigned get_approx_sym_count() const { SASSERT(m_stats); return m_sym_count; } - - void display(std::ostream & out, ast_manager & m, bool detailed = false) const; - }; - - COMPILE_TIME_ASSERT(sizeof(expr*) != 4 || sizeof(literal) == sizeof(expr *) + sizeof(unsigned)); // 32 bit machine - COMPILE_TIME_ASSERT(sizeof(expr*) != 8 || sizeof(literal) == sizeof(expr *) + sizeof(unsigned) + /* a structure must be aligned */ sizeof(unsigned)); // 64 bit machine - - void display(std::ostream & out, unsigned num_lists, literal * lits, ast_manager & m, bool detailed = false); - - order::result compare(order & o, literal const & l1, literal const & l2, unsigned offset = 0, substitution * s = 0); - bool greater(order & o, literal const & l1, literal const & l2, unsigned offset = 0, substitution * s = 0); - bool is_maximal(order & o, unsigned num_lists, literal * lits, literal const & l, unsigned offset = 0, substitution * s = 0); - bool is_sel_maximal(order & o, unsigned num_lists, literal * lits, literal const & l, unsigned offset = 0, substitution * s = 0); - - /** - \brief Set of found literals. - - This object is used to implement duplicate literal elimination, ans syntatic tautology. - */ - class found_literals { - bit_vector m_marks; - unsigned_vector m_lit_ids; - public: - /** - \brief Insert the given literal into the set. - */ - void insert(literal const & l); - - /** - \brief Return true if the set contains \c l. - */ - bool contains(literal const & l) const; - - /** - \brief Return true if the set contains the negation of \c l. - */ - bool contains_neg(literal const & l) const; - - bool empty() const { return m_lit_ids.empty(); } - - /** - \brief Remove all literals from the set. - */ - void reset(); - }; - - class literal_buffer { - ast_manager & m_manager; - buffer m_lits; - public: - literal_buffer(ast_manager & m): - m_manager(m) { - } - - ~literal_buffer() { - reset(); - } - - void push_back(literal const & l) { - m_manager.inc_ref(l.atom()); - m_lits.push_back(l); - } - - void reset(); - - unsigned size() const { - return m_lits.size(); - } - - literal * c_ptr() const { - return m_lits.c_ptr(); - } - }; - - expr * mk_or(ast_manager & m, unsigned num_lists, literal * lits); -}; - -#endif /* _SPC_LITERAL_H_ */ diff --git a/src/dead/spc/spc_literal_selection.cpp b/src/dead/spc/spc_literal_selection.cpp deleted file mode 100644 index b8ecb151e..000000000 --- a/src/dead/spc/spc_literal_selection.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_literal_selection.cpp - -Abstract: - - Superposition Calculus Literal Selection - -Author: - - Leonardo de Moura (leonardo) 2008-02-05. - -Revision History: - ---*/ -#include"spc_literal_selection.h" -#include"expr_stat.h" - -namespace spc { - - void diff_literal_selection::operator()(clause * cls) { - bool found = false; - unsigned target = UINT_MAX; - unsigned best_count = 0; - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - literal & l = cls->get_literal(i); - if (l.sign()) { - unsigned count; - if (m_manager.is_eq(l.atom())) { - unsigned c1 = get_symbol_count(to_app(l.atom())->get_arg(0)); - unsigned c2 = get_symbol_count(to_app(l.atom())->get_arg(1)); - count = c1 >= c2 ? c1 - c2 : c2 - c1; - } - else { - count = get_symbol_count(l.atom()); - } - if (count > best_count) { - found = true; - target = i; - best_count = count; - } - } - } - if (found) - cls->select_literal(target); - } - - void complex_literal_selection::operator()(clause * cls) { - // look for x != y - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - literal & l = cls->get_literal(i); - if (l.sign() && m_manager.is_eq(l.atom()) && is_var(to_app(l.atom())->get_arg(0)) && is_var(to_app(l.atom())->get_arg(1))) { - cls->select_literal(i); - return; - } - } - - // look for min ground neg literal - bool found = false; - unsigned target = UINT_MAX; - unsigned best_count = UINT_MAX; - for (unsigned i = 0; i < num; i++) { - literal & l = cls->get_literal(i); - if (l.sign() && is_ground(l.atom())) { - unsigned count = get_symbol_count(l.atom()); - if (count < best_count) { - found = true; - target = i; - best_count = count; - } - } - } - - if (found) { - cls->select_literal(target); - return; - } - - diff_literal_selection::operator()(cls); - } - - void max_no_selection::operator()(clause * cls) { - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l1 = cls->get_literal(i); - if (!l1.sign()) { - unsigned j = 0; - for (; j < num_lits; j++) { - if (i != j) { - literal const & l2 = cls->get_literal(j); - if (!greater(m_order, l1, l2)) - break; - } - } - if (j == num_lits) - return; // clause has maximal positive literal. - } - } - diff_literal_selection::operator()(cls); - } - -}; diff --git a/src/dead/spc/spc_literal_selection.h b/src/dead/spc/spc_literal_selection.h deleted file mode 100644 index 0d51af93d..000000000 --- a/src/dead/spc/spc_literal_selection.h +++ /dev/null @@ -1,95 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_literal_selection.h - -Abstract: - - Superposition Calculus Literal Selection - -Author: - - Leonardo de Moura (leonardo) 2008-02-05. - -Revision History: - ---*/ -#ifndef _SPC_LITERAL_SELECTION_H_ -#define _SPC_LITERAL_SELECTION_H_ - -#include"spc_clause.h" -#include"order.h" - -namespace spc { - - /** - \brief Abstract functor for literal selection. - */ - class literal_selection { - public: - virtual ~literal_selection() {} - /** - \brief Updates the selected status flag of the literals of the given clause. - */ - virtual void operator()(clause * cls) = 0; - }; - - /** - \brief Never selects a literal. This strategy is supposed to be good for planning problems - of TPTP. - */ - class no_literal_selection : public literal_selection { - public: - virtual void operator()(clause * cls) {} - }; - - - /** - \brief Selects a negative literal l with the largest V(l) - where V is defined as: - - - difference in symbol count for the left-right hand sides of equalities, . - - - symbol count for other predicates - - */ - class diff_literal_selection : public literal_selection { - protected: - ast_manager & m_manager; - public: - diff_literal_selection(ast_manager & m):m_manager(m) {} - virtual void operator()(clause * cls); - }; - - /** - \brief Selects a negative literal using the following algo: - - - if there is x != y, select it. - - - else if there is negative ground literal, select the smallest one. - - - else if use the approach in diff_literal_selection. - */ - class complex_literal_selection : public diff_literal_selection { - public: - complex_literal_selection(ast_manager & m):diff_literal_selection(m) {} - virtual void operator()(clause * cls); - }; - - /** - \brief Similar to diff_literal_selection, but a literal - is not selected if the clause contains a positive literal - greater than all other literals. - */ - class max_no_selection : public diff_literal_selection { - order & m_order; - public: - max_no_selection(order & o):diff_literal_selection(o.get_manager()), m_order(o) {} - virtual void operator()(clause * cls); - }; - -}; - -#endif /* _SPC_LITERAL_SELECTION_H_ */ diff --git a/src/dead/spc/spc_prover.cpp b/src/dead/spc/spc_prover.cpp deleted file mode 100644 index 76100c4f7..000000000 --- a/src/dead/spc/spc_prover.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_prover.cpp - -Abstract: - - Stand-alone SPC prover (it is mainly for debugging purposes). - -Author: - - Leonardo de Moura (leonardo) 2008-02-08. - -Revision History: - ---*/ -#include"spc_prover.h" -#include"spc_decl_plugin.h" -#include"for_each_expr.h" - -namespace spc { - prover::prover(ast_manager & m, front_end_params & params): - m_manager(m), - m_params(params), - m_simplifier(m), - m_defined_names(m), - m_preprocessor(m, m_defined_names, m_simplifier, params), - m_order(0), - m_cls_sel(0), - m_lit_sel(0), - m_context(0), - m_exprs(m), - m_expr_proofs(m), - m_has_theories(false) { - - family_id fid = m_manager.get_family_id("spc"); - if (!m_manager.has_plugin(fid)) - m_manager.register_plugin(fid, alloc(spc_decl_plugin)); - - // This piece of code shows why the old model for passing parameters is broken. - // spc::prover must overwrite some parameters, but this modification affects other - // components. :-( - // TODO: move everything to the new params_ref object - params.m_nnf_mode = NNF_FULL; - params.m_cnf_mode = CNF_FULL; - params.m_lift_ite = LI_CONSERVATIVE; - - basic_simplifier_plugin * basic = alloc(basic_simplifier_plugin, m_manager); - m_simplifier.register_plugin(basic); - m_simplifier.register_plugin(alloc(arith_simplifier_plugin, m_manager, *basic, params)); - } - - prover::~prover() { - if (m_context) { - dealloc(m_context); - dealloc(m_lit_sel); - dealloc(m_cls_sel); - dealloc(m_order); - } - } - - void prover::init() { - if (m_context) - return; - precedence * p = mk_precedence(m_manager, m_params); - - // TODO use params to configure the following functors. - m_order = alloc(kbo, m_manager, p); - - clause_eval * evals[2] = { alloc(symbol_count_clause_eval), alloc(time_clause_eval) }; - unsigned slots[2] = { 10, 1 }; - m_cls_sel = alloc(clause_selection, 2, evals, slots); - - m_lit_sel = alloc(max_no_selection, *m_order); - // m_lit_sel = new complex_literal_selection(m_manager); - // m_lit_sel = new diff_literal_selection(m_manager); - // m_lit_sel = new no_literal_selection(); // new diff_literal_selection(m_manager); - // END TODO - - m_context = alloc(context, m_manager, *m_order, *m_cls_sel, *m_lit_sel, m_simplifier, m_params); - } - - struct has_theories_proc { - ast_manager & m_manager; - has_theories_proc(ast_manager & m):m_manager(m) {} - struct found {}; - void operator()(var * n) {} - void operator()(app * n) { if (!m_manager.is_builtin_family_id(n->get_family_id())) throw found(); } - void operator()(quantifier * n) {} - }; - - bool has_theories(ast_manager & m, expr * e) { - has_theories_proc p(m); - try { - for_each_expr(p, e); - } - catch (has_theories_proc::found) { - return true; - } - return false; - } - - void prover::assert_expr(expr * e) { - if (!m_has_theories && has_theories(m_manager, e)) - m_has_theories = true; - TRACE("spc_assert", tout << mk_pp(e, m_manager) << "\nhas_theories: " << m_has_theories << "\n";); - m_preprocessor(e, m_manager.mk_asserted(e), m_exprs, m_expr_proofs); - } - - lbool prover::check() { - init(); - unsigned sz = m_exprs.size(); - for (unsigned i = 0; i < sz; i++) { - expr * curr = m_exprs.get(i); - proof * p = m_manager.proofs_enabled() ? m_expr_proofs.get(i) : m_manager.mk_undef_proof(); - m_context->assert_expr(curr, p); - } - m_exprs.reset(); - m_expr_proofs.reset(); - - m_context->saturate(m_params.m_spc_num_iterations); - if (m_context->inconsistent()) - return l_false; - else if (m_context->processed_all()) - return m_has_theories ? l_undef : l_true; - else - return l_undef; - } -}; - diff --git a/src/dead/spc/spc_prover.h b/src/dead/spc/spc_prover.h deleted file mode 100644 index a79773a5e..000000000 --- a/src/dead/spc/spc_prover.h +++ /dev/null @@ -1,59 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_prover.h - -Abstract: - - Stand-alone SPC prover (it is mainly for debugging purposes). - -Author: - - Leonardo de Moura (leonardo) 2008-02-08. - -Revision History: - ---*/ -#ifndef _SPC_PROVER_H_ -#define _SPC_PROVER_H_ - -#include"spc_context.h" -#include"front_end_params.h" -#include"kbo.h" -#include"lpo.h" -#include"basic_simplifier_plugin.h" -#include"arith_simplifier_plugin.h" -#include"preprocessor.h" -#include"defined_names.h" -#include"lbool.h" - -namespace spc { - class prover { - ast_manager & m_manager; - front_end_params & m_params; - simplifier m_simplifier; - defined_names m_defined_names; - preprocessor m_preprocessor; - order * m_order; - clause_selection * m_cls_sel; - literal_selection * m_lit_sel; - context * m_context; - expr_ref_vector m_exprs; - proof_ref_vector m_expr_proofs; - bool m_has_theories; - - void init(); - - public: - prover(ast_manager & m, front_end_params & params); - ~prover(); - void assert_expr(expr * e); - lbool check(); - void display_statistics(std::ostream & out) const { if (m_context) m_context->display_statistics(out); } - }; -}; - -#endif /* _SPC_PROVER_H_ */ - diff --git a/src/dead/spc/spc_rewriter.cpp b/src/dead/spc/spc_rewriter.cpp deleted file mode 100644 index 73d5f3668..000000000 --- a/src/dead/spc/spc_rewriter.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_rewrite.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-12. - -Revision History: - ---*/ -#include"spc_rewriter.h" -#include"spc_decl_plugin.h" -#include"ast_pp.h" - -namespace spc { - - rewriter::rewriter(ast_manager & m, simplifier & simp, order & ord, asserted_literals & al): - simplifier(m), - m_asserted_literals(al), - m_order(ord), - m_spc_fid(m.get_family_id("spc")), - m_subst(m), - m_st(m), - m_visitor(m_order, m_subst, m_cls_use_list) { - - reserve_offsets(3); - - borrow_plugins(simp); - } - - rewriter::~rewriter() { - release_plugins(); - } - - inline void rewriter::reserve_vars(unsigned num_vars) { - m_subst.reserve_vars(num_vars); - m_order.reserve_vars(num_vars); - m_asserted_literals.reserve_vars(num_vars); - } - - void rewriter::reserve_offsets(unsigned num_offsets) { - m_subst.reserve_offsets(num_offsets); - m_order.reserve_offsets(num_offsets); - } - - inline bool rewriter::demodulator(clause * cls) const { - if (cls->get_num_literals() != 1) - return false; - literal const & l = cls->get_literal(0); - return !l.sign() && m_manager.is_eq(l.atom()); - } - - inline void rewriter::insert(clause * cls, expr * source) { - if (!is_var(source)) { - TRACE("rewriter_detail", tout << "inserting into rewriter index:\n"; cls->display(tout, m_manager); tout << "\n";); - flush_cache(); - m_st.insert(to_app(source)); - m_cls_use_list.insert(cls, source); - } - } - - void rewriter::insert(clause * cls) { - if (demodulator(cls)) { - reserve_vars(cls->get_num_vars()); - literal const & l = cls->get_literal(0); - app * eq = to_app(l.atom()); - if (l.is_oriented()) { - expr * source = l.is_left() ? eq->get_arg(0) : eq->get_arg(1); - insert(cls, source); - } - else { - insert(cls, eq->get_arg(0)); - insert(cls, eq->get_arg(1)); - } - } - } - - inline void rewriter::erase(clause * cls, expr * source) { - if (!is_var(source)) { - flush_cache(); - m_cls_use_list.erase(cls, source); - if (m_cls_use_list.empty(source)) - m_st.erase(to_app(source)); - } - } - - void rewriter::erase(clause * cls) { - if (demodulator(cls)) { - literal const & l = cls->get_literal(0); - app * eq = to_app(l.atom()); - if (l.is_oriented()) { - expr * source = l.is_left() ? eq->get_arg(0) : eq->get_arg(1); - erase(cls, source); - } - else { - erase(cls, eq->get_arg(0)); - erase(cls, eq->get_arg(1)); - } - } - } - - bool rewriter::visitor::operator()(expr * e) { - if (m_cls_use_list.empty(e)) - return true; // continue; - clause_use_list::iterator it = m_cls_use_list.begin(e); - clause_use_list::iterator end = m_cls_use_list.end(e); - for (; it != end; ++it) { - m_clause = *it; - SASSERT(m_clause->get_num_literals() == 1); - literal & l = m_clause->get_literal(0); - expr * atom = l.atom(); - SASSERT(!l.sign() && m_manager.is_eq(atom)); - SASSERT(to_app(atom)->get_arg(0) == e || to_app(atom)->get_arg(1) == e); - m_source = to_app(atom)->get_arg(0); - m_target = to_app(atom)->get_arg(1); - if (m_source != e) - std::swap(m_source, m_target); - SASSERT(m_source == e); - TRACE("rewriter", tout << "found generalization:\n" << mk_pp(m_source, m_manager) << "\n" << - mk_pp(m_target, m_manager) << "\nsubstitution\n"; - m_subst.display(tout); tout << "m_subst: " << &m_subst << "\n"; - tout << "checking ordering constraints...\n";); - if (l.is_oriented() || m_order.greater(expr_offset(m_source, 1), expr_offset(m_target, 1), &m_subst)) { - m_found = true; - return false; // stop - } - TRACE("rewriter", tout << "failed ordering constraints...\n";); - } - return true; // continue - } - - void rewriter::save_justification(justification * j) { - if (std::find(m_justifications.begin(), m_justifications.end(), j) == m_justifications.end()) - m_justifications.push_back(j); - } - - proof * rewriter::mk_demodulation_proof(expr * old_expr, expr * new_expr, proof * parent) { - if (m_manager.fine_grain_proofs()) { - SASSERT(parent); - return m_manager.mk_app(m_spc_fid, PR_DEMODULATION, parent, m_manager.mk_eq(old_expr, new_expr)); - } - return 0; - } - - void rewriter::reset() { - m_st.reset(); - m_cls_use_list.reset(); - } - - void rewriter::reduce_literal(literal const & l, literal & l_r, proof * & l_pr) { - if (m_st.empty()) { - l_r = l; - l_pr = 0; - return; - } - - expr * atom = l.atom(); - expr * r; - proof * r_pr; - m_proofs.reset(); - while (true) { - reduce_core(atom); - get_cached(atom, r, r_pr); - if (m_manager.fine_grain_proofs() && r_pr) - m_proofs.push_back(r_pr); - if (atom == r) - break; - atom = r; - } - l_r = literal(atom, l.sign()); - if (m_manager.fine_grain_proofs()) - l_pr = m_proofs.empty() ? 0 : m_manager.mk_transitivity(m_proofs.size(), m_proofs.c_ptr()); - } - - clause * rewriter::operator()(clause * cls) { - reserve_vars(cls->get_num_vars()); - SASSERT(m_found_literals.empty()); - m_justifications.reset(); - m_max_scope_lvl = cls->get_scope_lvl(); - - literal_buffer new_literals(m_manager); - proof_ref_buffer new_proofs(m_manager); - bool changed = false; - - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal & l = cls->get_literal(i); - literal l_r; - proof * l_pr = 0; - reduce_literal(l, l_r, l_pr); - - if (l != l_r) { - changed = true; - } - - if (!l_r.is_false(m_manager) && !m_found_literals.contains(l_r)) { - m_found_literals.insert(l_r); - - // apply simplify reflect rules - expr * atom = l_r.atom(); - clause * unit = 0; - TRACE("rewriter", tout << "adding literal: " << mk_pp(atom, m_manager) << "\n";); - if (l_r.sign()) { - if (m_manager.is_eq(atom)) - unit = m_asserted_literals.subsumes(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1)); - else - unit = m_asserted_literals.gen(atom, false); - } - else { - // check if there is a generalization of the negation of the current literal. - unit = m_asserted_literals.gen(atom, true); - } - - if (unit) { - // new literal was resolved - justification * j = unit->get_justification(); - m_justifications.push_back(j); - changed = true; - } - else { - // keep new literal - new_literals.push_back(l_r); - } - } - else { - // removed duplicate or resolved literal. - changed = true; - } - - if (m_manager.fine_grain_proofs() && l_pr != 0) { - new_proofs.push_back(l_pr); - } - } - - m_found_literals.reset(); - - if (!changed) { - m_found_literals.reset(); - return cls; - } - - proof * new_pr = mk_rewrite_proof(m_manager, m_spc_fid, new_literals.size(), new_literals.c_ptr(), cls->get_justification()->get_proof(), - new_proofs.size(), new_proofs.c_ptr()); - - justification * new_j = rewrite_justification::mk(m_manager, cls->get_justification(), m_justifications.size(), m_justifications.c_ptr(), new_pr); - - if (m_max_scope_lvl == cls->get_scope_lvl()) { - // peform destructive update - cls->update_lits(m_manager, new_literals.size(), new_literals.c_ptr(), new_j); - return cls; - } - else { - SASSERT(m_max_scope_lvl > cls->get_scope_lvl()); - // create new clause - // the old clause will be frozen - return clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), new_j, m_max_scope_lvl); - } - } - -}; - diff --git a/src/dead/spc/spc_rewriter.h b/src/dead/spc/spc_rewriter.h deleted file mode 100644 index 73b0116ae..000000000 --- a/src/dead/spc/spc_rewriter.h +++ /dev/null @@ -1,122 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_rewriter.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-11. - -Revision History: - ---*/ -#ifndef _SPC_REWRITER_H_ -#define _SPC_REWRITER_H_ - -#include"simplifier.h" -#include"order.h" -#include"substitution_tree.h" -#include"spc_clause.h" -#include"spc_asserted_literals.h" -#include"sparse_use_list.h" - -namespace spc { - - /** - \brief Apply rewriting steps using demodulation rule: - - C[s] ==> C[sigma(r)] - when - - l = r is a known equality (demodulator) - sigma(l) = s - sigma(l) > sigma(r) - - It also applies the following rules: - - - Duplicate literal deletion - - - Resolved literal deletion - - - Positive simplify reflect - s = t, (u[p <- sigma(s)] != u[p <- sigma(t)] or R) - ==> - R - - - Negative simplify reflect - s != t (sigma(s = t) or R) - ===> - R - */ - class rewriter : public simplifier { - protected: - typedef sparse_use_list > clause_use_list; - asserted_literals & m_asserted_literals; - order & m_order; - family_id m_spc_fid; - - substitution m_subst; - substitution_tree m_st; // index for potential demodulators left-hand-side - clause_use_list m_cls_use_list; // index for demodulators left-hand-side to equation. - found_literals m_found_literals; - - ptr_vector m_justifications; - - struct visitor : public st_visitor { - ast_manager & m_manager; - order & m_order; - clause_use_list & m_cls_use_list; - bool m_found; - clause * m_clause; - expr * m_source; - expr * m_target; - - visitor(order & ord, substitution & subst, clause_use_list & ul): - st_visitor(subst), m_manager(ord.get_manager()), m_order(ord), m_cls_use_list(ul) { - } - - virtual bool operator()(expr * e); - }; - - unsigned m_max_scope_lvl; // maximal scope level used during rewrite. - visitor m_visitor; - - proof * mk_demodulation_proof(expr * old_expr, expr * new_expr, proof * parent); - - bool demodulator(clause * cls) const; - void insert(clause * cls, expr * source); - void erase(clause * cls, expr * source); - void reserve_vars(unsigned num_vars); - void reserve_offsets(unsigned num_offsets); - void save_justification(justification * j); - - void reduce_literal(literal const & l, literal & l_r, proof * & l_pr); - - public: - rewriter(ast_manager & m, simplifier & s, order & ord, asserted_literals & al); - virtual ~rewriter(); - - /** - \brief Insert clause into rewriter indexes - */ - void insert(clause * cls); - - /** - \brief Remove clause from rewriter indexes - */ - void erase(clause * cls); - - clause * operator()(clause * cls); - - void reset(); - }; -}; - -#endif /* _SPC_REWRITER_H_ */ - diff --git a/src/dead/spc/spc_semantic_tautology.cpp b/src/dead/spc/spc_semantic_tautology.cpp deleted file mode 100644 index fbbf09688..000000000 --- a/src/dead/spc/spc_semantic_tautology.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_semantic_tautology.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-11. - -Revision History: - ---*/ -#include"spc_semantic_tautology.h" -#include"ast_pp.h" - -namespace spc { - - expr * find(expr2expr & f, expr * n) { -#ifdef _TRACE - expr * _n = n; -#endif - ptr_buffer path; - expr * next; - while (f.find(n, next)) { - path.push_back(n); - n = next; - } - ptr_buffer::iterator it = path.begin(); - ptr_buffer::iterator end = path.end(); - for (; it != end; ++it) { - expr * prev = *it; - f.insert(prev, n); - } - SASSERT(n); - TRACE("semantic_tautology_detail", tout << "find(#" << _n->get_id() << ") = #" << n->get_id() << "\n";); - return n; - } - - semantic_tautology::semantic_tautology(ast_manager & m): - m_manager(m), - m_cg_table(DEFAULT_HASHTABLE_INITIAL_CAPACITY, cg_hash(m_manager, m_find), cg_eq(m_find)) { - } - - unsigned semantic_tautology::cg_hash::operator()(app * n) const { - TRACE("semantic_tautology_detail", tout << "hash code of:\n" << mk_pp(n, m_manager) << "\n";); - unsigned r = get_composite_hash(n, n->get_num_args(), m_k_hash, m_c_hash); - TRACE("semantic_tautology_detail", tout << "result: " << r << "\n";); - return r; - } - - bool semantic_tautology::cg_eq::operator()(app * n1, app * n2) const { - if (n1->get_decl() != n2->get_decl() || n1->get_num_args() != n2->get_num_args()) - return false; - unsigned num_args = n1->get_num_args(); - for (unsigned i = 0; i < num_args; i++) - if (spc::find(m_find, n1->get_arg(i)) != spc::find(m_find, n2->get_arg(i))) - return false; - return true; - } - - bool semantic_tautology::is_target(unsigned num_lits, literal * lits) { - bool has_diseq = false; - bool has_non_diseq = false; - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = lits[i]; - if (l.sign() && m_manager.is_eq(l.atom())) - has_diseq = true; - else - has_non_diseq = true; - } - return has_diseq && has_non_diseq; - } - - void semantic_tautology::reset() { - m_region.reset(); - m_init_todo.reset(); - m_todo.reset(); - m_already_found.reset(); - m_use_list.reset(); - m_find.reset(); - m_size.reset(); - m_cg_table.reset(); - } - - void semantic_tautology::update_use_list(app * parent, expr * child) { - list * use_list = 0; - m_use_list.find(child, use_list); - use_list = new (m_region) list(parent, use_list); - m_use_list.insert(child, use_list); - } - - inline void semantic_tautology::push_init_core(expr * n) { - if (is_app(n) && to_app(n)->get_num_args() > 0) - m_init_todo.push_back(to_app(n)); - } - - inline void semantic_tautology::push_init(expr * atom) { - if (m_manager.is_eq(atom)) { - push_init_core(to_app(atom)->get_arg(0)); - push_init_core(to_app(atom)->get_arg(1)); - } - else - push_init_core(atom); - } - - void semantic_tautology::init_use_list() { - while (!m_init_todo.empty()) { - app * n = m_init_todo.back(); - m_init_todo.pop_back(); - if (!m_already_found.contains(n)) { - unsigned num_args = n->get_num_args(); - SASSERT(num_args > 0); - m_cg_table.insert(n); - m_already_found.insert(n); - for (unsigned i = 0; i < num_args; i++) { - expr * c = n->get_arg(i); - update_use_list(n, c); - push_init_core(c); - } - } - } - } - - void semantic_tautology::init(unsigned num_lits, literal * lits) { - reset(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = lits[i]; - expr * atom = l.atom(); - push_init(atom); - if (l.sign() && m_manager.is_eq(atom)) - m_todo.push_back(expr_pair(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1))); - } - init_use_list(); - } - - void semantic_tautology::remove_parents(expr * n1) { - list * use_list = 0; - m_use_list.find(n1, use_list); - while (use_list) { - TRACE("semantic_tautology", tout << "removing parent from cg_table:\n" << mk_pp(use_list->head(), m_manager) << "\n";); - m_cg_table.erase(use_list->head()); - use_list = use_list->tail(); - } - } - - void semantic_tautology::restore_parents(expr * n1, expr * n2) { - list * use_list = 0; - m_use_list.find(n1, use_list); - while (use_list) { - app * parent = use_list->head(); - app * other = 0; - if (m_cg_table.find(parent, other)) { - TRACE("semantic_tautology", tout << "new congruence:\n" << mk_pp(parent, m_manager) << "\n" << mk_pp(other, m_manager) << "\n";); - if (parent != other) - m_todo.push_back(expr_pair(parent, other)); - } - else { - TRACE("semantic_tautology", tout << "restoring parent to cg_table:\n" << mk_pp(parent, m_manager) << "\n";); - m_cg_table.insert(parent); - update_use_list(parent, n2); - } - use_list = use_list->tail(); - } - } - - void semantic_tautology::assert_eq(expr * n1, expr * n2) { - n1 = find(n1); - n2 = find(n2); - if (n1 == n2) - return; - TRACE("semantic_tautology", tout << "processing equality:\n" << mk_pp(n1, m_manager) << " " << n1->get_id() << "\n" << - mk_pp(n2, m_manager) << " " << n2->get_id() << "\n";); - unsigned sz1 = 1; - unsigned sz2 = 1; - m_size.find(n1, sz1); - m_size.find(n2, sz2); - if (sz1 > sz2) - std::swap(n1, n2); - remove_parents(n1); - TRACE("semantic_tautology", tout << "merging equivalence classes\n";); - m_find.insert(n1, n2); - m_size.insert(n2, sz1 + sz2); - restore_parents(n1, n2); - } - - void semantic_tautology::process_eqs() { - while (!m_todo.empty()) { - expr_pair const & p = m_todo.back(); - expr * lhs = p.first; - expr * rhs = p.second; - m_todo.pop_back(); - assert_eq(lhs, rhs); - } - } - - bool semantic_tautology::contains_complement(unsigned num_lits, literal * lits, unsigned i, bool sign, expr * atom) { - atom = find(atom); - for (unsigned j = i + 1; j < num_lits; j++) { - literal const & l = lits[j]; - if (l.sign() != sign && find(l.atom()) == atom) - return true; - } - return false; - } - - bool semantic_tautology::is_tautology(unsigned num_lits, literal * lits) { - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = lits[i]; - expr * atom = l.atom(); - if (!l.sign() && m_manager.is_eq(atom) && find(to_app(atom)->get_arg(0)) == find(to_app(atom)->get_arg(1))) - return true; - if (!m_manager.is_eq(atom) && contains_complement(num_lits, lits, i, l.sign(), atom)) - return true; - } - return false; - } - - bool semantic_tautology::operator()(unsigned num_lits, literal * lits) { - if (!is_target(num_lits, lits)) - return false; - init(num_lits, lits); - process_eqs(); - bool r = is_tautology(num_lits, lits); - TRACE("semantic_tautology", display(tout, num_lits, lits, m_manager); tout << "\nis semantic tautology: " << r << "\n";); - return r; - } - -}; diff --git a/src/dead/spc/spc_semantic_tautology.h b/src/dead/spc/spc_semantic_tautology.h deleted file mode 100644 index 748809a24..000000000 --- a/src/dead/spc/spc_semantic_tautology.h +++ /dev/null @@ -1,114 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_semantic_tautology.h - -Abstract: - - Semantic tautology detection - -Author: - - Leonardo de Moura (leonardo) 2008-02-11. - -Revision History: - ---*/ -#ifndef _SPC_SEMANTIC_TAUTOLOGY_H_ -#define _SPC_SEMANTIC_TAUTOLOGY_H_ - -#include"spc_literal.h" -#include"list.h" -#include"obj_hashtable.h" -#include"map.h" - -namespace spc { - - typedef obj_map expr2expr; - - expr * find(expr2expr & f, expr * e); - - /** - \brief Functor for detecting semantic tautology. - A clause C is a semantic tautology if it has the following form: - - s_1 != t_1 or ... or s_n != t_n or s = t or R - - sigma(s_1 = t_1), ..., sigma(s_n t_n) |= sigma(s = t) - where sigma maps variables to constants. - */ - class semantic_tautology { - typedef std::pair expr_pair; - - typedef obj_hashtable already_found; - typedef expr2expr find_map; - typedef obj_map *> use_list; - typedef obj_map size_map; - - struct k_hash { - unsigned operator()(app * n) const { return n->get_decl()->get_id(); } - }; - - struct c_hash { - find_map & m_find; - c_hash(find_map & f):m_find(f) {} - unsigned operator()(app * n, unsigned i) const { - unsigned id = spc::find(m_find, n->get_arg(i))->get_id(); - TRACE("semantic_tautology_detail", tout << "child(" << i << ") = #" << id << "\n";); - return id; - } - }; - - struct cg_hash { - ast_manager & m_manager; - k_hash m_k_hash; - c_hash m_c_hash; - cg_hash(ast_manager & m, find_map & f):m_manager(m), m_c_hash(f) {} - unsigned operator()(app * n) const; - }; - - struct cg_eq { - find_map & m_find; - cg_eq(find_map & f):m_find(f) {} - bool operator()(app * n1, app * n2) const; - }; - - typedef ptr_hashtable cg_table; - - ast_manager & m_manager; - region m_region; - ptr_vector m_init_todo; - svector m_todo; - already_found m_already_found; - use_list m_use_list; - find_map m_find; - size_map m_size; - cg_table m_cg_table; - - bool is_target(unsigned num_lits, literal * lits); - void reset(); - void update_use_list(app * parent, expr * child); - void push_init_core(expr * n); - void push_init(expr * atom); - void init_use_list(); - void init(unsigned num_lits, literal * lits); - expr * find(expr * n) { return spc::find(m_find, n); } - void remove_parents(expr * n1); - void restore_parents(expr * n1, expr * n2); - void assert_eq(expr * n1, expr * n2); - void process_eqs(); - bool contains_complement(unsigned num_lits, literal * lits, unsigned i, bool sign, expr * atom); - bool is_tautology(unsigned num_lits, literal * lits); - - public: - semantic_tautology(ast_manager & m); - - bool operator()(unsigned num_lits, literal * lits); - }; - -}; - -#endif /* _SPC_SEMANTIC_TAUTOLOGY_H_ */ - diff --git a/src/dead/spc/spc_statistics.cpp b/src/dead/spc/spc_statistics.cpp deleted file mode 100644 index be27dc82d..000000000 --- a/src/dead/spc/spc_statistics.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_statistics.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-17. - -Revision History: - ---*/ -#include"spc_statistics.h" - -namespace spc { - - void statistics::reset() { - m_num_mk_clause = 0; - m_num_del_clause = 0; - m_num_processed = 0; - m_num_superposition = 0; - m_num_resolution = 0; - m_num_eq_factoring = 0; - m_num_factoring = 0; - m_num_eq_resolution = 0; - m_num_trivial = 0; - m_num_simplified = 0; - m_num_subsumed = 0; - m_num_redundant = 0; - } - - void statistics::display(std::ostream & out) const { - out << "num. mk. clause: " << m_num_mk_clause << "\n"; - out << "num. del. clause: " << m_num_del_clause << "\n"; - out << "num. processed: " << m_num_processed << "\n"; - out << "num. superposition: " << m_num_superposition << "\n"; - out << "num. resolution: " << m_num_resolution << "\n"; - out << "num. eq. factoring: " << m_num_eq_factoring << "\n"; - out << "num. factoring: " << m_num_factoring << "\n"; - out << "num. eq. resol.: " << m_num_eq_resolution << "\n"; - out << "num. simplified: " << m_num_simplified << "\n"; - out << "num. redundant: " << m_num_redundant << "\n"; - out << " num. trivial: " << m_num_trivial << "\n"; - out << " num. subsumed: " << m_num_subsumed << "\n"; - } - -}; - diff --git a/src/dead/spc/spc_statistics.h b/src/dead/spc/spc_statistics.h deleted file mode 100644 index 6274d0be7..000000000 --- a/src/dead/spc/spc_statistics.h +++ /dev/null @@ -1,49 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_statistics.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-17. - -Revision History: - ---*/ -#ifndef _SPC_STATISTICS_H_ -#define _SPC_STATISTICS_H_ - -#include - -namespace spc { - - struct statistics { - unsigned m_num_mk_clause; - unsigned m_num_del_clause; - unsigned m_num_processed; - unsigned m_num_superposition; - unsigned m_num_resolution; - unsigned m_num_eq_factoring; - unsigned m_num_factoring; - unsigned m_num_eq_resolution; - unsigned m_num_trivial; - unsigned m_num_simplified; - unsigned m_num_subsumed; - unsigned m_num_redundant; - statistics() { - reset(); - } - - void reset(); - void display(std::ostream & out) const; - }; -}; - -#endif /* _SPC_STATISTICS_H_ */ - diff --git a/src/dead/spc/spc_subsumption.cpp b/src/dead/spc/spc_subsumption.cpp deleted file mode 100644 index e61329345..000000000 --- a/src/dead/spc/spc_subsumption.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_subsumption.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-13. - -Revision History: - ---*/ -#include"spc_subsumption.h" -#include"fvi_def.h" -#include"ast_pp.h" - -namespace spc { - - /** - \brief Return true if literal l2 is an instance of l1. - - When ResetSubst == true, m_subst is reset before trying to match l1 and l2. - - When ResetSubst == false, it is assumed that m_subst.push_scope was invoked - before invoking match_literal. - */ - template - bool subsumption::match_literal(literal const & l1, literal const & l2) { - if (l1.sign() == l2.sign()) { - expr * atom1 = l1.atom(); - expr * atom2 = l2.atom(); - bool is_eq1 = m_manager.is_eq(atom1); - bool is_eq2 = m_manager.is_eq(atom2); - if (is_eq1 && is_eq2) { - expr * lhs1 = to_app(atom1)->get_arg(0); - expr * rhs1 = to_app(atom1)->get_arg(1); - expr * lhs2 = to_app(atom2)->get_arg(0); - expr * rhs2 = to_app(atom2)->get_arg(1); - if (ResetSubst) - m_subst.reset_subst(); - - if (m_matcher(lhs1, lhs2, m_subst) && m_matcher(rhs1, rhs2, m_subst)) - return true; - - if (ResetSubst) - m_subst.reset_subst(); - else { - // I'm assuming push_scope was invoked before executing match_literal - // So, pop_scope is equivalent to a local reset. - m_subst.pop_scope(); - m_subst.push_scope(); - } - - return (m_matcher(lhs1, rhs2, m_subst) && m_matcher(rhs1, lhs2, m_subst)); - } - else if (!is_eq1 && !is_eq2) { - if (ResetSubst) - m_subst.reset_subst(); - return m_matcher(atom1, atom2, m_subst); - } - } - return false; - } - - /** - \brief Return true if for every literal l1 in lits1 there is a - literal l2 in lits2 such that l2 is an instance of l1. - */ - bool subsumption::can_subsume(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2) { - for (unsigned i = 0; i < num_lits1; i++) { - literal const & l1 = lits1[i]; - unsigned j = 0; - for (; j < num_lits2; j++) { - literal const & l2 = lits2[j]; - if (match_literal(l1, l2)) - break; - } - if (j == num_lits2) - return false; - } - return true; - } - - /** - \brief Return true if cls1 can subsume cls2. It performs a series of quick checks. - */ - bool subsumption::quick_check(clause * cls1, clause * cls2) { - return - cls1->get_symbol_count() <= cls2->get_symbol_count() && - cls1->get_const_count() <= cls2->get_const_count() && - cls1->get_depth() <= cls2->get_depth() && - cls1->get_num_pos_literals() <= cls2->get_num_pos_literals() && - cls1->get_num_neg_literals() <= cls2->get_num_neg_literals() && - (!cls1->is_ground() || cls2->is_ground()); - } - - /** - \brief Return true if the set of literals lits1 subsumes the set of literals lits2. - */ - bool subsumption::subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2) { - enum state { - INVOKE, DECIDE, BACKTRACK, RETURN - }; - - if (num_lits1 == 0) - return true; - - m_stack.reset(); - m_subst.reset(); - - m_stack.push_back(assoc(0, 0)); - state st = DECIDE; - - unsigned i; - assoc * top; - unsigned counter = 0; -#ifdef _TRACE - unsigned opt = 0; - unsigned nopt = 0; -#endif - while (true && counter < 5000000) { - counter++; - switch (st) { - case INVOKE: - SASSERT(!m_stack.empty()); - i = m_stack.back().first + 1; - if (i >= num_lits1) { - TRACE("subsumption", tout << "subsumption result: YES.\n";); - TRACE_CODE({ - if (counter > 10000) { - TRACE("subsumption_perf", - tout << "subsumption succeeded: " << counter << " " << opt << " " << nopt << "\n"; - tout << "literals1:\n"; display(tout, num_lits1, lits1, m_manager); tout << "\n"; - tout << "literals2:\n"; display(tout, num_lits2, lits2, m_manager); tout << "\n";); - } - }); - return true; - } - else { - m_stack.push_back(assoc(i, 0)); - st = DECIDE; - } - break; - case DECIDE: - top = &(m_stack.back()); - m_subst.push_scope(); - if (match_literal(lits1[top->first], lits2[top->second])) - st = INVOKE; - else - st = BACKTRACK; - break; - case BACKTRACK: - top = &(m_stack.back()); - top->second++; - m_subst.pop_scope(); - if (top->second >= num_lits2) - st = RETURN; - else - st = DECIDE; - break; - case RETURN: - top = &(m_stack.back()); - m_stack.pop_back(); - if (m_stack.empty()) { - // no more alternatives - TRACE("subsumption", tout << "subsumption result: NO\n";); - TRACE_CODE({ - if (counter > 10000) { - TRACE("subsumption_perf", - tout << "subsumption failed: " << counter << " " << opt << " " << nopt << "\n"; - tout << "literals1:\n"; display(tout, num_lits1, lits1, m_manager); tout << "\n"; - tout << "literals2:\n"; display(tout, num_lits2, lits2, m_manager); tout << "\n";); - } - }); - return false; - } - if (m_subst.top_scope_has_bindings()) { - TRACE_CODE(nopt++;); - st = BACKTRACK; - } - else { - TRACE_CODE(opt++;); -#ifdef Z3DEBUG - unsigned num_bindings = m_subst.get_num_bindings(); -#endif - m_subst.pop_scope(); - SASSERT(num_bindings == m_subst.get_num_bindings()); - st = RETURN; - } - break; - } - } - return false; - } - - /** - \brief Return true if the set of ground literals lits1 subsumes the set of ground literals lits2. - */ - bool subsumption::ground_subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2) { - for (unsigned i = 0; i < num_lits1; i++) { - literal const & l1 = lits1[i]; - unsigned j = 0; - for (; j < num_lits2; j++) { - literal const & l2 = lits2[j]; - if (l1 == l2) - break; - } - if (j == num_lits2) - return false; - } - return true; - } - - /** - \brief Return true if the literal l1 subsumes the set of literals lits2. - */ - bool subsumption::subsumes_core(literal const & l1, unsigned num_lits2, literal * lits2) { - for (unsigned i = 0; i < num_lits2; i++) { - if (match_literal(l1, lits2[i])) - return true; - } - return false; - } - - subsumption::subsumption(ast_manager & m, asserted_literals & al, spc_params & params): - m_manager(m), - m_params(params), - m_asserted_literals(al), - m_subst(m), - m_matcher(m), - m_found_decls(m), - m_index(0), - m_num_processed_clauses(0), - m_opt_threshold(params.m_initial_subsumption_index_opt) { - - m_subst.reserve_offsets(1); - - init_indexes(); - } - - subsumption::~subsumption() { - if (m_index) - dealloc(m_index); - } - - /** - \brief Return true if cls1 subsumes cls2 - */ - bool subsumption::operator()(clause * cls1, clause * cls2) { - TRACE("subsumption_detail", tout << "checking if:\n"; cls1->display(tout, m_manager); tout << "\nsubsumes\n"; - cls2->display(tout, m_manager); tout << "\n";); - if (!quick_check(cls1, cls2)) { - TRACE("subsumption_detail", tout << "failed quick check\n";); - return false; - } - - m_subst.reserve_vars(std::max(cls1->get_num_vars(), cls2->get_num_vars())); - unsigned num_lits1 = cls1->get_num_literals(); - unsigned num_lits2 = cls2->get_num_literals(); - literal * lits1 = cls1->get_literals(); - literal * lits2 = cls2->get_literals(); - if (cls1->is_ground() && cls2->is_ground()) - return ground_subsumes_core(num_lits1, lits1, num_lits2, lits2); - if (num_lits1 == 1) - return subsumes_core(lits1[0], num_lits2, lits2); - // TODO: REMOVE true below... using it for debugging purposes. - if (true || cls1->get_num_neg_literals() >= 3 || cls1->get_num_pos_literals() >= 3) - if (!can_subsume(num_lits1, lits1, num_lits2, lits2)) { - TRACE("subsumption_detail", tout << "failed can_subsume\n";); - return false; - } - return subsumes_core(num_lits1, lits1, num_lits2, lits2); - } - - /** - \brief Update the set of function symbols found in the clause being inserted into the index, - and the set of clauses found since the index started to be built. - - Return true if the function symbol should be tracked. - */ - bool subsumption::mark_func_decl(func_decl * f) { - if (m_refining_index) { - if (!m_cls_found_decl_set.contains(f)) { - // update set of func_decls in the curr clause - m_cls_found_decl_set.insert(f); - m_cls_found_decls.push_back(f); - // update global set of founf func_decls - unsigned id = f->get_decl_id(); - m_found_decl_set.reserve(id+1); - if (!m_found_decl_set.get(id)) { - m_found_decl_set.set(id); - m_found_decls.push_back(f); - } - } - return true; - } - else { - unsigned id = f->get_decl_id(); - // if func_decl was not found yet, then ignore it. - if (id < m_found_decl_set.size() && m_found_decl_set.get(id)) { - if (!m_cls_found_decl_set.contains(f)) { - // update set of func_decls in the curr clause - m_cls_found_decl_set.insert(f); - m_cls_found_decls.push_back(f); - } - return true; - } - return false; - } - } - - /** - \brief Increment the number of occurrences of a function symbol in the clause being - inserted into the index. - */ - void subsumption::inc_f_count(func_decl * f, bool neg) { - decl2nat & f_count = m_f_count[static_cast(neg)]; - unsigned val; - if (f_count.find(f, val)) { - f_count.insert(f, val + 1); - } - else { - f_count.insert(f, 1); - } - } - - /** - \brief Update the min/max num. of occurrences of func symbol in a clause. - */ - void subsumption::update_min_max(func_decl * f) { - for (unsigned is_neg = 0; is_neg < 1; is_neg++) { - decl2nat & f_count = m_f_count[is_neg]; - decl2nat & f_min = m_f_min[is_neg]; - decl2nat & f_max = m_f_max[is_neg]; - unsigned count; - if (f_count.find(f, count)) { - unsigned old_count; - if (!f_min.find(f, old_count) || old_count > count) { - f_min.insert(f, count); - } - if (!f_max.find(f, old_count) || old_count < count) { - f_max.insert(f, count); - } - } - } - } - - /** - \brief Compute the number of occurences of function symbols in - a clause. - */ - void subsumption::update_neg_pos_func_counts(clause * cls) { - m_f_count[0].reset(); - m_f_count[1].reset(); - m_cls_found_decl_set.reset(); - m_cls_found_decls.reset(); - ptr_buffer todo; - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = cls->get_literal(i); - bool is_neg = l.sign(); - expr * n = l.atom(); - todo.push_back(n); - while (!todo.empty()) { - n = todo.back(); - todo.pop_back(); - if (is_app(n)) { - func_decl * f = to_app(n)->get_decl(); - if (fvi_candidate(f) && mark_func_decl(f)) - inc_f_count(f, is_neg); - unsigned num = to_app(n)->get_num_args(); - for (unsigned i = 0; i < num; i++) - todo.push_back(to_app(n)->get_arg(i)); - } - } - } - - if (m_refining_index) { - ptr_vector::iterator it = m_cls_found_decls.begin(); - ptr_vector::iterator end = m_cls_found_decls.end(); - for (; it != end; ++it) { - func_decl * f = *it; - update_min_max(f); - unsigned val; - if (m_f_freq.find(f, val)) - m_f_freq.insert(f, val + 1); - else - m_f_freq.insert(f, 1); - } - } - } - - /** - \brief Store in m_feature_vector the value for the features of cls. - */ - void subsumption::compute_features(clause * cls, unsigned * fvector) { - unsigned num = m_features.size(); - for (unsigned i = 0; i < num; i++) { - feature & f = m_features[i]; - switch (f.m_kind) { - case F_GROUND: - fvector[i] = cls->is_ground(); - break; - case F_NUM_POS_LITS: - fvector[i] = cls->get_num_pos_literals(); - break; - case F_NUM_NEG_LITS: - fvector[i] = cls->get_num_neg_literals(); - break; - case F_DEPTH: - fvector[i] = cls->get_depth(); - break; - case F_CONST_COUNT: - fvector[i] = cls->get_const_count(); - break; - case F_SYM_COUNT: - fvector[i] = cls->get_symbol_count(); - break; - case F_NUM_NEG_FUNCS: { - unsigned val; - if (m_f_count[1].find(f.m_decl, val)) - fvector[i] = val; - else - fvector[i] = 0; - break; - } - case F_NUM_POS_FUNCS: { - unsigned val; - if (m_f_count[0].find(f.m_decl, val)) - fvector[i] = val; - else - fvector[i] = 0; - break; - } - default: - UNREACHABLE(); - } - } - TRACE("subsumption_features", - tout << "features of: "; cls->display(tout, m_manager); tout << "\n"; - for (unsigned i = 0; i < num; i++) { - tout << fvector[i] << " "; - } - tout << "\n";); - } - - /** - \brief Initialise indexes for forward/backward subsumption. - */ - void subsumption::init_indexes() { - // index for forward/backward subsumption - // start with simple set of features - m_features.push_back(feature(F_GROUND)); - m_features.push_back(feature(F_NUM_POS_LITS)); - m_features.push_back(feature(F_NUM_NEG_LITS)); - m_features.push_back(feature(F_DEPTH)); - m_features.push_back(feature(F_CONST_COUNT)); - m_features.push_back(feature(F_SYM_COUNT)); - m_index = alloc(index, m_features.size(), to_feature_vector(*this)); - } - - unsigned subsumption::get_value_range(func_decl * f, bool neg) const { - unsigned i = static_cast(neg); - unsigned min; - unsigned max; - if (!m_f_min[i].find(f, min)) - min = 0; - if (!m_f_max[i].find(f, max)) - max = 0; - SASSERT(min <= max); - return max - min; - } - - inline unsigned subsumption::get_value_range(func_decl * f) const { - return std::max(get_value_range(f, false), get_value_range(f, true)); - } - - bool subsumption::f_lt::operator()(func_decl * f1, func_decl * f2) const { - unsigned vrange1 = m_owner.get_value_range(f1); - unsigned vrange2 = m_owner.get_value_range(f2); - if (vrange1 < vrange2) - return true; - if (vrange1 == vrange2) - return f1->get_id() < f2->get_id(); - return false; - } - - /** - \brief Optimize the index for (non unit) forward subsumption and - backward subsumption. - */ - void subsumption::optimize_feature_index() { - ptr_vector clauses; - m_index->collect(clauses); - - dealloc(m_index); - m_features.reset(); - - ptr_vector targets; - unsigned sz = m_found_decls.size(); - for (unsigned i = 0; i < sz; i++) { - func_decl * f = m_found_decls.get(i); - unsigned val; - if (m_f_freq.find(f, val) && val > m_params.m_min_func_freq_subsumption_index && get_value_range(f) > 0) - targets.push_back(f); - } - - - f_lt lt(*this); - std::sort(targets.begin(), targets.end(), lt); - - m_features.push_back(feature(F_GROUND)); - m_features.push_back(feature(F_NUM_POS_LITS)); - m_features.push_back(feature(F_NUM_NEG_LITS)); - m_features.push_back(feature(F_DEPTH)); - - ptr_vector::iterator it = targets.begin(); - ptr_vector::iterator end = targets.end(); - for (; it != end; ++it) { - func_decl * f = *it; - if (get_value_range(f, false) > 1) - m_features.push_back(feature(f, false)); - if (get_value_range(f, true) > 1) - m_features.push_back(feature(f, true)); - if (m_features.size() > m_params.m_max_subsumption_index_features) - break; - } - - m_features.push_back(feature(F_CONST_COUNT)); - m_features.push_back(feature(F_SYM_COUNT)); - m_index = alloc(index, m_features.size(), to_feature_vector(*this)); - m_num_processed_clauses = 0; - unsigned new_threshold = static_cast(m_opt_threshold * m_params.m_factor_subsumption_index_opt); - if (new_threshold > m_opt_threshold) - m_opt_threshold = new_threshold; - } - - /** - \brief Insert cls into the indexes used for forward/backward subsumption. - */ - void subsumption::insert(clause * cls) { - TRACE("subsumption", tout << "adding clause to subsumption index: " << cls << "\n"; cls->display(tout, m_manager); tout << "\n";); - unsigned num_lits = cls->get_num_literals(); - if (num_lits > 1 || m_params.m_backward_subsumption) { - m_index->insert(cls); - SASSERT(m_index->contains(cls)); - m_num_processed_clauses++; - if (m_num_processed_clauses > m_opt_threshold) - optimize_feature_index(); - } - } - - /** - \brief Remove cls from the indexes used for forward/backward subsumption. - */ - void subsumption::erase(clause * cls) { - TRACE("subsumption", tout << "removing clause from subsumption index:" << cls << "\n"; cls->display(tout, m_manager); tout << "\n"; - tout << "num lits.: " << cls->get_num_literals() << ", backward_sub: " << m_params.m_backward_subsumption << "\n";); - unsigned num_lits = cls->get_num_literals(); - if (num_lits > 1 || m_params.m_backward_subsumption) - m_index->erase(cls); - } - - /** - \brief Reset the indexes used for forward/backward subsumption. - */ - void subsumption::reset() { - if (m_index) - m_index->reset(); - m_num_processed_clauses = 0; - m_opt_threshold = m_params.m_initial_subsumption_index_opt; - } - - /** - \brief Return an unit clause C in the index that subsumes cls. - Return 0 if such clause does not exist. - */ - clause * subsumption::unit_forward(clause * cls) { - if (!m_asserted_literals.has_literals()) - return 0; - m_asserted_literals.reserve_vars(cls->get_num_vars()); - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = cls->get_literal(i); - clause * subsumer = m_asserted_literals.gen(l); - if (subsumer) - return subsumer; - } - return 0; - } - - struct non_unit_subsumption_visitor { - subsumption & m_owner; - clause * m_new_clause; - clause * m_subsumer; - non_unit_subsumption_visitor(subsumption & owner, clause * new_clause): - m_owner(owner), - m_new_clause(new_clause), - m_subsumer(0) { - } - bool operator()(clause * candidate) { - TRACE("subsumption_index", tout << "considering candidate:\n"; candidate->display(tout, m_owner.get_manager()); tout << "\n";); - if (candidate->get_num_literals() > 1 && m_owner(candidate, m_new_clause)) { - m_subsumer = candidate; - return false; // stop subsumer was found - } - return true; // continue; - } - }; - - /** - \brief Return a non unit clause C in the index that subsumes cls. - Return 0 if such clause does not exist. - */ - clause * subsumption::non_unit_forward(clause * cls) { - non_unit_subsumption_visitor visitor(*this, cls); - m_index->visit(cls, visitor, true); - return visitor.m_subsumer; - } - - /** - \brief Return a unit equality clause (= s t) that (eq) subsumes cls. - That is, cls contains a literal (= u[s'] u[t']) and there is - a substitution sigma s.t. sigma(s) = s' and sigma(t) = t'. - Return 0 if such clause does not exist. - */ - clause * subsumption::eq_subsumption(clause * cls) { - if (!m_asserted_literals.has_pos_literals()) - return 0; - m_asserted_literals.reserve_vars(cls->get_num_vars()); - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = cls->get_literal(i); - expr * atom = l.atom(); - if (!l.sign() && m_manager.is_eq(atom)) { - expr * lhs = to_app(atom)->get_arg(0); - expr * rhs = to_app(atom)->get_arg(1); - clause * subsumer = m_asserted_literals.subsumes(lhs, rhs); - if (subsumer) { - TRACE("eq_subsumption", tout << "equality subsumption:\n"; cls->display(tout, m_manager); - tout << "\nis subsumed by:\n"; subsumer->display(tout, m_manager); tout << "\n";); - return subsumer; - } - } - } - return 0; - } - - /** - \brief Return a clause C in the index (i.e., insert(C) was invoked) that subsumes cls. - Return 0 if such clause does not exist. - */ - clause * subsumption::forward(clause * cls) { - TRACE("subsumption", tout << "trying forward subsumption:\n"; cls->display(tout, m_manager); tout << "\n";); - clause * subsumer = unit_forward(cls); - if (subsumer) - return subsumer; - subsumer = non_unit_forward(cls); - if (subsumer) - return subsumer; - if (m_params.m_equality_subsumption) - return eq_subsumption(cls); - return 0; - } - - struct backward_subsumption_visitor { - subsumption & m_owner; - clause * m_new_clause; - ptr_buffer & m_result; - backward_subsumption_visitor(subsumption & owner, clause * new_clause, ptr_buffer & result): - m_owner(owner), - m_new_clause(new_clause), - m_result(result) { - } - - bool operator()(clause * candidate) { - if (m_owner(m_new_clause, candidate)) - m_result.push_back(candidate); - return true; // always continue in backward subsumption - } - }; - - /** - \brief Store in result the set of clauses in the index that are subsumes by cls. - */ - void subsumption::backward(clause * cls, ptr_buffer & result) { - if (m_params.m_backward_subsumption) { - backward_subsumption_visitor visitor(*this, cls, result); - m_index->visit(cls, visitor, false); - } - } -}; diff --git a/src/dead/spc/spc_subsumption.h b/src/dead/spc/spc_subsumption.h deleted file mode 100644 index 0d8c0c671..000000000 --- a/src/dead/spc/spc_subsumption.h +++ /dev/null @@ -1,156 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_subsumption.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-13. - -Revision History: - ---*/ -#ifndef _SPC_SUBSUMPTION_H_ -#define _SPC_SUBSUMPTION_H_ - -#include"spc_asserted_literals.h" -#include"matcher.h" -#include"fvi.h" -#include"spc_params.h" -#include"obj_hashtable.h" - -namespace spc { - - class subsumption { - ast_manager & m_manager; - spc_params & m_params; - asserted_literals & m_asserted_literals; - substitution m_subst; - matcher m_matcher; - - // A pair representing the association between l1 and l2 where - // first is the position of l1 in lits1 and second the position of l2 in - // lits2. - typedef std::pair assoc; - typedef vector stack; - stack m_stack; - - template - bool match_literal(literal const & l1, literal const & l2); - - bool can_subsume(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2); - bool quick_check(clause * cls1, clause * cls2); - bool subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2); - bool subsumes_core(literal const & l1, unsigned num_lits2, literal * lits2); - bool ground_subsumes_core(unsigned num_lits1, literal * lits1, unsigned num_lits2, literal * lits2); - - enum feature_kind { - F_GROUND, - F_NUM_POS_LITS, - F_NUM_NEG_LITS, - F_DEPTH, - F_CONST_COUNT, - F_SYM_COUNT, - F_NUM_NEG_FUNCS, - F_NUM_POS_FUNCS - }; - - struct feature { - feature_kind m_kind; - func_decl * m_decl; - feature(feature_kind k = F_GROUND):m_kind(k) {} - feature(func_decl * decl, bool neg):m_kind(neg ? F_NUM_NEG_FUNCS : F_NUM_POS_FUNCS), m_decl(decl) {} - }; - - vector m_features; - - bit_vector m_found_decl_set; - func_decl_ref_vector m_found_decls; // domain of m_found_decl_set; - - /** - \brief Return true if the function symbol is considered for feature vector indexing. - */ - bool fvi_candidate(func_decl * f) { - return f->get_family_id() == null_family_id || f->get_arity() > 0; - } - - typedef obj_hashtable found_func_decl_set; - found_func_decl_set m_cls_found_decl_set; // temporary set used to track the func_decl's found in a clause - ptr_vector m_cls_found_decls; - - bool mark_func_decl(func_decl * f); - - typedef obj_map decl2nat; - bool m_refining_index; // if true keep collecting data to refine index. - decl2nat m_f_count[2]; // temporary field used to track the num. of occurs. of function symbols in neg/pos literals. - decl2nat m_f_min[2]; - decl2nat m_f_max[2]; - decl2nat m_f_freq; - - void inc_f_count(func_decl * f, bool neg); - void update_min_max(func_decl * f); - void update_neg_pos_func_counts(clause * cls); - - void compute_features(clause * cls, unsigned * fvector); - - struct to_feature_vector; - friend struct to_feature_vector; - - struct to_feature_vector { - subsumption & m_owner; - to_feature_vector(subsumption & o):m_owner(o) {} - void operator()(clause * cls, unsigned * fvector) { - m_owner.compute_features(cls, fvector); - } - }; - - typedef fvi, ptr_eq > index; - index * m_index; - unsigned m_num_processed_clauses; - unsigned m_opt_threshold; - - void init_indexes(); - - struct f_lt; - friend struct f_lt; - - unsigned get_value_range(func_decl * f, bool neg) const; - unsigned get_value_range(func_decl * f) const; - - struct f_lt { - subsumption & m_owner; - f_lt(subsumption & o):m_owner(o) {} - bool operator()(func_decl * f1, func_decl * f2) const; - }; - - void optimize_feature_index(); - - clause * unit_forward(clause * cls); - clause * non_unit_forward(clause * cls); - clause * eq_subsumption(expr * lhs, expr * rhs); - clause * eq_subsumption(clause * cls); - - public: - subsumption(ast_manager & m, asserted_literals & al, spc_params & params); - ~subsumption(); - - bool operator()(clause * cls1, clause * cls2); - void insert(clause * cls); - void erase(clause * cls); - void reset(); - clause * forward(clause * cls); - void backward(clause * cls, ptr_buffer & result); - - ast_manager & get_manager() { return m_manager; } - }; - -}; - -#endif /* _SPC_SUBSUMPTION_H_ */ - diff --git a/src/dead/spc/spc_superposition.cpp b/src/dead/spc/spc_superposition.cpp deleted file mode 100644 index 510cc8e0d..000000000 --- a/src/dead/spc/spc_superposition.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_superposition.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-15. - -Revision History: - ---*/ -#include"spc_superposition.h" -#include"ast_pp.h" - -namespace spc { - - superposition::superposition(ast_manager & m, order & o, statistics & s): - m_manager(m), - m_order(o), - m_stats(s), - m_subst(m), - m_p(m), - m_r(m), - m_normalize_vars(m), - m_spc_fid(m.get_family_id("spc")) { - m_subst.reserve_offsets(3); - m_deltas[0] = 0; - m_deltas[1] = 0; - } - - superposition::~superposition() { - } - - void superposition::insert_p(clause * cls, expr * lhs, unsigned i) { - m_p.insert(lhs); - m_subst.reserve_vars(m_p.get_approx_num_regs()); - m_p2clause_set.insert(clause_pos_pair(cls, i), lhs); - } - - void superposition::insert_p(clause * cls, literal & l, unsigned i) { - l.set_p_indexed(true); - expr * atom = l.atom(); - if (!m_manager.is_eq(atom)) - return; - if (l.is_oriented()) - insert_p(cls, l.is_left() ? l.lhs() : l.rhs(), i); - else { - insert_p(cls, l.lhs(), i); - insert_p(cls, l.rhs(), i); - } - } - - void superposition::insert_r(clause * cls, expr * n, unsigned i, bool lhs) { - if (is_app(n)) { - unsigned idx = (i << 1) | static_cast(lhs); - - clause_pos_pair new_pair(cls, idx); - SASSERT(m_todo.empty()); - m_todo.push_back(to_app(n)); - while (!m_todo.empty()) { - app * n = m_todo.back(); - m_todo.pop_back(); - clause_pos_set * s = m_r2clause_set.get_parents(n); - if (s == 0 || !s->contains(new_pair)) { - m_r.insert(n); - m_r2clause_set.insert(new_pair, n); - unsigned num_args = n->get_num_args(); - for (unsigned i = 0; i < num_args; i++) { - expr * c = n->get_arg(i); - if (is_app(c)) - m_todo.push_back(to_app(c)); - } - } - } - } - } - - void superposition::insert_r(clause * cls, literal & l, unsigned i) { - l.set_r_indexed(true); - expr * atom = l.atom(); - if (m_manager.is_eq(atom)) { - expr * lhs = l.lhs(); - expr * rhs = l.rhs(); - if (l.is_oriented()) { - bool left = true; - if (!l.is_left()) { - left = false; - std::swap(lhs, rhs); - } - insert_r(cls, lhs, i, left); - } - else { - insert_r(cls, lhs, i, true); - insert_r(cls, rhs, i, false); - } - } - else { - insert_r(cls, atom, i, false); - } - m_subst.reserve_vars(m_r.get_approx_num_regs()); - } - - void superposition::insert(clause * cls) { - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal & l = cls->get_literal(i); - if (l.is_p_indexed() || cls->is_eligible_for_paramodulation(m_order, l)) { - if (!l.sign() && m_manager.is_eq(l.atom())) - insert_p(cls, l, i); - insert_r(cls, l, i); - } - else if (l.is_r_indexed() || cls->is_eligible_for_resolution(m_order, l)) { - insert_r(cls, l, i); - } - } - TRACE("superposition_detail", - tout << "adding clause: "; cls->display(tout, m_manager); tout << "\n"; - tout << "p index:\n"; - m_p.display(tout); - tout << "r index:\n"; - m_r.display(tout);); - } - - void superposition::erase_p(clause * cls, expr * lhs, unsigned i) { - m_p2clause_set.erase(clause_pos_pair(cls, i), lhs); - if (m_p2clause_set.empty(lhs)) - m_p.erase(lhs); - } - - void superposition::erase_p(clause * cls, literal & l, unsigned i) { - expr * atom = l.atom(); - if (!m_manager.is_eq(atom)) - return; - if (l.is_oriented()) - erase_p(cls, l.is_left() ? l.lhs() : l.rhs(), i); - else { - erase_p(cls, l.lhs(), i); - erase_p(cls, l.rhs(), i); - } - } - - void superposition::erase_r(clause * cls, literal & l, unsigned i) { - clause_pos_pair pair(cls, i); - - expr * atom = l.atom(); - SASSERT(is_app(atom)); - SASSERT(m_todo.empty()); - m_todo.push_back(to_app(atom)); - - while (!m_todo.empty()) { - app * n = m_todo.back(); - m_todo.pop_back(); - switch (m_r2clause_set.erase(pair, n)) { - case 0: // pair is not a parent of n - break; - case 1: // pair is the last parent of n - m_r.erase(n); - default: - unsigned num_args = n->get_num_args(); - for (unsigned i = 0; i < num_args; i++) { - expr * c = n->get_arg(i); - if (is_app(c)) - m_todo.push_back(to_app(c)); - } - } - } - } - - void superposition::erase(clause * cls) { - unsigned num_lits = cls->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) { - literal & l = cls->get_literal(i); - if (l.is_p_indexed()) - erase_p(cls, l, i); - if (l.is_r_indexed()) - erase_r(cls, l, i); - } - } - - void superposition::reset() { - m_p.reset(); - m_p2clause_set.reset(); - m_r.reset(); - m_r2clause_set.reset(); - } - - /** - \brief Copy to result the literals of s except literal at position idx. Apply the substitution m_subst, - assuming that the variables of s are in the variable bank offset. The deltas for each bank are - stored in m_deltas. - */ - void superposition::copy_literals(clause * s, unsigned idx, unsigned offset, literal_buffer & result) { - unsigned num_lits = s->get_num_literals(); - for (unsigned i = 0; i < num_lits; i++) - if (i != idx) { - literal const & l = s->get_literal(i); - expr_ref new_atom(m_manager); - m_subst.apply(2, m_deltas, expr_offset(l.atom(), offset), new_atom); - TRACE("superposition_copy", tout << "i: " << i << ", idx: " << idx << ", offset: " << offset << "\natom:\n"; - tout << mk_pp(l.atom(), m_manager) << "\nnew_atom:\n" << mk_pp(new_atom, m_manager) << "\n";); - result.push_back(literal(new_atom, l.sign())); - } - } - - void superposition::normalize_literals(unsigned num_lits, literal * lits, literal_buffer & result) { - m_normalize_vars.reset(); - for (unsigned i = 0; i < num_lits; i++) { - literal const & l = lits[i]; - result.push_back(literal(m_normalize_vars(l.atom()), l.sign())); - } - } - - void superposition::mk_sp_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2) { - literal_buffer new_literals(m_manager); - normalize_literals(num_lits, lits, new_literals); - justification * js = mk_superposition_justification(m_manager, m_spc_fid, p1, p2, - new_literals.size(), new_literals.c_ptr(), - m_normalize_vars.get_num_vars(), m_normalize_vars.get_vars()); - clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, 0); - m_new_clauses->push_back(new_cls); - TRACE("superposition", tout << "new superposition clause:\n"; new_cls->display(tout, m_manager); tout << "\n";); - m_stats.m_num_superposition++; - } - - void superposition::mk_res_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2) { - literal_buffer new_literals(m_manager); - normalize_literals(num_lits, lits, new_literals); - justification * js = mk_resolution_justification(m_manager, m_spc_fid, p1, p2, - new_literals.size(), new_literals.c_ptr(), - m_normalize_vars.get_num_vars(), m_normalize_vars.get_vars()); - clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, 0); - m_new_clauses->push_back(new_cls); - TRACE("superposition", tout << "new resolution clause:\n"; new_cls->display(tout, m_manager); tout << "\n";); - m_stats.m_num_resolution++; - } - - /** - \brief Given the equation (= lhs rhs) of the clause being - added, try to apply resolution where the clause being added - is the main clause in the superposition rule. - */ - void superposition::try_superposition_main(expr * lhs, expr * rhs) { - m_lhs = lhs; - m_rhs = rhs; - m_subst.reset_subst(); - TRACE("spc_superposition", tout << "try_superposition_main, lhs:\n" << mk_pp(m_lhs, m_manager) << "\nrhs:\n" << mk_pp(m_rhs, m_manager) << "\n"; - tout << "substitution:\n"; m_subst.display(tout);); - r_visitor v(*this, m_subst); - m_r.unify(lhs, v); - } - - /** - \brief Try to apply superposition rule using the clause - being added (m_clause) as main clause, and its literal m_lit - as the equation. - */ - void superposition::try_superposition_main() { - expr * lhs = m_lit->lhs(); - expr * rhs = m_lit->rhs(); - TRACE("spc_superposition", tout << "trying superposition:\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager) << "\nis_oriented: " << m_lit->is_oriented() << "\n";); - if (m_lit->is_oriented()) { - if (!m_lit->is_left()) - std::swap(lhs, rhs); - try_superposition_main(lhs, rhs); - } - else { - try_superposition_main(lhs, rhs); - try_superposition_main(rhs, lhs); - } - } - - void superposition::found_r(expr * r) { - TRACE("spc_superposition", tout << "found_r:\n" << mk_pp(r, m_manager) << "\n"; - tout << "substitution:\n"; m_subst.display(tout);); - if (m_r2clause_set.empty(r)) - return; - TRACE("spc_superposition", tout << "r2clause is not empty.\n";); - if (!m_lit->is_oriented() && m_order.greater(m_rhs, m_lhs, &m_subst)) - return; - TRACE("spc_superposition", tout << "order restriction was met.\n";); - if (!m_clause->is_eligible_for_paramodulation(m_order, *m_lit, 0, &m_subst)) - return; - TRACE("spc_superposition", tout << "literal is eligible for paramodulation.\n";); - r2clause_set::iterator it = m_r2clause_set.begin(r); - r2clause_set::iterator end = m_r2clause_set.end(r); - for (; it != end; ++it) { - clause_pos_pair & p = *it; - clause * aux_cls = p.first; - unsigned aux_idx = p.second >> 1; - // - // The following optimization is incorrect (if statement). - // For example, it prevents the Z3 from proving the trivial benchmark - // c = X, - // a != b - // using the order a < b < c - // - // To prove, this example we need to generate the clause Y = X by applying superposition of c = X on itself. - // We can see that by renaming the first clause to c = Y, and then, substituting c in the original by Y. - // - // Actually, this optimization is correct when the set of variables in m_lhs is a superset of the set of variables in m_rhs, - // because in this case, the new literal will be equivalent to true. In the example above, this is not the case, - // since m_lhs does not contain any variable, and m_rhs contains one. - // - - // - // if (r == m_lhs && m_clause == aux_cls && m_idx == aux_idx) - // continue; - // - bool in_lhs = (p.second & 1) != 0; - TRACE("spc_superposition", tout << "aux_cls:\n"; aux_cls->display(tout, m_manager); tout << "\naux_idx: " << aux_cls << ", in_lhs: " << in_lhs << "\n";); - literal & aux_lit = aux_cls->get_literal(aux_idx); - if (!aux_cls->is_eligible_for_resolution(m_order, aux_lit, 1, &m_subst)) - continue; - literal_buffer new_literals(m_manager); - m_subst.reset_cache(); - if (m_manager.is_eq(aux_lit.atom())) { - expr * lhs = aux_lit.lhs(); - expr * rhs = aux_lit.rhs(); - TRACE("spc_superposition", tout << "aux_lit lhs:\n" << mk_pp(lhs, m_manager) << "\nrhs:\n" << mk_pp(rhs, m_manager) << "\n";); - if (!in_lhs) - std::swap(lhs, rhs); - if (!aux_lit.is_oriented() && m_order.greater(rhs, lhs, 1, &m_subst)) { - TRACE("spc_superposition", tout << "failed order constraint.\n";); - continue; - } - expr_ref new_lhs(m_manager), new_rhs(m_manager); - m_subst.apply(2, m_deltas, expr_offset(lhs, 1), expr_offset(r, 1), expr_offset(m_rhs, 0), new_lhs); - m_subst.apply(2, m_deltas, expr_offset(rhs, 1), new_rhs); - TRACE("spc_superposition", tout << "aux_lit new_lhs:\n" << mk_pp(new_lhs, m_manager) << "\nnew_rhs:\n" << mk_pp(new_rhs, m_manager) << "\n";); - expr * new_eq = m_manager.mk_eq(new_lhs, new_rhs); - new_literals.push_back(literal(new_eq, aux_lit.sign())); - } - else { - expr_ref new_atom(m_manager); - m_subst.apply(2, m_deltas, expr_offset(aux_lit.atom(), 1), new_atom); - new_literals.push_back(literal(new_atom, aux_lit.sign())); - } - copy_literals(m_clause, m_idx, 0, new_literals); - copy_literals(aux_cls, aux_idx, 1, new_literals); - TRACE("superposition", tout << "found r target: " << mk_pp(r, m_manager) << " for \n" << - mk_pp(m_lhs, m_manager) << "\nmain clause: "; m_clause->display(tout, m_manager); - tout << "\naux clause: "; aux_cls->display(tout, m_manager); tout << "\nat pos: " << - aux_idx << "\n";); - mk_sp_clause(new_literals.size(), new_literals.c_ptr(), m_clause->get_justification(), aux_cls->get_justification()); - } - } - - /** - \brief Try to apply superposition rule using the clause - being added (m_clause) as the aux clause, and its literal m_lit - as the target. - */ - void superposition::try_superposition_aux() { - TRACE("superposition_aux", tout << "superposition aux:\n"; m_clause->display(tout, m_manager); - tout << "\nusing literal: " << m_idx << "\n";); - if (m_manager.is_eq(m_lit->atom())) { - expr * lhs = m_lit->lhs(); - expr * rhs = m_lit->rhs(); - if (m_lit->is_oriented()) { - if (!m_lit->is_left()) - std::swap(lhs, rhs); - try_superposition_aux(lhs, rhs); - } - else { - try_superposition_aux(lhs, rhs); - try_superposition_aux(rhs, lhs); - } - } - else { - try_superposition_aux(m_lit->atom(), 0); - } - } - - /** - \brief Use the clause being added as the auxiliary clause in the superposition rule. - */ - void superposition::try_superposition_aux(expr * lhs, expr * rhs) { - TRACE("superposition_aux", tout << "try_superposition_aux\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager) << "\n";); - if (is_var(lhs)) - return; - m_lhs = lhs; - m_rhs = rhs; - SASSERT(m_todo.empty()); - m_todo.push_back(to_app(lhs)); - while (!m_todo.empty()) { - m_target = m_todo.back(); - m_todo.pop_back(); - m_subst.reset_subst(); - p_visitor v(*this, m_subst); - TRACE("superposition_aux", tout << "trying to find unifier for:\n" << mk_pp(m_target, m_manager) << "\n";); - m_p.unify(m_target, v); - unsigned j = m_target->get_num_args(); - while (j > 0) { - --j; - expr * arg = m_target->get_arg(j); - if (is_app(arg)) - m_todo.push_back(to_app(arg)); - } - } - } - - void superposition::found_p(expr * p) { - TRACE("superposition_found_p", tout << "found p:\n" << mk_pp(p, m_manager) << "\n";); - if (m_p2clause_set.empty(p)) { - TRACE("superposition_found_p", tout << "clause set is empty.\n";); - return; - } - if (m_rhs && !m_lit->is_oriented() && m_order.greater(m_rhs, m_lhs, &m_subst)) { - TRACE("superposition_found_p", tout << "aux clause failed not rhs > lhs constraint.\n";); - return; - } - if (!m_clause->is_eligible_for_resolution(m_order, *m_lit, 0, &m_subst)) { - TRACE("superposition_found_p", tout << "aux literal is not eligible for resolution.\n";); - return; - } - p2clause_set::iterator it = m_p2clause_set.begin(p); - p2clause_set::iterator end = m_p2clause_set.end(p); - for (; it != end; ++it) { - clause_pos_pair & pair = *it; - clause * main_cls = pair.first; - TRACE("superposition_found_p", tout << "p clause:\n"; main_cls->display(tout, m_manager); tout << "\n";); - unsigned lit_idx = pair.second; - if (p == m_lhs && m_clause == main_cls && m_idx == lit_idx) - continue; - literal const & main_lit = main_cls->get_literal(lit_idx); - SASSERT(m_manager.is_eq(main_lit.atom())); - expr * lhs = main_lit.lhs(); - expr * rhs = main_lit.rhs(); - if (rhs == p) - std::swap(lhs, rhs); - SASSERT(lhs == p); - TRACE("superposition_found_p", tout << "lhs: " << mk_pp(lhs, m_manager) << "\nrhs: " << mk_pp(rhs, m_manager) << "\n";); - if (!main_lit.is_oriented() && m_order.greater(rhs, lhs, 1, &m_subst)) - continue; - if (!main_cls->is_eligible_for_paramodulation(m_order, main_lit, 1, &m_subst)) - continue; - literal_buffer new_literals(m_manager); - m_subst.reset_cache(); - TRACE("superposition_found_p", tout << "creating new_lhs\n";); - expr_ref new_lhs(m_manager); - m_subst.apply(2, m_deltas, expr_offset(m_lhs, 0), expr_offset(m_target, 0), expr_offset(rhs, 1), new_lhs); - // FIX: m_subst.reset_cache(); - TRACE("superposition_found_p", tout << "new_lhs: " << mk_pp(new_lhs, m_manager) << "\n"; - m_subst.display(tout);); - expr * new_atom = 0; - if (m_rhs) { - TRACE("superposition_found_p", tout << "creating new_rhs\n";); - expr_ref new_rhs(m_manager); - m_subst.apply(2, m_deltas, expr_offset(m_rhs, 0), new_rhs); - TRACE("superposition_found_p", tout << "new_rhs: " << mk_pp(new_rhs, m_manager) << "\n";); - new_atom = m_manager.mk_eq(new_lhs, new_rhs); - } - else - new_atom = new_lhs; - TRACE("superposition_found_p", tout << "new_atom: " << mk_pp(new_atom, m_manager) << "\n"; m_subst.display(tout);); - new_literals.push_back(literal(new_atom, m_lit->sign())); - TRACE("superposition_found_p", tout << "copying literals\n";); - copy_literals(main_cls, lit_idx, 1, new_literals); - copy_literals(m_clause, m_idx, 0, new_literals); - TRACE("superposition", tout << "found p target: " << mk_pp(p, m_manager) << " for \n" << - mk_pp(m_lhs, m_manager) << "\nmain clause: "; main_cls->display(tout, m_manager); - tout << "\naux clause: "; m_clause->display(tout, m_manager); tout << "\n";); - mk_sp_clause(new_literals.size(), new_literals.c_ptr(), main_cls->get_justification(), m_clause->get_justification()); - } - } - - /** - \brief Try to apply resolution rule using the clause being added (m_clause). - */ - void superposition::try_resolution() { - m_subst.reset_subst(); - res_visitor v(*this, m_subst); - m_r.unify(m_lit->atom(), v); - } - - void superposition::found_res(expr * r) { - if (m_r2clause_set.empty(r)) - return; - if (!m_clause->is_eligible_for_resolution(m_order, *m_lit, 0, &m_subst)) - return; - r2clause_set::iterator it = m_r2clause_set.begin(r); - r2clause_set::iterator end = m_r2clause_set.end(r); - for (; it != end; ++it) { - clause_pos_pair & pair = *it; - clause * aux_cls = pair.first; - unsigned aux_idx = pair.second >> 1; - literal const & aux_lit = aux_cls->get_literal(aux_idx); - if (aux_lit.sign() == m_lit->sign()) - continue; - if (aux_lit.atom() != r) - continue; - if (!aux_cls->is_eligible_for_resolution(m_order, aux_lit, 1, &m_subst)) - continue; - literal_buffer new_literals(m_manager); - m_subst.reset_cache(); - copy_literals(m_clause, m_idx, 0, new_literals); - copy_literals(aux_cls, aux_idx, 1, new_literals); - mk_res_clause(new_literals.size(), new_literals.c_ptr(), m_clause->get_justification(), aux_cls->get_justification()); - } - } - - void superposition::operator()(clause * cls, ptr_vector & new_clauses) { - m_subst.reserve_vars(cls->get_num_vars()); - m_clause = cls; - m_new_clauses = &new_clauses; - SASSERT(m_deltas[0] == 0); - m_deltas[1] = m_clause->get_num_vars(); - unsigned num_lits = cls->get_num_literals(); - for (m_idx = 0; m_idx < num_lits; m_idx++) { - m_lit = &(cls->get_literal(m_idx)); - bool is_eq = m_manager.is_eq(m_lit->atom()); - if (!m_lit->sign() && m_lit->is_p_indexed() && is_eq) - try_superposition_main(); - if (m_lit->is_r_indexed()) { - try_superposition_aux(); - if (!is_eq) - try_resolution(); - } - } - } - -}; - - diff --git a/src/dead/spc/spc_superposition.h b/src/dead/spc/spc_superposition.h deleted file mode 100644 index 622b95358..000000000 --- a/src/dead/spc/spc_superposition.h +++ /dev/null @@ -1,147 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_superposition.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-15. - -Revision History: - ---*/ -#ifndef _SPC_SUPERPOSITION_H_ -#define _SPC_SUPERPOSITION_H_ - -#include"spc_clause.h" -#include"spc_clause_pos_set.h" -#include"substitution_tree.h" -#include"obj_hashtable.h" -#include"sparse_use_list.h" -#include"normalize_vars.h" -#include"spc_statistics.h" - -namespace spc { - - /** - \brief Functor for applying the superposition right/left rules. - - - Superposition Left - s = t or S, u != v or R - ==> - sigma(u[p<-t] != v or S or R) - - sigma is the mgu(u|p, s) - sigma(s) not greater than sigma(t) - sigma(u) not greater than sigma(v) - sigma(s = t) is eligible for paramodulation - sigma(u != v) is eligible for resolution - u|p is not a variable - - - - Superposition Right - s = t or S, u = v or R - ==> - sigma(u[p<-t] != v or S or R) - - Same restrictions of Superposition Left - - This functor also applied binary resolution rule. - - We say the left clause is the main clause in the superposition. - */ - class superposition { - ast_manager & m_manager; - order & m_order; - statistics & m_stats; - substitution m_subst; - - // indexes for left clause - substitution_tree m_p; // potential left hand sides for superposition - typedef sparse_use_list > p2clause_set; - p2clause_set m_p2clause_set; - - void insert_p(clause * cls, expr * lhs, unsigned i); - void insert_p(clause * cls, literal & l, unsigned i); - - void erase_p(clause * cls, expr * lhs, unsigned i); - void erase_p(clause * cls, literal & l, unsigned i); - - // indexes for right clause - substitution_tree m_r; // potential targets for superposition - typedef sparse_use_list r2clause_set; - r2clause_set m_r2clause_set; - ptr_vector m_todo; - - void insert_r(clause * cls, expr * n, unsigned i, bool lhs); - void insert_r(clause * cls, literal & l, unsigned i); - void erase_r(clause * cls, literal & l, unsigned i); - - normalize_vars m_normalize_vars; - - // temporary fields... - ptr_vector * m_new_clauses; - clause * m_clause; - literal * m_lit; - expr * m_lhs; - expr * m_rhs; - app * m_target; - unsigned m_idx; - unsigned m_deltas[2]; - family_id m_spc_fid; - - void normalize_literals(unsigned num_lits, literal * lits, literal_buffer & result); - void copy_literals(clause * s, unsigned idx, unsigned offset, literal_buffer & result); - void mk_sp_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2); - void mk_res_clause(unsigned num_lits, literal * lits, justification * p1, justification * p2); - void try_superposition_main(expr * lhs, expr * rhs); - void try_superposition_main(); - void found_r(expr * r); - void try_superposition_aux(expr * lhs, expr * rhs); - void try_superposition_aux(); - void found_p(expr * p); - void try_resolution(); - void found_res(expr * r); - - friend struct r_visitor; - struct r_visitor : public st_visitor { - superposition & m_owner; - r_visitor(superposition & o, substitution & s):st_visitor(s), m_owner(o) {} - virtual bool operator()(expr * e) { m_owner.found_r(e); return true; /* continue */ } - }; - - friend struct p_visitor; - struct p_visitor : public st_visitor { - superposition & m_owner; - p_visitor(superposition & o, substitution & s):st_visitor(s), m_owner(o) {} - virtual bool operator()(expr * e) { m_owner.found_p(e); return true; /* continue */ } - }; - - friend struct res_visitor; - struct res_visitor : public st_visitor { - superposition & m_owner; - res_visitor(superposition & o, substitution & s):st_visitor(s), m_owner(o) {} - virtual bool operator()(expr * e) { m_owner.found_res(e); return true; /* continue */ } - }; - - public: - superposition(ast_manager & m, order & o, statistics & stats); - ~superposition(); - - void insert(clause * cls); - void erase(clause * cls); - void reset(); - - void operator()(clause * cls, ptr_vector & new_clauses); - }; - -}; - -#endif /* _SPC_SUPERPOSITION_H_ */ - diff --git a/src/dead/spc/spc_unary_inference.cpp b/src/dead/spc/spc_unary_inference.cpp deleted file mode 100644 index c5088b734..000000000 --- a/src/dead/spc/spc_unary_inference.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_unary_inference.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#include"spc_unary_inference.h" - -namespace spc { - - unary_inference::unary_inference(ast_manager & m, order & ord): - m_manager(m), - m_order(ord), - m_subst(m), - m_unifier(m) { - m_subst.reserve_offsets(1); - } - - /** - \brief Create the result clause. The literal at position j of \c cls in removed, - and the substitution m_subst is applied to the resultant clause. - */ - clause * unary_inference::mk_result(clause * cls, unsigned j) { - sbuffer new_literals; - unsigned num = cls->get_num_literals(); - for (unsigned i = 0; i < num; i++) { - if (i != j) { - literal const & l = cls->get_literal(i); - expr_ref new_atom(m_manager); - m_subst.apply(l.atom(), new_atom); - new_literals.push_back(literal(new_atom, l.sign())); - } - } - - justification * js = mk_justification(cls->get_justification(), new_literals.size(), new_literals.c_ptr()); - clause * new_cls = clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), js, cls->get_scope_lvl()); - return new_cls; - } - -}; diff --git a/src/dead/spc/spc_unary_inference.h b/src/dead/spc/spc_unary_inference.h deleted file mode 100644 index 5be156636..000000000 --- a/src/dead/spc/spc_unary_inference.h +++ /dev/null @@ -1,48 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - spc_unary_inference.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2008-02-14. - -Revision History: - ---*/ -#ifndef _SPC_UNARY_INFERENCE_H_ -#define _SPC_UNARY_INFERENCE_H_ - -#include"spc_clause.h" -#include"unifier.h" - -namespace spc { - - /** - \brief Superclass for eq_resolution and factoring. - */ - class unary_inference { - protected: - ast_manager & m_manager; - order & m_order; - substitution m_subst; - unifier m_unifier; - - clause * mk_result(clause * cls, unsigned j); - virtual justification * mk_justification(justification * parent, unsigned num_lits, literal * new_lits) = 0; - public: - unary_inference(ast_manager & m, order & ord); - virtual ~unary_inference() {} - }; - -}; - - -#endif /* _SPC_UNARY_INFERENCE_H_ */ - diff --git a/src/dead/spc/splay_tree.h b/src/dead/spc/splay_tree.h deleted file mode 100644 index 9135a5705..000000000 --- a/src/dead/spc/splay_tree.h +++ /dev/null @@ -1,180 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - splay_tree.h - -Abstract: - - Splay trees - -Author: - - Leonardo de Moura (leonardo) 2008-01-31. - -Revision History: - ---*/ -#ifndef _SPLAY_TREE_H_ -#define _SPLAY_TREE_H_ - -#include"util.h" -#include"buffer.h" - -template -class splay_tree : private Compare { - struct cell { - Key m_key; - cell * m_left; - cell * m_right; - - cell():m_left(0), m_right(0) {} - cell(Key const & k, cell * l = 0, cell * r = 0): - m_key(k), m_left(l), m_right(r) {} - }; - - cell * m_root; - int compare(Key const & k1, Key const & k2) const { return Compare::operator()(k1, k2); } - cell * splay(cell * c, Key const & k); - - void display_core(std::ostream & out, cell * c) const { - if (c) { - out << "(" << c->m_key << " "; - display_core(out, c->m_left); - out << " "; - display_core(out, c->m_right); - out << ")"; - } - else - out << "null"; - } - -public: - splay_tree(Compare const & c = Compare()): - Compare(c), - m_root(0) {} - - ~splay_tree() { - m_root = 0; - } - - void insert(Key const & k); - - bool find(Key const & k, Key & r) const; - - void erase(Key const & k); - - void reset(); - - bool empty() const { return m_root == 0; } - - bool singleton() const { return m_root != 0 && m_root->m_left == 0 && m_root->m_right == 0; } - - /** - \brief Visit nodes in the splay tree in ascending order. - The Visitor functor should provide the following methods: - - - bool visit_left(Key const & k) - return true if the left child should be visited - - - bool visit_right(Key const & k) - return true if the right child should be visited - - - void operator()(Key const & k) - do something with the key. - */ - template - void visit_core(Visitor & v) { - typedef std::pair entry; - if (m_root) { - buffer todo; - todo.push_back(entry(m_root, false)); - while (!todo.empty()) { - entry & curr = todo.back(); - cell * c = curr.first; - if (!curr.second) { - curr.second = true; - if (c->m_left && v.visit_left(c->m_key)) - todo.push_back(entry(c->m_left, false)); - } - else { - v(c->m_key); - todo.pop_back(); - if (c->m_right && v.visit_right(c->m_key)) - todo.push_back(entry(c->m_right, false)); - } - } - } - } - - template - struct all_visitor_wrapper { - Visitor & m_visitor; - all_visitor_wrapper(Visitor & v):m_visitor(v) {} - bool visit_right(Key const & k) { return true; } - bool visit_left(Key const & k) { return true; } - void operator()(Key const & k) { m_visitor.operator()(k); } - }; - - /** - \brief Visit all nodes in the splay tree in ascending order. - - - void operator()(Key const & k) - do something with the key pair. - */ - template - void visit(Visitor & v) { - all_visitor_wrapper w(v); - visit_core(w); - } - - template - struct visitor_wrapper { - Visitor & m_visitor; - splay_tree & m_tree; - Key m_key; - visitor_wrapper(Visitor & v, splay_tree & t, Key const & k):m_visitor(v), m_tree(t), m_key(k) {} - bool visit_left(Key const & k) { - return LE || m_tree.compare(k, m_key) > 0; - } - bool visit_right(Key const & k) { - return !LE || m_tree.compare(k, m_key) < 0; - } - void operator()(Key const & k) { - if ((LE && m_tree.compare(k, m_key) <= 0) || - (!LE && m_tree.compare(k, m_key) >= 0)) - m_visitor.operator()(k); - } - }; - - /** - \brief Visit all nodes with keys less than or equal to k. - - - void operator()(Key const & k) - do something with the key. - */ - template - void visit_le(Visitor & v, Key const & k) { - visitor_wrapper w(v, *this, k); - visit_core(w); - } - - /** - \brief Visit all nodes with keys greater than or equal to k. - - - void operator()(Key const & k) - do something with the key. - */ - template - void visit_ge(Visitor & v, Key const & k) { - visitor_wrapper w(v, *this, k); - visit_core(w); - } - - void display(std::ostream & out) const { - display_core(out, m_root); - } -}; - -#endif diff --git a/src/dead/spc/splay_tree_def.h b/src/dead/spc/splay_tree_def.h deleted file mode 100644 index d5f1fa032..000000000 --- a/src/dead/spc/splay_tree_def.h +++ /dev/null @@ -1,152 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - splay_tree_def.h - -Abstract: - - Splay trees - -Author: - - Leonardo de Moura (leonardo) 2008-01-31. - -Revision History: - ---*/ -#ifndef _SPLAY_TREE_DEF_H_ -#define _SPLAY_TREE_DEF_H_ - -#include"splay_tree.h" - -template -typename splay_tree::cell * splay_tree::splay(cell * root, Key const & k) { - if (!root) - return 0; - - cell aux; - cell * tmp; - cell * left = &aux; - cell * right = &aux; - cell * t = root; - - while (true) { - int r = compare(k, t->m_key); - if (r < 0) { - if (!t->m_left) - break; - if (compare(k, t->m_left->m_key) < 0) { - tmp = t->m_left; - t->m_left = tmp->m_right; - tmp->m_right = t; - t = tmp; - if (!t->m_left) - break; - } - right->m_left = t; - right = t; - t = t->m_left; - } - else if (r > 0) { - if (!t->m_right) - break; - if (compare(k, t->m_right->m_key) > 0) { - tmp = t->m_right; - t->m_right = tmp->m_left; - tmp->m_left = t; - t = tmp; - if (!t->m_right) - break; - - } - left->m_right = t; - left = t; - t = t->m_right; - } - else - break; - } - - left->m_right = t->m_left; - right->m_left = t->m_right; - t->m_left = aux.m_right; - t->m_right = aux.m_left; - - return t; -} - -template -void splay_tree::insert(Key const & k) { - if (!m_root) - m_root = alloc(cell, k); - else { - m_root = splay(m_root, k); - int r = compare(k, m_root->m_key); - if (r < 0) { - cell * new_cell = alloc(cell, k, m_root->m_left, m_root); - m_root->m_left = 0; - m_root = new_cell; - } - else if (r > 0) { - cell * new_cell = alloc(cell, k, m_root, m_root->m_right); - m_root->m_right = 0; - m_root = new_cell; - } - else - m_root->m_key = k; - } -} - -template -bool splay_tree::find(Key const & k, Key & r) const { - if (m_root) { - splay_tree * _this = const_cast *>(this); - _this->m_root = _this->splay(m_root, k); - if (compare(k, m_root->m_key) == 0) { - r = m_root->m_key; - return true; - } - } - return false; -} - -template -void splay_tree::erase(Key const & k) { - if (m_root) { - m_root = splay(m_root, k); - if (compare(k, m_root->m_key) == 0) { - cell * to_delete = m_root; - if (m_root->m_left) { - cell * aux = splay(m_root->m_left, k); - SASSERT(!aux->m_right); - aux->m_right = m_root->m_right; - m_root = aux; - } - else - m_root = m_root->m_right; - - dealloc(to_delete); - } - } -} - -template -void splay_tree::reset() { - ptr_buffer todo; - if (m_root) - todo.push_back(m_root); - while (!todo.empty()) { - cell * c = todo.back(); - todo.pop_back(); - if (c->m_left) - todo.push_back(c->m_left); - if (c->m_right) - todo.push_back(c->m_right); - dealloc(c); - } - m_root = 0; -} - -#endif /* _SPLAY_TREE_DEF_H_ */ diff --git a/src/dead/spc/splay_tree_map.h b/src/dead/spc/splay_tree_map.h deleted file mode 100644 index 89a82bd30..000000000 --- a/src/dead/spc/splay_tree_map.h +++ /dev/null @@ -1,114 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - splay_tree_map.h - -Abstract: - - A mapping as a splay tree. - -Author: - - Leonardo de Moura (leonardo) 2008-02-02. - -Revision History: - ---*/ -#ifndef _SPLAY_TREE_MAP_H_ -#define _SPLAY_TREE_MAP_H_ - -#include"splay_tree.h" - -template -class splay_tree_map { - typedef std::pair entry; - - struct entry_compare : private Compare { - entry_compare(Compare const & c):Compare(c) {} - int operator()(entry const & e1, entry const & e2) const { - return Compare::operator()(e1.first, e2.first); - } - }; - - typedef splay_tree tree; - - tree m_tree; - - template - struct core_visitor_wrapper { - Visitor & m_visitor; - core_visitor_wrapper(Visitor & v):m_visitor(v) {} - bool visit_right(entry const & k) { return m_visitor.visit_right(k.first); } - bool visit_left(entry const & k) { return m_visitor.visit_left(k.first); } - void operator()(entry const & k) { m_visitor.operator()(k.first, k.second); } - }; - - template - struct visitor_wrapper { - Visitor & m_visitor; - visitor_wrapper(Visitor & v):m_visitor(v) {} - void operator()(entry const & k) { m_visitor.operator()(k.first, k.second); } - }; - -public: - splay_tree_map(Compare const & c = Compare()): - m_tree(entry_compare(c)) {} - - void insert(Key const & k, Data const & d) { - m_tree.insert(entry(k, d)); - } - - bool find(Key const & k, Data & r) const { - entry e(k, r); - if (m_tree.find(e, e)) { - r = e.second; - return true; - } - return false; - } - - void erase(Key const & k) { - entry e; - e.first = k; - m_tree.erase(e); - } - - void reset() { m_tree.reset(); } - - bool empty() const { return m_tree.empty(); } - - void display(std::ostream & out) const { m_tree.display(out); } - - template - void visit_core(Visitor & v) { - core_visitor_wrapper w(v); - m_tree.visit_core(w); - } - - template - void visit(Visitor & v) { - visitor_wrapper w(v); - m_tree.visit(w); - } - - template - void visit_le(Visitor & v, Key const & k) { - visitor_wrapper w(v); - entry e; - e.first = k; - m_tree.visit_le(w, e); - } - - template - void visit_ge(Visitor & v, Key const & k) { - visitor_wrapper w(v); - entry e; - e.first = k; - m_tree.visit_ge(w, e); - } -}; - -#endif /* _SPLAY_TREE_MAP_H_ */ - diff --git a/src/dead/spc/use_list.cpp b/src/dead/spc/use_list.cpp deleted file mode 100644 index 15ef74714..000000000 --- a/src/dead/spc/use_list.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - use_list.cpp - -Abstract: - - Use list term index. - -Author: - - Leonardo de Moura (leonardo) 2008-02-04. - -Revision History: - ---*/ -#include"use_list.h" - -void app_use_list::inc_ref(app * n) { - if (n->get_num_args() == 0) - return; // ignore constants - unsigned id = n->get_id(); - unsigned c = m_ref_counter.get(id, 0); - m_ref_counter.setx(id, c+1, 0); - if (c == 0) - m_todo.push_back(n); -} - -void app_use_list::dec_ref(app * n) { - if (n->get_num_args() == 0) - return; // ignore constants - unsigned id = n->get_id(); - SASSERT(m_ref_counter[id] > 0); - m_ref_counter[id]--; - if (m_ref_counter[id] == 0) - m_todo.push_back(n); -} - -void app_use_list::insert(expr * n) { - if (is_var(n)) - return; // nothing to index - SASSERT(m_todo.empty()); - inc_ref(to_app(n)); - while (!m_todo.empty()) { - app * n = m_todo.back(); - unsigned num_args = n->get_num_args(); - for (unsigned i = 0; i < num_args; i++) { - expr * c = n->get_arg(i); - if (is_var(c)) { - if (!m_ignore_vars) - use_list::insert(n, c); - } - else { - SASSERT(is_app(c)); - use_list::insert(n, c); - inc_ref(to_app(c)); - } - } - } -} - -void app_use_list::erase(expr * n) { - if (is_var(n)) - return; // nothing to index - SASSERT(m_todo.empty()); - dec_ref(to_app(n)); - while (!m_todo.empty()) { - app * n = m_todo.back(); - unsigned num_args = n->get_num_args(); - for (unsigned i = 0; i < num_args; i++) { - expr * c = n->get_arg(i); - if (is_var(c)) { - if (!m_ignore_vars) - use_list::erase(n, c); - } - else { - SASSERT(is_app(c)); - use_list::erase(n, c); - dec_ref(to_app(c)); - } - } - } -} - -void app_use_list::reset() { - use_list::reset(); - m_ref_counter.reset(); -} diff --git a/src/dead/spc/use_list.h b/src/dead/spc/use_list.h deleted file mode 100644 index 28220dbf7..000000000 --- a/src/dead/spc/use_list.h +++ /dev/null @@ -1,120 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - use_list.h - -Abstract: - - Use list expression index. - -Author: - - Leonardo de Moura (leonardo) 2008-02-04. - -Revision History: - ---*/ -#ifndef _USE_LIST_H_ -#define _USE_LIST_H_ - -#include"ast.h" -#include"vector.h" - -/** - \brief Generic use-list data-structure. -*/ -template -class use_list { - typedef vector set; - vector m_use_list; -public: - typedef typename set::const_iterator iterator; - use_list() {} - - void insert(T const & parent, expr * child) { - unsigned id = child->get_id(); - if (id >= m_use_list.size()) - m_use_list.resize(id+1, set()); - set & s = m_use_list[id]; - s.push_back(parent); - } - - void erase(T const & parent, expr * child) { - unsigned id = child->get_id(); - if (id >= m_use_list.size()) - return; - set & s = m_use_list[id]; - s.erase(parent); - } - - void reset() { - m_use_list.reset(); - } - - iterator begin(expr * e) const { - unsigned id = e->get_id(); - if (id >= m_use_list.size()) - return 0; - return m_use_list[id].begin(); - } - - iterator end(expr * e) const { - unsigned id = e->get_id(); - if (id >= m_use_list.size()) - return 0; - return m_use_list[id].end(); - } - - bool empty(expr * e) const { - unsigned id = e->get_id(); - if (id >= m_use_list.size()) - return true; - return m_use_list[id].empty(); - } -}; - -/** - \brief Index for tracking the uses of an expression. It is a - mapping from expressions to expressions. For example, consider the - term (f a (g a)), the constant a is used by f and g applications. - - \remark The expressions inserted in this index should not contain - quantifiers. - - \warning This index will not increase the reference counter of the - indexed expressions. -*/ -class app_use_list : use_list { - - bool m_ignore_vars; //!< when true, variables are not indexed - unsigned_vector m_ref_counter; - ptr_vector m_todo; - - void inc_ref(app * n); - void dec_ref(app * n); - -public: - /** - \brief If ignore_vars = true, then the index will not track - the use of variables. - */ - app_use_list(bool ignore_vars = true): - m_ignore_vars(ignore_vars) { - } - - /** - \brief Update the use list of all direct/indirect children of n. - */ - void insert(expr * n); - - /** - \brief Remove n (and its unreachable direct/indirect children) from the index. - */ - void erase(expr * n); - - void reset(); -}; - -#endif /* _USE_LIST_H_ */ diff --git a/src/dead/st_cmds.h b/src/dead/st_cmds.h deleted file mode 100644 index 6ae40b546..000000000 --- a/src/dead/st_cmds.h +++ /dev/null @@ -1,26 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - st_cmds.h - -Abstract: - - Commands for testing strategies. - -Author: - - Leonardo de Moura (leonardo) 2011-04-27 - -Revision History: - ---*/ -#ifndef _ST_CMD_H_ -#define _ST_CMD_H_ - -class cmd_context; - -void install_st_cmds(cmd_context & ctx); - -#endif diff --git a/src/dead/value_compiler_extension.h b/src/dead/value_compiler_extension.h deleted file mode 100644 index a83e7e0a3..000000000 --- a/src/dead/value_compiler_extension.h +++ /dev/null @@ -1,46 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - value_compiler_extension.h - -Abstract: - - Compiler extension for creating values (i.e., "interpreted" constants that - are different any other constant). - -Author: - - Leonardo de Moura (leonardo) 2006-10-31. - -Revision History: - ---*/ -#ifndef _VALUE_COMPILER_EXTENSION_H_ -#define _VALUE_COMPILER_EXTENSION_H_ - -#include"ast_compiler.h" - -class value_compiler_extension : public ast_compiler_plugin { - context & m_context; -public: - value_compiler_extension(ast_manager & m, context & ctx): - ast_compiler_plugin(m.get_family_id(symbol("interpreted_value"))), - m_context(ctx) { - ctx.register_plugin(this); - } - - virtual ~value_compiler_extension() { - } - - virtual bool compile_term(ast_compiler & c, const_ast * a, enode * & r) { - SASSERT(a->get_decl()->get_family_id() == m_fid); - const_decl_ast * d = a->get_decl(); - r = m_context.mk_interpreted_const(d); - return true; - } -}; - -#endif /* _VALUE_COMPILER_EXTENSION_H_ */ - diff --git a/src/old_params/arith_simplifier_params.cpp b/src/front_end_params/arith_simplifier_params.cpp similarity index 100% rename from src/old_params/arith_simplifier_params.cpp rename to src/front_end_params/arith_simplifier_params.cpp diff --git a/src/old_params/arith_simplifier_params.h b/src/front_end_params/arith_simplifier_params.h similarity index 100% rename from src/old_params/arith_simplifier_params.h rename to src/front_end_params/arith_simplifier_params.h diff --git a/src/old_params/bit_blaster_params.h b/src/front_end_params/bit_blaster_params.h similarity index 100% rename from src/old_params/bit_blaster_params.h rename to src/front_end_params/bit_blaster_params.h diff --git a/src/old_params/bv_simplifier_params.h b/src/front_end_params/bv_simplifier_params.h similarity index 100% rename from src/old_params/bv_simplifier_params.h rename to src/front_end_params/bv_simplifier_params.h diff --git a/src/old_params/cnf_params.cpp b/src/front_end_params/cnf_params.cpp similarity index 100% rename from src/old_params/cnf_params.cpp rename to src/front_end_params/cnf_params.cpp diff --git a/src/old_params/cnf_params.h b/src/front_end_params/cnf_params.h similarity index 100% rename from src/old_params/cnf_params.h rename to src/front_end_params/cnf_params.h diff --git a/src/old_params/dyn_ack_params.cpp b/src/front_end_params/dyn_ack_params.cpp similarity index 100% rename from src/old_params/dyn_ack_params.cpp rename to src/front_end_params/dyn_ack_params.cpp diff --git a/src/old_params/dyn_ack_params.h b/src/front_end_params/dyn_ack_params.h similarity index 100% rename from src/old_params/dyn_ack_params.h rename to src/front_end_params/dyn_ack_params.h diff --git a/src/old_params/front_end_params.cpp b/src/front_end_params/front_end_params.cpp similarity index 100% rename from src/old_params/front_end_params.cpp rename to src/front_end_params/front_end_params.cpp diff --git a/src/old_params/front_end_params.h b/src/front_end_params/front_end_params.h similarity index 100% rename from src/old_params/front_end_params.h rename to src/front_end_params/front_end_params.h diff --git a/src/old_params/model_params.cpp b/src/front_end_params/model_params.cpp similarity index 100% rename from src/old_params/model_params.cpp rename to src/front_end_params/model_params.cpp diff --git a/src/old_params/model_params.h b/src/front_end_params/model_params.h similarity index 100% rename from src/old_params/model_params.h rename to src/front_end_params/model_params.h diff --git a/src/old_params/nnf_params.cpp b/src/front_end_params/nnf_params.cpp similarity index 100% rename from src/old_params/nnf_params.cpp rename to src/front_end_params/nnf_params.cpp diff --git a/src/old_params/nnf_params.h b/src/front_end_params/nnf_params.h similarity index 100% rename from src/old_params/nnf_params.h rename to src/front_end_params/nnf_params.h diff --git a/src/old_params/order_params.cpp b/src/front_end_params/order_params.cpp similarity index 100% rename from src/old_params/order_params.cpp rename to src/front_end_params/order_params.cpp diff --git a/src/old_params/order_params.h b/src/front_end_params/order_params.h similarity index 100% rename from src/old_params/order_params.h rename to src/front_end_params/order_params.h diff --git a/src/old_params/params2front_end_params.cpp b/src/front_end_params/params2front_end_params.cpp similarity index 100% rename from src/old_params/params2front_end_params.cpp rename to src/front_end_params/params2front_end_params.cpp diff --git a/src/old_params/params2front_end_params.h b/src/front_end_params/params2front_end_params.h similarity index 100% rename from src/old_params/params2front_end_params.h rename to src/front_end_params/params2front_end_params.h diff --git a/src/old_params/parser_params.cpp b/src/front_end_params/parser_params.cpp similarity index 100% rename from src/old_params/parser_params.cpp rename to src/front_end_params/parser_params.cpp diff --git a/src/old_params/parser_params.h b/src/front_end_params/parser_params.h similarity index 100% rename from src/old_params/parser_params.h rename to src/front_end_params/parser_params.h diff --git a/src/old_params/pattern_inference_params.cpp b/src/front_end_params/pattern_inference_params.cpp similarity index 100% rename from src/old_params/pattern_inference_params.cpp rename to src/front_end_params/pattern_inference_params.cpp diff --git a/src/old_params/pattern_inference_params.h b/src/front_end_params/pattern_inference_params.h similarity index 100% rename from src/old_params/pattern_inference_params.h rename to src/front_end_params/pattern_inference_params.h diff --git a/src/old_params/preprocessor_params.h b/src/front_end_params/preprocessor_params.h similarity index 100% rename from src/old_params/preprocessor_params.h rename to src/front_end_params/preprocessor_params.h diff --git a/src/old_params/qi_params.h b/src/front_end_params/qi_params.h similarity index 100% rename from src/old_params/qi_params.h rename to src/front_end_params/qi_params.h diff --git a/src/old_params/smt_params.cpp b/src/front_end_params/smt_params.cpp similarity index 100% rename from src/old_params/smt_params.cpp rename to src/front_end_params/smt_params.cpp diff --git a/src/old_params/smt_params.h b/src/front_end_params/smt_params.h similarity index 100% rename from src/old_params/smt_params.h rename to src/front_end_params/smt_params.h diff --git a/src/old_params/spc_params.cpp b/src/front_end_params/spc_params.cpp similarity index 100% rename from src/old_params/spc_params.cpp rename to src/front_end_params/spc_params.cpp diff --git a/src/old_params/spc_params.h b/src/front_end_params/spc_params.h similarity index 100% rename from src/old_params/spc_params.h rename to src/front_end_params/spc_params.h diff --git a/src/old_params/theory_arith_params.cpp b/src/front_end_params/theory_arith_params.cpp similarity index 100% rename from src/old_params/theory_arith_params.cpp rename to src/front_end_params/theory_arith_params.cpp diff --git a/src/old_params/theory_arith_params.h b/src/front_end_params/theory_arith_params.h similarity index 100% rename from src/old_params/theory_arith_params.h rename to src/front_end_params/theory_arith_params.h diff --git a/src/old_params/theory_array_params.h b/src/front_end_params/theory_array_params.h similarity index 100% rename from src/old_params/theory_array_params.h rename to src/front_end_params/theory_array_params.h diff --git a/src/old_params/theory_bv_params.h b/src/front_end_params/theory_bv_params.h similarity index 100% rename from src/old_params/theory_bv_params.h rename to src/front_end_params/theory_bv_params.h diff --git a/src/old_params/theory_datatype_params.h b/src/front_end_params/theory_datatype_params.h similarity index 100% rename from src/old_params/theory_datatype_params.h rename to src/front_end_params/theory_datatype_params.h diff --git a/src/old_params/z3_solver_params.cpp b/src/front_end_params/z3_solver_params.cpp similarity index 100% rename from src/old_params/z3_solver_params.cpp rename to src/front_end_params/z3_solver_params.cpp diff --git a/src/old_params/z3_solver_params.h b/src/front_end_params/z3_solver_params.h similarity index 100% rename from src/old_params/z3_solver_params.h rename to src/front_end_params/z3_solver_params.h diff --git a/src/muz_qe/pdr_context.cpp b/src/muz_qe/pdr_context.cpp index 08d410e5a..e85cbc031 100644 --- a/src/muz_qe/pdr_context.cpp +++ b/src/muz_qe/pdr_context.cpp @@ -1325,7 +1325,7 @@ namespace pdr { for (; it != end; ++it) { ptr_vector const& rules = it->m_value->rules(); for (unsigned i = 0; i < rules.size(); ++i) { - datalog::rule* rule = rules[i]; + // datalog::rule* rule = rules[i]; // vs(rule->get_head(), // apply interpretation of predicates to rule. // create formula and check for unsat. diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index ab32b384a..f288c526e 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -28,6 +28,7 @@ Revision History: #include"rewriter.h" #include"has_free_vars.h" #include"ast_smt2_pp.h" +#include"front_end_params.h" namespace smt2 { typedef cmd_exception parser_exception; diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index dd8987529..6711158fd 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -101,7 +101,7 @@ unsigned read_smtlib2_commands(char const* file_name, front_end_params& front_en // temporary hack until strategic_solver is ported to new tactic framework if (front_end_params.m_nlsat) { - tactic2solver_cmd * s = alloc(tactic2solver_cmd); + tactic_factory2solver * s = alloc(tactic_factory2solver); s->set_tactic(alloc(qfnra_nlsat_fct)); ctx.set_solver(s); } diff --git a/src/smt/default_solver.cpp b/src/smt/default_solver.cpp index ad611763b..73ce084f3 100644 --- a/src/smt/default_solver.cpp +++ b/src/smt/default_solver.cpp @@ -19,6 +19,7 @@ Notes: #include"solver.h" #include"smt_solver.h" #include"reg_decl_plugins.h" +#include"front_end_params.h" class default_solver : public solver { front_end_params * m_params; diff --git a/src/tactic/smt/ctx_solver_simplify_tactic.cpp b/src/smt/tactic/ctx_solver_simplify_tactic.cpp similarity index 100% rename from src/tactic/smt/ctx_solver_simplify_tactic.cpp rename to src/smt/tactic/ctx_solver_simplify_tactic.cpp diff --git a/src/tactic/smt/ctx_solver_simplify_tactic.h b/src/smt/tactic/ctx_solver_simplify_tactic.h similarity index 100% rename from src/tactic/smt/ctx_solver_simplify_tactic.h rename to src/smt/tactic/ctx_solver_simplify_tactic.h diff --git a/src/tactic/smt/smt_tactic.cpp b/src/smt/tactic/smt_tactic.cpp similarity index 100% rename from src/tactic/smt/smt_tactic.cpp rename to src/smt/tactic/smt_tactic.cpp diff --git a/src/tactic/smt/smt_tactic.h b/src/smt/tactic/smt_tactic.h similarity index 100% rename from src/tactic/smt/smt_tactic.h rename to src/smt/tactic/smt_tactic.h diff --git a/src/solver/check_sat_result.cpp b/src/solver/check_sat_result.cpp new file mode 100644 index 000000000..7a248e8b1 --- /dev/null +++ b/src/solver/check_sat_result.cpp @@ -0,0 +1,54 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + check_sat_result.cpp + +Abstract: + Abstract interface for storing the result produced by + a check_sat like command + +Author: + + Leonardo (leonardo) 2012-11-01 + +Notes: + +--*/ +#include"check_sat_result.h" + +simple_check_sat_result::simple_check_sat_result(ast_manager & m): + m_core(m), + m_proof(m) { + } + +simple_check_sat_result::~simple_check_sat_result() { +} + +void simple_check_sat_result::collect_statistics(statistics & st) const { + st.copy(m_stats); +} + +void simple_check_sat_result::get_unsat_core(ptr_vector & r) { + if (m_status == l_false) + r.append(m_core.size(), m_core.c_ptr()); +} + +void simple_check_sat_result::get_model(model_ref & m) { + if (m_status != l_false) + m = m_model; + else + m = 0; +} + +proof * simple_check_sat_result::get_proof() { + return m_status == l_false ? m_proof.get() : 0; +} + +std::string simple_check_sat_result::reason_unknown() const { + return m_unknown; +} + +void simple_check_sat_result::get_labels(svector & r) { +} diff --git a/src/cmd_context/check_sat_result.h b/src/solver/check_sat_result.h similarity index 56% rename from src/cmd_context/check_sat_result.h rename to src/solver/check_sat_result.h index fcb42acb7..ce0525fc9 100644 --- a/src/cmd_context/check_sat_result.h +++ b/src/solver/check_sat_result.h @@ -23,6 +23,18 @@ Notes: #include"lbool.h" #include"statistics.h" +/** + \brief Abstract interface for the result of a (check-sat) like command. + It encapsulates information such as: + - the actual result: l_true (satisfiable), l_false (unsatisfiable), l_undef (unknown) + - statistics + - model (if the result is satisfiable) + - proof (if the result is unsatisfiable) + - unsat-core (if the result is unsatisfiable) + - reason-unknown (if the result is unknown, i.e., the solver failed to solve the problem) + - label (if the result is satisfiable) this is legacy for Boogie + +*/ class check_sat_result { protected: unsigned m_ref_count; @@ -42,6 +54,9 @@ public: virtual void get_labels(svector & r) = 0; }; +/** + \brief Very simple implementation of the check_sat_result object. +*/ struct simple_check_sat_result : public check_sat_result { statistics m_stats; model_ref m_model; @@ -49,21 +64,14 @@ struct simple_check_sat_result : public check_sat_result { proof_ref m_proof; std::string m_unknown; - simple_check_sat_result(ast_manager & m): - m_core(m), - m_proof(m) { - } - virtual ~simple_check_sat_result() {} - virtual void collect_statistics(statistics & st) const { st.copy(m_stats); } - virtual void get_unsat_core(ptr_vector & r) { if (m_status == l_false) r.append(m_core.size(), m_core.c_ptr()); } - virtual void get_model(model_ref & m) { - if (m_status != l_false) m = m_model; else m = 0; - } - virtual proof * get_proof() { return m_status == l_false ? m_proof.get() : 0; } - virtual std::string reason_unknown() const { - return m_unknown; - } - virtual void get_labels(svector & r) {} + simple_check_sat_result(ast_manager & m); + virtual ~simple_check_sat_result(); + virtual void collect_statistics(statistics & st) const; + virtual void get_unsat_core(ptr_vector & r); + virtual void get_model(model_ref & m); + virtual proof * get_proof(); + virtual std::string reason_unknown() const; + virtual void get_labels(svector & r); }; #endif diff --git a/src/cmd_context/progress_callback.h b/src/solver/progress_callback.h similarity index 60% rename from src/cmd_context/progress_callback.h rename to src/solver/progress_callback.h index 6397d7bc4..fab054671 100644 --- a/src/cmd_context/progress_callback.h +++ b/src/solver/progress_callback.h @@ -23,11 +23,11 @@ class progress_callback { public: virtual ~progress_callback() {} - // Called approx. every m_progress_sampling_freq miliseconds - virtual void slow_progress_sample() { } - - // Called on every check for reqsource limit exceeded (mach more frequent). - virtual void fast_progress_sample() { } + // Called on every check for resource limit exceeded (much more frequent). + virtual void fast_progress_sample() {} + + // Less frequent invoked. + virtual void slow_progress_sample() {} }; #endif diff --git a/src/cmd_context/solver.cpp b/src/solver/solver.cpp similarity index 100% rename from src/cmd_context/solver.cpp rename to src/solver/solver.cpp diff --git a/src/solver/solver.h b/src/solver/solver.h new file mode 100644 index 000000000..e8823df4f --- /dev/null +++ b/src/solver/solver.h @@ -0,0 +1,153 @@ +/*++ +Copyright (c) 2011 Microsoft Corporation + +Module Name: + + solver.h + +Abstract: + + abstract solver interface + +Author: + + Leonardo (leonardo) 2011-03-19 + +Notes: + +--*/ +#ifndef _SOLVER_H_ +#define _SOLVER_H_ + +#include"check_sat_result.h" +#include"progress_callback.h" +#include"params.h" + +struct front_end_params; + +/** + \brief Abstract interface for making solvers available in the Z3 + API and front-ends such as SMT 2.0 and (legacy) SMT 1.0. + + It provides the basic functionality for incremental solvers. + - assertions + - push/pop + - parameter setting (updt_params) + - statistics + - results based on check_sat_result API + - interruption (set_cancel) + - resets +*/ +class solver : public check_sat_result { +public: + virtual ~solver() {} + + /** + \brief This method is invoked to allow the solver to access the front_end_params (environment parameters). + + \warning This method is used for backward compatibility. The first solver implemented in Z3 used + front_end_params to store its configuration parameters. + */ + virtual void set_front_end_params(front_end_params & p) {} + + /** + \brief Update the solver internal settings. + */ + virtual void updt_params(params_ref const & p) {} + + /** + \brief Store in \c r a description of the configuration + parameters available in this solver. + */ + virtual void collect_param_descrs(param_descrs & r) {} + + /** + \brief Enable/Disable proof production for this solver object. + + It is invoked before init(m, logic). + */ + virtual void set_produce_proofs(bool f) {} + /** + \brief Enable/Disable model generation for this solver object. + + It is invoked before init(m, logic). + */ + virtual void set_produce_models(bool f) {} + /** + \brief Enable/Disable unsat core generation for this solver object. + + It is invoked before init(m, logic). + */ + virtual void set_produce_unsat_cores(bool f) {} + + /** + \brief Initialize the solver object with the given ast_manager and logic. + */ + virtual void init(ast_manager & m, symbol const & logic) = 0; + + /** + \brief Reset the solver internal state. All assertions should be removed. + */ + virtual void reset() = 0; + + /** + \brief Add a new formula to the assertion stack. + */ + virtual void assert_expr(expr * t) = 0; + + /** + \brief Create a backtracking point. + */ + virtual void push() = 0; + + /** + \brief Remove \c n backtracking points. All assertions between the pop and matching push are removed. + */ + virtual void pop(unsigned n) = 0; + + /** + \brief Return the number of backtracking points. + */ + virtual unsigned get_scope_level() const = 0; + + /** + \brief Check if the set of assertions in the assertion stack is satisfiable modulo the given assumptions. + + If it is unsatisfiable, and unsat-core generation is enabled. Then, the unsat-core is a subset of these assumptions. + */ + virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) = 0; + + virtual void set_cancel(bool f) {} + /** + \brief Interrupt this solver. + */ + void cancel() { set_cancel(true); } + /** + \brief Reset the interruption. + */ + void reset_cancel() { set_cancel(false); } + + /** + \brief Set a progress callback procedure that is invoked by this solver during check_sat. + + This is essentially for backward compatibility and integration with VCC tools. + */ + virtual void set_progress_callback(progress_callback * callback) = 0; + + /** + \brief Return the number of assertions in the assertion stack. + */ + virtual unsigned get_num_assertions() const; + + /** + \brief Return the assertion at position idx in the assertion stack. + */ + virtual expr * get_assertion(unsigned idx) const; + + /** + \brief Display the content of this solver. + */ + virtual void display(std::ostream & out) const; +}; + +#endif diff --git a/src/cmd_context/strategic_solver.cpp b/src/solver/strategic_solver.cpp similarity index 80% rename from src/cmd_context/strategic_solver.cpp rename to src/solver/strategic_solver.cpp index c8d5c6fcb..a32aec2b1 100644 --- a/src/cmd_context/strategic_solver.cpp +++ b/src/solver/strategic_solver.cpp @@ -17,15 +17,15 @@ Notes: --*/ #include"strategic_solver.h" -#include"cmd_context.h" #include"scoped_timer.h" +#include"front_end_params.h" #include"params2front_end_params.h" #include"ast_smt2_pp.h" // minimum verbosity level for portfolio verbose messages #define PS_VB_LVL 15 -strategic_solver::strategic_solver(): +strategic_solver_core::strategic_solver_core(): m_manager(0), m_fparams(0), m_force_tactic(false), @@ -45,7 +45,7 @@ strategic_solver::strategic_solver(): m_produce_unsat_cores = false; } -strategic_solver::~strategic_solver() { +strategic_solver_core::~strategic_solver_core() { SASSERT(!m_curr_tactic); dictionary::iterator it = m_logic2fct.begin(); dictionary::iterator end = m_logic2fct.end(); @@ -56,7 +56,7 @@ strategic_solver::~strategic_solver() { m().dec_ref(m_proof); } -bool strategic_solver::has_quantifiers() const { +bool strategic_solver_core::has_quantifiers() const { unsigned sz = get_num_assertions(); for (unsigned i = 0; i < sz; i++) { if (::has_quantifiers(get_assertion(i))) @@ -68,7 +68,7 @@ bool strategic_solver::has_quantifiers() const { /** \brief Return true if a tactic should be used when the incremental solver returns unknown. */ -bool strategic_solver::use_tactic_when_undef() const { +bool strategic_solver_core::use_tactic_when_undef() const { switch (m_inc_unknown_behavior) { case IUB_RETURN_UNDEF: return false; case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); @@ -79,7 +79,7 @@ bool strategic_solver::use_tactic_when_undef() const { } } -void strategic_solver::set_inc_solver(solver * s) { +void strategic_solver_core::set_inc_solver(solver * s) { SASSERT(m_inc_solver == 0); SASSERT(m_num_scopes == 0); m_inc_solver = s; @@ -87,7 +87,7 @@ void strategic_solver::set_inc_solver(solver * s) { m_inc_solver->set_progress_callback(m_callback); } -void strategic_solver::updt_params(params_ref const & p) { +void strategic_solver_core::updt_params(params_ref const & p) { if (m_inc_solver) m_inc_solver->updt_params(p); if (m_fparams) @@ -95,7 +95,7 @@ void strategic_solver::updt_params(params_ref const & p) { } -void strategic_solver::collect_param_descrs(param_descrs & r) { +void strategic_solver_core::collect_param_descrs(param_descrs & r) { if (m_inc_solver) m_inc_solver->collect_param_descrs(r); } @@ -105,7 +105,7 @@ void strategic_solver::collect_param_descrs(param_descrs & r) { timeout == UINT_MAX means infinite After the timeout a strategy is used. */ -void strategic_solver::set_inc_solver_timeout(unsigned timeout) { +void strategic_solver_core::set_inc_solver_timeout(unsigned timeout) { m_inc_solver_timeout = timeout; } @@ -113,14 +113,14 @@ void strategic_solver::set_inc_solver_timeout(unsigned timeout) { \brief Set the default tactic factory. It is used if there is no tactic for a given logic. */ -void strategic_solver::set_default_tactic(tactic_factory * fct) { +void strategic_solver_core::set_default_tactic(tactic_factory * fct) { m_default_fct = fct; } /** \brief Set a tactic factory for a given logic. */ -void strategic_solver::set_tactic_for(symbol const & logic, tactic_factory * fct) { +void strategic_solver_core::set_tactic_for(symbol const & logic, tactic_factory * fct) { tactic_factory * old_fct; if (m_logic2fct.find(logic, old_fct)) { dealloc(old_fct); @@ -128,7 +128,7 @@ void strategic_solver::set_tactic_for(symbol const & logic, tactic_factory * fct m_logic2fct.insert(logic, fct); } -void strategic_solver::init(ast_manager & m, symbol const & logic) { +void strategic_solver_core::init(ast_manager & m, symbol const & logic) { m_manager = &m; m_logic = logic; if (m_inc_mode) { @@ -138,7 +138,7 @@ void strategic_solver::init(ast_manager & m, symbol const & logic) { } // delayed inc solver initialization -void strategic_solver::init_inc_solver() { +void strategic_solver_core::init_inc_solver() { if (m_inc_mode) return; // solver was already initialized if (!m_inc_solver) @@ -152,7 +152,7 @@ void strategic_solver::init_inc_solver() { } } -void strategic_solver::collect_statistics(statistics & st) const { +void strategic_solver_core::collect_statistics(statistics & st) const { if (m_use_inc_solver_results) { SASSERT(m_inc_solver); m_inc_solver->collect_statistics(st); @@ -165,7 +165,7 @@ void strategic_solver::collect_statistics(statistics & st) const { } } -void strategic_solver::reset() { +void strategic_solver_core::reset() { m_logic = symbol::null; m_inc_mode = false; m_check_sat_executed = false; @@ -176,7 +176,7 @@ void strategic_solver::reset() { reset_results(); } -void strategic_solver::reset_results() { +void strategic_solver_core::reset_results() { m_use_inc_solver_results = false; m_model = 0; if (m_proof) { @@ -187,7 +187,7 @@ void strategic_solver::reset_results() { m_stats.reset(); } -void strategic_solver::assert_expr(expr * t) { +void strategic_solver_core::assert_expr(expr * t) { if (m_check_sat_executed && !m_inc_mode) { // a check sat was already executed --> switch to incremental mode init_inc_solver(); @@ -199,14 +199,14 @@ void strategic_solver::assert_expr(expr * t) { } } -void strategic_solver::push() { +void strategic_solver_core::push() { DEBUG_CODE(m_num_scopes++;); init_inc_solver(); if (m_inc_solver) m_inc_solver->push(); } -void strategic_solver::pop(unsigned n) { +void strategic_solver_core::pop(unsigned n) { DEBUG_CODE({ SASSERT(n <= m_num_scopes); m_num_scopes -= n; @@ -216,7 +216,7 @@ void strategic_solver::pop(unsigned n) { m_inc_solver->pop(n); } -unsigned strategic_solver::get_scope_level() const { +unsigned strategic_solver_core::get_scope_level() const { if (m_inc_solver) return m_inc_solver->get_scope_level(); else @@ -233,10 +233,10 @@ struct aux_timeout_eh : public event_handler { } }; -struct strategic_solver::mk_tactic { - strategic_solver * m_solver; +struct strategic_solver_core::mk_tactic { + strategic_solver_core * m_solver; - mk_tactic(strategic_solver * s, tactic_factory * f):m_solver(s) { + mk_tactic(strategic_solver_core * s, tactic_factory * f):m_solver(s) { ast_manager & m = s->m(); params_ref p; front_end_params2params(*s->m_fparams, p); @@ -259,14 +259,14 @@ struct strategic_solver::mk_tactic { } }; -tactic_factory * strategic_solver::get_tactic_factory() const { +tactic_factory * strategic_solver_core::get_tactic_factory() const { tactic_factory * f = 0; if (m_logic2fct.find(m_logic, f)) return f; return m_default_fct.get(); } -lbool strategic_solver::check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions) { +lbool strategic_solver_core::check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions) { if (!m_inc_solver) { IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver was not installed, returning unknown...\n";); m_use_inc_solver_results = false; @@ -278,7 +278,7 @@ lbool strategic_solver::check_sat_with_assumptions(unsigned num_assumptions, exp return m_inc_solver->check_sat(num_assumptions, assumptions); } -lbool strategic_solver::check_sat(unsigned num_assumptions, expr * const * assumptions) { +lbool strategic_solver_core::check_sat(unsigned num_assumptions, expr * const * assumptions) { reset_results(); m_check_sat_executed = true; if (num_assumptions > 0 || // assumptions were provided @@ -351,7 +351,7 @@ lbool strategic_solver::check_sat(unsigned num_assumptions, expr * const * assum return r; } -void strategic_solver::set_cancel(bool f) { +void strategic_solver_core::set_cancel(bool f) { if (m_inc_solver) m_inc_solver->set_cancel(f); #pragma omp critical (strategic_solver) @@ -361,14 +361,14 @@ void strategic_solver::set_cancel(bool f) { } } -void strategic_solver::get_unsat_core(ptr_vector & r) { +void strategic_solver_core::get_unsat_core(ptr_vector & r) { if (m_use_inc_solver_results) { SASSERT(m_inc_solver); m_inc_solver->get_unsat_core(r); } } -void strategic_solver::get_model(model_ref & m) { +void strategic_solver_core::get_model(model_ref & m) { if (m_use_inc_solver_results) { SASSERT(m_inc_solver); m_inc_solver->get_model(m); @@ -378,7 +378,7 @@ void strategic_solver::get_model(model_ref & m) { } } -proof * strategic_solver::get_proof() { +proof * strategic_solver_core::get_proof() { if (m_use_inc_solver_results) { SASSERT(m_inc_solver); return m_inc_solver->get_proof(); @@ -388,7 +388,7 @@ proof * strategic_solver::get_proof() { } } -std::string strategic_solver::reason_unknown() const { +std::string strategic_solver_core::reason_unknown() const { if (m_use_inc_solver_results) { SASSERT(m_inc_solver); return m_inc_solver->reason_unknown(); @@ -396,20 +396,20 @@ std::string strategic_solver::reason_unknown() const { return m_reason_unknown; } -void strategic_solver::get_labels(svector & r) { +void strategic_solver_core::get_labels(svector & r) { if (m_use_inc_solver_results) { SASSERT(m_inc_solver); m_inc_solver->get_labels(r); } } -void strategic_solver::set_progress_callback(progress_callback * callback) { +void strategic_solver_core::set_progress_callback(progress_callback * callback) { m_callback = callback; if (m_inc_solver) m_inc_solver->set_progress_callback(callback); } -void strategic_solver::display(std::ostream & out) const { +void strategic_solver_core::display(std::ostream & out) const { if (m_manager) { unsigned num = get_num_assertions(); out << "(solver"; @@ -423,62 +423,50 @@ void strategic_solver::display(std::ostream & out) const { } } -strategic_solver_cmd::strategic_solver_cmd(cmd_context & ctx): - m_ctx(ctx) { + +strategic_solver::ctx::ctx(ast_manager & m):m_assertions(m) { } -unsigned strategic_solver_cmd::get_num_assertions() const { - return static_cast(m_ctx.end_assertions() - m_ctx.begin_assertions()); -} - -expr * strategic_solver_cmd::get_assertion(unsigned idx) const { - SASSERT(idx < get_num_assertions()); - return m_ctx.begin_assertions()[idx]; -} - -strategic_solver_api::ctx::ctx(ast_manager & m):m_assertions(m) { -} - -void strategic_solver_api::init(ast_manager & m, symbol const & logic) { - strategic_solver::init(m, logic); +void strategic_solver::init(ast_manager & m, symbol const & logic) { + strategic_solver_core::init(m, logic); m_ctx = alloc(ctx, m); } -unsigned strategic_solver_api::get_num_assertions() const { +unsigned strategic_solver::get_num_assertions() const { if (m_ctx == 0) return 0; return m_ctx->m_assertions.size(); } -expr * strategic_solver_api::get_assertion(unsigned idx) const { +expr * strategic_solver::get_assertion(unsigned idx) const { SASSERT(m_ctx); return m_ctx->m_assertions.get(idx); } -void strategic_solver_api::assert_expr(expr * t) { +void strategic_solver::assert_expr(expr * t) { SASSERT(m_ctx); - strategic_solver::assert_expr(t); + strategic_solver_core::assert_expr(t); m_ctx->m_assertions.push_back(t); } -void strategic_solver_api::push() { +void strategic_solver::push() { SASSERT(m_ctx); - strategic_solver::push(); + strategic_solver_core::push(); m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); } -void strategic_solver_api::pop(unsigned n) { +void strategic_solver::pop(unsigned n) { SASSERT(m_ctx); unsigned new_lvl = m_ctx->m_scopes.size() - n; unsigned old_sz = m_ctx->m_scopes[new_lvl]; m_ctx->m_assertions.shrink(old_sz); m_ctx->m_scopes.shrink(new_lvl); - strategic_solver::pop(n); + strategic_solver_core::pop(n); } -void strategic_solver_api::reset() { +void strategic_solver::reset() { m_ctx = 0; - strategic_solver::reset(); + strategic_solver_core::reset(); } diff --git a/src/cmd_context/strategic_solver.h b/src/solver/strategic_solver.h similarity index 80% rename from src/cmd_context/strategic_solver.h rename to src/solver/strategic_solver.h index b145da5f7..4d4a47388 100644 --- a/src/cmd_context/strategic_solver.h +++ b/src/solver/strategic_solver.h @@ -25,7 +25,28 @@ Notes: class progress_callback; struct front_end_params; -class strategic_solver : public solver { +/** + \brief Implementation of the solver API that supports: + - a different tactic for each logic + - a general purpose tactic + - a default incremental solver + + The strategic solver has two modes: + - non-incremental + - incremental + In non-incremental mode, tactics are used. + In incremental model, the incremental (general purpose) solver is used. + + A timeout for the incremental solver can be specified. + If the timeout is reached, then the strategic_solver tries to solve the problem using tactics. + + The strategic_solver switches to incremental when: + - push is used + - assertions are peformed after a check_sat + It goes back to non_incremental mode when: + - reset is invoked. +*/ +class strategic_solver_core : public solver { public: // Behavior when the incremental solver returns unknown. enum inc_unknown_behavior { @@ -76,8 +97,8 @@ private: bool use_tactic_when_undef() const; public: - strategic_solver(); - ~strategic_solver(); + strategic_solver_core(); + ~strategic_solver_core(); ast_manager & m() const { SASSERT(m_manager); return *m_manager; } @@ -119,17 +140,10 @@ public: virtual void set_progress_callback(progress_callback * callback); }; -// Specialization for the SMT 2.0 command language frontend -class strategic_solver_cmd : public strategic_solver { - cmd_context & m_ctx; -public: - strategic_solver_cmd(cmd_context & ctx); - virtual unsigned get_num_assertions() const; - virtual expr * get_assertion(unsigned idx) const; -}; - -// Specialization for Z3 API -class strategic_solver_api : public strategic_solver { +/** + \brief Default implementation of strategic_solver_core +*/ +class strategic_solver : public strategic_solver_core { struct ctx { expr_ref_vector m_assertions; unsigned_vector m_scopes; @@ -137,7 +151,7 @@ class strategic_solver_api : public strategic_solver { }; scoped_ptr m_ctx; public: - strategic_solver_api() {} + strategic_solver() {} virtual void init(ast_manager & m, symbol const & logic); diff --git a/src/cmd_context/tactic2solver.cpp b/src/solver/tactic2solver.cpp similarity index 72% rename from src/cmd_context/tactic2solver.cpp rename to src/solver/tactic2solver.cpp index 6b67faae1..0747c7c9d 100644 --- a/src/cmd_context/tactic2solver.cpp +++ b/src/solver/tactic2solver.cpp @@ -23,26 +23,26 @@ Notes: #include"params2front_end_params.h" #include"ast_smt2_pp.h" -tactic2solver::ctx::ctx(ast_manager & m, symbol const & logic): +tactic2solver_core::ctx::ctx(ast_manager & m, symbol const & logic): m_logic(logic), m_assertions(m) { } -tactic2solver::~tactic2solver() { +tactic2solver_core::~tactic2solver_core() { } -void tactic2solver::init(ast_manager & m, symbol const & logic) { +void tactic2solver_core::init(ast_manager & m, symbol const & logic) { m_ctx = alloc(ctx, m, logic); } -void tactic2solver::updt_params(params_ref const & p) { +void tactic2solver_core::updt_params(params_ref const & p) { m_params = p; } -void tactic2solver::collect_param_descrs(param_descrs & r) { +void tactic2solver_core::collect_param_descrs(param_descrs & r) { if (m_ctx) { if (!m_ctx->m_tactic) { - #pragma omp critical (tactic2solver) + #pragma omp critical (tactic2solver_core) { m_ctx->m_tactic = get_tactic(m_ctx->m(), m_params); } @@ -51,7 +51,7 @@ void tactic2solver::collect_param_descrs(param_descrs & r) { m_ctx->m_tactic->collect_param_descrs(r); } - #pragma omp critical (tactic2solver) + #pragma omp critical (tactic2solver_core) { m_ctx->m_tactic = 0; } @@ -62,26 +62,26 @@ void tactic2solver::collect_param_descrs(param_descrs & r) { } } -void tactic2solver::reset() { +void tactic2solver_core::reset() { SASSERT(m_ctx); m_ctx->m_assertions.reset(); m_ctx->m_scopes.reset(); m_ctx->m_result = 0; } -void tactic2solver::assert_expr(expr * t) { +void tactic2solver_core::assert_expr(expr * t) { SASSERT(m_ctx); m_ctx->m_assertions.push_back(t); m_ctx->m_result = 0; } -void tactic2solver::push() { +void tactic2solver_core::push() { SASSERT(m_ctx); m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); m_ctx->m_result = 0; } -void tactic2solver::pop(unsigned n) { +void tactic2solver_core::pop(unsigned n) { SASSERT(m_ctx); unsigned new_lvl = m_ctx->m_scopes.size() - n; unsigned old_sz = m_ctx->m_scopes[new_lvl]; @@ -90,18 +90,18 @@ void tactic2solver::pop(unsigned n) { m_ctx->m_result = 0; } -unsigned tactic2solver::get_scope_level() const { +unsigned tactic2solver_core::get_scope_level() const { SASSERT(m_ctx); return m_ctx->m_scopes.size(); } -lbool tactic2solver::check_sat(unsigned num_assumptions, expr * const * assumptions) { +lbool tactic2solver_core::check_sat(unsigned num_assumptions, expr * const * assumptions) { SASSERT(m_ctx); ast_manager & m = m_ctx->m(); params_ref p = m_params; if (m_fparams) front_end_params2params(*m_fparams, p); - #pragma omp critical (tactic2solver) + #pragma omp critical (tactic2solver_core) { m_ctx->m_tactic = get_tactic(m, p); if (m_ctx->m_tactic) { @@ -147,7 +147,7 @@ lbool tactic2solver::check_sat(unsigned num_assumptions, expr * const * assumpti throw ex; } catch (z3_exception & ex) { - TRACE("tactic2solver", tout << "exception: " << ex.msg() << "\n";); + TRACE("tactic2solver_core", tout << "exception: " << ex.msg() << "\n";); result.set_status(l_undef); result.m_unknown = ex.msg(); } @@ -160,63 +160,63 @@ lbool tactic2solver::check_sat(unsigned num_assumptions, expr * const * assumpti result.m_core.append(core_elems.size(), core_elems.c_ptr()); } - #pragma omp critical (tactic2solver) + #pragma omp critical (tactic2solver_core) { m_ctx->m_tactic = 0; } return result.status(); } -void tactic2solver::set_cancel(bool f) { - #pragma omp critical (tactic2solver) +void tactic2solver_core::set_cancel(bool f) { + #pragma omp critical (tactic2solver_core) { if (m_ctx && m_ctx->m_tactic) m_ctx->m_tactic->set_cancel(f); } } -void tactic2solver::collect_statistics(statistics & st) const { +void tactic2solver_core::collect_statistics(statistics & st) const { if (m_ctx->m_result.get()) m_ctx->m_result->collect_statistics(st); } -void tactic2solver::get_unsat_core(ptr_vector & r) { +void tactic2solver_core::get_unsat_core(ptr_vector & r) { if (m_ctx->m_result.get()) m_ctx->m_result->get_unsat_core(r); } -void tactic2solver::get_model(model_ref & m) { +void tactic2solver_core::get_model(model_ref & m) { if (m_ctx->m_result.get()) m_ctx->m_result->get_model(m); } -proof * tactic2solver::get_proof() { +proof * tactic2solver_core::get_proof() { if (m_ctx->m_result.get()) return m_ctx->m_result->get_proof(); else return 0; } -std::string tactic2solver::reason_unknown() const { +std::string tactic2solver_core::reason_unknown() const { if (m_ctx->m_result.get()) return m_ctx->m_result->reason_unknown(); else return std::string("unknown"); } -unsigned tactic2solver::get_num_assertions() const { +unsigned tactic2solver_core::get_num_assertions() const { if (m_ctx) return m_ctx->m_assertions.size(); else return 0; } -expr * tactic2solver::get_assertion(unsigned idx) const { +expr * tactic2solver_core::get_assertion(unsigned idx) const { SASSERT(m_ctx); return m_ctx->m_assertions.get(idx); } -void tactic2solver::display(std::ostream & out) const { +void tactic2solver_core::display(std::ostream & out) const { if (m_ctx) { ast_manager & m = m_ctx->m_assertions.m(); unsigned num = m_ctx->m_assertions.size(); @@ -231,19 +231,28 @@ void tactic2solver::display(std::ostream & out) const { } } -void tactic2solver_cmd::set_tactic(tactic_factory * f) { - m_tactic_factory = f; +tactic2solver::tactic2solver(tactic * t): + m_tactic(t) { } -tactic * tactic2solver_cmd::get_tactic(ast_manager & m, params_ref const & p) { - if (m_tactic_factory == 0) - return 0; - return (*m_tactic_factory)(m, p); +tactic2solver::~tactic2solver() { } -tactic * tactic2solver_api::get_tactic(ast_manager & m, params_ref const & p) { +tactic * tactic2solver::get_tactic(ast_manager & m, params_ref const & p) { m_tactic->cleanup(); m_tactic->updt_params(p); return m_tactic.get(); } +tactic_factory2solver::~tactic_factory2solver() { +} + +void tactic_factory2solver::set_tactic(tactic_factory * f) { + m_tactic_factory = f; +} + +tactic * tactic_factory2solver::get_tactic(ast_manager & m, params_ref const & p) { + if (m_tactic_factory == 0) + return 0; + return (*m_tactic_factory)(m, p); +} diff --git a/src/cmd_context/tactic2solver.h b/src/solver/tactic2solver.h similarity index 82% rename from src/cmd_context/tactic2solver.h rename to src/solver/tactic2solver.h index 954dda041..fe92f3a7d 100644 --- a/src/cmd_context/tactic2solver.h +++ b/src/solver/tactic2solver.h @@ -25,7 +25,14 @@ Notes: #include"solver.h" #include"tactic.h" -class tactic2solver : public solver { +/** + \brief Simulates the incremental solver interface using a tactic. + + Every query will be solved from scratch. So, this is not a good + option for applications trying to solve many easy queries that a + similar to each other. +*/ +class tactic2solver_core : public solver { struct ctx { symbol m_logic; expr_ref_vector m_assertions; @@ -42,8 +49,8 @@ class tactic2solver : public solver { bool m_produce_proofs; bool m_produce_unsat_cores; public: - tactic2solver():m_ctx(0), m_fparams(0), m_produce_models(false), m_produce_proofs(false), m_produce_unsat_cores(false) {} - virtual ~tactic2solver(); + tactic2solver_core():m_ctx(0), m_fparams(0), m_produce_models(false), m_produce_proofs(false), m_produce_unsat_cores(false) {} + virtual ~tactic2solver_core(); virtual tactic * get_tactic(ast_manager & m, params_ref const & p) = 0; @@ -81,13 +88,19 @@ public: virtual void display(std::ostream & out) const; }; -/** - \brief Specialization for cmd_context -*/ -class tactic2solver_cmd : public tactic2solver { +class tactic2solver : public tactic2solver_core { + tactic_ref m_tactic; +public: + tactic2solver(tactic * t); + virtual ~tactic2solver(); + virtual tactic * get_tactic(ast_manager & m, params_ref const & p); +}; + + +class tactic_factory2solver : public tactic2solver_core { scoped_ptr m_tactic_factory; public: - virtual ~tactic2solver_cmd() {} + virtual ~tactic_factory2solver(); /** \brief Set tactic that will be used to process the satisfiability queries. */ @@ -95,16 +108,5 @@ public: virtual tactic * get_tactic(ast_manager & m, params_ref const & p); }; -/** - \brief Specialization for API -*/ -class tactic2solver_api : public tactic2solver { - tactic_ref m_tactic; -public: - tactic2solver_api(tactic * t):m_tactic(t) {} - virtual ~tactic2solver_api() {} - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; - #endif diff --git a/src/tactic/arith/dead/lu.cpp b/src/tactic/arith/dead/lu.cpp deleted file mode 100644 index b2cf0fd88..000000000 --- a/src/tactic/arith/dead/lu.cpp +++ /dev/null @@ -1,1792 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - lu.cpp - -Abstract: - - Simple LU factorization module based on the paper: - - "Maintaining LU factors of a General Sparse Matrix" - P. E. Gill, W. Murray, M. Saunders, M. Wright - -Author: - - Leonardo de Moura (leonardo) 2011-06-09 - -Revision History: - ---*/ -#include"lu.h" - -template -void lu::todo::init(unsigned capacity) { - m_elem2len.reset(); - m_elem2pos.reset(); - m_elems_per_len.reset(); - m_elem2len.resize(capacity, UINT_MAX); - m_elem2pos.resize(capacity, UINT_MAX); - m_elems_per_len.resize(capacity+1); - m_size = 0; -} - -template -void lu::todo::display(std::ostream & out) const { - vector::const_iterator it = m_elems_per_len.begin(); - vector::const_iterator end = m_elems_per_len.end(); - for (unsigned idx = 0; it != end; ++it, ++idx) { - unsigned_vector const & v = *it; - if (!v.empty()) { - out << idx << ": ["; - unsigned_vector::const_iterator it2 = v.begin(); - unsigned_vector::const_iterator end2 = v.end(); - for (bool first = true; it2 != end2; ++it2) { - if (first) first = false; else out << " "; - out << *it2; - } - out << "] "; - } - } -} - -template -void lu::todo::updt_len(unsigned elem, unsigned len) { - erase(elem); - m_elem2len[elem] = len; - unsigned pos = m_elems_per_len[len].size(); - m_elems_per_len[len].push_back(elem); - m_elem2pos[elem] = pos; - m_size++; -} - -template -void lu::todo::erase(unsigned elem) { - if (!contains(elem)) - return; - unsigned len = m_elem2len[elem]; - unsigned pos = m_elem2pos[elem]; - unsigned_vector & v = m_elems_per_len[len]; - SASSERT(v[pos] == elem); - if (pos != v.size() - 1) { - unsigned last_elem = v.back(); - m_elem2pos[last_elem] = pos; - v[pos] = last_elem; - } - v.pop_back(); - m_elem2pos[elem] = UINT_MAX; - m_size--; -} - -template -void lu::todo::iterator::find_next() { - unsigned sz = m_todo.m_elems_per_len.size(); - while (m_i < sz) { - if (m_j < m_todo.m_elems_per_len[m_i].size()) - return; - m_j = 0; - m_i++; - } -} - -// ----------------------- -// -// Main -// -// ----------------------- -template -lu::lu(manager & m, params_ref const & p): - m_manager(m), - m_tmp_xU_vector(m, 0), - m_tmp_replace_column_vector(m, 0), - m_tmp_vector(m, 0), - m_tmp_row(m, 0), - m_tmp_col(m, 0) { - m_sz = 0; - CASSERT("lu", check_invariant()); - ini = false; - updt_params(p); -} - -template -lu::~lu() { - m().del(m_mu); - - // temporary values - m().del(tol); - m().del(C_max); - m().del(A_ij); - m().del(A_best); - m().del(A_aux); - m().del(tmp); - m().del(mu_best); - m().del(mu_1); - - del_nums(L.A); - del_nums(U.A); - del_nums(T.A); -} - -template -void lu::updt_params(params_ref const & p) { - unsigned mu = p.get_uint(":lu-mu", 100); // it was 10... - m().set(m_mu, mu); - m_selection_cutoff = p.get_uint(":lu-selection-cutoff", 10); -} - -/** - \brief Delete the numerals in the given vector, and reset it. -*/ -template -void lu::del_nums(numeral_vector & nums) { - typename numeral_vector::iterator it = nums.begin(); - typename numeral_vector::iterator end = nums.end(); - for (; it != end; ++it) { - m().del(*it); - } - nums.reset(); -} - -template -void lu::reset() { - m_sz = 0; - - P.reset(m_sz); - Q.reset(m_sz); - - del_nums(L.A); - L.indc.reset(); - L.indr.reset(); - - del_nums(U.A); - U.indr.reset(); - U.begr.reset(); - U.endr.reset(); - U.num_entries = 0; - - T.indr.reset(); - T.begr.reset(); - T.endr.reset(); - del_nums(T.A); - T.indc.reset(); - T.begc.reset(); - T.endc.reset(); - T.num_entries = 0; - - locw.reset(); -} - -// ----------------------- -// -// Initialization -// -// ----------------------- -#define INI_COL_SZ 16 -#define INV_FILLIN_FACTOR 5 -#define COMPRESSION_FACTOR 4 - -template -inline unsigned lu::fillin_for(unsigned sz) { - return (sz / INV_FILLIN_FACTOR) + 1; -} - -template -void lu::init(unsigned size) { - reset(); - - m_num_replacements = 0; - - m_sz = size; - - m_todo_rows.init(size); - m_todo_cols.init(size); - m_enabled_rows.reset(); - m_enabled_cols.reset(); - m_enabled_rows.resize(m_sz, true); - m_enabled_cols.resize(m_sz, true); - - P.reset(m_sz); - Q.reset(m_sz); - - locw.reset(); // force it to be reinitialized, it may contain unintended content if LU was interrupted due to floating point imprecision. - locw.resize(m_sz, UINT_MAX); - - ini = size > 0; - ini_irow = 0; - T.begr.push_back(0); - T.endr.push_back(0); - T.num_entries = 0; - - SASSERT(T.begc.empty()); - SASSERT(T.endc.empty()); - - T.A.resize(m_sz * INI_COL_SZ); - T.indc.resize(m_sz * INI_COL_SZ, UINT_MAX); - unsigned locc = 0; - for (unsigned i = 0; i < m_sz; i++) { - T.begc.push_back(locc); - T.endc.push_back(locc); - locc += INI_COL_SZ; - } - - SASSERT(T.begc.size() == m_sz); - SASSERT(T.endc.size() == m_sz); - - m_tmp_vector.reset(m_sz); - m_tmp_col.reset(m_sz); - m_tmp_xU_vector.reset(m_sz); - m_tmp_replace_column_vector.reset(m_sz); -} - -template -void lu::add_entry(numeral const & a, unsigned x) { - SASSERT(T.endc[x] >= T.begc[x]); - SASSERT(T.endc[x] - T.begc[x] + 1 <= m_sz); // has space for another element in column x - SASSERT(ini); - SASSERT(x < m_sz); - TRACE("lu", tout << "add_entry(" << m().to_string(a) << ", " << x << ")\n";); - if (T.endc[x] == T.indc.size()) { - // expand last column - T.A.push_back(numeral()); - m().set(T.A.back(), a); - T.indc.push_back(ini_irow); - T.endc[x]++; - SASSERT(T.endc[x] == T.indc.size()); - } - else { - if (T.indc[T.endc[x]] != UINT_MAX) { - TRACE("lu", tout << "moving column to the end: " << x << "\n";); - move_col_to_end(x); - } - SASSERT(T.indc[T.endc[x]] == UINT_MAX); - // use free space - unsigned pos = T.endc[x]; - m().set(T.A[pos], a); - T.indc[pos] = ini_irow; - T.endc[x]++; - } - T.indr.push_back(x); - T.endr.back()++; - T.num_entries++; - SASSERT(T.endc[x] >= T.begc[x]); - SASSERT(T.endc[x] - T.begc[x] <= m_sz); -} - -template -void lu::move_col_to_end(unsigned c) { - SASSERT(T.endc[c] >= T.begc[c]); - SASSERT(T.endc[c] - T.begc[c] <= m_sz); - unsigned begin = T.begc[c]; - unsigned end = T.endc[c]; - T.begc[c] = T.indc.size(); - T.endc[c] = T.begc[c] + end - begin; - for (unsigned j = begin; j < end; j++) { - T.A.push_back(numeral()); - m().swap(T.A.back(), T.A[j]); - unsigned r = T.indc[j]; - T.indc.push_back(r); - T.indc[j] = UINT_MAX; // mark as free - } - unsigned sz = end - begin; - unsigned fillin = fillin_for(sz); - for (unsigned i = 0; i < fillin; i++) { - T.indc.push_back(UINT_MAX); // leave space - T.A.push_back(numeral()); - } - SASSERT(T.endc[c] >= T.begc[c]); - SASSERT(T.endc[c] - T.begc[c] <= m_sz); -} - -template -void lu::move_row_to_end(unsigned r) { - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; - T.begr[r] = T.indr.size(); - T.endr[r] = T.begr[r] + end - begin; - for (unsigned j = begin; j < end; j++) { - unsigned c = T.indr[j]; - T.indr.push_back(c); - T.indr[j] = UINT_MAX; // mark as free - } - unsigned sz = end - begin; - unsigned fillin = fillin_for(sz); - for (unsigned i = 0; i < fillin; i++) - T.indr.push_back(UINT_MAX); -} - -template -void lu::end_row() { - TRACE("lu", tout << "end_row()\n";); - SASSERT(ini); - ini_irow++; - if (ini_irow == m_sz) { - // completed initialization - ini = false; - CASSERT("lu", check_T()); - } - else { - unsigned sz = T.endr.back() - T.begr.back(); - unsigned fillin = fillin_for(sz); - for (unsigned i = 0; i < fillin; i++) - T.indr.push_back(UINT_MAX); // leave space - T.begr.push_back(T.indr.size()); - T.endr.push_back(T.indr.size()); - } -} - -// ----------------------- -// -// Factorization -// -// ----------------------- - -// Initialize the todo vectors: todo_rows and todo_cols. -// The auxiliary vectors iplocr and iplocc are also initialized. -template -void lu::init_fact() { - for (unsigned i = 0; i < m_sz; i++) { - SASSERT(T.endr[i] >= T.begr[i]); - SASSERT(T.endc[i] >= T.begc[i]); - SASSERT(T.endr[i] - T.begr[i] <= m_sz); - SASSERT(T.endc[i] - T.begc[i] <= m_sz); - m_todo_rows.updt_len(i, T.endr[i] - T.begr[i]); - m_todo_cols.updt_len(i, T.endc[i] - T.begc[i]); - } - m_marked_rows.reset(); - m_marked_rows.resize(m_sz, false); -} - -template -bool lu::stability_test(unsigned rin, unsigned cin, bool improvingM) { - if (NM::precise()) { - if (improvingM) { - // must save coefficient of rin, cin in A_best - unsigned begin = T.begc[cin]; - unsigned end = T.endc[cin]; - for (unsigned j = begin; j < end; j++) { - unsigned r = T.indc[j]; - if (rin == r) { - m().set(A_best, T.A[j]); - break; - } - } - return true; - } - else { - return false; - } - } - // Stability test for imprecise numerals - // See section 5.3 of "Maintaining LU factors of a General Sparse Matrix" - m().set(C_max, 0); - m().set(tol, 0); - m().set(A_ij, 0); - bool C_max_init = false; - unsigned begin = T.begc[cin]; - unsigned end = T.endc[cin]; -#if 0 - static unsigned stability_test_counter = 0; - static unsigned stability_test_cost = 0; - stability_test_counter++; - stability_test_cost += end - begin; - if (stability_test_counter % 1000000 == 0) { - verbose_stream() << "[stability-test] cost: " << stability_test_cost << " num-calls: " << stability_test_counter - << " selection-cutoff: " << m_selection_cutoff << " sz: " << m_sz - << " avg-col-sz: " << stability_test_cost / stability_test_counter << "\n"; - } -#endif - for (unsigned j = begin; j < end; j++) { - unsigned r = T.indc[j]; - if (rin == r) { - m().set(A_ij, T.A[j]); - m().set(tol, A_ij); - m().abs(tol); - if (improvingM) { - // tol = |A_ij| / mu - m().mul(tol, m_mu, tol); - } - else { - // tol = |A_ij| / mu_best - m().mul(tol, mu_best, tol); - } - if (C_max_init && m().ge(C_max, tol)) { - TRACE("stability", tout << "failure 1. C_max: " << m().to_string(C_max) << ", tol: " << m().to_string(tol) - << ", A_ij: " << m().to_string(A_ij) << ", m_mu: " << m().to_string(m_mu) - << ", mu_best: " << m().to_string(mu_best) << ", improvingM: " << improvingM << "\n";); - return false; - } - continue; - } - if (!enabled_row(r)) - continue; - m().set(A_aux, T.A[j]); - m().abs(A_aux); - if (m().gt(A_aux, C_max)) { - m().set(C_max, A_aux); - C_max_init = true; - if (m().is_pos(tol)) { - // if tol was already set test, then reject if C_max >= tol - if (m().ge(C_max, tol)) { - TRACE("stability", tout << "failure 2. C_max: " << m().to_string(C_max) << ", tol: " << m().to_string(tol) - << ", A_ij: " << m().to_string(A_ij) << ", m_mu: " << m().to_string(m_mu) - << ", mu_best: " << m().to_string(mu_best) << "\n";); - return false; - } - } - } - } - - m().set(A_best, A_ij); - m().set(mu_best, C_max); - m().abs(A_ij); - m().div(mu_best, A_ij, mu_best); - CTRACE("stability", m().is_zero(mu_best), tout << "found: A_ij: " << m().to_string(A_ij) << " mu_best: " << m().to_string(mu_best) - << " C_max: " << m().to_string(C_max) << "\n";); - return true; -} - -/** - \brief Select the next pivot and store in (r_out, c_out) - The coefficient is stored in A_best. -*/ -template -void lu::select_pivot(unsigned & r_out, unsigned & c_out) { - unsigned M_best = UINT_MAX; - unsigned M2_best = UINT_MAX; - m().set(mu_best, 0); - - SASSERT(m_todo_rows.size() == m_todo_cols.size()); - TRACE("lu_todo", - tout << "rows: "; m_todo_rows.display(tout); tout << "\n"; - tout << "cols: "; m_todo_cols.display(tout); tout << "\n";); - - typename todo::iterator it(m_todo_rows); - unsigned counter = 0; - while (!it.at_end()) { - unsigned r = it.curr(); - it.next(); - counter++; - TRACE("lu_todo", tout << "row r: " << r << ", r_out: " << r_out << ", c_out: " << c_out << "\n";); - SASSERT(enabled_row(r)); - if (counter >= m_selection_cutoff && M_best != UINT_MAX) - break; - CTRACE("stability", counter > m_selection_cutoff, - tout << "counter: " << counter << " mu_best: " << m().to_string(mu_best) << " M_best: " << M_best << "\n";); - unsigned lenr = m_todo_rows.len(r); - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; -#if 0 - // ----------------------------------- - // enable this block of code to simulate singular matrix exception after a couple of pivoting steps... -#define NUM_STEPS_UNTIL_EXCEPTION 10 - static unsigned g_num_pivots = 0; - if (!m().precise()) { - g_num_pivots++; - if (g_num_pivots == NUM_STEPS_UNTIL_EXCEPTION) { - g_num_pivots = 0; - throw lu_exception("singular matrix"); - } - } - //------------------------------------ -#endif - if (lenr == 0) - throw lu_exception("singular matrix"); - for (unsigned j = begin; j < end; j++) { - unsigned c = T.indr[j]; - if (!enabled_col(c)) - continue; - unsigned lenc = m_todo_cols.len(c); - unsigned M = (lenc - 1) * (lenr - 1); - TRACE("lu_todo", tout << "c: " << c << ", M: " << M << ", M_best: " << M_best << "\n";); - if (M > M_best) - continue; - bool improving; - if (NM::precise()) - improving = M_best == UINT_MAX || M < M_best || (M == M_best && lenc < M2_best); - else - improving = M_best == UINT_MAX || M < M_best; - if (stability_test(r, c, improving)) { - M_best = M; - M2_best = lenc; - r_out = r; - c_out = c; - CTRACE("stability", !m().precise(), tout << "mu_best: " << m().to_string(mu_best) << "\n";); - } - else { - CTRACE("stability", !m().precise(), - tout << "failed stability, improving: " << improving << " mu_best: " << m().to_string(mu_best) << "\n";); - } - } - } - - if (M_best == UINT_MAX) - throw lu_exception("failed stability test"); - - typename todo::iterator it2(m_todo_cols); - counter = 0; - while (!it2.at_end()) { - unsigned c = it2.curr(); - it2.next(); - counter++; - TRACE("lu_todo", tout << "col c: " << c << ", r_out: " << r_out << ", c_out: " << c_out << "\n";); - SASSERT(enabled_col(c)); - if (counter >= m_selection_cutoff) - break; - unsigned lenc = m_todo_cols.len(c); - unsigned begin = T.begc[c]; - unsigned end = T.endc[c]; - for (unsigned j = begin; j < end; j++) { - unsigned r = T.indc[j]; - if (!enabled_row(r)) - continue; - unsigned lenr = m_todo_rows.len(r); - unsigned M = (lenc - 1) * (lenr - 1); - TRACE("lu_todo", tout << "r: " << r << ", M: " << M << ", M_best: " << M_best << "\n";); - if (M > M_best) - continue; - bool improving; - if (NM::precise()) - improving = M < M_best || (M == M_best && lenc < M2_best); - else - improving = M < M_best; - if (stability_test(r, c, M < M_best)) { - M_best = M; - M2_best = lenc; - r_out = r; - c_out = c; - } - } - } -} - -/** - \brief For debugging: checks whether all position in locw are UINT_MAX. -*/ -template -bool lu::check_locw() const { - for (unsigned i = 0; i < m_sz; i++) { - SASSERT(locw[i] == UINT_MAX); - } - return true; -} - -template -inline void lu::dec_lenr(unsigned r) { - SASSERT(m_todo_rows.len(r) > 0); - SASSERT(enabled_row(r)); - m_todo_rows.updt_len(r, m_todo_rows.len(r) - 1); -} - -template -inline void lu::inc_lenr(unsigned r) { - SASSERT(enabled_row(r)); - m_todo_rows.updt_len(r, m_todo_rows.len(r) + 1); -} - -template -inline void lu::dec_lenc(unsigned c) { - SASSERT(m_todo_cols.len(c) > 0); - SASSERT(enabled_col(c)); - m_todo_cols.updt_len(c, m_todo_cols.len(c) - 1); -} - -template -inline void lu::inc_lenc(unsigned c) { - SASSERT(enabled_col(c)); - m_todo_cols.updt_len(c, m_todo_cols.len(c) + 1); -} - -/** - \brief Remove the disabled columns from the row r. -*/ -template -void lu::del_disabled_cols(unsigned r) { - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; - unsigned j = begin; - for (unsigned i = begin; i < end; i++) { - unsigned c = T.indr[i]; - if (!enabled_col(c)) - continue; - T.indr[j] = c; - j++; - } - T.endr[r] = j; - for (; j < end; j++) - T.indr[j] = UINT_MAX; -} - -/** - \brief Remove colum c from row r. - It also removes any disabled column. -*/ -template -void lu::del_row_entry(unsigned r, unsigned c) { - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; - TRACE("del_row_entry", tout << "del_row_entry, r: " << r << ", c: " << c << ", begin: " << begin << ", end: " << end << "\n";); - unsigned j = begin; - for (unsigned i = begin; i < end; i++) { - unsigned c_prime = T.indr[i]; - if (c_prime == c || !enabled_col(c_prime)) - continue; - T.indr[j] = c_prime; - j++; - } - SASSERT(j < end); - T.endr[r] = j; - for (; j < end; j++) - T.indr[j] = UINT_MAX; - TRACE("del_row_entry", tout << "after del_row_entry, begin: " << T.begr[r] << ", end: " << T.endr[r] << "\n";); -} - -/** - \brief Compress T rows -*/ -template -void lu::compress_rows() { - unsigned_vector new_indr; - for (unsigned r = 0; r < m_sz; r++) { - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; - T.begr[r] = new_indr.size(); - for (unsigned i = begin; i < end; i++) { - new_indr.push_back(T.indr[i]); - } - T.endr[r] = new_indr.size(); - unsigned fillin = T.endr[r] - T.begr[r]; - for (unsigned i = 0; i < fillin; i++) - T.indr.push_back(UINT_MAX); - } - T.indr.swap(new_indr); - TRACE("lu_bug", tout << "compressed rows\n";); - CASSERT("lu", check_T()); -} - -/** - \brief Compress T columns -*/ -template -void lu::compress_columns() { - CASSERT("lu", check_T()); - unsigned_vector new_indc; - numeral_vector new_A; - for (unsigned c = 0; c < m_sz; c++) { - unsigned begin = T.begc[c]; - unsigned end = T.endc[c]; - T.begc[c] = new_indc.size(); - for (unsigned i = begin; i < end; i++) { - new_A.push_back(numeral()); - m().swap(new_A.back(), T.A[i]); - new_indc.push_back(T.indc[i]); - } - T.endc[c] = new_indc.size(); - unsigned fillin = T.endc[c] - T.begc[c]; - for (unsigned i = 0; i < fillin; i++) - T.indc.push_back(UINT_MAX); - } - T.indc.swap(new_indc); - T.A.swap(new_A); - // I don't need to delete the elements of new_A, since I did not use m().set, but m().swap. - TRACE("lu_bug", tout << "compressed columns\n";); - CASSERT("lu", check_T()); -} - -template -void lu::compress_if_needed() { - if (T.indr.size() > COMPRESSION_FACTOR * T.num_entries) - compress_rows(); - if (T.indc.size() > COMPRESSION_FACTOR * T.num_entries) - compress_columns(); - CASSERT("lu", check_lenr() && check_lenc()); -} - -template -void lu::add_row_entry(unsigned r, unsigned c) { - if (T.endr[r] == T.indr.size()) { - // expand last row - T.indr.push_back(c); - T.endr[r]++; - SASSERT(T.endr[r] == T.indr.size()); - } - else { - if (T.indr[T.endr[r]] != UINT_MAX) - move_row_to_end(r); - // use free space - SASSERT(T.indr[T.endr[r]] == UINT_MAX); - T.indr[T.endr[r]] = c; - T.endr[r]++; - } -} - -template -void lu::add_col_entry(unsigned r, unsigned c, numeral const & a) { - if (T.endc[c] == T.indc.size()) { - // expand last column - T.A.push_back(numeral()); - m().set(T.A.back(), a); - T.indc.push_back(r); - T.endc[c]++; - SASSERT(T.endc[c] == T.indc.size()); - } - else { - if (T.indc[T.endc[c]] != UINT_MAX) - move_col_to_end(c); - SASSERT(T.indc[T.endc[c]] == UINT_MAX); - // use free space - unsigned pos = T.endc[c]; - m().set(T.A[pos], a); - T.indc[pos] = r; - T.endc[c]++; - } -} - -template -void lu::process_pivot_core(unsigned r, unsigned c) { - SASSERT(m_todo_cols.len(c) > 0); - if (m_todo_cols.len(c) == 1) { - // simple case... just update lenc for every c_prime != c in r. - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; - for (unsigned k = begin; k < end; k++) { - unsigned c_prime = T.indr[k]; - if (c_prime != c) { - SASSERT(enabled_col(c_prime)); - dec_lenc(c_prime); - } - } - return; - } - -#ifdef Z3DEBUG - unsigned num_set_locw = 0; -#endif - // Compute multipliers and update L - m_toadd_rows.reset(); - unsigned begin = T.begc[c]; - unsigned end = T.endc[c]; - for (unsigned k = begin; k < end; k++) { - unsigned r_prime = T.indc[k]; - if (r_prime == r) { - SASSERT(m().eq(A_best, T.A[k])); - continue; - } - - if (!enabled_row(r_prime)) - continue; - - // mu_1 = - A_(r_prime, c) / A_(r,c) - m().set(mu_1, T.A[k]); - m().div(mu_1, A_best, mu_1); - // hack: mu_1 contains A_(r_prime, c) / A_(r,c) at this point - // since we have to store -mu_1 in L - // store (- mu_1, r_prime, r) in L - L.A.push_back(numeral()); - m().set(L.A.back(), mu_1); - // r_prime is the row being updated - // with r_prime += mu_1 * r - L.indc.push_back(r_prime); - L.indr.push_back(r); - - m().neg(mu_1); - // Now, mu_1 contains -A_(r_prime, c) / A_(r,c) - - // little hack: temporarily store mu_1 at T.A[k] and save position at locw - m().set(T.A[k], mu_1); - locw[r_prime] = k; - DEBUG_CODE(num_set_locw++;); - m_toadd_rows.push_back(r_prime); - - SASSERT(T_row_contains(r_prime, c)); - // decrement the length of the row since column c will be removed. - dec_lenr(r_prime); - - // the row entry (r_prime, c) is actually removed by del_disabled_cols - T.num_entries--; - } - - // Update every non-zero column of r different from c. - begin = T.begr[r]; - end = T.endr[r]; - TRACE("dec_len_bug", tout << "row r: " << r << ", begin: " << begin << ", end: " << end << "\n";); - for (unsigned k = begin; k < end; k++) { - unsigned c_prime = T.indr[k]; - TRACE("dec_len_bug", tout << "processing c_prime: " << c_prime << ", c: " << c << "\n";); - if (c_prime == c) - continue; - // The row is going to be disabled, so decrementing length of c_prime from r. - // Remark: don't need to do that for c, since it will be disabled. - dec_lenc(c_prime); - TRACE("dec_len_bug", tout << "c_prime: " << c_prime << ", lenc[c_prime] : " << m_todo_cols.len(c_prime) << "\n";); - - SASSERT(enabled_col(c_prime)); - unsigned begin2 = T.begc[c_prime]; - unsigned end2 = T.endc[c_prime]; - // Find coefficient of (r, c_prime) and store it in A_aux - for (unsigned i = begin2; true; i++) { - SASSERT(i < end2); - if (T.indc[i] == r) { - m().set(A_aux, T.A[i]); - break; - } - } - - // Update column - unsigned j = begin2; - for (unsigned i = begin2; i < end2; i++) { - unsigned r_prime = T.indc[i]; - if (r_prime == r // row r is not going to be modified - || !enabled_row(r_prime) // row was already processed (i.e., it is already in the triangular part) - || locw[r_prime] == UINT_MAX // row is not being updated - ) { - if (i != j) { - T.indc[j] = T.indc[i]; - m().set(T.A[j], T.A[i]); - T.indc[i] = UINT_MAX; - } - j++; - continue; - } - // mark row as visited - m_marked_rows[r_prime] = true; - // update T.A[j] with T.A[i] + mu_1 * A_aux, - // where mu_1 is stored at T.A[locw[r_prime]] - m().addmul(T.A[i], T.A[locw[r_prime]], A_aux, T.A[j]); - T.indc[j] = T.indc[i]; - if (i != j) - T.indc[i] = UINT_MAX; - if (m().is_zero(T.A[j])) { - // entry was canceled - dec_lenr(r_prime); - dec_lenc(c_prime); - T.indc[j] = UINT_MAX; - del_row_entry(r_prime, c_prime); - T.num_entries--; - } - else { - j++; - } - } - - T.endc[c_prime] = j; - // Process rows that were not visited. - unsigned num = m_toadd_rows.size(); - for (unsigned i = 0; i < num; i++) { - unsigned r_prime = m_toadd_rows[i]; - if (m_marked_rows[r_prime]) { - // row was already added - m_marked_rows[r_prime] = false; - continue; - } - // add entry (r_prime, c_prime) with coefficient mu_1 * A_aux - // where mu_1 is stored at T.A[locw[r_prime]] - add_row_entry(r_prime, c_prime); - m().mul(T.A[locw[r_prime]], A_aux, tmp); - add_col_entry(r_prime, c_prime, tmp); - inc_lenr(r_prime); - inc_lenc(c_prime); - T.num_entries++; - } - } - - // Reset column c - begin = T.begc[c]; - end = T.endc[c]; - unsigned j = begin; - for (unsigned k = begin; k < end; k++) { - unsigned r_prime = T.indc[k]; - if (r_prime == r || !enabled_row(r_prime)) { - if (j != k) { - T.indc[j] = T.indc[k]; - m().set(T.A[j], T.A[k]); - T.indc[k] = UINT_MAX; - } - j++; - continue; - } - SASSERT(locw[r_prime] != UINT_MAX); - locw[r_prime] = UINT_MAX; - DEBUG_CODE(num_set_locw--;); - } - SASSERT(num_set_locw == 0); - T.endc[c] = j; -} - -template -void lu::process_pivot(unsigned i, unsigned r, unsigned c) { - CASSERT("lu", check_locw()); - del_disabled_cols(r); - SASSERT(T.begr[r] < T.endr[r]); - process_pivot_core(r, c); - - m_todo_rows.erase(r); - m_todo_cols.erase(c); - m_enabled_rows[r] = false; - m_enabled_cols[c] = false; - - P.swap(i, P.inv(r)); - Q.swap(i, Q.inv(c)); - CASSERT("lu", check_locw()); -} - -template -void lu::copy_T_to_U() { - U.num_entries = T.num_entries; - U.begr.resize(m_sz); - U.endr.resize(m_sz); - // reserve space for each row - unsigned pos = 0; - for (unsigned r = 0; r < m_sz; r++) { - U.begr[r] = pos; - U.endr[r] = pos; - unsigned r_sz = T.endr[r] - T.begr[r]; - pos += r_sz; - pos += fillin_for(r_sz); - } - U.A.resize(pos); - U.indr.resize(pos, UINT_MAX); - - // fill rows - for (unsigned c = 0; c < m_sz; c++) { - unsigned c_prime = Q(c); // make sure the first element in each row is the pivot; - unsigned begin = T.begc[c_prime]; - unsigned end = T.endc[c_prime]; - CTRACE("lu_bug", end < begin + 1 || end > begin + c + 1, - tout << "begin: " << begin << ", end: " << end << ", c: " << c << ", c_prime: " << c_prime << "\n"; - display_T(tout); tout << "P: " << P << "\nQ: " << Q << "\n";); - SASSERT(end >= begin + 1); - SASSERT(end <= begin + c + 1); - for (unsigned t_idx = begin; t_idx < end; t_idx++) { - unsigned r = T.indc[t_idx]; - unsigned u_idx = U.endr[r]; - SASSERT(U.indr[u_idx] == UINT_MAX); - m().swap(U.A[u_idx], T.A[t_idx]); - U.indr[u_idx] = c_prime; - U.endr[r]++; - } - } - - SASSERT(check_U()); -} - -template -void lu::fact() { - SASSERT(!ini); - TRACE("fact", display_T(tout);); - init_fact(); - - CASSERT("lu", check_lenr() && check_lenc()); - unsigned r, c; - for (unsigned i = 0; i < m_sz; i++) { - select_pivot(r, c); - - TRACE("lu_pivot", tout << "pivot: " << r << " " << c << "\n";); - - process_pivot(i, r, c); - - TRACE("lu_pivot", tout << "P: " << P << "\nQ: " << Q << "\n";); - CASSERT("lu", check_lenr() && check_lenc()); - - TRACE("lu_pivot_detail", display_T(tout);); - compress_if_needed(); - } - copy_T_to_U(); -} - -// During factorization, the following invariant must hold. -// For every row r, enabled_row(r) => m_todo_rows.len(r) == number of enabled columns in r. -// For every column c, enabled_col(c) => m_todo_cols.len(c) == number of enabled rows in c. - -template -bool lu::check_lenr() const { - for (unsigned r = 0; r < m_sz; r++) { - if (enabled_row(r)) { - unsigned len = 0; - unsigned begin = T.begr[r]; - unsigned end = T.endr[r]; - for (unsigned k = begin; k < end; k++) { - unsigned c = T.indr[k]; - CTRACE("lu_bug", c == UINT_MAX, tout << "r: " << r << ", c: " << c << "\n";); - if (enabled_col(c)) - len++; - } - CTRACE("lu_bug", m_todo_rows.len(r) != len, tout << "failed for row: " << r << " len: " << len << " lenr[r]: " << m_todo_rows.len(r) << "\n"; - display_T(tout);); - SASSERT(m_todo_rows.len(r) == len); - } - } - return true; -} - -template -bool lu::check_lenc() const { - for (unsigned c = 0; c < m_sz; c++) { - if (enabled_col(c)) { - unsigned len = 0; - unsigned begin = T.begc[c]; - unsigned end = T.endc[c]; - for (unsigned k = begin; k < end; k++) { - unsigned r = T.indc[k]; - if (enabled_row(r)) - len++; - } - CTRACE("lu_bug", m_todo_cols.len(c) != len, tout << "failed for column: " << c << " len: " << len << " lenc[c]: " - << m_todo_cols.len(c) << "\n"; display_T(tout);); - SASSERT(m_todo_cols.len(c) == len); - } - } - return true; -} - -// ----------------------- -// -// Invariants -// -// ----------------------- - -template -bool lu::check_P() const { - SASSERT(P.check_invariant()); - return true; -} - -template -bool lu::check_Q() const { - SASSERT(Q.check_invariant()); - return true; -} - -template -bool lu::check_L() const { - SASSERT(L.A.size() == L.indc.size()); - SASSERT(L.A.size() == L.indr.size()); - for (unsigned i = 0; i < L.A.size(); i++) { - SASSERT(L.indc[i] < m_sz); - SASSERT(L.indr[i] < m_sz); - } - return true; -} - -template -bool lu::check_U() const { - unsigned num_entries = 0; - SASSERT(U.begr.size() == m_sz); - SASSERT(U.endr.size() == m_sz); - for (unsigned r = 0; r < m_sz; r++) { - SASSERT(U.begr[r] <= U.endr[r]); - SASSERT(U.endr[r] <= U.A.size()); - for (unsigned j = U.begr[r]; j < U.endr[r]; j++) { - num_entries++; - unsigned c = U.indr[j]; - SASSERT(c < m_sz); // valid variable/column - // it is really upper triangular - CTRACE("lu_bug", Q.inv(c) < P.inv(r), - tout << "c: " << c << ", r: " << r << ", Q.inv(c): " << Q.inv(c) << ", P.inv(r): " << P.inv(r) << "\n"; display_U(tout);); - SASSERT(Q.inv(c) >= P.inv(r)); - } - } - SASSERT(num_entries == U.num_entries); - return true; -} - -/** - \brief Return true if the T column c contains a reference to row r. -*/ -template -bool lu::T_col_contains(unsigned c, unsigned r) const { - for (unsigned i = T.begc[c]; i < T.endc[c]; i++) - if (T.indc[i] == r) - return true; - return false; -} - -/** - \brief Return true if the T row r contains a reference to column c. -*/ -template -bool lu::T_row_contains(unsigned r, unsigned c) const { - for (unsigned i = T.begr[r]; i < T.endr[r]; i++) - if (T.indr[i] == c) - return true; - return false; -} - -template -bool lu::check_T() const { - SASSERT(T.begr.size() == m_sz); - SASSERT(T.endr.size() == m_sz); - - SASSERT(T.A.size() == T.indc.size()); - SASSERT(T.begc.size() == m_sz); - SASSERT(T.endc.size() == m_sz); - - for (unsigned i = 0; i < m_sz; i++) { - SASSERT(T.begr[i] <= T.endr[i]); - SASSERT(T.endr[i] <= T.indr.size()); - for (unsigned j = T.begr[i]; j < T.endr[i]; j++) { - if (enabled_col(T.indr[j])) { - SASSERT(T.indr[j] < m_sz); - SASSERT(T_col_contains(T.indr[j], i)); - } - } - - SASSERT(T.begc[i] <= T.endc[i]); - SASSERT(T.endc[i] <= T.indc.size()); - for (unsigned j = T.begc[i]; j < T.endc[i]; j++) { - if (enabled_row(T.indc[j])) { - SASSERT(T.indc[j] < m_sz); - CTRACE("lu_bug", !T_row_contains(T.indc[j], i), tout << "T.indc[j]: " << T.indc[j] << ", i: " << i << "\n"; display_T(tout);); - SASSERT(T_row_contains(T.indc[j], i)); - } - } - } - return true; -} - -template -bool lu::check_invariant() const { - SASSERT(check_P()); - SASSERT(check_Q()); - if (!ini) { - SASSERT(check_L()); - SASSERT(check_U()); - } - SASSERT(locw.size() == m_sz); - return true; -} - -template -void lu::display_T(std::ostream & out) const { - for (unsigned r = 0; r < m_sz; r++) { - unsigned begin_r = T.begr[r]; - unsigned end_r = T.endr[r]; - for (unsigned j = begin_r; j < end_r; j++) { - unsigned c = T.indr[j]; - if (j > begin_r) - out << " "; - unsigned begin_c = T.begc[c]; - unsigned end_c = T.endc[c]; - unsigned i; - for (i = begin_c; i < end_c; i++) { - if (T.indc[i] == r) { - // found coeff - out << m().to_string(T.A[i]) << "*x" << c; - break; - } - } - if (i == end_c) { - out << "*x" << c; - } - } - out << "\n"; - } -} - -template -void lu::display_U(std::ostream & out, unsigned_vector const * var_ids) const { - out << "U:\n"; - for (unsigned i = 0; i < m_sz; i++) { - unsigned begin = U.begr[i]; - unsigned end = U.endr[i]; - for (unsigned j = begin; j < end; j++) { - if (j > begin) - out << " "; - out << m().to_string(U.A[j]) << "*x"; - if (var_ids) - out << (*var_ids)[U.indr[j]]; - else - out << U.indr[j]; - } - out << "\n"; - } -} - -template -void lu::display_L(std::ostream & out) const { - out << "L: "; - unsigned sz = L.A.size(); - for (unsigned i = 0; i < sz; i++) { - out << "(" << L.indc[i] << ", " << L.indr[i] << ", " << m().to_string(L.A[i]) << ")"; - } - out << "\n"; -} - -template -void lu::display(std::ostream & out, unsigned_vector const * var_ids) const { - out << "P: " << P << "\n"; - out << "Q: " << Q << "\n"; - display_U(out, var_ids); - display_L(out); -} - -template -lu::dense_vector::dense_vector(manager & m, unsigned sz): - m_manager(m) { - m_in_non_zeros.resize(sz, false); - m_values.resize(sz); -} - -template -lu::dense_vector::~dense_vector() { - reset(); -} - -template -void lu::dense_vector::reset() { - iterator it = begin_non_zeros(); - iterator end = end_non_zeros(); - for (; it != end; ++it) { - m().reset(m_values[*it]); - m_in_non_zeros[*it] = false; - } - m_non_zeros.reset(); -} - -template -void lu::dense_vector::reset(unsigned new_sz) { - reset(); - m_in_non_zeros.resize(new_sz, false); - m_values.resize(new_sz); -} - -template -void lu::solve_Lx_eq_y(dense_vector & y) { - TRACE("lu_solve", tout << "before: Lx = y\n"; y.display(tout); tout << "\n";); - SASSERT(y.size() == m_sz); // compatible size - SASSERT(&(y.m()) == &(m())); // same manager - unsigned sz = L.A.size(); - unsigned k = 0; - while (k < sz) { - TRACE("Lx_eq_y", tout << "(" << L.indc[k] << " " << L.indr[k] << " " << m().to_string(L.A[k]) << ")\n"; y.display(tout); tout << "\n";); - unsigned j_k = L.indr[k]; // L.indr contains column numbers. - numeral const & y_j = y[j_k]; - if (m().is_zero(y_j)) { - for (; k < sz && L.indr[k] == j_k; k++) - ; - continue; - } - numeral const & mu_k = L.A[k]; - unsigned i_k = L.indc[k]; // L.indc contains row numbers - numeral & y_i = y.get(i_k); - m().submul(y_i, mu_k, y_j, y_i); - k++; - } - TRACE("lu_solve", tout << "after Lx = y\n"; y.display(tout); tout << "\n";); -} - -template -void lu::solve_Ux_eq_y(dense_vector & y) { - TRACE("lu_solve", tout << "before: Ux = y\n"; y.display(tout); tout << "\n";); - TRACE("lu_solve_PQ", tout << "P: " << P << "\nQ: " << Q << "\n";); - // TODO: super-sparse case, where the number of zeros in y is much smaller than m_sz - SASSERT(y.size() == m_sz); // compatible size - SASSERT(&(y.m()) == &(m())); // same manager - numeral delta; - unsigned i = m_sz; - dense_vector & x = m_tmp_xU_vector; - x.reset(); - while (i > 0) { - --i; - unsigned i_prime = P(i); - unsigned j_prime = Q(i); - unsigned begin = U.begr[i_prime]; - unsigned end = U.endr[i_prime]; - TRACE("lu_solve_bug", tout << "i_prime: " << i_prime << ", j_prime: " << j_prime << "\n"; - tout << "y: "; y.display(tout); tout << "\n"; - tout << "x: "; x.display(tout); tout << "\n";); - SASSERT(end >= begin + 1); // row must be non empty - CTRACE("lu_bug", U.indr[begin] != j_prime, tout << "i: " << i << ", i_prime: " << i_prime << ", j_prime: " << j_prime - << ", U.indr[begin]: " << U.indr[begin] << "\n"; display_U(tout);); - SASSERT(U.indr[begin] == j_prime); // j_prime must be in the first position - if (end == begin + 1) { - // row of size one - if (m().is_zero(y[i_prime])) - continue; - numeral & x_j = x.get(j_prime); - m().div(y[i_prime], U.A[begin], x_j); - } - else { - // row has at least two elements. - SASSERT(end > begin + 1); - numeral const & a = U.A[begin]; - m().reset(delta); - for (unsigned k = begin+1; k < end; k++) { - unsigned c = U.indr[k]; - TRACE("lu_solve_bug", tout << "c: " << c << ", x[c]: " << m().to_string(x[c]) << ", delta: " << m().to_string(delta) << "\n";); - m().addmul(delta, U.A[k], x[c], delta); - } - if (m().is_zero(delta) && m().is_zero(y[i_prime])) - continue; - numeral & x_j = x.get(j_prime); - m().sub(y[i_prime], delta, x_j); - m().div(x_j, a, x_j); - } - } - y.swap(x); - m().del(delta); - TRACE("lu_solve", tout << "after: Ux = y\n"; y.display(tout); tout << "\n";); -} - -template -void lu::solve_xL_eq_y(dense_vector & y) { - TRACE("lu_solve", tout << "before: xL = y\n"; y.display(tout); tout << "\n";); - SASSERT(y.size() == m_sz); // compatible size - SASSERT(&(y.m()) == &(m())); // same manager - unsigned k = L.A.size(); - while (k > 0) { - --k; - unsigned i_k = L.indc[k]; - numeral const & y_i = y[i_k]; - if (m().is_zero(y_i)) - continue; - numeral const & mu_k = L.A[k]; - unsigned j_k = L.indr[k]; - numeral & y_j = y.get(j_k); - m().submul(y_j, mu_k, y_i, y_j); - } - TRACE("lu_solve", tout << "after: xL = y\n"; y.display(tout); tout << "\n";); -} - -template -void lu::solve_xU_eq_y(dense_vector & y) { - // TODO: super-sparse case, where the number of zeros in y is much smaller than m_sz - TRACE("lu_solve", tout << "before: xU = y\n"; y.display(tout); tout << "\n";); - TRACE("lu_solve_PQ", tout << "P: " << P << "\nQ: " << Q << "\n";); - SASSERT(y.size() == m_sz); // compatible size - SASSERT(&(y.m()) == &(m())); // same manager - dense_vector & x = m_tmp_xU_vector; - x.reset(); - for (unsigned i = 0; i < m_sz; i++) { - unsigned i_prime = P(i); - unsigned j_prime = Q(i); - TRACE("lu_solve_step", tout << "i: " << i << ", P(i): " << P(i) << ", Q(i): " << Q(i) << ", x: "; x.display(tout); - tout << ", y[j_prime]: " << m().to_string(y[j_prime]) << "\n";); - if (!m().is_zero(y[j_prime])) { - numeral & x_i = x.get(i_prime); - m().add(x_i, y[j_prime], x_i); - } - if (m().is_zero(x[i_prime])) - continue; - numeral & x_i = x.get(i_prime); - unsigned begin = U.begr[i_prime]; - unsigned end = U.endr[i_prime]; - SASSERT(end >= begin + 1); // row must be non empty - SASSERT(U.indr[begin] == j_prime); - numeral const & a = U.A[begin]; - m().div(x_i, a, x_i); - for (unsigned k = begin+1; k < end; k++) { - // propagate x_i - unsigned c = U.indr[k]; - numeral & x_j = x.get(P(Q.inv(c))); - m().submul(x_j, U.A[k], x_i, x_j); - } - } - TRACE("lu_solve_step", tout << "x: "; x.display(tout); tout << "\n";); - y.swap(x); - TRACE("lu_solve", tout << "after: xU = y\n"; y.display(tout); tout << "\n";); -} - -// ----------------------- -// -// Column replacement -// -// ----------------------- - -/** - \brief Remove colum c from U row r. -*/ -template -void lu::del_U_row_entry(unsigned r, unsigned c) { - unsigned begin = U.begr[r]; - unsigned end = U.endr[r]; - TRACE("del_row_entry", tout << "del_U_row_entry, r: " << r << ", c: " << c << ", begin: " << begin << ", end: " << end << "\n";); - for (unsigned i = begin; i < end; i++) { - unsigned c_prime = U.indr[i]; - if (c_prime == c) { - U.num_entries--; - i++; - for (; i < end; i++) { - U.indr[i-1] = U.indr[i]; - m().swap(U.A[i-1], U.A[i]); - } - U.indr[end-1] = UINT_MAX; // mark as free - U.endr[r] = end-1; - return; - } - } -} - -/** - \brief Compress U rows -*/ -template -void lu::compress_U_rows() { - unsigned_vector new_indr; - numeral_vector new_A; - for (unsigned r = 0; r < m_sz; r++) { - unsigned begin = U.begr[r]; - unsigned end = U.endr[r]; - U.begr[r] = new_indr.size(); - for (unsigned i = begin; i < end; i++) { - new_A.push_back(numeral()); - m().swap(new_A.back(), U.A[i]); - new_indr.push_back(U.indr[i]); - } - U.endr[r] = new_indr.size(); - unsigned fillin = U.endr[r] - U.begr[r]; - for (unsigned i = 0; i < fillin; i++) - U.indr.push_back(UINT_MAX); - } - U.indr.swap(new_indr); - U.A.swap(new_A); - TRACE("lu_bug", tout << "compressed U rows\n";); - CASSERT("lu", check_U()); -} - -template -void lu::compress_U_if_needed() { - if (U.indr.size() > COMPRESSION_FACTOR * U.num_entries) { - compress_U_rows(); - CASSERT("lu", check_U()); - } -} - -template -void lu::move_U_row_to_end(unsigned r) { - unsigned begin = U.begr[r]; - unsigned end = U.endr[r]; - U.begr[r] = U.indr.size(); - U.endr[r] = U.begr[r] + end - begin; - for (unsigned j = begin; j < end; j++) { - U.A.push_back(numeral()); - m().swap(U.A.back(), U.A[j]); - unsigned c = U.indr[j]; - U.indr.push_back(c); - U.indr[j] = UINT_MAX; // mark as free - } - unsigned sz = end - begin; - unsigned fillin = fillin_for(sz); - for (unsigned i = 0; i < fillin; i++) { - U.A.push_back(numeral()); - U.indr.push_back(UINT_MAX); - } -} - -template -void lu::add_U_row_entry(unsigned r, unsigned c, numeral const & a) { - TRACE("add_U_row_entry", tout << "r: " << r << ", c: " << c << ", a: " << m().to_string(a) << " row:\n"; - for (unsigned i = U.begr[r]; i < U.endr[r]; i++) tout << m().to_string(U.A[i]) << "*x" << U.indr[i] << " "; tout << "\n";); - U.num_entries++; - if (U.endr[r] == U.indr.size()) { - // expand last row - U.A.push_back(numeral()); - m().set(U.A.back(), a); - U.indr.push_back(c); - U.endr[r]++; - SASSERT(U.endr[r] == U.indr.size()); - } - else { - if (U.indr[U.endr[r]] != UINT_MAX) - move_U_row_to_end(r); - // use free space - SASSERT(U.indr[U.endr[r]] == UINT_MAX); - unsigned pos = U.endr[r]; - m().set(U.A[pos], a); - U.indr[pos] = c; - U.endr[r]++; - } -} - -/** - \brief Remove colum c from U row r. -*/ -template -void lu::add_replace_U_row_entry(unsigned r, unsigned c, numeral const & a) { - unsigned begin = U.begr[r]; - unsigned end = U.endr[r]; - TRACE("del_row_entry", tout << "replace_U_row_entry, r: " << r << ", c: " << c << ", begin: " << begin << ", end: " << end << "\n";); - for (unsigned i = begin; i < end; i++) { - unsigned c_prime = U.indr[i]; - if (c_prime == c) { - m().set(U.A[i], a); - return; - } - } - add_U_row_entry(r, c, a); -} - -/** - \brief Just replace the column. After the replacement PUQ is not triangular anymore. -*/ -template -unsigned lu::replace_U_column_core(unsigned j, dense_vector & new_col) { - unsigned max = 0; - // Traverse rows in pivotal order, removing/updating entries. - // We can stop at Q.inv(j) because: - // For every entry (r,c) in U Q.inv(c) >= P.inv(r) - // Thus j does not occur in any r' such that Q.inv(j) < P.inv(r') - unsigned stop_at = Q.inv(j); - for (unsigned i = 0; i <= stop_at; i++) { - unsigned r = P(i); - if (m().is_zero(new_col[r])) { - del_U_row_entry(r, j); - } - else { - max = i; - // replace/add - add_replace_U_row_entry(r, j, new_col[r]); - // reset entry in new_col - numeral & v = new_col.get(r); - m().reset(v); - } - } - - // Add remaining rows of new_col to U - unsigned_vector::const_iterator it = new_col.begin_non_zeros(); - unsigned_vector::const_iterator end = new_col.m_non_zeros.end(); - for (; it != end; ++it) { - unsigned r = *it; - if (m().is_zero(new_col[r])) - continue; - if (P.inv(r) > max) - max = P.inv(r); - add_U_row_entry(r, j, new_col[r]); - } - return max; -} - -/** - \brief Return true if PUQ is triangular with the exception of column c_prime. -*/ -template -bool lu::check_U_except_col(unsigned c_prime) const { - for (unsigned r = 0; r < m_sz; r++) { - for (unsigned j = U.begr[r]; j < U.endr[r]; j++) { - unsigned c = U.indr[j]; - if (c == c_prime) - continue; - SASSERT(Q.inv(c) >= P.inv(r)); - } - } - return true; -} - -/** - \brief Return true if PUQ is triangular with the exception of row r_prime. -*/ -template -bool lu::check_U_except_row(unsigned r_prime) const { - for (unsigned r = 0; r < m_sz; r++) { - if (r == r_prime) - continue; - for (unsigned j = U.begr[r]; j < U.endr[r]; j++) { - unsigned c = U.indr[j]; - SASSERT(Q.inv(c) >= P.inv(r)); - } - } - return true; -} - -template -void lu::replace_U_column(unsigned j, dense_vector & new_col) { - TRACE("lu_replace", tout << "replacing U column j: " << j << " with\n"; new_col.display_non_zeros(tout); tout << "\n";); - unsigned k = replace_U_column_core(j, new_col); - if (k <= Q.inv(j)) { - TRACE("lu_replace", tout << "result 1:\n"; display(tout);); - CASSERT("lu", check_U()); - if (m().is_zero(U.A[U.begr[P(Q.inv(j))]])) - throw lu_exception("bad new column"); // column does not have the pivot. - return; - } - - TRACE("lu_replace", tout << "after replace_core:\n"; display_U(tout); - tout << "P: " << P << "\n"; tout << "Q: " << Q << "\n"; - tout << "Q.inv(j): " << Q.inv(j) << ", k: " << k << "\n";); - - // fix spike at j - CASSERT("lu", check_U_except_col(j)); - P.move_after(Q.inv(j), k); - Q.move_after(Q.inv(j), k); - - TRACE("lu_replace", tout << "P: " << P << "\n"; tout << "Q: " << Q << "\n";); - - // fix row P_k - unsigned P_k = P(k); - unsigned Q_k = Q(k); - CASSERT("lu", check_U_except_row(P_k)); - - // 1. search for smallest bad column - unsigned smallest = k; - unsigned begin = U.begr[P_k]; - unsigned end = U.endr[P_k]; - for (unsigned i = begin; i < end; i++) { - unsigned c = U.indr[i]; - unsigned inv_c = Q.inv(c); - if (inv_c < smallest) - smallest = inv_c; - } - - if (smallest == k) { - // nothing to be done - TRACE("lu_replace", tout << "result 2:\n"; display(tout);); - if (m().is_zero(U.A[U.begr[P_k]])) - throw lu_exception("bad new column"); // column does not have the pivot. - CASSERT("lu", check_U()); - return; - } - - // 2. eliminate bad columns using other rows. - // 2.a. save coefficients in tmp dense vector - dense_vector & row_k = m_tmp_replace_column_vector; - row_k.reset(); - begin = U.begr[P_k]; - end = U.endr[P_k]; - for (unsigned i = begin; i < end; i++) { - unsigned c = U.indr[i]; - U.indr[i] = UINT_MAX; // mark as free - numeral & a = row_k.get(c); - m().swap(a, U.A[i]); - } - U.num_entries -= end - begin; - U.endr[P_k] = begin; - - // 2.b eliminate columns in m_to_fix from P_k - for (; smallest < k; smallest++) { - unsigned c = Q(smallest); - numeral const & a_k = row_k[c]; - if (m().is_zero(a_k)) - continue; - - // use row r to eliminate c - unsigned r = P(Q.inv(c)); - SASSERT(U.indr[U.begr[r]] == c); - numeral const & a_r = U.A[U.begr[r]]; - - // to eliminate c from k, we must add (-a_k/a_r * r) to row_k - // Save transformation at L - m().set(mu_1, a_k); - m().div(mu_1, a_r, mu_1); - L.A.push_back(numeral()); - m().set(L.A.back(), mu_1); - L.indc.push_back(P_k); - L.indr.push_back(r); - m().neg(mu_1); - // k += mu_1 * r - begin = U.begr[r]; - end = U.endr[r]; - for (unsigned i = begin; i < end; i++) { - unsigned c_prime = U.indr[i]; - numeral & a_prime = row_k.get(c_prime); - if (c_prime == c) - m().reset(a_prime); - else - m().addmul(a_prime, mu_1, U.A[i], a_prime); - } - } - - CTRACE("lu_bug", m().is_zero(row_k[Q_k]), row_k.display_non_zeros(tout); tout << "\n";); - - // 2.c Copy row_k back to U - SASSERT(!NM::precise() || !m().is_zero(row_k[Q_k])); - if (m().is_zero(row_k[Q_k])) - throw lu_exception("singular matrix"); - - // Add pivot first - SASSERT(U.begr[P_k] == U.endr[P_k]); // the row k in U is empty - add_U_row_entry(P_k, Q_k, row_k[Q_k]); - - // Copy remaining elements - typename dense_vector::iterator it3 = row_k.begin_non_zeros(); - typename dense_vector::iterator end3 = row_k.end_non_zeros(); - for (; it3 != end3; ++it3) { - unsigned c = *it3; - if (c == Q_k) - continue; // already added - if (m().is_zero(row_k[c])) - continue; - add_U_row_entry(P_k, c, row_k[c]); - } - - TRACE("lu_replace", tout << "result 3:\n"; display(tout);); - CASSERT("lu", check_U()); - compress_U_if_needed(); -} - -template -void lu::replace_column(unsigned j, dense_vector & new_col) { - TRACE("lu_replace", tout << "replacing column j: " << j << " with\n"; new_col.display_non_zeros(tout); tout << "\n";); - SASSERT(j < m_sz); - solve_Lx_eq_y(new_col); - replace_U_column(j, new_col); - m_num_replacements++; -} - -// ----------------------- -// -// Dense vector -// -// ----------------------- - -// Make sure that every position in m_non_zeros really contains a non-zero value. -template -void lu::dense_vector::elim_zeros() { - unsigned_vector::iterator it = m_non_zeros.begin(); - unsigned_vector::iterator end = m_non_zeros.end(); - unsigned_vector::iterator it2 = it; - for (; it != end; ++it) { - unsigned idx = *it; - SASSERT(m_in_non_zeros[idx]); - if (m().is_zero(m_values[idx])) { - m().reset(m_values[idx]); - m_in_non_zeros[idx] = false; - continue; - } - *it2 = idx; - ++it2; - } - m_non_zeros.set_end(it2); -} - - -template -void lu::dense_vector::display(std::ostream & out) const { - out << "("; - unsigned sz = m_values.size(); - for (unsigned i = 0; i < sz; i++) { - if (i > 0) out << " "; - out << m().to_string(m_values[i]); - } - out << ")"; -} - -template -void lu::dense_vector::display_non_zeros(std::ostream & out) const { - out << "("; - bool first = true; - for (unsigned i = 0; i < m_non_zeros.size(); i++) { - unsigned pos = m_non_zeros[i]; - if (m().is_zero(m_values[pos])) - continue; - if (first) first = false; else out << " "; - out << m().to_string(m_values[pos]) << ":" << pos; - } - out << ")"; -} - -template -void lu::dense_vector::display_pol(std::ostream & out) const { - bool first = true; - for (unsigned i = 0; i < m_non_zeros.size(); i++) { - unsigned pos = m_non_zeros[i]; - if (m().is_zero(m_values[pos])) - continue; - if (first) first = false; else out << " + "; - out << m().to_string(m_values[pos]) << "*x" << pos; - } -} - - -template class lu; -template class lu; - diff --git a/src/tactic/arith/dead/lu.h b/src/tactic/arith/dead/lu.h deleted file mode 100644 index 16dd5a6ab..000000000 --- a/src/tactic/arith/dead/lu.h +++ /dev/null @@ -1,404 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - lu.h - -Abstract: - - Simple LU factorization module based on the paper: - - "Maintaining LU factors of a General Sparse Matrix" - P. E. Gill, W. Murray, M. Saunders, M. Wright - -Author: - - Leonardo de Moura (leonardo) 2011-06-09 - -Revision History: - ---*/ -#ifndef _LU_H_ -#define _LU_H_ - -#include"vector.h" -#include"mpq.h" -#include"double_manager.h" -#include"permutation.h" -#include"params.h" -#include"strategy_exception.h" - -MK_ST_EXCEPTION(lu_exception); - -template -class lu { -public: - typedef NumManager manager; - typedef typename NumManager::numeral numeral; - typedef svector numeral_vector; - -private: - manager & m_manager; - - // Configuration - numeral m_mu; // maximum multiplier when selecting a pivot - unsigned m_selection_cutoff; - - // Matrix size - unsigned m_sz; // supporting only square matrices - - // Permutations - permutation P; - permutation Q; - - // L - // - // It is 3 parallel vectors representing the sequence (product) of matrices - // L[0] L[1] ... L[m-1] - // where each L[i] is a tuple (A[i], indc[i], indr[i]). - // Each tuple represents a triangular factor. That is, an identity matrix - // where the position at row indc[i], and column indr[i] contains the value A[i]. - // Remark: The product L[0] L[1] ... L[n-1] is not really a triangular matrix. - struct L_file { - numeral_vector A; - unsigned_vector indc; - unsigned_vector indr; - }; - L_file L; - - - // U - // - // It is not really upper triangular, but the product PUQ is. - // The rows of U are stored in the parallel vectors (A, indr) - // Only the non-zero values are stored at U. - // The non-zeros of row i start at position begr[i] and end at - // position endr[i] of the parallel vectors (A, indr). - // The length of the row is endr[i] - begr[i]. - // The coefficients are stored in A, and the column ids at indr. - // - // The factorization of a matrix A is represented as: - // L[0] L[1] ... L[m-1] P U Q - struct U_file { - numeral_vector A; - unsigned_vector indr; - unsigned_vector begr; - unsigned_vector endr; - - unsigned num_entries; - U_file():num_entries(0) {} - }; - U_file U; - - // The actual factorization - - - // T_file: temporary file used for factorization - struct T_file { - // row list - unsigned_vector indr; - unsigned_vector begr; - unsigned_vector endr; - - // column list - numeral_vector A; - unsigned_vector indc; - unsigned_vector begc; - unsigned_vector endc; - - unsigned num_entries; - T_file():num_entries(0) {} - }; - T_file T; - - // Auxiliary fields - unsigned_vector locw; - - // ----------------------- - // - // Main - // - // ----------------------- -public: - lu(manager & m, params_ref const & p); - ~lu(); - - manager & m() const { return m_manager; } - - void updt_params(params_ref const & p); - - void reset(); - - unsigned size() const { return m_sz; } - -protected: - void del_nums(numeral_vector & nums); - - // ----------------------- - // - // Initialization - // - // ----------------------- -public: - // Contract for setting up the initial matrix: - // lu.init(size) - // - for each row r in the matrix - // - for each non-zero (a,x) in the row - // lu.add_entry(a, x) - // lu.end_row() - void init(unsigned size); - void add_entry(numeral const & a, unsigned x); - void end_row(); - -protected: - // auxiliary fields used during initialization - bool ini; // try if the matrix T is being setup using the protocol above - unsigned ini_irow; - unsigned fillin_for(unsigned sz); - void move_col_to_end(unsigned x); - void move_row_to_end(unsigned x); - - // ----------------------- - // - // Factorization - // - // ----------------------- -public: - void fact(); - -protected: - class todo { - unsigned_vector m_elem2len; - unsigned_vector m_elem2pos; - vector m_elems_per_len; - unsigned m_size; - public: - todo():m_size(0) {} - bool contains(unsigned elem) const { return m_elem2pos[elem] != UINT_MAX; } - void init(unsigned capacity); - void updt_len(unsigned elem, unsigned len); - unsigned len(unsigned elem) const { return m_elem2len[elem]; } - void erase(unsigned elem); - unsigned size() const { return m_size; } - void display(std::ostream & out) const; - class iterator { - todo const & m_todo; - unsigned m_i; - unsigned m_j; - unsigned m_c; - void find_next(); - public: - iterator(todo const & t):m_todo(t), m_i(0), m_j(0), m_c(0) { if (!at_end()) find_next(); } - bool at_end() const { return m_c == m_todo.m_size; } - unsigned curr() const { - unsigned_vector const & v_i = m_todo.m_elems_per_len[m_i]; - return v_i[m_j]; - } - void next() { SASSERT(!at_end()); m_j++; m_c++; find_next(); } - }; - }; - - todo m_todo_rows; - todo m_todo_cols; - svector m_enabled_rows; - svector m_enabled_cols; - - bool enabled_row(unsigned r) const { return m_enabled_rows[r]; } - bool enabled_col(unsigned c) const { return m_enabled_cols[c]; } - - unsigned_vector m_toadd_rows; - svector m_marked_rows; - - // Temporary numerals - // I do not use local numerals to avoid memory leaks - numeral tol; - numeral C_max; - numeral A_ij; - numeral A_best; - numeral A_aux; - numeral tmp; - numeral mu_best; - numeral mu_1; - - void init_fact(); - bool stability_test(unsigned rin, unsigned cin, bool improvingM); - void select_pivot(unsigned & r_out, unsigned & c_out); - void process_pivot_core(unsigned r, unsigned c); - void process_pivot(unsigned i, unsigned r, unsigned c); - bool check_locw() const; - void dec_lenr(unsigned r); - void inc_lenr(unsigned r); - void dec_lenc(unsigned c); - void inc_lenc(unsigned c); - void del_row_entry(unsigned r, unsigned c); - void del_disabled_cols(unsigned r); - void add_row_entry(unsigned r, unsigned c); - void add_col_entry(unsigned r, unsigned c, numeral const & a); - void compress_rows(); - void compress_columns(); - void compress_if_needed(); - void copy_T_to_U(); - - bool check_lenr() const; - bool check_lenc() const; - - // ----------------------- - // - // Solving - // - // ----------------------- -public: - - // Temporary vector used to interact with different solvers. - // The vector has support for tracking non-zeros. - class dense_vector { - public: - typedef typename lu::manager manager; - typedef typename lu::numeral numeral; - private: - friend class lu; - manager & m_manager; - unsigned_vector m_non_zeros; // positions that may contain non-zeros. if a position is not here, then it must contain a zero - char_vector m_in_non_zeros; // m_in_non_zeros[i] == true if m_non_zeros contains i. - numeral_vector m_values; - public: - dense_vector(manager & m, unsigned sz); - ~dense_vector(); - - manager & m() const { return m_manager; } - - void reset(); - void reset(unsigned new_sz); - - unsigned size() const { return m_values.size(); } - numeral const & operator[](unsigned idx) const { return m_values[idx]; } - - void swap(dense_vector & other) { - m_non_zeros.swap(other.m_non_zeros); - m_in_non_zeros.swap(other.m_in_non_zeros); - m_values.swap(other.m_values); - } - - // Get a given position for performing an update. - // idx is inserted into m_non_zeros. - numeral & get(unsigned idx) { - if (!m_in_non_zeros[idx]) { - m_in_non_zeros[idx] = true; - m_non_zeros.push_back(idx); - } - return m_values[idx]; - } - - typedef unsigned_vector::const_iterator iterator; - - // iterator for positions that may contain non-zeros - iterator begin_non_zeros() const { return m_non_zeros.begin(); } - iterator end_non_zeros() const { return m_non_zeros.end(); } - - void display(std::ostream & out) const; - void display_non_zeros(std::ostream & out) const; - void display_pol(std::ostream & out) const; - - void elim_zeros(); - }; - - // Solve: Lx = y - // The result is stored in y. - void solve_Lx_eq_y(dense_vector & y); - - // Solve: PUQx = y - // The result is stored in y. - void solve_Ux_eq_y(dense_vector & y); - - // Solve: LPUQx = y - // The result is stored in y. - void solve_Ax_eq_y(dense_vector & y) { - solve_Lx_eq_y(y); - solve_Ux_eq_y(y); - } - - // Solve: xL = y - // The result is stored in y. - void solve_xL_eq_y(dense_vector & y); - - // Solve: xPUQ = y - // The result is stored in y. - void solve_xU_eq_y(dense_vector & y); - - // Solve: xA = y - // The result is stored in y. - void solve_xA_eq_y(dense_vector & y) { - solve_xU_eq_y(y); - solve_xL_eq_y(y); - } - -private: - dense_vector m_tmp_xU_vector; - dense_vector m_tmp_replace_column_vector; - dense_vector m_tmp_vector; - dense_vector m_tmp_row; - -public: - dense_vector & get_tmp_vector() { return m_tmp_vector; } - dense_vector & get_tmp_row(unsigned size) { m_tmp_row.reset(size); return m_tmp_row; } - - // ----------------------- - // - // Column replacement - // - // ----------------------- -public: - void replace_column(unsigned j, dense_vector & new_col); - void replace_U_column(unsigned j, dense_vector & new_col); - unsigned get_num_replacements() const { return m_num_replacements; } - dense_vector & get_tmp_col() { return m_tmp_col; } - -private: - unsigned m_num_replacements; - dense_vector m_tmp_col; - - void del_U_row_entry(unsigned r, unsigned c); - void compress_U_rows(); - void compress_U_if_needed(); - void move_U_row_to_end(unsigned r); - void add_U_row_entry(unsigned r, unsigned c, numeral const & a); - void add_replace_U_row_entry(unsigned r, unsigned c, numeral const & a); - unsigned replace_U_column_core(unsigned j, dense_vector & new_col); - bool check_U_except_col(unsigned c) const; - bool check_U_except_row(unsigned r) const; - - // ----------------------- - // - // Invariants - // - // ----------------------- -public: - bool check_P() const; - bool check_Q() const; - bool check_L() const; - bool check_U() const; - bool T_col_contains(unsigned c, unsigned r) const; - bool T_row_contains(unsigned r, unsigned c) const; - bool check_T() const; - bool check_invariant() const; - - void display_T(std::ostream & out) const; - void display_U(std::ostream & out, unsigned_vector const * var_ids = 0) const; - void display_L(std::ostream & out) const; - void display(std::ostream & out, unsigned_vector const * var_ids = 0) const; - - // ----------------------- - // - // Info - // - // ----------------------- -public: - unsigned L_size() const { return L.indc.size(); } - unsigned U_size() const { return U.num_entries; } -}; - -typedef lu rational_lu; -typedef lu double_lu; - -#endif diff --git a/src/tactic/arith/dead/mip_tactic.cpp b/src/tactic/arith/dead/mip_tactic.cpp deleted file mode 100644 index 5408b1f9b..000000000 --- a/src/tactic/arith/dead/mip_tactic.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - mip_tactic.cpp - -Abstract: - - Tactic for solvig MIP (mixed integer) problem. - This is a temporary tactic. It should be deleted - after theory_arith is upgraded. - -Author: - - Leonardo (leonardo) 2012-02-26 - -Notes: - ---*/ -#include"tactical.h" -#include"smt_solver_exp.h" - -class mip_tactic : public tactic { - struct imp; - ast_manager & m; - params_ref m_params; - statistics m_stats; - scoped_ptr m_solver; - - void init_solver() { - smt::solver_exp * new_solver = alloc(smt::solver_exp, m, m_params); - #pragma omp critical (tactic_cancel) - { - m_solver = new_solver; - } - } - -public: - mip_tactic(ast_manager & _m, params_ref const & p): - m(_m), - m_params(p) { - } - - virtual tactic * translate(ast_manager & m) { - return alloc(mip_tactic, m, m_params); - } - - virtual ~mip_tactic() {} - - virtual void updt_params(params_ref const & p) { - m_params = p; - } - virtual void collect_param_descrs(param_descrs & r) { - } - - virtual void operator()(goal_ref const & g, - goal_ref_buffer & result, - model_converter_ref & mc, - proof_converter_ref & pc, - expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - bool produce_models = g->models_enabled(); - mc = 0; pc = 0; core = 0; result.reset(); - tactic_report report("mip", *g); - fail_if_proof_generation("mip", g); - fail_if_unsat_core_generation("mip", g); - - g->elim_redundancies(); - if (g->inconsistent()) { - result.push_back(g.get()); - return; - } - - init_solver(); - m_solver->assert_goal(*g); - - lbool r; - try { - r = m_solver->check(); - } - catch (strategy_exception & ex) { - // solver_exp uses assertion_sets and strategy_exception's - throw tactic_exception(ex.msg()); - } - - m_solver->collect_statistics(m_stats); - - if (r == l_false) { - g->reset(); - g->assert_expr(m.mk_false()); - } - else if (r == l_true) { - g->reset(); - if (produce_models) { - model_ref md; - m_solver->get_model(md); - mc = model2model_converter(md.get()); - } - } - else { - // failed - } - g->inc_depth(); - result.push_back(g.get()); - TRACE("mip", g->display(tout);); - SASSERT(g->is_well_sorted()); - } - - virtual void cleanup() { - if (m_solver) - m_solver->collect_statistics(m_stats); - #pragma omp critical (tactic_cancel) - { - m_solver = 0; - } - } - - virtual void collect_statistics(statistics & st) const { - st.copy(m_stats); - } - - virtual void reset_statistics() { - m_stats.reset(); - } - - virtual void set_cancel(bool f) { - if (m_solver) - m_solver->set_cancel(f); - } -}; - -tactic * mk_mip_tactic(ast_manager & m, params_ref const & p) { - return clean(alloc(mip_tactic, m, p)); -} diff --git a/src/tactic/arith/dead/mip_tactic.h b/src/tactic/arith/dead/mip_tactic.h deleted file mode 100644 index 06dad2694..000000000 --- a/src/tactic/arith/dead/mip_tactic.h +++ /dev/null @@ -1,30 +0,0 @@ -/*++ -Copyright (c) 2012 Microsoft Corporation - -Module Name: - - mip_tactic.h - -Abstract: - - Tactic for solvig MIP (mixed integer) problem. - This is a temporary tactic. It should be deleted - after theory_arith is upgraded. - -Author: - - Leonardo (leonardo) 2012-02-26 - -Notes: - ---*/ -#ifndef _MIP_TACTIC_H_ -#define _MIP_TACTIC_H_ - -#include"params.h" -class ast_manager; -class tactic; - -tactic * mk_mip_tactic(ast_manager & m, params_ref const & p = params_ref()); - -#endif diff --git a/src/tactic/arith/dead/smt_arith.cpp b/src/tactic/arith/dead/smt_arith.cpp deleted file mode 100644 index 82c54d543..000000000 --- a/src/tactic/arith/dead/smt_arith.cpp +++ /dev/null @@ -1,3605 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_arith.cpp - -Abstract: - - Arithmetic solver for smt::solver - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - ---*/ -#include"smt_arith.h" -#include"bound_propagator.h" -#include"linear_equation.h" -#include"mpq.h" -#include"mpq_inf.h" -#include"double_manager.h" -#include"small_object_allocator.h" -#include"arith_decl_plugin.h" -#include"ast_smt2_pp.h" -#include"assertion_set_strategy.h" -#include"statistics.h" -#include"lu.h" -#include"cooperate.h" -#include"model.h" - -namespace smt { - - typedef unsigned var; - - class var_set { - unsigned_vector m_var2pos; - unsigned_vector m_vars; - public: - typedef unsigned_vector::const_iterator iterator; - var_set() {} - - void reset() { - if (4 * m_vars.size() < m_var2pos.size()) { - unsigned_vector::iterator it = m_vars.begin(); - unsigned_vector::iterator end = m_vars.end(); - for (; it != end; ++it) - m_var2pos[*it] = UINT_MAX; - } - else { - m_var2pos.reset(); - } - m_vars.reset(); - } - - bool empty() const { return m_vars.empty(); } - - unsigned size() const { return m_vars.size(); } - - var operator[](unsigned idx) const { return m_vars[idx]; } - - bool contains(var x) const { - return x < m_var2pos.size() && m_var2pos[x] != UINT_MAX; - } - - void insert(var x) { - if (contains(x)) - return; - m_var2pos.reserve(x+1, UINT_MAX); - m_var2pos[x] = m_vars.size(); - m_vars.push_back(x); - SASSERT(contains(x)); - } - - void erase(var x) { - if (contains(x)) { - unsigned pos = m_var2pos[x]; - SASSERT(m_vars[pos] == x); - if (pos != m_vars.size() - 1) { - unsigned last_x = m_vars.back(); - m_var2pos[last_x] = pos; - m_vars[pos] = last_x; - } - m_vars.pop_back(); - m_var2pos[x] = UINT_MAX; - } - SASSERT(!contains(x)); - } - - iterator begin() const { return m_vars.begin(); } - - iterator end() const { return m_vars.end(); } - }; - - struct arith::imp { - typedef small_object_allocator allocator; - typedef unsynch_mpq_manager numeral_manager; - typedef unsynch_mpq_inf_manager numeral_inf_manager; - typedef svector mpq_inf_vector; - typedef numeral_buffer mpq_buffer; - typedef numeral_buffer mpq_inf_buffer; - typedef numeral_buffer mpz_buffer; - typedef svector var_buffer; - typedef ptr_vector equations; - typedef lu lu_double; - typedef lu lu_mpq; - typedef numeral_inf_manager::inf_kind inf_kind; - - class double_vector : public svector { - public: - typedef double numeral; - typedef double_manager manager; - }; - -#define null_var UINT_MAX - - // "handy" infinitesimals -#define pos_inf numeral_inf_manager::POS -#define neg_inf numeral_inf_manager::NEG -#define zero_inf numeral_inf_manager::ZERO - - struct ineq_cnstr { - var m_x; - mpq m_k; - double m_approx_k; - bool m_lower; - atom_id m_atom; - }; - - typedef svector ineq_cnstrs; - typedef unsigned_vector ineq_cnstr_ids; - - // track the position of a variable in a equation - struct eq_occ { - unsigned m_idx; // equation index - unsigned m_pos; // position in the equation - eq_occ(unsigned idx, unsigned pos):m_idx(idx), m_pos(pos) {} - }; - - typedef svector eq_occs; - - ast_manager & m; - arith_util m_util; - expr_ref_vector m_var2expr; - obj_map m_expr2var; - - allocator m_allocator; - numeral_manager m_num_manager; - numeral_inf_manager m_num_inf_manager; - double_manager m_double_manager; - equations m_equations; - vector m_eq_occs; - lu_mpq m_lu_mpq; - lu_double m_lu_double; - char_vector m_eliminated; - unsigned_vector m_basic; // var -> eq_idx, UINT_MAX if not basic, otherwise it is a value in [0, m_equations.size()) - unsigned_vector m_inv_basic; // eq_idx -> var inverse of m_basic - mpq_inf_buffer m_values; - mpq_inf_buffer m_old_values; - double_vector m_approx_values; - double_vector m_old_approx_values; - var_set m_updated; - var_set m_approx_updated; - var_set m_bad_vars; - var_set m_int_bad_vars; - linear_equation_manager m_eq_manager; - bound_propagator m_asserted_bounds; - bound_propagator m_bounds; - unsigned m_conflict_eq_idx; // != UINT_MAX if the corresponding get_row(m_conflict_eq_idx) is in conflict. - ineq_cnstrs m_ineq_cnstrs; - ineq_cnstr_ids m_atom2ineq_cnstr; // atom idx to ineq cnstr idx - vector m_var_occs; // ineq_cnstrs that constain a variable - mpq_buffer m_mpq_buffer; - mpz_buffer m_mpz_buffer; - var_buffer m_var_buffer; - - typedef std::pair elim_var_info; - typedef svector elim_vars; - - elim_vars m_elim_vars; - - volatile bool m_cancel; - - // Modes of operation for mk_feasible - bool m_use_approx; // use approximated values - bool m_use_asserted; // consider only asserted bounds - - bool m_approx_forbidden; // disable approx mode when approximation gets lost trying to find feasible solution. - - // statistics - unsigned m_eliminated_vars; - unsigned m_lu_factorizations; - unsigned m_pivots; - unsigned m_approx_pivots; - unsigned m_max_l; - unsigned m_max_u; - unsigned m_branches; - unsigned m_cuts; - - // configuration - unsigned m_refactor_threshold; - unsigned m_blands_rule_factor; - unsigned m_approx_threshold_factor; // factor*num_eqs == max pivots to try when using approximated - bool m_elim_vars_enabled; - bool m_elim_int_vars_enabled; - bool m_branch_vars_only; // do not branch on auxiliary variables - bool m_cuts_enabled; - - // backtracking - struct scope { - bool m_bad_vars_empty; - unsigned m_conflict_eq_idx_old; - }; - - svector m_scopes; - - // Data-structures for branch & bound - unsigned_vector m_bb_var; - char_vector m_bb_lower; - char_vector m_bb_first; - mpq_buffer m_bb_k; - - - // ----------------------- - // - // Basic - // - // ----------------------- - imp(ast_manager & _m, params_ref const & p): - m(_m), - m_util(m), - m_var2expr(m), - m_allocator("arith"), - m_num_inf_manager(m_num_manager), - m_double_manager(p), - m_lu_mpq(m_num_manager, p), - m_lu_double(m_double_manager, p), - m_values(m_num_inf_manager), - m_old_values(m_num_inf_manager), - m_eq_manager(m_num_manager, m_allocator), - m_asserted_bounds(m_num_manager, m_allocator, p), - m_bounds(m_num_manager, m_allocator, p), - m_mpq_buffer(m_num_manager), - m_mpz_buffer(m_num_manager), - m_bb_k(m_num_manager) { - m_approx_forbidden = false; - m_cancel = false; - m_conflict_eq_idx = UINT_MAX; - updt_params_core(p); - reset_statistics(); - m_use_approx = false; - set_mode_core(false, false); - } - - ~imp() { - del_equations(); - del_ineq_cnstrs(); - del_elim_vars(); - } - - void updt_params(params_ref const & p) { - m_double_manager.updt_params(p); - m_asserted_bounds.updt_params(p); - m_bounds.updt_params(p); - m_lu_mpq.updt_params(p); - m_lu_double.updt_params(p); - updt_params_core(p); - } - - void updt_params_core(params_ref const & p) { - m_refactor_threshold = p.get_uint(":lu-refactor", 20); - m_blands_rule_factor = p.get_uint(":blands-rule-factor", 4); - m_elim_vars_enabled = p.get_bool(":arith-elim-vars", false); - m_elim_int_vars_enabled = p.get_bool(":arith-elim-int-vars", true); - m_approx_threshold_factor = p.get_uint(":approx-max-pivots", 32); - m_branch_vars_only = p.get_bool(":arith-branch-vars-only", true); - m_cuts_enabled = p.get_bool(":arith-cuts", false); - } - - void set_cancel(bool f) { - m_cancel = f; - } - - void reset_statistics() { - m_eliminated_vars = 0; - m_lu_factorizations = 0; - m_pivots = 0; - m_approx_pivots = 0; - m_max_l = 0; - m_max_u = 0; - m_branches = 0; - m_cuts = 0; - m_bounds.reset_statistics(); - } - - void collect_statistics(statistics & st) const { - st.update("elim tableau vars", m_eliminated_vars); - st.update("LU factorizations", m_lu_factorizations); - st.update("pivots", m_pivots); - st.update("approx pivots", m_approx_pivots); - st.update("max L", m_max_l); - st.update("max U", m_max_u); - st.update("bb decisions", m_branches); - st.update("cuts", m_cuts); - m_bounds.collect_statistics(st); - } - - void checkpoint() { - if (m_cancel) - throw strategy_exception(STE_CANCELED_MSG); - cooperate("arith"); - } - - unsigned scope_lvl() const { - return m_scopes.size(); - } - - void del_equations() { - equations::iterator it = m_equations.begin(); - equations::iterator end = m_equations.end(); - for (; it != end; ++it) - m_eq_manager.del(*it); - } - - void del_ineq_cnstrs() { - ineq_cnstrs::iterator it = m_ineq_cnstrs.begin(); - ineq_cnstrs::iterator end = m_ineq_cnstrs.end(); - for (; it != end; ++it) { - m_num_manager.del(it->m_k); - } - } - - void del_elim_vars() { - elim_vars::iterator it = m_elim_vars.begin(); - elim_vars::iterator end = m_elim_vars.end(); - for (; it != end; ++it) { - m_eq_manager.del(it->second); - } - } - - bool is_int(var x) const { - return m_asserted_bounds.is_int(x); - } - - bool is_unconstrained(var x) const { - return - !m_asserted_bounds.has_lower(x) && - !m_asserted_bounds.has_upper(x) && - m_var_occs[x].empty(); - } - - bool was_eliminated(var x) const { - return m_eliminated[x] != 0; - } - - bool basic(var x) const { - return m_basic[x] != UINT_MAX; - } - - bool nonbasic(var x) const { - return m_basic[x] == UINT_MAX; - } - - unsigned num_vars() const { - return m_var2expr.size(); - } - - bound_propagator const & bp() const { return m_use_asserted ? m_asserted_bounds : m_bounds; } - - bound_propagator & bp() { return m_use_asserted ? m_asserted_bounds : m_bounds; } - - bool has_lower(var x) const { return bp().has_lower(x); } - - bool has_upper(var x) const { return bp().has_upper(x); } - -#define MK_LOWER_METHOD(NAME, OP, NO_BOUND_RESULT) \ - bool NAME(var x) const { \ - if (!bp().has_lower(x)) \ - return NO_BOUND_RESULT; \ - if (m_use_approx) { \ - return m_double_manager.OP(m_approx_values[x], bp().approx_lower(x)); \ - } \ - else { \ - bool strict; \ - mpq const & l = bp().lower(x, strict); \ - return m_num_inf_manager.OP(m_values[x], l, strict ? pos_inf : zero_inf); \ - } \ - } - -#define MK_UPPER_METHOD(NAME, OP, NO_BOUND_RESULT) \ - bool NAME(var x) const { \ - if (!bp().has_upper(x)) \ - return NO_BOUND_RESULT; \ - if (m_use_approx) { \ - return m_double_manager.OP(m_approx_values[x], bp().approx_upper(x)); \ - } \ - else { \ - bool strict; \ - mpq const & u = bp().upper(x, strict); \ - return m_num_inf_manager.OP(m_values[x], u, strict ? neg_inf : zero_inf); \ - } \ - } - - MK_LOWER_METHOD(at_lower, eq, false); - MK_LOWER_METHOD(below_lower, lt, false); - MK_LOWER_METHOD(above_lower, gt, true); - MK_UPPER_METHOD(at_upper, eq, false); - MK_UPPER_METHOD(above_upper, gt, false); - MK_UPPER_METHOD(below_upper, lt, true); - - void save_value(var x) { - SASSERT(!m_use_approx); - if (!m_updated.contains(x)) { - m_updated.insert(x); - m_num_inf_manager.set(m_old_values[x], m_values[x]); - } - } - - void save_approx_value(var x) { - SASSERT(m_use_approx); - if (!m_approx_updated.contains(x)) { - m_approx_updated.insert(x); - m_old_approx_values[x] = m_approx_values[x]; - } - } - - bool int_feasible(var x) const { - return !is_int(x) || m_num_inf_manager.is_int(m_values[x]); - } - - void check_int(var x) { - if (!int_feasible(x)) - m_int_bad_vars.insert(x); - } - - void set_value(var x, mpq_inf const & val) { - SASSERT(!m_use_approx); - save_value(x); - m_num_inf_manager.set(m_values[x], val); - check_int(x); - } - - void set_value(var x, mpq const & val, inf_kind k) { - SASSERT(!m_use_approx); - save_value(x); - m_num_inf_manager.set(m_values[x], val, k); - check_int(x); - } - - void set_value(var x, double val) { - SASSERT(m_use_approx); - save_approx_value(x); - m_approx_values[x] = val; - } - - void acc_value(var x, mpq_inf const & delta) { - SASSERT(!m_use_approx); - save_value(x); - m_num_inf_manager.add(m_values[x], delta, m_values[x]); - check_int(x); - } - - void acc_value(var x, double val) { - SASSERT(m_use_approx); - save_approx_value(x); - m_approx_values[x] += val; - if (m_double_manager.is_zero(m_approx_values[x])) - m_approx_values[x] = 0.0; - } - - /** - \brief Assign x to its lower bound - */ - void lower2value(var x) { - if (m_use_approx) { - set_value(x, bp().approx_lower(x)); - } - else { - bool strict; - mpq const & l = bp().lower(x, strict); - set_value(x, l, strict ? pos_inf : zero_inf); - } - } - - /** - \brief Assign x to its upper bound - */ - void upper2value(var x) { - if (m_use_approx) { - set_value(x, bp().approx_upper(x)); - } - else { - bool strict; - mpq const & u = bp().upper(x, strict); - set_value(x, u, strict ? neg_inf : zero_inf); - } - } - - // ----------------------- - // - // Model Generation - // - // ----------------------- - - void update_epsilon(mpq_inf const & l, mpq_inf const & u, mpq & epsilon) { - numeral_manager & nm = m_num_manager; - if (nm.lt(l.first, u.first) && nm.gt(l.second, u.second)) { - mpq new_epsilon; - mpq tmp; - nm.sub(u.first, l.first, new_epsilon); - nm.sub(l.second, u.second, tmp); - nm.div(new_epsilon, tmp, new_epsilon); - if (nm.lt(new_epsilon, epsilon)) - nm.swap(new_epsilon, epsilon); - nm.del(new_epsilon); - nm.del(tmp); - } - SASSERT(nm.is_pos(epsilon)); - } - - void compute_epsilon(mpq & epsilon) { - m_num_manager.set(epsilon, 1); - mpq_inf v; - mpq k; - unsigned num = num_vars(); - for (unsigned x = 0; x < num; x++) { - bool strict; unsigned ts; - if (m_bounds.lower(x, k, strict, ts)) { - m_num_inf_manager.set(v, k, strict ? pos_inf : zero_inf); - update_epsilon(v, m_values[x], epsilon); - } - if (m_bounds.upper(x, k, strict, ts)) { - m_num_inf_manager.set(v, k, strict ? neg_inf : zero_inf); - update_epsilon(m_values[x], v, epsilon); - } - } - } - - void update_elim_vars_assignment() { - mpq_inf val; - mpq_inf tmp; - mpq inv_a; - unsigned i = m_elim_vars.size(); - while (i > 0) { - --i; - elim_var_info & info = m_elim_vars[i]; - m_num_inf_manager.reset(val); - var x = info.first; - unsigned x_pos = UINT_MAX; - linear_equation const & eq = *(info.second); - unsigned sz = eq.size(); - for (unsigned j = 0; j < sz; j++) { - var x_j = eq.x(j); - if (x_j == x) { - x_pos = j; - continue; - } - m_num_inf_manager.mul(m_values[x_j], eq.a(j), tmp); - m_num_inf_manager.add(val, tmp, val); - } - SASSERT(x_pos != UINT_MAX); - m_num_manager.set(inv_a, eq.a(x_pos)); - m_num_manager.inv(inv_a); - m_num_inf_manager.mul(val, inv_a, val); - m_num_inf_manager.neg(val); - m_num_inf_manager.set(m_values[x], val); - } - m_num_inf_manager.del(val); - m_num_inf_manager.del(tmp); - m_num_manager.del(inv_a); - } - - void mk_model(model * md) { - // - update_elim_vars_assignment(); - numeral_manager & nm = m_num_manager; - mpq epsilon; - mpq val; - compute_epsilon(epsilon); - for (unsigned x = 0; x < num_vars(); x++) { - expr * t = m_var2expr.get(x); - if (t == 0) - continue; - if (!is_uninterp_const(t)) - continue; - nm.set(val, m_values[x].first); - nm.addmul(val, m_values[x].second, epsilon, val); - func_decl * d = to_app(t)->get_decl(); - md->register_decl(d, m_util.mk_numeral(rational(val), is_int(x))); - } - nm.del(epsilon); - nm.del(val); - } - - // ----------------------- - // - // Backtracking - // - // ----------------------- - - void push() { - m_scopes.push_back(scope()); - scope & s = m_scopes.back(); - s.m_bad_vars_empty = m_bad_vars.empty(); - s.m_conflict_eq_idx_old = m_conflict_eq_idx; - m_bounds.push(); - m_asserted_bounds.push(); - SASSERT(m_bounds.scope_lvl() == scope_lvl()); - SASSERT(m_asserted_bounds.scope_lvl() == scope_lvl()); - } - - void pop(unsigned num_scopes) { - unsigned lvl = scope_lvl(); - SASSERT(num_scopes <= lvl); - unsigned new_lvl = lvl - num_scopes; - scope & s = m_scopes[new_lvl]; - bool bad_vars_empty = s.m_bad_vars_empty; - m_conflict_eq_idx = s.m_conflict_eq_idx_old; - m_scopes.shrink(new_lvl); - m_bounds.pop(num_scopes); - m_asserted_bounds.pop(num_scopes); - if (!bad_vars_empty) - reset_bad_vars(); - SASSERT(m_bounds.scope_lvl() == scope_lvl()); - SASSERT(m_asserted_bounds.scope_lvl() == scope_lvl()); - } - - // ----------------------- - // - // Compilation - // - // ----------------------- - - var mk_var(expr * t) { - var x; - if (t != 0) { - if (m_util.is_to_real(t)) - t = to_app(t)->get_arg(0); - if (m_expr2var.find(t, x)) - return x; - } - x = m_var2expr.size(); - m_var2expr.push_back(t); - bool is_int = true; - if (t != 0) { - m_expr2var.insert(t, x); - is_int = m_util.is_int(t); - } - m_eliminated.push_back(false); - m_basic.push_back(UINT_MAX); - m_values.push_back(mpq_inf()); - m_old_values.push_back(mpq_inf()); - m_approx_values.push_back(0.0); - m_old_approx_values.push_back(0.0); - m_asserted_bounds.mk_var(x, is_int); - m_bounds.mk_var(x, is_int); - m_var_occs.push_back(ineq_cnstr_ids()); - return x; - } - - void expr2lp(expr * t, mpq_buffer & as, var_buffer & xs) { - mpq c_mpq_val; - if (m_util.is_add(t)) { - rational c_val; - unsigned num = to_app(t)->get_num_args(); - for (unsigned i = 0; i < num; i++) { - expr * mon = to_app(t)->get_arg(i); - expr * c, * x; - if (m_util.is_mul(mon, c, x) && m_util.is_numeral(c, c_val)) { - m_num_manager.set(c_mpq_val, c_val.to_mpq()); - as.push_back(c_mpq_val); - xs.push_back(mk_var(x)); - } - else { - as.push_back(mpq(1)); - xs.push_back(mk_var(mon)); - } - } - } - else { - as.push_back(mpq(1)); - xs.push_back(mk_var(t)); - } - m_num_manager.del(c_mpq_val); - } - - var mk_lp(expr * t) { - if (m_util.is_to_real(t)) - t = to_app(t)->get_arg(0); - var x; - if (m_expr2var.find(t, x)) - return x; - - x = mk_var(t); - if (m_util.is_add(t)) { - m_mpq_buffer.reset(); - m_var_buffer.reset(); - expr2lp(t, m_mpq_buffer, m_var_buffer); - m_mpq_buffer.push_back(mpq(-1)); - m_var_buffer.push_back(x); - linear_equation * new_eq = m_eq_manager.mk(m_mpq_buffer.size(), m_mpq_buffer.c_ptr(), m_var_buffer.c_ptr(), true); - SASSERT(new_eq); - unsigned eq_idx = m_equations.size(); - m_basic[x] = eq_idx; - m_inv_basic.push_back(x); - m_equations.push_back(new_eq); - SASSERT(m_inv_basic.size() == m_equations.size()); - SASSERT(basic(x)); - } - return x; - } - - void mk_ineq_cnstr(var x, mpq const & k, bool lower, atom_id p) { - unsigned cnstr_id = m_ineq_cnstrs.size(); - m_ineq_cnstrs.push_back(ineq_cnstr()); - ineq_cnstr & cnstr = m_ineq_cnstrs.back(); - cnstr.m_x = x; - m_num_manager.set(cnstr.m_k, k); - cnstr.m_approx_k = m_num_manager.get_double(k); - cnstr.m_lower = lower; - cnstr.m_atom = p; - m_atom2ineq_cnstr.reserve(p+1, UINT_MAX); - m_atom2ineq_cnstr[p] = cnstr_id; - m_var_occs[x].push_back(cnstr_id); - } - - void mk_ineq(expr * t, bool neg, atom_id p) { - TRACE("mk_ineq", tout << "mk_ineq, neg: " << neg << ", p: " << p << "\n" << mk_ismt2_pp(t, m) << "\n";); - SASSERT(m_util.is_le(t) || m_util.is_ge(t)); - SASSERT(!neg || p == null_atom_id); - - bool strict = false; - bool le; - if (m_util.is_le(t)) { - if (neg) { - le = false; - strict = true; - } - else { - le = true; - } - } - else { - SASSERT(m_util.is_ge(t)); - if (neg) { - le = true; - strict = true; - } - else { - le = false; - } - } - expr * lhs = to_app(t)->get_arg(0); - expr * rhs = to_app(t)->get_arg(1); - - SASSERT(m_util.is_numeral(rhs)); - rational c; - m_util.is_numeral(rhs, c); - - var x = mk_lp(lhs); - mpq c_prime; - m_num_manager.set(c_prime, c.to_mpq()); - TRACE("mk_ineq", tout << "le: " << le << ", strict: " << strict << ", c: " << c << ", c_prime: " << - m_num_manager.to_string(c_prime) << "\n";); - - if (p == null_atom_id) { - // inequality is an axiom - if (le) - assert_upper(x, c_prime, strict); - else - assert_lower(x, c_prime, strict); - } - else { - SASSERT(!strict); - mk_ineq_cnstr(x, c_prime, !le, p); - } - m_num_manager.del(c_prime); - } - - void assert_upper(var x, mpq const & k, bool strict) { - m_bounds.assert_upper(x, k, strict); - m_asserted_bounds.assert_upper(x, k, strict); - if (above_upper(x)) - m_bad_vars.insert(x); - } - - void assert_lower(var x, mpq const & k, bool strict) { - m_bounds.assert_lower(x, k, strict); - m_asserted_bounds.assert_lower(x, k, strict); - if (below_lower(x)) - m_bad_vars.insert(x); - } - - // ----------------------- - // - // Approximate <-> Precise - // - // ----------------------- - - /** - \brief "Copy" nonbasic m_values to m_approx_values - */ - void mpq2double_nonbasic_values() { - unsigned num = num_vars(); - for (unsigned x = 0; x < num; x++) { - if (nonbasic(x)) - m_approx_values[x] = m_num_inf_manager.get_double(m_values[x]); - } - } - - /** - \brief "Copy" nonbasic m_approx_values to m_values. - It actually checks whether m_approx_values[x] is at lower or uppers, - and copy the corresponding value. - */ - void double2mpq_nonbasic_values() { - unsigned num = num_vars(); - for (unsigned x = 0; x < num; x++) { - if (nonbasic(x)) { - if (at_lower(x)) { - bool strict; - mpq const & l = bp().lower(x, strict); - m_num_inf_manager.set(m_values[x], l, strict ? pos_inf : zero_inf); - } - else if (at_upper(x)) { - bool strict; - mpq const & u = bp().upper(x, strict); - m_num_inf_manager.set(m_values[x], u, strict ? neg_inf : zero_inf); - } - else { - m_num_inf_manager.set(m_values[x], 0); - } - } - } - } - - /** - \brief Set the value of the basic variables using the value of the non-basic ones. - */ - template - void update_basic_values(LU & _lu, Values & values, NumInfMng & infm) { - unsigned num = m_equations.size(); - typename LU::dense_vector & row = _lu.get_tmp_row(num_vars()); - typename NumInfMng::numeral val; - typename NumInfMng::numeral aux; - typename LU::manager & nm = _lu.m(); - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - var x_b = m_inv_basic[eq_idx]; - row.reset(); - get_row(_lu, eq_idx, row, true, m_use_asserted, true); - infm.reset(val); - typename LU::dense_vector::iterator it = row.begin_non_zeros(); - typename LU::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x_n = *it; - if (nm.is_zero(row[x_n])) - continue; - infm.mul(values[x_n], row[x_n], aux); - infm.add(val, aux, val); - } - if (infm.is_zero(val)) { - infm.set(values[x_b], 0); - } - else { - infm.neg(val); - infm.swap(values[x_b], val); - } - } - infm.del(val); - infm.del(aux); - } - - void update_mpq_basic_values() { - update_basic_values(m_lu_mpq, m_values, m_num_inf_manager); - } - - void update_double_basic_values() { - update_basic_values(m_lu_double, m_approx_values, m_double_manager); - } - - /** - \brief Faster version of update_basic_values. Instead of extracting rows, - I comput the Column C = N*V_n, where N is the matrix containing the coefficient of the non-basic variables, - and V_n is the assignment of the non_basic variables. Then, I solve Ax = C - The resultant column x is the assignment for the basic variables. - - The assignment is a mpq_inf, so the update is performed in two steps. - inf == true, the infinitesimal part is updated, - inf == false, the rational part is updated - */ - void fast_update_basic_values_mpq(bool inf) { - lu_mpq::dense_vector & C = m_lu_mpq.get_tmp_col(); - C.reset(); - mpq aux; - // 1. Compute column C' - unsigned num = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - mpq & c_i = C.get(eq_idx); - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - var x = eq.x(i); - if (basic(x)) - continue; - if (inf) - m_num_manager.mul(eq.a(i), m_values[x].second, aux); - else - m_num_manager.mul(eq.a(i), m_values[x].first, aux); - m_num_manager.add(c_i, aux, c_i); - } - } - TRACE("update_basic_values", tout << "inf: " << inf << " "; C.display_non_zeros(tout); tout << "\n";); - // 2. Solve - m_lu_mpq.solve_Ax_eq_y(C); - C.elim_zeros(); - // 3. Update basic variable assignment - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - var x_b = m_inv_basic[eq_idx]; - mpq & c_i = C.get(eq_idx); - m_num_manager.neg(c_i); - TRACE("update_basic_values", tout << "inf: " << inf << " x" << x_b << " " << m_num_manager.to_string(c_i) << "\n";); - if (inf) - m_num_manager.swap(m_values[x_b].second, c_i); - else - m_num_manager.swap(m_values[x_b].first, c_i); - } - m_num_manager.del(aux); - } - - void fast_update_mpq_basic_values() { - fast_update_basic_values_mpq(false); - fast_update_basic_values_mpq(true); - SASSERT(check_eqs_satisfied_core()); // use core to make sure it will be checked even when m_use_approx = false - } - - void fast_update_double_basic_values() { - lu_double::dense_vector & C = m_lu_double.get_tmp_col(); - // 1. Compute column C' - unsigned num = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - double & c_i = C.get(eq_idx); - c_i = 0.0; - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - var x = eq.x(i); - if (basic(x)) - continue; - c_i += eq.approx_a(i) * m_approx_values[x]; - } - } - TRACE("update_basic_values", C.display_non_zeros(tout); tout << "\n";); - // 2. Solve - m_lu_double.solve_Ax_eq_y(C); - C.elim_zeros(); - // 3. Update basic variable assignment - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - var x_b = m_inv_basic[eq_idx]; - m_approx_values[x_b] = -C[eq_idx]; - } - } - - void reset_bad_vars() { - m_bad_vars.reset(); - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - if (below_lower(x) || above_upper(x)) - m_bad_vars.insert(x); - } - } - - void reset_int_bad_vars() { - m_int_bad_vars.reset(); - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - check_int(x); - } - } - - void set_mode_core(bool use_approx, bool use_asserted) { - if (m_use_approx != use_approx) { - if (use_approx) { - init_lu_double(); - mpq2double_nonbasic_values(); - // update_double_basic_values(); - fast_update_double_basic_values(); - } - else { - init_lu_mpq(); - double2mpq_nonbasic_values(); - // update_mpq_basic_values(); - fast_update_mpq_basic_values(); - } - } - m_approx_updated.reset(); - m_updated.reset(); - m_use_approx = use_approx; - m_use_asserted = use_asserted; - reset_bad_vars(); - if (!m_use_approx) - reset_int_bad_vars(); - } - - void set_mode(bool use_approx, bool use_asserted) { - if (use_approx == m_use_approx && use_asserted == m_use_asserted) - return; - set_mode_core(use_approx, use_asserted); - TRACE("set_mode", display(tout);); - } - - // ----------------------- - // - // Simplex & make_feasible - // - // ----------------------- - - template - void update_lu_stats(LU const & _lu) { - unsigned l_sz = _lu.L_size(); - unsigned u_sz = _lu.U_size(); - if (l_sz > m_max_l) - m_max_l = l_sz; - if (u_sz > m_max_u) - m_max_u = u_sz; - } - - template - void init_lu_core(LU & _lu) { - m_lu_factorizations++; - TRACE("arith_lu", display(tout);); - typename LU::numeral a; - unsigned num_eqs = m_equations.size(); - _lu.init(num_eqs); - for (unsigned i = 0; i < num_eqs; i++) { -#ifdef Z3DEBUG - unsigned num_entries_added = 0; -#endif - linear_equation const & eq = *(m_equations[i]); - unsigned sz = eq.size(); - for (unsigned j = 0; j < sz; j++) { - var x = eq.x(j); - if (basic(x)) { - eq.get_a(_lu.m(), j, a); - _lu.add_entry(a, m_basic[x]); - DEBUG_CODE(num_entries_added++;); - } - } - SASSERT(num_entries_added <= num_eqs); - _lu.end_row(); - } - _lu.m().del(a); - _lu.fact(); - update_lu_stats(_lu); - TRACE("init_lu", display(tout);); - } - - void init_lu_double() { init_lu_core(m_lu_double); } - void init_lu_mpq() { init_lu_core(m_lu_mpq); } - - void init_lu() { - if (m_use_approx) - init_lu_double(); - else - init_lu_mpq(); - } - - // Extract a column from m_equations. The result is stored in c. - template - void get_column(var j, Vector & c) { - TRACE("get_column", tout << "get_column x" << j << "\n"; display_eqs(tout);); - typename Vector::manager & m = c.m(); - c.reset(); - eq_occs const & occs = m_eq_occs[j]; - for (unsigned i = 0; i < occs.size(); i++) { - eq_occ const & occ = occs[i]; - unsigned eq_idx = occ.m_idx; - linear_equation const & eq = *(m_equations[eq_idx]); - SASSERT(eq.x(occ.m_pos) == j); - eq.get_a(m, occ.m_pos, c.get(eq_idx)); - } - TRACE("get_column", tout << "result: "; c.display_non_zeros(tout); tout << "\n";); - } - - // Extract a non basic column. The result is stored in c. - template - void get_nonbasic_column(LU & _lu, var j, typename LU::dense_vector & c) { - get_column(j, c); - _lu.solve_Ax_eq_y(c); - } - - void get_nonbasic_column_double(var j, lu_double::dense_vector & c) { get_nonbasic_column(m_lu_double, j, c); } - void get_nonbasic_column_mpq(var j, lu_mpq::dense_vector & c) { get_nonbasic_column(m_lu_mpq, j, c); } - - // Get the linear combination needed for extracting a row. - template - void get_lin_comb_for_row(LU & _lu, unsigned eq_idx, typename LU::dense_vector & r) { - typename LU::numeral one(1); - SASSERT(eq_idx < m_equations.size()); - r.reset(); - _lu.m().set(r.get(eq_idx), one); - _lu.solve_xA_eq_y(r); - } - - - // Apply the given linear combination to the equaltions in m_equations, and store - // the result in r. - // If include_fixed = false, then fixed variables are ignored. - // If only_nonbasic = true, then only non-basic variables are considered. - // If use_asserted = true, then m_asserted_bounds is used for detecting fixed variables, otherwise m_bounds is used. - template - void extract_row(Vector const & lin_comb, Vector & r, bool only_nonbasic = true, bool use_asserted = false, bool include_fixed = false) const { - r.reset(); - bound_propagator const & bp = use_asserted ? m_asserted_bounds : m_bounds; - typename Vector::manager & m = lin_comb.m(); - typename Vector::numeral a; - typename Vector::iterator it = lin_comb.begin_non_zeros(); - typename Vector::iterator end = lin_comb.end_non_zeros(); - for (; it != end; ++it) { - unsigned eq_idx = *it; - typename Vector::numeral const & b = lin_comb[eq_idx]; - if (m.is_zero(b)) - continue; - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - var x_i = eq.x(i); - if (only_nonbasic && basic(x_i)) - continue; - if (!include_fixed && bp.is_fixed(x_i)) - continue; - eq.get_a(m, i, a); - typename Vector::numeral & r_i = r.get(x_i); - m.addmul(r_i, a, b, r_i); - } - } - r.elim_zeros(); - m.del(a); - } - - // Get the non-basic variables occurring in the given row of B^{-1}N. - template - void get_row(LU & _lu, unsigned eq_idx, typename LU::dense_vector & r, - bool only_nonbasic = true, bool use_asserted = false, bool include_fixed = false) { - TRACE("get_row", tout << "original: "; m_eq_manager.display(tout, *(m_equations[eq_idx])); tout << "\n";); - - typename LU::dense_vector & lc = _lu.get_tmp_vector(); - get_lin_comb_for_row(_lu, eq_idx, lc); - extract_row(lc, r, only_nonbasic, use_asserted, include_fixed); - - TRACE("get_row", - tout << "eq " << eq_idx << "\n"; - tout << "linear combination: "; r.display_non_zeros(tout); tout << "\n";; - tout << "result: "; r.display_pol(tout); tout << "\n";); - } - - void get_row_double(unsigned eq_idx, lu_double::dense_vector & r, - bool only_nonbasic = true, bool use_asserted = false, bool include_fixed = false) { - get_row(m_lu_double, eq_idx, r, only_nonbasic, use_asserted, include_fixed); - } - void get_row_mpq(unsigned eq_idx, lu_mpq::dense_vector & r, - bool only_nonbasic = true, bool use_asserted = false, bool include_fixed = false) { - get_row(m_lu_mpq, eq_idx, r, only_nonbasic, use_asserted, include_fixed); - } - - void tst_extract_non_basic_columns(std::ostream & out) { - unsigned sz = m_lu_double.size(); - lu_double::dense_vector v(m_double_manager, sz); - out << "columns:\n"; - for (var x = 0; x < num_vars(); x++) { - if (basic(x) || was_eliminated(x)) - continue; - v.reset(); - get_nonbasic_column_double(x, v); - out << "x" << x << ": "; - v.display(out); - out << "\n"; - } - } - - void tst_extract_rows(std::ostream & out) { - lu_double::dense_vector v(m_double_manager, num_vars()); - out << "rows:\n"; - unsigned num_eqs = m_equations.size(); - for (unsigned i = 0; i < num_eqs; i++) { - get_row_double(i, v); - out << "eq " << i << ": "; - v.display_pol(out); - out << "\n"; - } - } - - template - void pivot(LU & _lu, var x_b, var x_n) { - if (m_use_approx) - m_approx_pivots++; - else - m_pivots++; - SASSERT(basic(x_b)); - SASSERT(!basic(x_n)); - unsigned eq_idx = m_basic[x_b]; - SASSERT(m_inv_basic[eq_idx] == x_b); - unsigned normalized_threshold = std::min((m_equations.size()/10) + 1, m_refactor_threshold); -#if 1 - // TODO: incremental update is producing too much imprecision when using floating point numbers. - // So: I'm disabling it for now. - if (!_lu.m().precise()) normalized_threshold = 0; -#endif - if (_lu.get_num_replacements() < normalized_threshold) { - try { - typename LU::dense_vector & c = _lu.get_tmp_col(); - get_column(x_n, c); - TRACE("pivot", tout << "column x" << m_basic[x_b] << " "; c.display_non_zeros(tout); tout << "\n";); - _lu.replace_column(m_basic[x_b], c); - update_lu_stats(_lu); - m_basic[x_b] = UINT_MAX; - m_basic[x_n] = eq_idx; - m_inv_basic[eq_idx] = x_n; - TRACE("pivot_bug", display(tout);); - CASSERT("arith", !_lu.m().precise() || check_lu()); - return; - } - catch (lu_exception) { - IF_VERBOSE(ST_VERBOSITY_LVL, verbose_stream() << "(arith-approx-failed)\n";); - } - } - // refactor from scratch - m_basic[x_b] = UINT_MAX; - m_basic[x_n] = eq_idx; - m_inv_basic[eq_idx] = x_n; - init_lu_core(_lu); - CASSERT("arith", !_lu.m().precise() || check_lu()); - } - - void pivot_double(var x_b, var x_n) { pivot(m_lu_double, x_b, x_n); } - void pivot_mpq(var x_b, var x_n) { pivot(m_lu_mpq, x_b, x_n); } - - template - void tst_random_pivoting(LU & _lu, unsigned num) { - TRACE("random_pivoting", display_eqs(tout);); - init_lu_core(_lu); - random_gen rgen; - - typename LU::numeral small(10000); - _lu.m().inv(small); - typename LU::numeral neg_small; - _lu.m().set(neg_small, small); - _lu.m().neg(neg_small); - - typename LU::dense_vector row(_lu.m(), num_vars()); - unsigned num_eqs = m_equations.size(); - for (unsigned i = 0; i < num; i++) { - verbose_stream() << "+"; verbose_stream().flush(); - // select random equation/row - TRACE("random_pivoting", display_basic(tout); display_LU(tout, _lu);); - unsigned eq_idx = rgen() % num_eqs; - var x_b = m_inv_basic[eq_idx]; - get_row(_lu, eq_idx, row); - TRACE("random_pivoting", tout << "x" << x_b << " : "; row.display_pol(tout); tout << "\n";); - TRACE("pivot_row", tout << "x" << x_b << " : "; row.display_pol(tout); tout << "\n";); - typename LU::dense_vector::iterator it = row.begin_non_zeros(); - typename LU::dense_vector::iterator end = row.end_non_zeros(); - if (it == end) { - // row doesn't have non-basic variable - TRACE("random_pivoting", tout << "eq_idx: " << eq_idx << " does not have non-basic variables\n";); - continue; - } - unsigned num_non_zeros = end - it; - var x_n = *(it + (rgen() % num_non_zeros)); - if (!LU::manager::precise()) { - if (_lu.m().lt(neg_small, row[x_n]) && _lu.m().lt(row[x_n], small)) { - verbose_stream() << "*"; - continue; - } - } - TRACE("random_pivoting", tout << "pivoting x" << x_b << " with x" << x_n << "\n";); - pivot(_lu, x_b, x_n); - } - } - - /** - \brief Check LU mpq (this method does not really work for m_lu_double due to floating point imprecision). - */ - bool check_lu() const { - if (m_use_approx) - return true; - lu_mpq::dense_vector row(const_cast(this)->m_num_manager, num_vars()); - unsigned num_eqs = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num_eqs; eq_idx++) { - var x_b = m_inv_basic[eq_idx]; - row.reset(); - const_cast(this)->get_row_mpq(eq_idx, row, false /* get basic too */, false, true /* also include fixed vars */); - TRACE("check_lu", tout << "x" << x_b << ", eq " << eq_idx << ": "; row.display_pol(tout); tout << "\n";); - // row must contain one and only one basic variable: x_b - // The coefficient of x_b must be 1 - bool found_x_b = false; - lu_mpq::dense_vector::iterator it = row.begin_non_zeros(); - lu_mpq::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x = *it; - if (m_num_manager.is_zero(row[x])) - continue; - if (x == x_b) { - CTRACE("arith_bug", !m_num_manager.is_one(row[x]), tout << "x" << x_b << ": "; row.display_pol(tout); tout << "\n"; - display(tout);); - SASSERT(m_num_manager.is_one(row[x])); - found_x_b = true; - continue; - } - CTRACE("arith_bug", basic(x), tout << "row " << eq_idx << " contains unexpected basic variable x" << x << "\n"; - row.display_pol(tout); tout << "\n"; display(tout);); - SASSERT(!basic(x)); - } - SASSERT(found_x_b); - } - return true; - } - - template - void update_dependents(LU & _lu, Values & values, NumInfMng & infm, var x_n, Numeral const & old_val) { - Numeral aux; - Numeral delta; - infm.sub(values[x_n], old_val, delta); - typename LU::dense_vector & c = _lu.get_tmp_col(); - typename LU::dense_vector::manager & nm = c.m(); - get_nonbasic_column(_lu, x_n, c); - TRACE("fix_nonbasic_var", tout << "fixing x" << x_n << ", old_val: " << infm.to_string(old_val) << ", new_val: " << - infm.to_string(values[x_n]) << ", delta: " << infm.to_string(delta) << "\n"; - tout << "column: "; c.display_non_zeros(tout); tout << "\n";); - typename LU::dense_vector::iterator it = c.begin_non_zeros(); - typename LU::dense_vector::iterator end = c.end_non_zeros(); - for (; it != end; ++it) { - unsigned eq_idx = *it; - if (nm.is_zero(c[eq_idx])) - continue; - var x_b = m_inv_basic[eq_idx]; - SASSERT(m_basic[x_b] == eq_idx); - infm.mul(delta, c[eq_idx], aux); - infm.neg(aux); - TRACE("fix_nonbasic_var", tout << "adjusting x" << x_b << " of: " << eq_idx << " with " << infm.to_string(aux) << "\n";); - acc_value(x_b, aux); - if (below_lower(x_b) || above_upper(x_b)) - m_bad_vars.insert(x_b); - } - infm.del(aux); - infm.del(delta); - } - - /** - \brief Fix a nonbasic variable by moving it to offending bound and propagating the - update to the basic variables. - */ - template - void fix_nonbasic_var(LU & _lu, Values & values, NumInfMng & infm, var x_n) { - SASSERT(below_lower(x_n) || above_upper(x_n)); - SASSERT(nonbasic(x_n)); - typename NumInfMng::numeral old_val; - infm.set(old_val, values[x_n]); - if (below_lower(x_n)) { - lower2value(x_n); - } - else { - SASSERT(above_upper(x_n)); - upper2value(x_n); - } - update_dependents(_lu, values, infm, x_n, old_val); - infm.del(old_val); - } - - void fix_nonbasic_var(var x) { - if (!below_lower(x) && !above_upper(x)) - return; // nothing to be done - SASSERT(nonbasic(x)); - if (m_use_approx) - fix_nonbasic_var(m_lu_double, m_approx_values, m_double_manager, x); - else - fix_nonbasic_var(m_lu_mpq, m_values, m_num_inf_manager, x); - } - - /** - \brief Remove the given variables from m_bad_vars. - */ - void erase_from_bad_vars(var_set & bad_vars, var_buffer const & vars) { - var_buffer::const_iterator it2 = vars.begin(); - var_buffer::const_iterator end2 = vars.end(); - for (; it2 != end2; ++it2) { - bad_vars.erase(*it2); - SASSERT(!bad_vars.contains(*it2)); - } - } - - var_buffer m_to_delete; - - void fix_nonbasic_vars() { - TRACE("fix_nonbasic_vars", display_LU(tout);); - m_to_delete.reset(); - unsigned sz = m_bad_vars.size(); - for (unsigned i = 0; i < sz; i++) { - var x = m_bad_vars[i]; - if (basic(x)) - continue; - TRACE("fix_nonbasic_vars", tout << "fixed x" << x << "\n";); - fix_nonbasic_var(x); - m_to_delete.push_back(x); - } - - erase_from_bad_vars(m_bad_vars, m_to_delete); - SASSERT(check_no_nonbasic_bad_var()); - } - - /** - \brief Remove satisfied variables from m_bad_vars - */ - void cleanup_bad_vars() { - m_to_delete.reset(); - var_set::iterator it = m_bad_vars.begin(); - var_set::iterator end = m_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - if (!below_lower(x) && !above_upper(x)) - m_to_delete.push_back(x); - } - erase_from_bad_vars(m_bad_vars, m_to_delete); - } - - void cleanup_int_bad_vars() { - m_to_delete.reset(); - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - TRACE("int_bad_vars", tout << "x" << x << ", int_feasible: " << int_feasible(x) << ", val: " - << m_num_inf_manager.to_string(m_values[x]) << "\n";); - if (int_feasible(x)) - m_to_delete.push_back(x); - } - erase_from_bad_vars(m_int_bad_vars, m_to_delete); - } - - /** - \brief Return the smallest variable in m_bad_vars. - */ - var get_smallest_bad_var() const { - var r = null_var; // NOTE: null_var is the biggest variable - var_set::iterator it = m_bad_vars.begin(); - var_set::iterator end = m_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - SASSERT(x < null_var); - if (x < r) - r = x; - } - return r; - } - - /** - \brief Return the variable in m_bad_vars with the least/greatest error - */ - template - var get_lg_error_bad_var() { - var r = null_var; - if (m_use_approx) { - double error_r; - double error_x; - var_set::iterator it = m_bad_vars.begin(); - var_set::iterator end = m_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - if (below_lower(x)) - error_x = bp().approx_lower(x) - m_approx_values[x]; - else if (above_upper(x)) - error_x = m_approx_values[x] - bp().approx_upper(x); - else - continue; - if (r == null_var || (LEAST && error_x < error_r) || (!LEAST && error_x > error_r)) { - r = x; - error_r = error_x; - } - } - TRACE("get_bad_var", tout << "x" << r << " error: " << error_r << "\n";); - return r; - } - else { - mpq error_r; // ignore infinitesimals - mpq error_x; - var_set::iterator it = m_bad_vars.begin(); - var_set::iterator end = m_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - if (below_lower(x)) - m_num_manager.sub(bp().lower(x), m_values[x].first, error_x); - else if (above_upper(x)) - m_num_manager.sub(m_values[x].first, bp().upper(x), error_x); - else - continue; - SASSERT(m_num_manager.is_nonneg(error_x)); - if (r == null_var || (LEAST && m_num_manager.lt(error_x, error_r)) || (!LEAST && m_num_manager.gt(error_x, error_r))) { - r = x; - m_num_manager.swap(error_x, error_r); - } - } - m_num_manager.del(error_r); - m_num_manager.del(error_x); - TRACE("get_bad_var", tout << "x" << r << " error: " << m_num_manager.to_string(error_r) << "\n";); - return r; - } - } - - /** - \brief Return the variable in m_bad_vars with the greatest error - */ - var get_least_error_bad_var() { return get_lg_error_bad_var(); } - - /** - \brief Return the variable in m_bad_vars with the least error - */ - var get_greatest_error_bad_var() { return get_lg_error_bad_var(); } - - unsigned get_num_bounds(var x) const { - unsigned r = 0; - if (has_lower(x)) r++; - if (has_upper(x)) r++; - return r; - } - - // Return true if x1 is a better pivot than x2 - template - bool better_pivot(var x_1, var x_2, Vector const & row) const { - SASSERT(x_1 != null_var); - if (x_2 == null_var) - return true; - typename Vector::manager & nm = row.m(); - unsigned num_bounds1 = get_num_bounds(x_1); - unsigned num_bounds2 = get_num_bounds(x_2); - if (num_bounds1 == 0 && num_bounds2 > 0) - return true; - if (num_bounds1 > 0 && num_bounds2 == 0) - return false; - if (nm.gt(row[x_1], row[x_2])) - return true; - if (nm.lt(row[x_1], row[x_2])) - return false; - unsigned num_occs1 = m_eq_occs[x_1].size(); - unsigned num_occs2 = m_eq_occs[x_2].size(); - return num_occs1 < num_occs2; - } - - template - var select_pivot(LU & _lu, Values & values, NumInfMng & infm, var x_b, bool is_below, bool blands_rule) { - SASSERT(basic(x_b)); - typename LU::dense_vector & row = _lu.get_tmp_row(num_vars()); - typename LU::dense_vector::manager & nm = row.m(); - unsigned eq_idx = m_basic[x_b]; - get_row(_lu, eq_idx, row, true, m_use_asserted, false /* there is not point in collecting fixed variables */); - TRACE("select_pivot", tout << "select_pivot x_b: x" << x_b << ", is_below: " << is_below << "\n"; - bp().display_var_bounds(tout, x_b, true, true); tout << "\nval: " << infm.to_string(values[x_b]) << "\n"; - row.display_pol(tout); tout << "\n"; - tout << "below_lower(x_b): " << below_lower(x_b) << "\n"; - tout << "above_upper(x_b): " << above_upper(x_b) << "\n";); - var r = null_var; - typename LU::dense_vector::iterator it = row.begin_non_zeros(); - typename LU::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x_n = *it; - if (nm.is_zero(row[x_n])) - continue; // leftover - bool is_neg = is_below ? nm.is_neg(row[x_n]) : nm.is_pos(row[x_n]); - bool is_pos = !is_neg; - if ((is_pos && above_lower(x_n)) || (is_neg && below_upper(x_n))) { - // x_n is a candidate for pivoting - if (blands_rule) { - if (x_n < r) { - r = x_n; - TRACE("select_pivot", tout << "new-candidate: x" << r << "\n";); - } - } - else if (better_pivot(x_n, r, row)) { - r = x_n; - TRACE("select_pivot", tout << "new-candidate: x" << r << ", num-bounds: " << get_num_bounds(r) - << " num-occs: " << m_eq_occs[r].size() << "\n";); - } - } - } - return r; - } - - /** - \brief Fix a basic variable. - */ - template - bool fix_basic_var(LU & _lu, Values & values, NumInfMng & infm, var x_b, bool blands_rule) { - bool is_below; - if (below_lower(x_b)) { - is_below = true; - } - else if (above_upper(x_b)) { - is_below = false; - } - else { - return true; // nothing to be done - } - var x_n = select_pivot(_lu, values, infm, x_b, is_below, blands_rule); - if (x_n == null_var) - return false; - SASSERT(basic(x_b)); - SASSERT(nonbasic(x_n)); - TRACE("fix_basic_var", tout << "pivoting x" << x_b << " x" << x_n << "\n";); - pivot(_lu, x_b, x_n); - SASSERT(nonbasic(x_b)); - fix_nonbasic_var(_lu, values, infm, x_b); - TRACE("fix_basic_var", tout << "x" << x_b << " -> " << infm.to_string(values[x_b]) << "\n"; - bp().display_var_bounds(tout, x_b); tout << "\n";); - SASSERT(!below_lower(x_b)); - SASSERT(!above_upper(x_b)); - return true; - } - - bool fix_basic_var(var x_b, bool blands_rule) { - if (m_use_approx) - return fix_basic_var(m_lu_double, m_approx_values, m_double_manager, x_b, blands_rule); - else - return fix_basic_var(m_lu_mpq, m_values, m_num_inf_manager, x_b, blands_rule); - } - - // Debugging: make sure m_bad_vars does not contain nonbasic variables. - bool check_no_nonbasic_bad_var() const { - var_set::iterator it = m_bad_vars.begin(); - var_set::iterator end = m_bad_vars.end(); - for (; it != end; ++it) { - CTRACE("arith_bug", nonbasic(*it), tout << "nonbasic var at bad_vars x" << *it << "\n";); - SASSERT(!nonbasic(*it)); - } - return true; - } - - void set_conflict(var x_b) { - m_conflict_eq_idx = m_basic[x_b]; - } - - bool inconsistent() const { - return m_conflict_eq_idx != UINT_MAX || m_bounds.inconsistent() || m_asserted_bounds.inconsistent(); - } - - void reset_updated() { - if (m_use_approx) - m_approx_updated.reset(); - else - m_updated.reset(); - } - -#define DISPLAY_STAT(NAME, VAL) if (VAL > 0) out << " " << NAME << " " << VAL; - - void display_progress(std::ostream & out) const { - out << "(arith"; - DISPLAY_STAT(":pivots", m_pivots); - DISPLAY_STAT(":approx-pivots", m_approx_pivots); - DISPLAY_STAT(":branches", m_branches); - DISPLAY_STAT(":cuts", m_cuts); - out << ")\n"; - } - - /** - \brief Try to satisfy all bounds. - Result: - l_true: succeeded - l_false: problem is unsat - l_undef: gave up - */ - lbool make_feasible_core(unsigned max_pivots = UINT_MAX) { - if (inconsistent()) - return l_false; - TRACE("make_feasible_detail", display(tout);); - if (m_bad_vars.empty()) - return l_true; - - reset_updated(); - TRACE("make_feasible_begin", display(tout);); - - CASSERT("arith", check_eqs_satisfied()); - CASSERT("arith", check_bad_vars()); - fix_nonbasic_vars(); - - // limit for switching to blands rule - unsigned limit = num_vars() * m_blands_rule_factor; - unsigned counter = 0; - - while (true) { - CASSERT("arith", check_bad_vars()); - CASSERT("arith", check_eqs_satisfied()); - CASSERT("arith", check_basic_assignment()); - CASSERT("arith", check_no_nonbasic_bad_var()); - TRACE("make_feasible_step", display(tout);); - checkpoint(); - counter++; - cleanup_bad_vars(); - if (m_bad_vars.empty()) { - TRACE("make_feasible", tout << "satisfied:\n"; display(tout);); - return l_true; - } - // var x_b = counter >= limit ? get_smallest_bad_var() : get_least_error_bad_var(); - var x_b = counter >= limit ? get_smallest_bad_var() : get_greatest_error_bad_var(); - // verbose_stream() << "x" << x_b << " "; verbose_stream().flush(); - TRACE("make_feasible", tout << "next var to be fixed: x" << x_b << "\n";); - SASSERT(basic(x_b)); - if (!fix_basic_var(x_b, counter >= limit)) { - TRACE("make_feasible", tout << "inconsistent:\n"; display(tout);); - SASSERT(basic(x_b)); - set_conflict(x_b); - return l_false; - } - m_bad_vars.erase(x_b); -#ifndef _EXTERNAL_RELEASE - IF_VERBOSE(ST_VERBOSITY_LVL, if (counter % 100 == 0) display_progress(verbose_stream());); -#endif - if (counter > max_pivots) - return l_undef; - } - } - - void reset_conflict() { - m_conflict_eq_idx = UINT_MAX; - } - - unsigned_vector m_cached_basic; - - /** - \brief When using floating point numbers, we may reach an "invalid" basis. - We say a basis is invalid the corresponding matrix is singular. - To avoid this problem, we cache the last "valid" basis. - */ - void cache_basis() { - m_cached_basic.reset(); - unsigned_vector::iterator it = m_basic.begin(); - unsigned_vector::iterator end = m_basic.end(); - for (; it != end; ++it) - m_cached_basic.push_back(*it); - } - - /** - \brief Restore last cached basis. - */ - void restore_basis() { - SASSERT(m_basic.size() == m_cached_basic.size()); - unsigned sz = m_basic.size(); - for (var x = 0; x < sz; x++) { - if (m_cached_basic[x] != UINT_MAX) { - // variables was on the basis - m_basic[x] = m_cached_basic[x]; - m_inv_basic[m_basic[x]] = x; - } - else { - // variable was not on the basis - m_basic[x] = UINT_MAX; - } - } - } - - lbool make_feasible_approx_then_precise() { - // find "promising" basis using approx. - cache_basis(); - try { - set_mode(true, m_use_asserted); - unsigned limit = m_equations.size() * m_approx_threshold_factor; - lbool r = make_feasible_core(limit); - if (r == l_undef) { - // approximation failed to satisfy all constraints. - // so, disable it. - m_approx_forbidden = true; - } - } - catch (lu_exception) { - IF_VERBOSE(ST_VERBOSITY_LVL, verbose_stream() << "(arith-approx-failed)\n";); - restore_basis(); - } - reset_conflict(); // do not trust approx solver - // try again using precise - set_mode(false, m_use_asserted); - TRACE("make_feasible_approx", tout << "second round m_use_approx: " << m_use_approx << "\n";); - try { - // may fail because the basis computed by the approximation is not valid. - return make_feasible_core(); - } - catch (lu_exception) { - restore_basis(); - init_lu_mpq(); - return make_feasible_core(); - } - } - - lbool make_feasible() { - if (inconsistent()) - return l_false; - if (m_bad_vars.empty()) - return l_true; - SASSERT(check_basic_assignment()); - CASSERT("arith", check_bad_vars()); - - lbool r; - if (m_approx_threshold_factor == 0 || m_approx_forbidden) - r = make_feasible_core(); - else - r = make_feasible_approx_then_precise(); - - CASSERT("arith", check_bad_vars()); - SASSERT(r != l_true || check_bounds_satisfied()); - SASSERT(check_basic_assignment()); - - if (r != l_true) - restore_assignment(); - - cleanup_int_bad_vars(); - - TRACE("make_feasible_result", tout << "r: " << r << "\n"; display(tout);); - return r; - } - - void restore_assignment() { - CASSERT("arith", check_eqs_satisfied()); - CASSERT("arith", check_bad_vars()); - TRACE("restore_assignment", tout << "restore_assignment:\n"; display_assignment(tout);); - var_set::iterator it1 = m_approx_updated.begin(); - var_set::iterator end1 = m_approx_updated.end(); - for (; it1 != end1; ++it1) { - var x = *it1; - m_approx_values[x] = m_old_approx_values[x]; - } - m_approx_updated.reset(); - - var_set::iterator it2 = m_updated.begin(); - var_set::iterator end2 = m_updated.end(); - for (; it2 != end2; ++it2) { - var x = *it2; - m_num_inf_manager.swap(m_values[x], m_old_values[x]); - check_int(x); - } - m_updated.reset(); - - SASSERT(m_approx_updated.empty()); - SASSERT(m_updated.empty()); - TRACE("restore_assignment", tout << "restore_assignment:\n"; display_assignment(tout);); - CASSERT("arith", check_eqs_satisfied()); - CASSERT("arith", check_bad_vars()); - } - - // ----------------------- - // - // make_int_feasible - // - // ----------------------- - - random_gen m_rand; - - void init_make_int_feasible() { - set_mode(false, false); // use derived bounds - if (m_cuts_enabled) { - move_nonbasic_to_bounds(); - make_feasible(); - add_cuts(); - // if (make_feasible() != l_false && !m_int_bad_vars.empty()) - // add_cuts(); - make_feasible(); - } - } - - // Buffer for storing cuts that will be added. - struct new_cut_buffer { - var_buffer m_ys; - ptr_vector m_eqs; - mpq_buffer m_cs; - svector m_is_lower; - - new_cut_buffer(numeral_manager & m):m_cs(m) {} - - void save(var y, linear_equation * eq, mpq const & c, bool is_lower) { - m_ys.push_back(y); - m_eqs.push_back(eq); - m_cs.push_back(c); - m_is_lower.push_back(is_lower); - } - - unsigned size() const { return m_ys.size(); } - - bool empty() const { return m_ys.empty(); } - }; - - void insert_cuts(new_cut_buffer & new_cuts) { - for (unsigned i = 0; i < new_cuts.size(); i++) { - m_cuts++; - unsigned eq_idx = m_equations.size(); - var y = new_cuts.m_ys[i]; - m_basic[y] = eq_idx; - m_inv_basic.push_back(y); - m_equations.push_back(new_cuts.m_eqs[i]); - m_eq_occs.push_back(eq_occs()); // for y - init_eq_occs(eq_idx); - mpq const & c = new_cuts.m_cs[i]; - if (new_cuts.m_is_lower[i]) - assert_lower(y, c, false); - else - assert_upper(y, c, false); - // register_propagation_eq(*(new_cuts.m_eqs[i])); - } - } - - // dual == false ==> as*xs >= c - // dual == true ==> as*xs <= c - void add_cut(mpq_buffer & as, var_buffer & xs, mpq const & c, bool dual, new_cut_buffer & new_cuts) { - mpq val; - var y = mk_var(0); - // compute initial value of y - for (unsigned i = 0; i < xs.size(); i++) { - m_num_manager.addmul(val, as[i], m_values[xs[i]].first, val); - } - m_num_inf_manager.set(m_values[y], val); - xs.push_back(y); - as.push_back(mpq(-1)); - m_num_manager.del(val); - linear_equation * new_eq = m_eq_manager.mk(as.size(), as.c_ptr(), xs.c_ptr()); - TRACE("cut", tout << "new cut y" << y << " val: " << m_num_manager.to_string(val) << "\n"; - m_eq_manager.display(tout, *new_eq); tout << "\n";); - new_cuts.save(y, new_eq, c, !dual); - } - - void add_cuts() { - mpq k(1); - mpq c; - new_cut_buffer new_cuts(m_num_manager); - lu_mpq::dense_vector & row = m_lu_mpq.get_tmp_row(num_vars()); - for (var x = 0; x < num_vars(); x++) { - if (!basic(x) || was_eliminated(x) || int_feasible(x)) - continue; - row.reset(); - get_row_mpq(m_basic[x], row, true, m_use_asserted, true); - - if (mk_jdm_cut(k, x, row, m_mpq_buffer, m_var_buffer, c)) - add_cut(m_mpq_buffer, m_var_buffer, c, false, new_cuts); - } - if (!new_cuts.empty()) { - insert_cuts(new_cuts); - init_lu(); - TRACE("add_cuts", display(tout);); - make_feasible(); - } - m_num_manager.del(c); - } - - bool is_cut_var(var x) const { - // TODO: refine... I'm using the fact that a variable introduced by a cut is not associated with an expr - return m_var2expr.get(x) == 0; - } - - /** - \brief A cut variable is not "useful" if it is on the basis. - So, we garbage collect any cut that is - */ - void gc_cuts() { - } - - bool is_nonslact_var(var x) const { - // TODO: refine... - expr * t = m_var2expr.get(x); - return t != 0 && is_uninterp_const(t); - } - - var bb_select_rand_var() { -#if 0 - // Give preference to non cut vars -#define BB_MAX_TRIES 8 - unsigned counter = 0; - while (!m_int_bad_vars.empty()) { - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - unsigned num_candidates = end - it; - unsigned idx = m_rand() % num_candidates; - var x = it[idx]; - if (int_feasible(x)) - m_int_bad_vars.erase(x); - if (!is_cut_var(x)) - return x; - counter++; - if (counter >= BB_MAX_TRIES) - break; - } - - if (m_int_bad_vars.empty()) - return null_var; - - // search for non-cut var - var x = null_var; - unsigned num = 1; - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - for (; it != end; ++it) { - if (int_feasible(x)) - continue; - if (is_cut_var(*it)) - continue; - if (x == null_var || m_rand() % num == 0) - x = *it; - num++; - } -#endif - // pick a random variable - while (!m_int_bad_vars.empty()) { - var_set::iterator it = m_int_bad_vars.begin(); - unsigned num_candidates = m_int_bad_vars.size(); - unsigned idx = m_rand() % num_candidates; - var x = it[idx]; - if (!int_feasible(x)) - return x; - m_int_bad_vars.erase(x); - } - - return null_var; - } - - var_buffer m_bb_var_buffer; - - var bb_select_rand_nonslack_var() { - m_bb_var_buffer.reset(); - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - if (int_feasible(x)) - continue; - if (is_nonslact_var(x)) - m_bb_var_buffer.push_back(x); - } - if (m_bb_var_buffer.empty()) - return bb_select_rand_var(); - - unsigned idx = rand() % m_bb_var_buffer.size(); - return m_bb_var_buffer[idx]; - } - - /** - \brief Select a variable x >= k (or x <= k) s.t. |k| <= threshold, and |k| is maximal. - */ - var bb_select_largest_smaller_than(mpz const & threshold) { - var best = null_var; - mpz k_best; - mpz aux; - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - if (int_feasible(x)) - continue; - if (has_lower(x) || has_upper(x)) - continue; - if (m_num_manager.is_neg(m_values[x].first)) - m_num_manager.ceil(m_values[x].first, aux); - else - m_num_manager.floor(m_values[x].first, aux); - m_num_manager.abs(aux); - if (m_num_manager.le(aux, threshold) && (best == null_var || m_num_manager.gt(aux, k_best))) { - best = x; - m_num_manager.swap(aux, k_best); - } - } - m_num_manager.del(k_best); - m_num_manager.del(aux); - return best; - } - - var bb_select_var() { - if (m_branch_vars_only) - return bb_select_rand_nonslack_var(); - else - return bb_select_rand_var(); -#if 0 - mpz limit1, limit2; - var x; - m_num_manager.set(limit1, 128); - x = bb_select_largest_smaller_than(limit1); - if (x != null_var) - return x; - m_num_manager.set(limit2, 1024); - x = bb_select_largest_smaller_than(limit2); - if (x != null_var) - return x; - return bb_select_rand_var(); -#endif - } - - bool bb_plunging(var x) { - SASSERT(!int_feasible(x)); - mpq k; - m_num_inf_manager.ceil(m_values[x], k); - push(); - bb_assert_decision(x, true, k); - if (make_feasible() == l_false) { - pop(1); - m_num_inf_manager.floor(m_values[x], k); - bb_assert_decision(x, false, k); - return true; - } - pop(1); - push(); - m_num_inf_manager.floor(m_values[x], k); - bb_assert_decision(x, false, k); - if (make_feasible() == l_false) { - pop(1); - m_num_inf_manager.ceil(m_values[x], k); - bb_assert_decision(x, true, k); - return true; - } - pop(1); - return false; - } - - var_buffer m_todo_plunging; - - void bb_plunging() { - if (inconsistent()) - return; - m_todo_plunging.reset(); - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - for (; it != end; ++it) { - var x = *it; - if (!int_feasible(x)) - m_todo_plunging.push_back(x); - } - - while (!m_todo_plunging.empty()) { - if (inconsistent()) - return; - if (bb_plunging(m_todo_plunging.back())) { - // verbose_stream() << "plunging worked: x" << m_todo_plunging.back() << "\n"; - } - m_todo_plunging.pop_back(); - } - } - - /** - \brief Propagation procedure for branch&bound - */ - bool bb_propagate() { - CASSERT("arith", check_eqs_satisfied() && check_bad_vars()); - propagate_bounds(); // propagate_bounds - CASSERT("arith", check_eqs_satisfied() && check_bad_vars()); - make_feasible(); // make sure the problem is real feasible - // bb_plunging(); - return !inconsistent(); - } - - void bb_push(var x, bool lower, mpq const & k) { - push(); - m_bb_var.push_back(x); - m_bb_lower.push_back(lower); - m_bb_first.push_back(true); - m_bb_k.push_back(mpq()); - m_num_manager.set(m_bb_k.back(), k); - SASSERT(m_bb_var.size() == m_bb_lower.size()); - SASSERT(m_bb_k.size() == m_bb_lower.size()); - SASSERT(m_bb_first.size() == m_bb_lower.size()); - } - - void bb_pop() { - pop(1); - m_bb_var.pop_back(); - m_bb_lower.pop_back(); - m_bb_first.pop_back(); - m_bb_k.pop_back(); - SASSERT(m_bb_var.size() == m_bb_lower.size()); - SASSERT(m_bb_k.size() == m_bb_lower.size()); - SASSERT(m_bb_first.size() == m_bb_lower.size()); - } - - void bb_assert_decision(var x, bool lower, mpq const & k) { - if (lower) { - m_bounds.assert_decided_lower(x, k); - } - else { - m_bounds.assert_decided_upper(x, k); - } - if (above_upper(x) || below_lower(x)) - m_bad_vars.insert(x); - } - - void bb_branch(var x) { - m_branches++; - SASSERT(m_bad_vars.empty()); - SASSERT(!m_num_inf_manager.is_int(m_values[x])); - TRACE("make_int_feasible", tout << "x" << x << " -> " << m_num_inf_manager.to_string(m_values[x]) << "\n";); - bool lower; -#if 1 - if (has_lower(x) && has_upper(x)) - lower = (m_rand() % 2) == 0; - else if (has_upper(x)) - lower = true; - else if (has_lower(x)) - lower = false; - else - lower = (m_rand() % 2) == 0; -#else - lower = (m_rand() % 2) == 0; -#endif - mpq k; - if (lower) - m_num_inf_manager.ceil(m_values[x], k); - else - m_num_inf_manager.floor(m_values[x], k); - bb_push(x, lower, k); - bb_assert_decision(x, lower, k); - TRACE("bb_branch", tout << "branching on x" << x << " " << (lower ? ">=" : "<=") << " " << m_num_manager.to_string(k) << "\n"; - tout << "new-lvl: " << m_bb_var.size() << "\n";); - m_num_manager.del(k); - } - - bool bb_resolve_conflict() { - SASSERT(inconsistent()); - while (!m_bb_var.empty()) { - if (m_bb_first.back() == false) { - // tried both branches... - TRACE("make_int_feasible", tout << "backtracking lvl: " << m_bb_var.size() << "\n";); - bb_pop(); - continue; - } - pop(1); // pop just the bounds - push(); - var x = m_bb_var.back(); - m_bb_first.back() = false; - SASSERT(m_bb_first.back() == false); - bool lower = m_bb_lower.back() != 0; - if (lower) { - // k <= x is inconsistent, then flip to x <= k-1 - m_num_manager.dec(m_bb_k.back()); - } - else { - // x <= k is inconsistent, then flip to k+1 <= x - m_num_manager.inc(m_bb_k.back()); - } - lower = !lower; - m_bb_lower.back() = lower; - // assert new decision - bb_assert_decision(x, lower, m_bb_k.back()); - TRACE("bb_branch", tout << "[flip] branching on x" << x << " " << (lower ? ">=" : "<=") - << " " << m_num_manager.to_string(m_bb_k.back()) << "\n"; tout << "lvl: " << m_bb_var.size() << "\n";); - return true; - } - return false; - } - - void bb_restart() { - while (!m_bb_var.empty()) { - bb_pop(); - } - } - - lbool bb_bounded_search(unsigned limit) { - if (inconsistent()) - return l_false; - unsigned counter = 0; - while (true) { - while (!bb_propagate()) { - if (!bb_resolve_conflict()) - return l_false; - } - TRACE("make_int_feasible_step", display_bounds(tout); display_assignment(tout); display_bad_vars(tout);); - SASSERT(!inconsistent()); - var x = bb_select_var(); - // verbose_stream() << "lvl: " << m_bb_var.size() << " x" << x << "\n"; - if (x == null_var) - return l_true; - bb_branch(x); - counter++; - if (counter >= limit) - break; - TRACE("make_int_feasible", tout << "selected: x" << x << "\n";); -#ifndef _EXTERNAL_RELEASE - IF_VERBOSE(ST_VERBOSITY_LVL, if (counter % 100 == 0) display_progress(verbose_stream());); -#endif - } - return l_undef; - } - - /** - \brief Add bounds to all integer variables that are unbounded - */ - void bb_add_bounds(mpq const & limit) { - mpq neg_limit; - m_num_manager.set(neg_limit, limit); - m_num_manager.neg(neg_limit); - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - if (is_int(x) && !was_eliminated(x)) { - if (!has_lower(x)) - bb_assert_decision(x, true, neg_limit); - if (!has_upper(x)) - bb_assert_decision(x, false, limit); - } - } - m_num_manager.del(neg_limit); - } - - lbool make_int_feasible_core() { - lbool r = bb_bounded_search(1024*16); - bb_restart(); - return r; - } - - lbool bb_model_finder(unsigned range, unsigned num_branches) { - mpq limit; - m_num_manager.set(limit, range); - push(); // protect state - bb_add_bounds(limit); - lbool r = bb_bounded_search(num_branches); - if (r == l_false) - r = l_undef; - m_num_manager.del(limit); - pop(1); // restore state - return r; - } - - lbool make_int_feasible() { - if (inconsistent()) - return l_false; - init_make_int_feasible(); - - TRACE("make_int_feasible_begin", display(tout);); - TRACE("make_int_feasible_begin", display_int_infeasible_rows(tout);); - - unsigned num_branches = m_int_bad_vars.size() * 2; - bool find_model = true; - unsigned range = 32; - - lbool r; - while (true) { - SASSERT(scope_lvl() == 0); - if (find_model) - r = bb_model_finder(range, num_branches); - else - r = bb_bounded_search(num_branches); - if (r != l_undef) - break; - find_model = !find_model; - bb_restart(); - // init_make_int_feasible(); - num_branches += (m_equations.size() / 10) + 1; - } - - // lbool r = bb_model_finder(128); - TRACE("make_int_feasible_result", tout << "r: " << r << "\n"; display(tout);); -#if 0 - switch (r) { - case l_true: verbose_stream() << "sat\n"; break; - case l_undef: verbose_stream() << "unknown\n"; break; - case l_false: verbose_stream() << "unsat\n"; break; - } -#endif - return r; - } - - // ----------------------- - // - // Preprocessing - // - // ----------------------- - - void register_propagation_eq(linear_equation const & eq) { - // copy coeffs and vars to temporary buffers just to be safe - m_var_buffer.reset(); - m_mpz_buffer.reset(); - unsigned sz = eq.size(); - for (unsigned j = 0; j < sz; j++) { - m_mpz_buffer.push_back(eq.a(j)); - m_var_buffer.push_back(eq.x(j)); - } - m_bounds.mk_eq(m_mpz_buffer.size(), m_mpz_buffer.c_ptr(), m_var_buffer.c_ptr()); - } - - // Copy constraints (only linear_equations at this point) to m_bounds. - void init_bound_propagation_cnstrs() { - SASSERT(scope_lvl() == 0); - m_bounds.del_constraints(); - unsigned num_eqs = m_equations.size(); - for (unsigned i = 0; i < num_eqs; i++) { - linear_equation const & eq = *(m_equations[i]); - register_propagation_eq(eq); - } - } - - /** - \brief Select a (unconstrained) variable in eq for elimination. - If there is more than one option, then select the one with the fewest number of occurrences. - If eq does not contain an unconstrained variable then return null_var. - An integer variable is selected only if it has unary coefficient, and eq does not contain real variables. - */ - var choose_elim_var(linear_equation const & eq, vector const & use_list) const { - bool has_real = false; - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - if (!is_int(eq.x(i))) { - has_real = true; - break; - } - } - var best_x = null_var; - for (unsigned i = 0; i < sz; i++) { - var x = eq.x(i); - if (!is_unconstrained(x)) - continue; - if (is_int(x)) { - if (has_real) - continue; - if (!m_num_manager.is_one(eq.a(i)) && !m_num_manager.is_minus_one(eq.a(i))) - continue; - } - if (best_x == null_var || use_list[x].size() < use_list[best_x].size()) - best_x = x; - } - return best_x; - } - - /** - \brief Update use list for replacing eq with new_eq, the use list of var except is not touched. - */ - void update_use_list(unsigned eq_idx, linear_equation const & eq, linear_equation const & new_eq, vector & use_list, - var except) { - unsigned sz = eq.size(); - unsigned new_sz = new_eq.size(); - unsigned j = 0; - unsigned new_j = 0; - while (true) { - if (j == sz) { - // add remaining variables in new_eq to use list - for (; new_j < new_sz; new_j++) - use_list[new_eq.x(new_j)].push_back(eq_idx); - break; - } - if (new_j == new_sz) { - // remove remaining variables in eq from use list - for (; j < sz; j++) { - var x = eq.x(j); - if (x != except) - use_list[x].erase(eq_idx); - } - break; - } - var x = eq.x(j); - var new_x = new_eq.x(new_j); - if (x < new_x) { - // variable x was removed - if (x != except) - use_list[x].erase(eq_idx); - j++; - } - else if (x > new_x) { - // variable new_x was added - use_list[new_x].push_back(eq_idx); - new_j++; - } - else { - // keep variable - j++; - new_j++; - } - } - } - - /** - \brief Eliminate x from all equations but eq_idx. - */ - void eliminate_var_from_other_eqs(var x, unsigned eq_idx, vector & use_list) { - linear_equation * eq1 = m_equations[eq_idx]; - unsigned i1 = eq1->pos(x); - SASSERT(i1 != UINT_MAX); - mpz b1; - m_num_manager.set(b1, eq1->a(i1)); - m_num_manager.neg(b1); - unsigned_vector & occs = use_list[x]; - unsigned_vector::iterator it = occs.begin(); - unsigned_vector::iterator end = occs.end(); - for (; it != end; ++it) { - unsigned eq2_idx = *it; - if (eq_idx == eq2_idx) - continue; - linear_equation * eq2 = m_equations[eq2_idx]; - unsigned i2 = eq2->pos(x); - SASSERT(i2 != UINT_MAX); - mpz const & b2 = eq2->a(i2); - linear_equation * new_eq2 = m_eq_manager.mk(b2, *eq1, b1, *eq2); - CTRACE("arith_preprocess_new_bug", new_eq2->pos(x) != UINT_MAX, - tout << "x" << x << "\n"; - tout << m_num_manager.to_string(b2) << " * "; m_eq_manager.display(tout, *eq1); tout << "\n"; - tout << m_num_manager.to_string(b1) << " * "; m_eq_manager.display(tout, *eq2); tout << "\n"; - tout << "----->\n"; - m_eq_manager.display(tout, *new_eq2); - tout << "\n";); - SASSERT(new_eq2 != 0); - SASSERT(new_eq2->pos(x) == UINT_MAX); - // update use list - update_use_list(eq2_idx, *eq2, *new_eq2, use_list, x); - m_eq_manager.del(eq2); - m_equations[eq2_idx] = new_eq2; - } - // - m_num_manager.del(b1); - occs.reset(); - occs.push_back(eq_idx); // x occurs only in eq_idx - } - - void eliminate_var(var x, unsigned eq_idx, vector & use_list) { - eliminate_var_from_other_eqs(x, eq_idx, use_list); - linear_equation * eq1 = m_equations[eq_idx]; - // remove x and eq_idx from use list - unsigned_vector & occs = use_list[x]; - occs.reset(); - unsigned sz = eq1->size(); - for (unsigned i = 0; i < sz; i++) { - var x_i = eq1->x(i); - use_list[x_i].erase(eq_idx); - } - // mark x as eliminated. - m_eliminated[x] = true; - m_elim_vars.push_back(elim_var_info(x, eq1)); - } - - void mk_tmp_use_list(vector & use_list) { - use_list.resize(num_vars()); - unsigned num_eqs = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num_eqs; ++eq_idx) { - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) - use_list[eq.x(i)].push_back(eq_idx); - } - } - - void remove_equations(svector const & to_remove) { - unsigned num_eqs = m_equations.size(); - unsigned j = 0; - for (unsigned i = 0; i < num_eqs; i++) { - if (to_remove[i]) - continue; - linear_equation * eq = m_equations[i]; - var x_b = m_inv_basic[i]; - SASSERT(m_basic[x_b] == i); - m_basic[x_b] = j; - m_equations[j] = eq; - m_inv_basic[j] = x_b; - j++; - } - - TRACE("arith_preprocess_bug", for (unsigned i = 0; i < j; i++) display_eq_basics(tout, i);); - m_equations.shrink(j); - m_inv_basic.shrink(j); - } - - void elim_unconstrained_vars() { - SASSERT(elim_var_applicable()); - // build temporary use list - vector use_list; - mk_tmp_use_list(use_list); - - // eliminate - unsigned old_eliminated_vars = m_eliminated_vars; - unsigned num_eqs = m_equations.size(); - svector to_remove; - to_remove.resize(num_eqs, false); - for (unsigned eq_idx = 0; eq_idx < num_eqs; ++eq_idx) { - linear_equation * eq = m_equations[eq_idx]; - var x = choose_elim_var(*eq, use_list); - if (x == null_var) - continue; - var x_b = m_inv_basic[eq_idx]; - SASSERT(m_basic[x_b] == eq_idx); - m_basic[x_b] = UINT_MAX; // x_b is not basic anymore. - m_eliminated_vars++; - TRACE("arith_preprocess", tout << "eliminating: x" << x << " using "; m_eq_manager.display(tout, *eq); tout << "\n";); - SASSERT(!was_eliminated(x)); - SASSERT(!basic(x)); - eliminate_var(x, eq_idx, use_list); - to_remove[eq_idx] = true; - } - - report_st_progress(":elim-tableau-vars", m_eliminated_vars - old_eliminated_vars); - - remove_equations(to_remove); - } - - // Compress basic variables ids after rows have been eliminated. - void compress_basic_ids() { - unsigned_vector id2var; - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - if (basic(x)) { - unsigned id = m_basic[x]; - id2var.reserve(id+1, null_var); - id2var[id] = x; - } - } - unsigned next_id = 0; - unsigned sz = id2var.size(); - for (unsigned i = 0; i < sz; i++) { - var x = id2var[i]; - if (x != null_var) { - m_basic[x] = next_id; - m_inv_basic[next_id] = x; - next_id++; - } - } - } - - /** - Make int_eqs[eq_idx] == true if eq_idx constains only integer variables. - */ - void mark_int_eqs(svector & int_eqs) { - unsigned num_eqs = m_equations.size(); - int_eqs.reset(); - for (unsigned i = 0; i < num_eqs; i++) { - linear_equation const & eq = *(m_equations[i]); - unsigned sz = eq.size(); - unsigned j; - for (j = 0; j < sz; j++) { - if (!is_int(eq.x(j))) - break; - } - int_eqs.push_back(j == sz); - } - } - - /** - \brief Eliminate integer variable x by producing the equation c * eq_idx1 + d * eq_idx2. - The coefficient of x in this equation is 1. - This function replaces eq_idx1 with c * eq_idx1 + d * eq_idx2, and invokes eliminate_var(x, eq_idx1, use_list) - */ - void eliminate_int_var(var x, unsigned eq_idx1, unsigned eq_idx2, mpz const & c, mpz const & d, vector & use_list) { - linear_equation * eq1 = m_equations[eq_idx1]; - linear_equation * new_eq1 = m_eq_manager.mk(c, *eq1, d, *(m_equations[eq_idx2])); - SASSERT(new_eq1->pos(x) != UINT_MAX); - SASSERT(m_num_manager.is_one(new_eq1->a(new_eq1->pos(x)))); // coefficient of x in the new equation is one. - update_use_list(eq_idx1, *eq1, *new_eq1, use_list, null_var); - m_eq_manager.del(eq1); - m_equations[eq_idx1] = new_eq1; - eliminate_var(x, eq_idx1, use_list); - } - - void elim_int_unconstrained_vars() { - SASSERT(elim_var_applicable()); - - vector use_list; - mk_tmp_use_list(use_list); - - unsigned old_eliminated_vars = m_eliminated_vars; - - svector int_eqs; - mark_int_eqs(int_eqs); - mpz c, d, g; - - numeral_manager & nm = m_num_manager; - - unsigned num_eqs = m_equations.size(); - svector to_remove; - to_remove.resize(num_eqs, false); - - for (var x = 0; x < num_vars(); x++) { - if (was_eliminated(x) || !is_int(x) || !is_unconstrained(x)) - continue; - TRACE("elim_int", tout << "visiting x" << x << "\n";); - unsigned_vector & occs = use_list[x]; - unsigned_vector::iterator it = occs.begin(); - unsigned_vector::iterator end = occs.end(); - for (; it != end; ++it) { - unsigned eq_idx1 = *it; - if (!int_eqs[eq_idx1]) - continue; // skip: contains real variables... - linear_equation const & eq1 = *(m_equations[eq_idx1]); - SASSERT(elim_var_applicable(eq_idx1)); - unsigned pos1 = eq1.pos(x); - if (pos1 == UINT_MAX) - continue; - mpz const & a1 = eq1.a(pos1); - if (nm.is_one(a1) || nm.is_minus_one(a1)) { - // easy case - m_eliminated_vars++; - var x_b = m_inv_basic[eq_idx1]; - SASSERT(m_basic[x_b] == eq_idx1); - m_basic[x_b] = UINT_MAX; // x_b is not basic anymore. - eliminate_var(x, eq_idx1, use_list); - to_remove[eq_idx1] = true; - break; - } - unsigned_vector::iterator it2 = it+1; - for (; it2 != end; ++it2) { - unsigned eq_idx2 = *it2; - if (!int_eqs[eq_idx2]) - continue; - linear_equation const & eq2 = *(m_equations[eq_idx2]); - SASSERT(elim_var_applicable(eq_idx2)); - unsigned pos2 = eq2.pos(x); - if (pos2 == UINT_MAX) - continue; - mpz const & a2 = eq2.a(pos2); - if (nm.is_one(a2) || nm.is_minus_one(a2)) { - // easy case - m_eliminated_vars++; - var x_b = m_inv_basic[eq_idx2]; - SASSERT(m_basic[x_b] == eq_idx2); - m_basic[x_b] = UINT_MAX; // x_b is not basic anymore. - eliminate_var(x, eq_idx2, use_list); - to_remove[eq_idx2] = true; - goto elim_int_var_processed; - } - nm.gcd(a1, a2, c, d, g); - if (nm.is_one(g)) { - TRACE("elim_int", tout << "found candidate eqs for eliminating x" << x << "\n"; - tout << "a1: " << nm.to_string(a1) << ", a2: " << nm.to_string(a2) << "\n"; - tout << "c: " << nm.to_string(c) << ", d: " << nm.to_string(d) << ", g: " << nm.to_string(g) << "\n"; - m_eq_manager.display(tout, eq1); tout << "\n"; - m_eq_manager.display(tout, eq2); tout << "\n";); - var x_b2 = m_inv_basic[eq_idx2]; - // c * eq1 + d * eq2 --> generates an equation where x has coefficient 1. - // So, we can eliminate x, delete eq1 (or eq2), and replace x everywhere with c*eq1 + d*eq2. - eliminate_int_var(x, eq_idx1, eq_idx2, c, d, use_list); - var x_b = m_inv_basic[eq_idx1]; - SASSERT(m_basic[x_b] == eq_idx1); - m_basic[x_b] = UINT_MAX; // x_b is not basic anymore. - to_remove[eq_idx1] = true; - m_eliminated_vars++; - // the basic variable of eq_idx2 may occur in many equations... eliminate it from all but eq_idx2 - // the idea is to make sure that elim_var_applicable is true for all equations. - linear_equation const & new_eq2 = *(m_equations[eq_idx2]); - SASSERT(new_eq2.pos(x_b2) != UINT_MAX); // eq2 still contains its basic variable - SASSERT(elim_var_applicable(eq_idx2)); // the only basic variable in eq2 is still x_b2 - eliminate_var_from_other_eqs(x_b2, eq_idx2, use_list); - goto elim_int_var_processed; - } - } - } - elim_int_var_processed: - ; - } - nm.del(c); - nm.del(d); - nm.del(g); - - report_st_progress(":elim-int-tableau-vars", m_eliminated_vars - old_eliminated_vars); - remove_equations(to_remove); - } - - // assert axiom x == 0 - void assert_eq_zero_axiom(var x) { - mpq zero(0); - assert_upper(x, zero, false); - assert_lower(x, zero, false); - } - - // Eliminate variables fixed at zero from equations. - bool elim_zero_vars() { - bool eliminated = false; - SASSERT(scope_lvl() == 0); - unsigned num_eqs = m_equations.size(); - svector to_remove; - to_remove.resize(num_eqs, false); - for (unsigned eq_idx = 0; eq_idx < num_eqs; eq_idx++) { - linear_equation * eq = m_equations[eq_idx]; - unsigned sz = eq->size(); - unsigned k; - for (k = 0; k < sz; k++) { - var x_k = eq->x(k); - // To eliminate a basic variable, we have to - // create the LU factorization, and extract the actual row, and then select - // a variable to enter the basis. Perhaps, it is not worth to do that at this point. - // It is better to wait the variable to leave the basis. - if (!basic(x_k) && m_bounds.is_zero(x_k)) - break; - } - if (k == sz) - continue; - // equation has zero variables - m_var_buffer.reset(); - m_mpz_buffer.reset(); - for (k = 0; k < sz; k++) { - var x_k = eq->x(k); - if (!basic(x_k) && m_bounds.is_zero(x_k)) - continue; - // keep non-zero vars and the basic variable - m_var_buffer.push_back(x_k); - m_mpz_buffer.push_back(eq->a(k)); - } - - SASSERT(m_var_buffer.size() < sz); - eliminated = true; - unsigned new_sz = m_var_buffer.size(); - SASSERT(new_sz != 0); - linear_equation * new_eq = m_eq_manager.mk(new_sz, m_mpz_buffer.c_ptr(), m_var_buffer.c_ptr()); - if (new_eq != 0) { - m_equations[eq_idx] = new_eq; - } - else { - assert_eq_zero_axiom(m_var_buffer[0]); - SASSERT(new_sz == 1); - to_remove[eq_idx] = true; - var x_b = m_inv_basic[eq_idx]; - m_basic[x_b] = UINT_MAX; - m_eliminated_vars++; - } - m_eq_manager.del(eq); - } - remove_equations(to_remove); - return eliminated; - } - - bool propagate_bounds() { - unsigned qhead = m_bounds.qhead(); - m_bounds.propagate(); - if (m_bounds.inconsistent()) - return false; - TRACE("propagate_bounds", tout << "propagate_bounds, m_use_asserted: " << m_use_asserted << "\n";); - if (!m_use_asserted) { - // update bad vars using new bounds - bound_propagator::trail_iterator it = m_bounds.begin_trail() + qhead; - bound_propagator::trail_iterator end = m_bounds.end_trail(); - for (; it != end; ++it) { - var x = it->x(); - bool is_lower = it->is_lower(); - TRACE("propagate_bounds", tout << "propagated x" << x << " is_lower: " << is_lower << "\n";); - if (is_lower) { - if (below_lower(x)) - m_bad_vars.insert(x); - } - else { - if (above_upper(x)) - m_bad_vars.insert(x); - } - } - } - return true; - } - - void init_eq_occs(unsigned eq_idx) { - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) - m_eq_occs[eq.x(i)].push_back(eq_occ(eq_idx, i)); - } - - void init_eq_occs() { - m_eq_occs.reset(); - m_eq_occs.resize(num_vars()); - unsigned num_eqs = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num_eqs; ++eq_idx) { - init_eq_occs(eq_idx); - } - } - - /** - \brief We apply variable elimination only if - For all equation eq, the only and only one basic variable x_b in eq is m_inv_basic[eq]. - - This condition prevents us from ending up with a basis that corresponds to a - singular matrix. - - After compilation, the set of equations always satisfies this condition, since - the basic variable "owning" each equation is the slack introduced during compilation. - */ - bool elim_var_applicable(unsigned eq_idx) const { - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - var x = eq.x(i); - if (basic(x) && m_basic[x] != eq_idx) - return false; - } - return true; - } - - bool elim_var_applicable() const { - unsigned num_eqs = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num_eqs; eq_idx++) { - if (!elim_var_applicable(eq_idx)) - return false; - } - return true; - } - - void preprocess() { - CASSERT("arith", check_invariant()); - IF_VERBOSE(ST_VERBOSITY_LVL, display_status(verbose_stream());); - - TRACE("arith_preprocess", tout << "eqs before elimination\n"; display_eqs(tout);); - - if (m_elim_vars_enabled && elim_var_applicable()) { - elim_unconstrained_vars(); - // TODO: the following transformation is producing a singular basis - if (m_elim_int_vars_enabled) - elim_int_unconstrained_vars(); - } - - init_bound_propagation_cnstrs(); - if (!propagate_bounds()) - return; // inconsistency detected. - - IF_VERBOSE(ST_VERBOSITY_LVL, display_status(verbose_stream());); - - TRACE("arith_preprocess", tout << "eqs after elimination\n"; display_eqs(tout); display_eliminated_vars(tout);); - -#if 1 - if (elim_zero_vars()) { - init_bound_propagation_cnstrs(); - propagate_bounds(); - IF_VERBOSE(ST_VERBOSITY_LVL, display_status(verbose_stream());); - } -#endif - - init_eq_occs(); - - CASSERT("arith", check_invariant()); - TRACE("arith_preprocess_bug", for (unsigned i = 0; i < m_equations.size(); i++) display_eq_basics(tout, i);); - - init_lu(); - - TRACE("arith_int_preprocess", display_unconstrained_vars(tout); display_eqs(tout);); - - CASSERT("arith", check_invariant()); - TRACE("arith_preprocess", display(tout);); - - // tst_random_pivoting(m_lu_double, 2000); - // tst_random_pivoting(m_lu_mpq, 2000); - } - - // ----------------------- - // - // Cuts - // - // ----------------------- - - /** - \brief Move non-basic variables to bounds. - */ - void move_nonbasic_to_bounds() { - mpq_inf old_val; - unsigned num = num_vars(); - for (var x = 0; x < num; x++) { - if (basic(x)) - continue; - if (at_lower(x) || at_upper(x)) - continue; - m_num_inf_manager.set(old_val, m_values[x]); - if (has_lower(x)) - lower2value(x); - else if (has_upper(x)) - upper2value(x); - else - continue; - update_dependents(m_lu_mpq, m_values, m_num_inf_manager, x, old_val); - } - m_num_inf_manager.del(old_val); - } - - bool is_jdm_cut_applicable(mpq const & k, var x_i, lu_mpq::dense_vector const & row) { - if (!m_num_inf_manager.is_rational(m_values[x_i])) - return false; - numeral_manager & nm = m_num_manager; - mpq a; - nm.mul(m_values[x_i].first, k, a); - if (nm.is_int(a)) { - nm.del(a); - return false; - } - // check if cut is applicable - lu_mpq::dense_vector::iterator it = row.begin_non_zeros(); - lu_mpq::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x_j = *it; - if (!is_int(x_j)) { - TRACE("cut", tout << "failed: row constains non int var\n";); - return false; - } - m_num_manager.mul(k, row[x_j], a); - if (nm.is_int(a)) { - // integer coeffs can be ignored when x_j is assigned to an integer - if (!m_num_inf_manager.is_int(m_values[x_j])) - return false; - continue; - } - if (!at_lower(x_j) && !at_upper(x_j)) { - TRACE("cut", tout << "failed: variable is not at bound x" << x_j << "\n";); - return false; - } - } - nm.del(a); - return true; - } - - bool mk_jdm_cut(mpq const & k, var x_i, lu_mpq::dense_vector const & row, mpq_buffer & as, var_buffer & xs, mpq & c) { - if (!is_jdm_cut_applicable(k, x_i, row)) - return false; - numeral_manager & nm = m_num_manager; - SASSERT(nm.is_pos(k)); - as.reset(); - xs.reset(); - nm.reset(c); - mpq a, a_prime; - nm.mul(m_values[x_i].first, k, c); - nm.ceil(c, c); - lu_mpq::dense_vector::iterator it = row.begin_non_zeros(); - lu_mpq::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x_j = *it; - nm.mul(row[x_j], k, a); - if (nm.is_int(a)) { - // I - nm.addmul(c, a, m_values[x_j].first, c); - // ignore monomial - } - else { - if (nm.is_neg(a)) { - if (at_lower(x_j)) { - // L- - // doesn't contribute to c. - // add -a*x_j - nm.neg(a); - as.push_back(a); - } - else { - // U- - nm.floor(a, a_prime); - nm.addmul(c, a_prime, m_values[x_j].first, c); - // new coeff floor(a_ij) - a_ij - nm.sub(a_prime, a, a_prime); - as.push_back(a_prime); - } - } - else { - if (at_lower(x_j)) { - // L+ - nm.ceil(a, a_prime); - nm.addmul(c, a_prime, m_values[x_j].first, c); - // new coeff ceil(a_ij) - a_ij - nm.sub(a_prime, a, a_prime); - as.push_back(a_prime); - } - else { - // U+ - // doesn't contribute to c - // add -a*x_j - nm.neg(a); - as.push_back(a); - } - } - xs.push_back(x_j); - } - } - TRACE("cut", - tout << "new cut:\n"; - for (unsigned i = 0; i < xs.size(); i++) { - if (i > 0) tout << " + "; - tout << nm.to_string(as[i]) << "*x" << xs[i]; - } - tout << " >= " << nm.to_string(c) << "\n"; - tout << "\n";); - nm.del(a); - nm.del(a_prime); - return true; - } - - bool mk_jdm_dual_cut(mpq const & k, var x_i, lu_mpq::dense_vector const & row, mpq_buffer & as, var_buffer & xs, mpq & c) { - if (!is_jdm_cut_applicable(k, x_i, row)) - return false; - numeral_manager & nm = m_num_manager; - SASSERT(nm.is_pos(k)); - as.reset(); - xs.reset(); - nm.reset(c); - mpq a, a_prime; - nm.mul(m_values[x_i].first, k, c); - nm.floor(c, c); - lu_mpq::dense_vector::iterator it = row.begin_non_zeros(); - lu_mpq::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x_j = *it; - nm.mul(row[x_j], k, a); - if (nm.is_int(a)) { - // I - nm.addmul(c, a, m_values[x_j].first, c); - // ignore monomial - } - else { - if (nm.is_neg(a)) { - if (at_lower(x_j)) { - // L- - nm.floor(a, a_prime); - nm.addmul(c, a_prime, m_values[x_j].first, c); - // new coeff floor(a_ij) - a_ij - nm.sub(a_prime, a, a_prime); - as.push_back(a_prime); - } - else { - // U- - // doesn't contribute to c. - // add -a*x_j - nm.neg(a); - as.push_back(a); - } - } - else { - if (at_lower(x_j)) { - // L+ - // doesn't contribute to c - // add -a*x_j - nm.neg(a); - as.push_back(a); - } - else { - // U+ - nm.ceil(a, a_prime); - nm.addmul(c, a_prime, m_values[x_j].first, c); - // new coeff ceil(a_ij) - a_ij - nm.sub(a_prime, a, a_prime); - as.push_back(a_prime); - } - } - xs.push_back(x_j); - } - } - TRACE("cut", - tout << "new cut:\n"; - for (unsigned i = 0; i < xs.size(); i++) { - if (i > 0) tout << " + "; - tout << nm.to_string(as[i]) << "*x" << xs[i]; - } - tout << " <= " << nm.to_string(c) << "\n"; - tout << "\n";); - nm.del(a); - nm.del(a_prime); - return true; - } - - // ----------------------- - // - // Status - // - // ----------------------- - - unsigned matrix_size() const { - unsigned r = 0; - equations::const_iterator it = m_equations.begin(); - equations::const_iterator end = m_equations.end(); - for (; it != end; ++it) - r += (*it)->size(); - return r; - } - - void display_status(std::ostream & out) { - out << "(arith :vars " << num_vars() << " :eliminated " << m_elim_vars.size() << " :eqs " << m_equations.size() - << " :matrix-size " << matrix_size() << ")\n"; - } - - // ----------------------- - // - // Pretty printing - // - // ----------------------- - - void display_int_infeasible_rows(std::ostream & out) { - mpq c; - out << "rows of int infeasible vars:\n"; - lu_mpq::dense_vector & row = m_lu_mpq.get_tmp_row(num_vars()); - for (var x = 0; x < num_vars(); x++) { - if (!basic(x) || was_eliminated(x) || int_feasible(x)) - continue; - row.reset(); - get_row_mpq(m_basic[x], row, true, m_use_asserted, true); - out << "x" << x << " -> " << m_num_inf_manager.to_string(m_values[x]) << " : "; row.display_pol(out); out << "\n"; - mk_jdm_cut(mpq(1), x, row, m_mpq_buffer, m_var_buffer, c); - mk_jdm_dual_cut(mpq(1), x, row, m_mpq_buffer, m_var_buffer, c); - } - m_num_manager.del(c); - } - - /** - \brief Display unbounded variables that were not eliminated. - */ - void display_unconstrained_vars(std::ostream & out) const { - for (var x = 0; x < num_vars(); x++) { - if (!was_eliminated(x) && is_unconstrained(x)) { - out << "x" << x << " "; - } - } - out << "\n"; - } - - void display_ineq_cnstr(std::ostream & out, ineq_cnstr const & c) const { - out << "p" << c.m_atom << " := x" << c.m_x << " " << (c.m_lower ? ">=" : "<=") << " " << m_num_manager.to_string(c.m_k) << "\n"; - } - - void display_ineq_cnstrs(std::ostream & out) const { - out << "ineq-constraints:\n"; - for (unsigned i = 0; i < m_ineq_cnstrs.size(); i++) { - display_ineq_cnstr(out, m_ineq_cnstrs[i]); - } - } - - void display_eliminated_vars(std::ostream & out) const { - out << "eliminated variables:\n"; - elim_vars::const_iterator it = m_elim_vars.begin(); - elim_vars::const_iterator end = m_elim_vars.end(); - for (; it != end; ++it) { - out << "x" << it->first << " --> "; - m_eq_manager.display(out, *(it->second)); - out << "\n"; - } - } - - void display_eq_basics(std::ostream & out, unsigned eq_idx) const { - out << "eq " << eq_idx << ":"; - linear_equation const & eq = *(m_equations[eq_idx]); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - if (basic(eq.x(i))) - out << " x" << eq.x(i) << "|" << m_basic[eq.x(i)]; - } - out << "\n"; - } - - void display_eqs(std::ostream & out) const { - out << "equations:\n"; - for (unsigned i = 0; i < m_equations.size(); i++) { - linear_equation const & eq = *(m_equations[i]); - out << "eq " << i << ": "; - m_eq_manager.display(out, eq); - out << "\n"; - } - } - - void display_basic(std::ostream & out) const { - out << "basic:"; - for (unsigned x = 0; x < num_vars(); x++) { - if (basic(x)) - out << " (x" << x << " -> " << m_basic[x] << ")"; - } - out << "\n"; - } - - void display_definitions(std::ostream & out) const { - out << "definitions:\n"; - for (unsigned i = 0; i < num_vars(); i++) { - out << "x" << std::left << std::setw(6) << i << " : "; - if (m_var2expr.get(i) == 0) - out << ""; - else - out << mk_ismt2_pp(m_var2expr.get(i), m, 10); - out << "\n"; - } - } - - template - void display_LU(std::ostream & out, LU const & _lu) const { - _lu.display(out); - _lu.display(out, &m_inv_basic); - } - - void display_bad_vars(std::ostream & out) const { - if (m_bad_vars.empty()) { - out << "all constraints are satisfied\n"; - return; - } - out << "bad vars: "; - var_set::iterator it = m_bad_vars.begin(); - var_set::iterator end = m_bad_vars.end(); - for (; it != end; ++it) { - out << "x" << *it << " "; - } - out << "\n"; - } - - void display_int_bad_vars(std::ostream & out) const { - if (m_int_bad_vars.empty()) { - out << "integrality constraints are satisfied\n"; - return; - } - out << "int bad vars: "; - var_set::iterator it = m_int_bad_vars.begin(); - var_set::iterator end = m_int_bad_vars.end(); - for (; it != end; ++it) { - out << "x" << *it << " "; - } - out << "\n"; - } - - void display_assignment(std::ostream & out) const { - out << "assignment:\n"; - for (var x = 0; x < num_vars(); x++) { - if (was_eliminated(x)) - continue; - if (m_use_approx) { - out << "x" << x << " -> " << m_approx_values[x]; - } - else { - out << "x" << x << " -> " << m_num_inf_manager.to_string(m_values[x]); - } - if (is_int(x)) - out << " *"; - out << "\n"; - } - } - - void display_LU(std::ostream & out) const { - if (m_use_approx) - m_lu_double.display(out); - else - m_lu_mpq.display(out); - } - - void display_bounds(std::ostream & out) const { - // display only bounds of variables that were not eliminated. - out << "bounds:\n"; - for (var x = 0; x < num_vars(); x++) { - if (was_eliminated(x)) - continue; - if (m_use_approx) - bp().display_var_bounds(out, x, true, false); - else - bp().display_var_bounds(out, x, false, true); - out << "\n"; - } - } - - void display(std::ostream & out) const { - display_definitions(out); - display_basic(out); - display_eqs(out); - display_bounds(out); - display_LU(out); - display_assignment(out); - display_bad_vars(out); - display_int_bad_vars(out); - display_ineq_cnstrs(out); - display_eliminated_vars(out); - } - - // ----------------------- - // - // Invariants - // - // ----------------------- - - bool check_bounds_satisfied() const { - for (var x = 0; x < num_vars(); x++) { - CTRACE("arith_bug", above_upper(x) || below_lower(x), tout << "bad var: x" << x << "\n"; display(tout);); - SASSERT(!above_upper(x)); - SASSERT(!below_lower(x)); - } - return true; - } - - /** - \brief Check if m_bad_vars contains all variables not satisfying their bounds. - */ - bool check_bad_vars() const { - if (!inconsistent()) { - for (var x = 0; x < num_vars(); x++) { - if (above_upper(x) || below_lower(x)) { - CTRACE("arith_bug", !m_bad_vars.contains(x), tout << "missing bad var: x" << x << "\n"; display(tout);); - SASSERT(m_bad_vars.contains(x)); - } - } - } - return true; - } - - /** - \brief When precise mode is on, this method checks if the assignment of the basic - variables is consistent with the non-basic ones. - */ - bool check_basic_assignment_core() { - if (m_use_approx) - return true; - unsigned num = m_equations.size(); - lu_mpq::dense_vector & row = m_lu_mpq.get_tmp_row(num_vars()); - mpq_inf val; - mpq_inf aux; - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - var x_b = m_inv_basic[eq_idx]; - SASSERT(m_basic[x_b] == eq_idx); - row.reset(); - get_row_mpq(eq_idx, row, true, m_use_asserted, true); - m_num_inf_manager.reset(val); - lu_mpq::dense_vector::iterator it = row.begin_non_zeros(); - lu_mpq::dense_vector::iterator end = row.end_non_zeros(); - for (; it != end; ++it) { - var x_n = *it; - SASSERT(nonbasic(x_n)); - if (m_num_manager.is_zero(row[x_n])) - continue; - m_num_inf_manager.mul(m_values[x_n], row[x_n], aux); - m_num_inf_manager.add(val, aux, val); - } - m_num_inf_manager.neg(val); - CTRACE("arith_bug", !m_num_inf_manager.eq(m_values[x_b], val), - tout << "x_b: " << x_b << " val: " << m_num_inf_manager.to_string(m_values[x_b]) - << ", computed val: " << m_num_inf_manager.to_string(val) << "\n"; - tout << "row: "; row.display_pol(tout); tout << "\n"; - display(tout);); - SASSERT(m_num_inf_manager.eq(m_values[x_b], val)); - } - m_num_inf_manager.del(val); - m_num_inf_manager.del(aux); - return true; - } - - bool check_basic_assignment() const { - return const_cast(this)->check_basic_assignment_core(); - } - - bool check_eqs_satisfied_core() { - mpq_inf val; - mpq_inf aux; - unsigned num = m_equations.size(); - for (unsigned eq_idx = 0; eq_idx < num; eq_idx++) { - linear_equation const & eq = *(m_equations[eq_idx]); - m_num_inf_manager.reset(val); - unsigned sz = eq.size(); - for (unsigned i = 0; i < sz; i++) { - var x = eq.x(i); - mpz const & a = eq.a(i); - m_num_inf_manager.mul(m_values[x], a, aux); - m_num_inf_manager.add(val, aux, val); - } - CTRACE("arith_bug", !m_num_inf_manager.is_zero(val), - m_eq_manager.display(tout, eq); tout << "\nval: " << m_num_inf_manager.to_string(val) << "\n"; - display(tout);); - SASSERT(m_num_inf_manager.is_zero(val)); - } - m_num_inf_manager.del(val); - m_num_inf_manager.del(aux); - return true; - } - - bool check_eqs_satisfied() const { - if (m_use_approx) - return true; - return const_cast(this)->check_eqs_satisfied_core(); - } - - // Debugging: check eq contains at least one basic variable. - bool check_has_basic(unsigned eq_idx) const { - linear_equation const & eq = *(m_equations[eq_idx]); - for (unsigned i = 0; i < eq.size(); i++) { - if (basic(eq.x(i))) - return true; - } - TRACE("arith_bug", m_eq_manager.display(tout, eq); tout << "\n";); - UNREACHABLE(); - return false; - } - - // Debugging: check eq does not contain eliminated variables - bool check_no_elim_var(linear_equation const & eq) const { - for (unsigned i = 0; i < eq.size(); i++) { - SASSERT(!was_eliminated(eq.x(i))); - } - return true; - } - - svector m_visited; - - bool check_invariant() const { - SASSERT(m_inv_basic.size() == m_equations.size()); - svector & visited = const_cast(this)->m_visited; - - visited.reserve(m_equations.size(), false); - - unsigned num_basic = 0; - // check basic variables - for (unsigned x = 0; x < num_vars(); x++) { - if (basic(x)) { - SASSERT(m_inv_basic[m_basic[x]] == x); - num_basic++; - SASSERT(!was_eliminated(x)); - SASSERT(m_basic[x] < m_equations.size()); - SASSERT(!visited[m_basic[x]]); - visited[m_basic[x]] = true; - } - } - SASSERT(num_basic == m_equations.size()); - for (unsigned x = 0; x < num_vars(); x++) { - if (basic(x)) { - SASSERT(visited[m_basic[x]]); - visited[m_basic[x]] = false; - } - } - - // check all eqs contain at least one basic variable and no eliminated variable - for (unsigned i = 0; i < m_equations.size(); i++) { - SASSERT(m_basic[m_inv_basic[i]] == i); - linear_equation const & eq = *(m_equations[i]); - SASSERT(check_no_elim_var(eq)); - SASSERT(check_has_basic(i)); - } - - // check ineq_cnstrs - for (unsigned i = 0; i < m_ineq_cnstrs.size(); i++) { - SASSERT(m_atom2ineq_cnstr[m_ineq_cnstrs[i].m_atom] == i); - SASSERT(!was_eliminated(m_ineq_cnstrs[i].m_x)); - } - - // check m_atom2ineq_cnstr - for (unsigned i = 0; i < m_atom2ineq_cnstr.size(); i++) { - if (m_atom2ineq_cnstr[i] != UINT_MAX) { - SASSERT(m_ineq_cnstrs[m_atom2ineq_cnstr[i]].m_atom == i); - } - } - - return true; - } - - }; - - arith::arith(ast_manager & m, params_ref const & p): - m_params(p) { - m_imp = alloc(imp, m, p); - } - - arith::~arith() { - imp * d = m_imp; - #pragma omp critical (smt_arith) - { - m_imp = 0; - } - dealloc(d); - } - - void arith::updt_params(params_ref const & p) { - m_params = p; - m_imp->updt_params(p); - } - - void arith::assert_axiom(expr * t, bool neg) { - TRACE("arith", tout << "asserting neg: " << neg << "\n" << mk_ismt2_pp(t, m_imp->m) << "\n";); - m_imp->mk_ineq(t, neg, null_atom_id); - } - - void arith::mk_atom(expr * t, atom_id p) { - TRACE("arith", tout << "mk_atom p: " << p << "\n" << mk_ismt2_pp(t, m_imp->m) << "\n";); - m_imp->mk_ineq(t, false, p); - } - - void arith::asserted(atom_id id, bool is_true) { - } - - bool arith::inconsistent() const { - // TODO - return false; - } - - void arith::push() { - } - - void arith::pop(unsigned num_scopes) { - } - - void arith::set_cancel(bool f) { - #pragma omp critical (smt_arith) - { - if (m_imp) - m_imp->set_cancel(f); - } - } - - void arith::reset() { - ast_manager & m = m_imp->m; - #pragma omp critical (smt_arith) - { - dealloc(m_imp); - m_imp = alloc(imp, m, m_params); - } - } - - void arith::preprocess() { - m_imp->preprocess(); - } - - void arith::simplify() { - } - - void arith::display(std::ostream & out) const { - m_imp->display(out); - } - - void arith::collect_statistics(statistics & st) const { - m_imp->collect_statistics(st); - } - - void arith::reset_statistics() { - m_imp->reset_statistics(); - } - - lbool arith::check() { - m_imp->make_feasible(); - return m_imp->make_int_feasible(); - } - - void arith::mk_model(model * md) { - m_imp->mk_model(md); - } - -}; - diff --git a/src/tactic/arith/dead/smt_arith.h b/src/tactic/arith/dead/smt_arith.h deleted file mode 100644 index 051d27369..000000000 --- a/src/tactic/arith/dead/smt_arith.h +++ /dev/null @@ -1,56 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_arith.h - -Abstract: - - Arithmetic solver for smt::solver - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - ---*/ -#ifndef _SMT_ARITH_H_ -#define _SMT_ARITH_H_ - -#include"ast.h" -#include"smt_solver_types.h" -#include"params.h" -#include"statistics.h" -class model; - -namespace smt { - - class arith { - struct imp; - imp * m_imp; - params_ref m_params; - public: - arith(ast_manager & m, params_ref const & p); - ~arith(); - void updt_params(params_ref const & p); - void assert_axiom(expr * t, bool neg); - void mk_atom(expr * t, atom_id id); - void asserted(atom_id id, bool is_true); - bool inconsistent() const; - void push(); - void pop(unsigned num_scopes); - void set_cancel(bool f); - void simplify(); - void display(std::ostream & out) const; - void reset(); - void preprocess(); - void collect_statistics(statistics & st) const; - void reset_statistics(); - lbool check(); - void mk_model(model * md); - }; -}; - -#endif diff --git a/src/tactic/arith/dead/smt_formula_compiler.cpp b/src/tactic/arith/dead/smt_formula_compiler.cpp deleted file mode 100644 index 7920d4e70..000000000 --- a/src/tactic/arith/dead/smt_formula_compiler.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_formula_compiler.cpp - -Abstract: - - Auxiliary class for smt::solver - Convert Exprs into Internal data-structures. - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - This was an experiment to rewrite Z3 kernel. - It will be deleted after we finish revamping Z3 kernel. - ---*/ -#include"smt_formula_compiler.h" -#include"smt_solver_exp.h" -#include"assertion_set_util.h" -#include"assertion_set2sat.h" -#include"for_each_expr.h" - -namespace smt { - - formula_compiler::formula_compiler(solver_exp & _s, params_ref const & p): - s(_s), - m_a_util(s.m), - m_normalizer(s.m), - m_elim_ite(s.m) { - updt_params(p); - - params_ref s_p; - s_p.set_bool(":elim-and", true); - s_p.set_bool(":blast-distinct", true); - s_p.set_bool(":eq2ineq", true); - s_p.set_bool(":arith-lhs", true); - s_p.set_bool(":gcd-rounding", true); - s_p.set_bool(":sort-sums", true); - s_p.set_bool(":som", true); - m_normalizer.updt_params(s_p); - } - - formula_compiler::~formula_compiler() { - - } - - // mark theory axioms: literals that do not occur in the boolean structure - void formula_compiler::mark_axioms(assertion_set const & s, expr_fast_mark2 & axioms) { - ast_manager & m = s.m(); - unsigned sz = s.size(); - for (unsigned i = 0; i < sz; i++) { - expr * f = s.form(i); - while (m.is_not(f, f)); - if (!is_app(f) || to_app(f)->get_family_id() != m.get_basic_family_id()) { - axioms.mark(f); - continue; - } - SASSERT(is_app(f)); - SASSERT(to_app(f)->get_family_id() == m.get_basic_family_id()); - switch (to_app(f)->get_decl_kind()) { - case OP_OR: - case OP_IFF: - break; - case OP_ITE: - SASSERT(m.is_bool(to_app(f)->get_arg(1))); - break; - case OP_EQ: - if (!m.is_bool(to_app(f)->get_arg(1))) - axioms.mark(f); - break; - case OP_AND: - case OP_XOR: - case OP_IMPLIES: - case OP_DISTINCT: - UNREACHABLE(); - break; - default: - break; - } - } - } - - struct unmark_axioms_proc { - expr_fast_mark2 & m_axioms; - unmark_axioms_proc(expr_fast_mark2 & axioms):m_axioms(axioms) {} - void operator()(quantifier *) {} - void operator()(var *) {} - void operator()(app * t) { - m_axioms.reset_mark(t); - } - }; - - /** - \brief Unmark atoms that occur in the boolean structure. - */ - void formula_compiler::unmark_nested_atoms(assertion_set const & s, expr_fast_mark2 & axioms) { - ast_manager & m = s.m(); - expr_fast_mark1 visited; - unmark_axioms_proc proc(axioms); - unsigned sz = s.size(); - for (unsigned i = 0; i < sz; i++) { - expr * f = s.form(i); - while (m.is_not(f, f)); - if (axioms.is_marked(f)) - continue; - quick_for_each_expr(proc, visited, f); - } - } - - void formula_compiler::assert_axiom(expr * f, bool neg) { - if (is_app(f)) { - if (to_app(f)->get_family_id() == m_a_util.get_family_id()) - s.m_arith.assert_axiom(f, neg); - } - } - - void formula_compiler::register_atom(expr * f, sat::bool_var p) { - if (is_app(f)) { - if (to_app(f)->get_family_id() == m_a_util.get_family_id()) - s.m_arith.mk_atom(f, p); - } - } - - void formula_compiler::compile_formulas(assertion_set const & assertions) { - ast_manager & m = assertions.m(); - expr_fast_mark2 axioms; - mark_axioms(assertions, axioms); - unmark_nested_atoms(assertions, axioms); - ptr_vector formulas; - - // send axioms to theories, and save formulas to compile - unsigned sz = assertions.size(); - for (unsigned i = 0; i < sz; i++) { - expr * f = assertions.form(i); - bool neg = false; - while (m.is_not(f, f)) - neg = !neg; - if (axioms.is_marked(f)) { - assert_axiom(f, neg); - } - else { - formulas.push_back(f); - } - } - - // compile formulas into sat::solver - m_to_sat(m, formulas.size(), formulas.c_ptr(), s.m_params, *(s.m_sat), s.m_atom2bvar); - - // register atoms nested in the boolean structure in the theories - atom2bool_var::recent_iterator it = s.m_atom2bvar.begin_recent(); - atom2bool_var::recent_iterator end = s.m_atom2bvar.end_recent(); - for (; it != end; ++it) { - expr * atom = *it; - register_atom(atom, s.m_atom2bvar.to_bool_var(atom)); - } - s.m_atom2bvar.reset_recent(); - } - - void formula_compiler::normalize() { - // make sure that the assertions are in the right format. - m_normalizer(s.m_assertions); - m_normalizer.cleanup(); - } - - void formula_compiler::elim_term_ite() { - if (has_term_ite(s.m_assertions)) { - model_converter_ref mc; - m_elim_ite(s.m_assertions, mc); - s.m_mc = concat(s.m_mc.get(), mc.get()); - m_elim_ite.cleanup(); - } - } - - void formula_compiler::operator()() { - if (s.m_assertions.inconsistent()) - return; - // normalization - elim_term_ite(); - normalize(); - - TRACE("before_formula_compiler", s.m_assertions.display(tout);); - - s.init(); - - compile_formulas(s.m_assertions); - - s.m_arith.preprocess(); - TRACE("after_formula_compiler", s.display_state(tout);); - } - - void formula_compiler::updt_params(params_ref const & p) { - // TODO - } - - void formula_compiler::collect_param_descrs(param_descrs & d) { - // TODO - } - - void formula_compiler::collect_statistics(statistics & st) { - // TODO - } - - void formula_compiler::reset_statistics() { - // TODO - } - - void formula_compiler::set_cancel(bool f) { - m_normalizer.set_cancel(f); - m_elim_ite.set_cancel(f); - m_to_sat.set_cancel(f); - } - -}; diff --git a/src/tactic/arith/dead/smt_formula_compiler.h b/src/tactic/arith/dead/smt_formula_compiler.h deleted file mode 100644 index 6bd9ad913..000000000 --- a/src/tactic/arith/dead/smt_formula_compiler.h +++ /dev/null @@ -1,63 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_formula_compiler.h - -Abstract: - - Auxiliary class for smt::solver - Convert Exprs into Internal data-structures. - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - ---*/ -#ifndef _SMT_FORMULA_COMPILER_H_ -#define _SMT_FORMULA_COMPILER_H_ - -#include"smt_solver_types.h" -#include"assertion_set_rewriter.h" -#include"elim_term_ite_strategy.h" -#include"arith_decl_plugin.h" -#include"assertion_set2sat.h" - -namespace smt { - - class formula_compiler { - solver_exp & s; - arith_util m_a_util; - assertion_set_rewriter m_normalizer; - elim_term_ite_strategy m_elim_ite; - assertion_set2sat m_to_sat; - - void normalize(); - void elim_term_ite(); - void mark_axioms(assertion_set const & s, expr_fast_mark2 & axioms); - void unmark_nested_atoms(assertion_set const & s, expr_fast_mark2 & axioms); - void assert_axiom(expr * f, bool neg); - void register_atom(expr * f, sat::bool_var p); - void compile_formulas(assertion_set const & assertions); - - public: - formula_compiler(solver_exp & s, params_ref const & p); - ~formula_compiler(); - - void updt_params(params_ref const & p); - static void collect_param_descrs(param_descrs & d); - - void operator()(); - - void set_cancel(bool f); - - void collect_statistics(statistics & st); - void reset_statistics(); - }; - -}; - -#endif diff --git a/src/tactic/arith/dead/smt_solver_exp.cpp b/src/tactic/arith/dead/smt_solver_exp.cpp deleted file mode 100644 index d65562dfa..000000000 --- a/src/tactic/arith/dead/smt_solver_exp.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_solver_exp.cpp - -Abstract: - - SMT solver using strategies and search on top of sat::solver - This solver uses assertion_set strategies during restarts. - - It also uses the sat::solver to handle the Boolean structure of the problem. - - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - This was an experiment to rewrite Z3 kernel. - It will be deleted after we finish revamping Z3 kernel. - ---*/ -#include"smt_solver_exp.h" -#include"sat_solver.h" -#include"ast_translation.h" -#include"model.h" - -namespace smt { - - void solver_exp::bridge::get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector & r) { - } - - void solver_exp::bridge::asserted(sat::literal l) { - } - - sat::check_result solver_exp::bridge::check() { - return sat::CR_DONE; - } - - void solver_exp::bridge::push() { - } - - void solver_exp::bridge::pop(unsigned n) { - } - - void solver_exp::bridge::simplify() { - } - - void solver_exp::bridge::clauses_modifed() { - } - - lbool solver_exp::bridge::get_phase(sat::bool_var v) { - return l_undef; - } - - solver_exp::solver_exp(ast_manager & ext_mng, params_ref const & p): - m_ext_mng(ext_mng), - m(ext_mng, true /* disable proof gen */), - m_compiler(*this, p), - m_assertions(m), - m_atom2bvar(m), - m_arith(m, p), - m_bridge(*this) { - updt_params_core(p); - m_cancel = false; - } - - solver_exp::~solver_exp() { - } - - void solver_exp::updt_params_core(params_ref const & p) { - m_params = p; - } - - void solver_exp::updt_params(params_ref const & p) { - updt_params_core(p); - m_arith.updt_params(p); - if (m_sat) - m_sat->updt_params(p); - } - - void solver_exp::collect_param_descrs(param_descrs & d) { - // TODO - } - - void solver_exp::set_cancel(bool f) { - m_cancel = f; - #pragma omp critical (smt_solver_exp) - { - if (m_sat) { - m_sat->set_cancel(f); - } - } - m_arith.set_cancel(f); - m_compiler.set_cancel(f); - } - - void solver_exp::init() { - m_atom2bvar.reset(); - if (m_sat) - m_sat->collect_statistics(m_stats); - #pragma omp critical (smt_solver_exp) - { - m_sat = alloc(sat::solver, m_params, &m_bridge); - } - m_arith.collect_statistics(m_stats); - m_arith.reset(); - set_cancel(m_cancel); - } - - void solver_exp::assert_expr_core(expr * t, ast_translation & translator) { - expr * new_t = translator(t); - m_assertions.assert_expr(new_t); - } - - /** - \brief Assert an expression t (owned by the external manager) - */ - void solver_exp::assert_expr(expr * t) { - ast_translation translator(m_ext_mng, m, false); - assert_expr_core(t, translator); - } - - /** - \brief Assert an assertion set s (owned by the external manager) - */ - void solver_exp::assert_set(assertion_set const & s) { - SASSERT(&(s.m()) == &m_ext_mng); - ast_translation translator(m_ext_mng, m, false); - unsigned sz = s.size(); - for (unsigned i = 0; i < sz; i++) { - assert_expr_core(s.form(i), translator); - } - } - - void solver_exp::assert_goal(goal const & g) { - SASSERT(&(g.m()) == &m_ext_mng); - ast_translation translator(m_ext_mng, m, false); - unsigned sz = g.size(); - for (unsigned i = 0; i < sz; i++) { - assert_expr_core(g.form(i), translator); - } - } - - /** - \brief Store in r the current set of assertions. - r is (owned) by the external assertion set - */ - void solver_exp::get_assertions(assertion_set & r) { - SASSERT(&(r.m()) == &m_ext_mng); - ast_translation translator(m, m_ext_mng, false); - unsigned sz = m_assertions.size(); - for (unsigned i = 0; i < sz; i++) { - expr * f = m_assertions.form(i); - r.assert_expr(translator(f)); - } - } - - void solver_exp::get_model_converter(model_converter_ref & mc) { - ast_translation translator(m, m_ext_mng, false); - if (m_mc) - mc = m_mc->translate(translator); - else - mc = 0; - } - - // ----------------------- - // - // Search - // - // ----------------------- - lbool solver_exp::check() { - compile(); - lbool r = m_arith.check(); - if (r == l_false) - return r; - if (m_sat->num_vars() == 0 && r == l_true) { - model_ref md = alloc(model, m); - m_arith.mk_model(md.get()); - if (m_mc) - (*m_mc)(md); - ast_translation translator(m, m_ext_mng, false); - m_model = md->translate(translator); - return l_true; - } - return l_undef; - } - - void solver_exp::compile() { - m_compiler(); - } - - // ----------------------- - // - // Pretty Printing - // - // ----------------------- - void solver_exp::display(std::ostream & out) const { - m_assertions.display(out); - } - - void solver_exp::display_state(std::ostream & out) const { - if (m_sat) m_sat->display(out); - m_arith.display(out); - } - - // ----------------------- - // - // Statistics - // - // ----------------------- - void solver_exp::collect_statistics(statistics & st) const { - solver_exp * _this = const_cast(this); - if (m_sat) { - m_sat->collect_statistics(_this->m_stats); - m_sat->reset_statistics(); - } - m_arith.collect_statistics(_this->m_stats); - _this->m_arith.reset_statistics(); - st.copy(m_stats); - } - - void solver_exp::reset_statistics() { - m_stats.reset(); - } - - -}; - - diff --git a/src/tactic/arith/dead/smt_solver_exp.h b/src/tactic/arith/dead/smt_solver_exp.h deleted file mode 100644 index f686f02e7..000000000 --- a/src/tactic/arith/dead/smt_solver_exp.h +++ /dev/null @@ -1,130 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_solver_exp.h - -Abstract: - - SMT solver using strategies and search on top of sat::solver - This solver uses assertion_set strategies during restarts. - - It also uses the sat::solver to handle the Boolean structure of the problem. - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - This was an experiment to rewrite Z3 kernel. - It will be deleted after we finish revamping Z3 kernel. ---*/ -#ifndef _SMT_SOLVER_EXP_H_ -#define _SMT_SOLVER_EXP_H_ - -#include"smt_solver_types.h" -#include"model.h" -#include"model_converter.h" -#include"smt_formula_compiler.h" -#include"smt_arith.h" -#include"sat_extension.h" -#include"goal.h" - -namespace smt { - - class solver_exp { - friend class formula_compiler; - - struct bridge : public sat::extension { - solver_exp & s; - bridge(solver_exp & _s):s(_s) {} - virtual void propagate(sat::literal l, sat::ext_constraint_idx idx, bool & keep) {} - virtual void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector & r); - virtual void asserted(sat::literal l); - virtual sat::check_result check(); - virtual void push(); - virtual void pop(unsigned n); - virtual void simplify(); - virtual void clauses_modifed(); - virtual lbool get_phase(sat::bool_var v); - }; - - // External ASTs are coming from m_ext_mng - ast_manager & m_ext_mng; - // The ASTs are translated into the internal manager for the following reasons: - // 1. We can run multiple smt::solver_exps in parallel with minimal synchronization - // 2. Minimize gaps in the AST ids. - ast_manager m; // internal manager - params_ref m_params; - formula_compiler m_compiler; - - // Set of asserted expressions. - // This assertion set belongs to ast_manager m. - assertion_set m_assertions; - - model_ref m_model; - model_converter_ref m_mc; // chain of model converters - - atom2bool_var m_atom2bvar; - scoped_ptr m_sat; - arith m_arith; - bridge m_bridge; - - statistics m_stats; - - volatile bool m_cancel; - - void updt_params_core(params_ref const & p); - void assert_expr_core(expr * t, ast_translation & translator); - - void init(); - void compile(); - - public: - solver_exp(ast_manager & ext_mng, params_ref const & p); - ~solver_exp(); - - void updt_params(params_ref const & p); - void collect_param_descrs(param_descrs & d); - - void set_cancel(bool f); - - void assert_expr(expr * t); - void assert_set(assertion_set const & s); - void assert_goal(goal const & g); - - void get_assertions(assertion_set & r); - - // ----------------------- - // - // Search - // - // ----------------------- - public: - lbool check(); - void get_model(model_ref & m) const { m = m_model.get(); } - void get_model_converter(model_converter_ref & mc); - - // ----------------------- - // - // Pretty Printing - // - // ----------------------- - public: - void display(std::ostream & out) const; - void display_state(std::ostream & out) const; - - // ----------------------- - // - // Statistics - // - // ----------------------- - public: - void collect_statistics(statistics & st) const; - void reset_statistics(); - }; - -}; - -#endif diff --git a/src/tactic/arith/dead/smt_solver_types.h b/src/tactic/arith/dead/smt_solver_types.h deleted file mode 100644 index 7680c5727..000000000 --- a/src/tactic/arith/dead/smt_solver_types.h +++ /dev/null @@ -1,47 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - smt_solver_types.h - -Abstract: - - Auxiliary definitions for smt::solver class. - -Author: - - Leonardo de Moura (leonardo) 2011-06-25. - -Revision History: - This was an experiment to rewrite Z3 kernel. - It will be deleted after we finish revamping Z3 kernel. - ---*/ -#ifndef _SMT_SOLVER_TYPES_H_ -#define _SMT_SOLVER_TYPES_H_ - -#include"assertion_set.h" -#include"strategy_exception.h" -#include"params.h" -#include"statistics.h" -#include"lbool.h" -#include"sat_types.h" - -class ast_translation; - -namespace sat { - class solver; -}; - -namespace smt { - class solver_exp; - class formula_compiler; - typedef unsigned atom_id; - typedef unsigned_vector atom_id_vector; - const atom_id null_atom_id = sat::null_bool_var; -}; - -MK_ST_EXCEPTION(smt_solver_exception); - -#endif diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index caf67084d..52762edc4 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -19,7 +19,7 @@ Notes: --*/ #include"cmd_context.h" #include"ni_solver.h" -#include"strategic_solver.h" +#include"strategic_solver_cmd.h" #include"qfbv_tactic.h" #include"qflia_tactic.h" #include"qfnia_tactic.h" @@ -56,7 +56,7 @@ MK_SIMPLE_TACTIC_FACTORY(qfnra_fct, mk_qfnra_tactic(m, p)); MK_SIMPLE_TACTIC_FACTORY(qffpa_fct, mk_qffpa_tactic(m, p)); MK_SIMPLE_TACTIC_FACTORY(ufbv_fct, mk_ufbv_tactic(m, p)); -static void init(strategic_solver * s) { +static void init(strategic_solver_core * s) { s->set_default_tactic(alloc(default_fct)); s->set_tactic_for(symbol("QF_UF"), alloc(qfuf_fct)); s->set_tactic_for(symbol("QF_BV"), alloc(qfbv_fct)); @@ -81,14 +81,14 @@ static void init(strategic_solver * s) { } solver * mk_smt_strategic_solver(cmd_context & ctx) { - strategic_solver * s = alloc(strategic_solver_cmd, ctx); + strategic_solver_cmd * s = alloc(strategic_solver_cmd, ctx); s->set_inc_solver(mk_quasi_incremental_smt_solver(ctx)); init(s); return s; } solver * mk_smt_strategic_solver(bool force_tactic) { - strategic_solver * s = alloc(strategic_solver_api); + strategic_solver * s = alloc(strategic_solver); s->force_tactic(force_tactic); s->set_inc_solver(mk_default_solver()); init(s); diff --git a/src/test/dead/ackermanize.cpp b/src/test/dead/ackermanize.cpp deleted file mode 100644 index b61f79440..000000000 --- a/src/test/dead/ackermanize.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "ackermanize.h" -#include "smtparser.h" -#include "ast_pp.h" - -void tst_ackermanize() -{ - ast_manager manager; - - smtlib::parser* parser = smtlib::parser::create(manager); - ackermanize ack(manager); - - ast_ref fD(manager); - ast_ref xD(manager); - ast_ref AD(manager); - ast_ref A(manager); - ast_ref<> a1(manager), a2(manager), a3(manager), a4(manager), - a5(manager), a6(manager), a7(manager); - ast_ref<> r(manager); - - AD = manager.mk_type_decl(symbol("A")); - A = manager.mk_type(AD.get()); - fD = manager.mk_const_decl(symbol("f"), A.get(), A.get(), A.get()); - a1 = manager.mk_const(manager.mk_const_decl(symbol("a1"), A.get())); - a2 = manager.mk_const(manager.mk_const_decl(symbol("a2"), A.get())); - a3 = manager.mk_const(manager.mk_const_decl(symbol("a3"), A.get())); - a4 = manager.mk_const(manager.mk_const_decl(symbol("a4"), A.get())); - a5 = manager.mk_const(manager.mk_const_decl(symbol("a5"), A.get())); - a6 = manager.mk_const(manager.mk_const_decl(symbol("a6"), A.get())); - a7 = manager.mk_const(manager.mk_const_decl(symbol("a7"), A.get())); - - r = manager.mk_const(manager.get_basic_family_id(), - OP_EQ, - manager.mk_const(fD.get(), a1.get(), a2.get()), - manager.mk_const(fD.get(), a2.get(), a3.get())); - - TRACE("ackermanize", tout << mk_pp(r.get()) << std::endl;); - - ack.reduce(r); - - TRACE("ackermanize", tout << mk_pp(r.get()) << std::endl;); - -} diff --git a/src/test/dead/array_property_expander.cpp b/src/test/dead/array_property_expander.cpp deleted file mode 100644 index 6b43efa8f..000000000 --- a/src/test/dead/array_property_expander.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "array_property_expander.h" -#include "array_property_recognizer.h" -#include "smtparser.h" -#include "array_decl_plugin.h" -#include "ast_pp.h" -#include - -static void test_array_expand(ast_manager& m, expr* fml) { - std::cout << mk_pp(fml, m) << "\n"; - expr_ref_vector result(m); - array_property_expander exp(m); - array_property_recognizer rec(m); - exp(1, &fml, result); - std::cout << mk_pp(result[0].get(), m) << "\n"; - std::cout << rec(1, &fml) << "\n"; -} - - -static void parse_string(char const* fml) { - ast_manager m; - m.register_plugin(symbol("array"), alloc(array_decl_plugin)); - scoped_ptr parser = smtlib::parser::create(m); - parser->initialize_smtlib(); - - std::ostringstream buffer; - buffer << "(benchmark array :status unknown :logic AUFLIA \n" - << ":extrafuns ((A (Array Int Int)) (B (Array Int Int)))\n" - << ":extrafuns ((C (Array Int (Array Int Int))))\n" - << ":extrafuns ((D (Array Int Bool Int)))\n" - << ":extrafuns ((i Int) (j Int))\n" - << ":extrafuns ((f Int Int))\n" - << ":formula " << fml << ")"; - parser->parse_string(buffer.str().c_str()); - smtlib::benchmark* b = parser->get_benchmark(); - smtlib::theory::expr_iterator it = b->begin_formulas(); - smtlib::theory::expr_iterator end = b->end_formulas(); - for (; it != end; ++it) { - test_array_expand(m, *it); - } -} - - -void tst_array_property_expander() { - parse_string("(= A B)"); - parse_string("(= A (store B i 4))"); - parse_string("(= C (store C 0 (store (select C 0) i 1)))"); - parse_string("(exists (i Int) (= C (store C 0 (store (select C 0) i 1))))"); - parse_string("(forall (i Int) (b Bool) (= D (store D i b 4)))"); - parse_string("(= (const[Array] 3) A)"); - parse_string("(= (map[f] A) B)"); - -} - diff --git a/src/test/dead/core_theory.cpp b/src/test/dead/core_theory.cpp deleted file mode 100644 index cd46951cb..000000000 --- a/src/test/dead/core_theory.cpp +++ /dev/null @@ -1,821 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - core_theory.cpp - -Abstract: - - Test core theory - -Author: - - Leonardo de Moura (leonardo) 2006-10-20. - -Revision History: - ---*/ -#include"core_theory.h" -#include"theory_diff_logic.h" - -class core_theory_tester { - static void tst1() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - SASSERT(n1->check_invariant()); - enode * n2 = t.mk_const(); - SASSERT(n2->check_invariant()); - enode * app1 = t.mk_app_core(1, n1, n2); - enode * app2 = t.mk_app_core(1, n2, n2); - enode * app3 = t.mk_app_core(1, n1, n2); - SASSERT(app1 != app2); - SASSERT(app1 == app3); - - literal l1 = t.mk_eq(n1, n2); - literal l2 = t.mk_eq(n2, n1); - literal l4 = t.mk_eq(n2, app1); - SASSERT(l1 == l2); - SASSERT(l1 != l4); - - SASSERT(n1->get_root() != n2->get_root()); - - t.assert_lit(l1); - t.assert_lit(l4); - t.propagate(); - - SASSERT(n1->get_root() == n2->get_root()); - TRACE("core_theory", t.display(tout);); - } - - static void tst2() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - enode * a1 = t.mk_app_core(1, n1, n2); - - literal l1 = t.mk_eq(n1, n2); - t.assert_lit(l1); - t.propagate(); - - t.push_scope(); - - literal l2 = t.mk_eq(n1, n3); - t.assign(l2, mk_axiom()); - - enode * a2 = t.mk_app_core(1, n1, n1); - enode * a3 = t.mk_app_core(1, n1, n3); - - TRACE("core_theory", t.display(tout);); - - t.propagate(); - SASSERT(t.is_equal(a1, a2)); - SASSERT(!t.is_equal(a1, a3)); - t.m_sat->mark_as_relevant(l2.var()); - t.propagate(); - SASSERT(t.is_equal(a1, a2)); - SASSERT(t.is_equal(a1, a3)); - - t.pop_scope(1); - - t.propagate(); - SASSERT(to_app(a1)->get_cg() == a1); - TRACE("core_theory", t.display(tout);); - } - - static void tst3() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - enode * a1 = t.mk_app_core(1, n1, n2); - - literal l1 = t.mk_eq(n1, n2); - t.assert_lit(l1); - t.propagate(); - - t.push_scope(); - - literal l2 = t.mk_eq(n1, n3); - t.assign(l2, mk_axiom()); - - enode * a2 = t.mk_app_core(1, n1, n1); - enode * a3 = t.mk_app_core(1, n1, n3); - - TRACE("core_theory", t.display(tout);); - - t.propagate(); - SASSERT(t.is_equal(a1, a2)); - SASSERT(t.is_equal(a1, a3)); - - t.pop_scope(1); - - t.propagate(); - SASSERT(to_app(a1)->get_cg() == a1); - TRACE("core_theory", t.display(tout);); - } - - static void tst8() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_const(); - enode * n5 = t.mk_const(); - enode * n6 = t.mk_const(); - - t.push_scope(); - - t.assert_lit(~t.mk_eq(n1, n2)); - t.assert_lit(t.mk_eq(n1, n3)); - t.assert_lit(t.mk_eq(n2, n4)); - t.assert_lit(t.mk_eq(n3, n6)); - t.assert_lit(t.mk_eq(n1, n5)); - t.propagate(); - - SASSERT(!t.inconsistent()); - - t.assert_lit(t.mk_eq(n3, n4)); - TRACE("core_theory", t.display(tout);); - t.propagate(); - - SASSERT(t.inconsistent()); - - t.pop_scope(1); - } - - static void tst9() { - TRACE("core_theory", tout << "tst9\n";); - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - t.push_scope(); - enode * n = t.mk_const(); - unsigned id = n->get_id(); - t.pop_scope(1); - TRACE("core_theory", tout << "after pop\n";); - n = t.mk_const(); - SASSERT(id == n->get_id()); - TRACE("core_theory", tout << "end of tst9\n";); - } - - static void tst10() { - TRACE("core_theory", tout << "tst10\n";); - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - t.push_scope(); - enode * n = t.mk_const(); - unsigned id = n->get_id(); - t.inc_weak_ref(id); - t.pop_scope(1); - TRACE("core_theory", tout << "after pop\n";); - n = t.mk_const(); - SASSERT(id + 1 == n->get_id()); - t.dec_weak_ref(id); - n = t.mk_const(); - SASSERT(id = n->get_id()); - TRACE("core_theory", tout << "end of tst10\n";); - } - - static void tst11() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - t.add_eq(n1, n2, proto_eq_proof::mk_axiom()); - enode * f1 = t.mk_app_core(1, n1); - enode * f2 = t.mk_app_core(1, n2); - t.propagate(); - SASSERT(t.is_equal(f1, f2)); - t.push_scope(); - literal l1 = t.mk_lit(); - literal l2 = t.mk_eq(f1, f2); - t.mk_main_clause(l1, l2); - SASSERT(t.get_assignment(l2) == l_true); - t.pop_scope(1); - SASSERT(t.get_assignment(l2) == l_true); - } - - static void tst12() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - t.add_diseq(n1, n2, proto_diseq_proof::mk_axiom()); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_const(); - t.add_eq(n1, n3, proto_eq_proof::mk_axiom()); - t.add_eq(n2, n4, proto_eq_proof::mk_axiom()); - t.propagate(); - SASSERT(t.is_diseq(n3, n4)); - t.push_scope(); - literal l1 = t.mk_lit(); - literal l2 = t.mk_eq(n3, n4); - t.mk_main_clause(l1, l2); - SASSERT(t.get_assignment(l2) == l_false); - t.pop_scope(1); - SASSERT(t.get_assignment(l2) == l_false); - } - - static void tst13() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_app_core(1, n1); - enode * n5 = t.mk_app_core(1, n4); - enode * n6 = t.mk_app_core(1, n3); - enode * n7 = t.mk_app_core(1, n6); - - SASSERT(!t.is_relevant(n1)); - SASSERT(!t.is_relevant(n2)); - SASSERT(!t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - - t.add_eq(n6, n1, proto_eq_proof::mk_axiom()); - - SASSERT(!t.is_relevant(n1)); - SASSERT(!t.is_relevant(n2)); - SASSERT(!t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - - t.push_scope(); - - t.assert_lit(t.mk_eq(n7,n2)); - t.propagate(); - SASSERT(t.is_equal(n7, n2)); - - SASSERT(t.is_relevant(n1)); - SASSERT(t.is_relevant(n2)); - SASSERT(t.is_relevant(n3)); - SASSERT(t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(t.is_relevant(n6)); - SASSERT(t.is_relevant(n7)); - - t.pop_scope(1); - - SASSERT(!t.is_relevant(n1)); - SASSERT(!t.is_relevant(n2)); - SASSERT(!t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - } - - static void tst14() { - core_theory t; - t.m_params.m_relevancy_lvl = 2; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_app_core(1, n1); - enode * n5 = t.mk_app_core(1, n4); - enode * n6 = t.mk_app_core(1, n3); - enode * n7 = t.mk_app_core(1, n6); - - t.assert_lit(t.mk_eq(n1,n2)); - t.propagate(); - - SASSERT(t.is_relevant(n1)); - SASSERT(t.is_relevant(n2)); - SASSERT(!t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - - t.push_scope(); - t.assign_eq(n2, n3, proto_eq_proof::mk_axiom()); - t.propagate(); - - SASSERT(t.is_relevant(n1)); - SASSERT(t.is_relevant(n2)); - SASSERT(t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - - t.pop_scope(1); - - SASSERT(t.is_relevant(n1)); - SASSERT(t.is_relevant(n2)); - SASSERT(!t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - - t.push_scope(); - t.assign_eq(n2, n7, proto_eq_proof::mk_axiom()); - t.propagate(); - - SASSERT(t.is_relevant(n1)); - SASSERT(t.is_relevant(n2)); - SASSERT(t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(t.is_relevant(n6)); - SASSERT(t.is_relevant(n7)); - - t.pop_scope(1); - - SASSERT(t.is_relevant(n1)); - SASSERT(t.is_relevant(n2)); - SASSERT(!t.is_relevant(n3)); - SASSERT(!t.is_relevant(n4)); - SASSERT(!t.is_relevant(n5)); - SASSERT(!t.is_relevant(n6)); - SASSERT(!t.is_relevant(n7)); - } - - static void tst15() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - literal l1 = t.mk_lit(); - literal l2 = t.mk_lit(); - literal l3 = t.mk_lit(); - literal l4 = t.mk_lit(); - - t.push_scope(); - t.assign(l1, mk_axiom()); - t.push_scope(); - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * a1 = t.mk_app_core(1, n1); - enode * a2 = t.mk_app_core(1, n2); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_const(); - - literal eq1 = t.mk_eq(a1, n3); - t.assign(eq1, mk_axiom()); - - t.push_scope(); - literal eq2 = t.mk_eq(a2, n4); - t.assign(eq2, mk_axiom()); - - TRACE("core_theory", tout << "eq1: " << eq1 << ", eq2: " << eq2 << "\n";); - - t.mk_transient_clause(~eq2, l3); - t.mk_transient_clause(~eq2, l4); - t.mk_transient_clause(~eq1, l2); - literal_vector lits; - lits.push_back(~l4); lits.push_back(~l3); lits.push_back(~l2); lits.push_back(~l1); - t.mk_transient_clause(lits); - SASSERT(t.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - t.m_sat->resolve_conflict(); - SASSERT(r); - SASSERT(t.m_sat->m_scope_lvl == 2); - SASSERT(t.m_sat->m_ref_count[eq1.var()] > 0); - SASSERT(t.m_sat->m_ref_count[eq2.var()] > 0); - t.pop_scope(2); - SASSERT(n1->get_ref_count() > 0); - SASSERT(n2->get_ref_count() > 0); - SASSERT(a1->get_ref_count() > 0); - SASSERT(a2->get_ref_count() > 0); - t.push_scope(); - literal eq3 = t.mk_eq(n1, n2); - t.assign(eq3, mk_axiom()); - t.propagate(); - TRACE("core_theory", t.display(tout);); - SASSERT(a1->get_root() == a2->get_root()); -#ifdef Z3DEBUG - t.m_sat->del_learned_clauses(); -#endif - t.pop_scope(1); - } - - static void tst16(bool use_relevancy) { - core_theory t; - t.m_params.m_relevancy_lvl = use_relevancy ? 2 : 0; - - literal l0 = t.mk_lit(); - literal l1 = t.mk_lit(); - literal l2 = t.mk_lit(); - literal l3 = t.mk_lit(); - literal l4 = t.mk_lit(); - - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_app_core(1, n1); - - t.push_scope(); - t.assign(l0, mk_axiom()); - - t.push_scope(); - t.assign(l1, mk_axiom()); - - t.push_scope(); - enode * n5 = t.mk_app_core(1, n2); - enode * n6 = t.mk_const(); - literal eq1 = t.mk_eq(n5, n6); - t.assign(eq1, mk_axiom()); - t.mk_transient_clause(~l1, l2); - t.mk_transient_clause(~eq1, l3); - t.mk_transient_clause(~eq1, l4); - literal_vector lits; - lits.push_back(~l4); lits.push_back(~l3); lits.push_back(~l2); - t.mk_transient_clause(lits); - SASSERT(t.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - t.m_sat->resolve_conflict(); - SASSERT(r); - t.propagate(); - SASSERT(t.m_sat->m_scope_lvl == 2); - SASSERT(t.m_sat->m_ref_count[eq1.var()] > 0); - SASSERT(t.m_sat->get_assignment(eq1) == l_false); - - t.pop_scope(1); - SASSERT(t.m_sat->m_scope_lvl == 1); - SASSERT(t.m_sat->m_ref_count[eq1.var()] > 0); - SASSERT(t.m_sat->get_assignment(eq1) == l_undef); - - t.push_scope(); - SASSERT(n5->get_ref_count() == 1); - t.add_eq(n1, n2, proto_eq_proof::mk_axiom()); - SASSERT(to_app(n4)->get_cg() == n5); - if (use_relevancy) { - t.mark_as_relevant(n5); - } - SASSERT(!use_relevancy || n5->get_ref_count() == 3); - SASSERT(use_relevancy || n5->get_ref_count() == 2); - SASSERT(n5->get_root() != n4->get_root()); - SASSERT(!use_relevancy || t.is_relevant(n5)); - t.propagate(); - SASSERT(n5->get_root() == n4->get_root()); - SASSERT(!use_relevancy || n5->get_ref_count() == 4); - SASSERT(use_relevancy || n5->get_ref_count() == 3); -#ifdef Z3DEBUG - t.m_sat->del_learned_clauses(); -#endif - SASSERT(!use_relevancy || n5->get_ref_count() == 3); - SASSERT(use_relevancy || n5->get_ref_count() == 2); - - SASSERT(t.m_sat->m_ref_count[eq1.var()] == 0); - - t.pop_scope(1); - } - - static void tst17() { - theory_idl idl; - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - t.add_theory(&idl); - - literal l0 = t.mk_lit(); - literal l1 = t.mk_lit(); - literal l2 = t.mk_lit(); - literal l3 = t.mk_lit(); - literal l4 = t.mk_lit(); - enode * n1 = t.mk_const(); - - t.push_scope(); - t.assign(l0, mk_axiom()); - - t.push_scope(); - t.assign(l1, mk_axiom()); - - t.push_scope(); - enode * n2 = idl.mk_offset(n1, rational(1)); - enode * n3 = t.mk_const(); - literal eq1 = t.mk_eq(n2, n3); - t.assign(eq1, mk_axiom()); - t.mk_transient_clause(~l1, l2); - t.mk_transient_clause(~eq1, l3); - t.mk_transient_clause(~eq1, l4); - literal_vector lits; - lits.push_back(~l4); lits.push_back(~l3); lits.push_back(~l2); - t.mk_transient_clause(lits); - SASSERT(t.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - t.m_sat->resolve_conflict(); - SASSERT(r); - t.propagate(); - SASSERT(t.m_sat->m_scope_lvl == 2); - SASSERT(t.m_sat->m_ref_count[eq1.var()] > 0); - SASSERT(t.m_sat->get_assignment(eq1) == l_false); - - t.pop_scope(1); - SASSERT(t.m_sat->m_scope_lvl == 1); - SASSERT(t.m_sat->m_ref_count[eq1.var()] > 0); - SASSERT(t.m_sat->get_assignment(eq1) == l_undef); - SASSERT(n2->get_ref_count() == 1); - unsigned n2_id = n2->get_id(); - - // n2 is still alive -#ifdef Z3DEBUG - t.m_sat->del_learned_clauses(); -#endif - // n2 is dead - SASSERT(t.m_enodes[n2_id] == 0); - // n2_id cannot be reused since its weak_counter > 0 - // SASSERT(t.m_weak_counters[n2_id] > 0); - - enode * n4 = idl.mk_offset(n1, rational(1)); - SASSERT(n4->get_id() != n2_id); - SASSERT(n4->get_id() < static_cast(t.m_next_id)); - } - - static void tst18() { - core_theory t; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - enode * a1 = t.mk_app_core(1, n1, n2); - - literal l1 = t.mk_eq(n1, n3); - t.assert_lit(l1); - t.propagate(); - - enode * args[2] = { n3, n2 }; - - SASSERT(t.get_enode_eq_to_app(1, 2, args) != 0); - SASSERT(a1->get_root() == t.get_enode_eq_to_app(1, 2, args)->get_root()); - } - - static void tst19() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - literal l1 = t.mk_eq(n1, n2); - literal l2 = t.mk_eq(n2, n3); - literal l3 = t.mk_eq(n1, n3); - - enode * n4 = t.mk_const(); - enode * n5 = t.mk_const(); - enode * n6 = t.mk_const(); - enode * n7 = t.mk_const(); - - literal l4 = t.mk_eq(n4, n5); - literal l5 = t.mk_eq(n6, n7); - literal l6 = t.mk_eq(n5, n7); - literal l7 = t.mk_eq(n4, n6); - - t.mk_main_clause(l3, l7); - - t.push_scope(); - t.assign(l1, mk_axiom()); - t.assign(~l2, mk_axiom()); - t.assign(l4, mk_axiom()); - t.assign(l5, mk_axiom()); - t.assign(~l6, mk_axiom()); - t.propagate(); - SASSERT(t.inconsistent()); - t.m_sat->resolve_conflict(); - } - - static void tst20() { - theory_idl idl; - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - t.add_theory(&idl); - - enode * n1 = t.mk_const(); - enode * n2 = idl.mk_offset(n1, rational(1)); - enode * n3 = idl.mk_offset(n2, rational(1)); - enode * n4 = idl.mk_offset(n1, rational(2)); - SASSERT(n4 == n3); - - enode * r1 = idl.mk_num(rational(1)); - enode * r2 = idl.mk_offset(r1, rational(1)); - enode * r3 = idl.mk_num(rational(2)); - SASSERT(r2 == r3); - } - - static void tst21() { - enable_debug("add_eq"); - enable_debug("core_invariant"); - theory_idl idl; - core_theory t; - t.m_params.m_relevancy_lvl = 0; - t.add_theory(&idl); - theory_id idl_id = idl.get_id(); - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_const(); - enode * n5 = t.mk_const(); - literal l1 = t.mk_eq(n1, n2); - literal l2 = t.mk_eq(n1, n3); - literal l3 = t.mk_eq(n4, n5); - literal l4 = t.mk_eq(n4, n3); - - t.push_scope(); - t.assign(l1, mk_axiom()); - t.propagate(); - SASSERT(n2->get_root() == n2); - t.push_scope(); - t.assign(l2, mk_axiom()); - t.propagate(); - t.push_scope(); - t.assign(l3, mk_axiom()); - t.propagate(); - SASSERT(n5->get_root() == n5); - SASSERT(n4->get_root() == n5); - t.push_scope(); - t.assign(l4, mk_axiom()); - t.propagate(); - SASSERT(n2->get_root() == n2); - enode * o1 = idl.mk_offset(n4, rational(1)); - SASSERT(n4->get_th_var(idl_id) != null_theory_var); - SASSERT(n2->get_th_var(idl_id) == n4->get_th_var(idl_id)); - t.pop_scope(1); - SASSERT(n4->get_th_var(idl_id) != null_theory_var); - SASSERT(n5->get_th_var(idl_id) == n4->get_th_var(idl_id)); - SASSERT(n2->get_th_var(idl_id) == null_theory_var); - t.pop_scope(1); - SASSERT(n4->get_th_var(idl.get_id()) != null_theory_var); - SASSERT(n5->get_th_var(idl_id) == null_theory_var); - SASSERT(n2->get_th_var(idl_id) == null_theory_var); - } - - static void tst22() { - enable_debug("add_eq"); - enable_debug("core_invariant"); - theory_idl idl; - core_theory t; - t.m_params.m_relevancy_lvl = 0; - t.add_theory(&idl); - theory_id idl_id = idl.get_id(); - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_const(); - enode * n5 = t.mk_const(); - enode * o1 = idl.mk_offset(n2, rational(1)); - literal l1 = t.mk_eq(n1, n2); - literal l2 = t.mk_eq(n1, n3); - literal l3 = t.mk_eq(n4, n5); - literal l4 = t.mk_eq(n4, n3); - - t.push_scope(); - t.assign(l1, mk_axiom()); - t.propagate(); - SASSERT(n2->get_root() == n2); - - t.push_scope(); - t.assign(l2, mk_axiom()); - t.propagate(); - - t.push_scope(); - t.assign(l3, mk_axiom()); - t.propagate(); - SASSERT(n5->get_root() == n5); - SASSERT(n4->get_root() == n5); - - t.push_scope(); - t.assign(l4, mk_axiom()); - t.propagate(); - SASSERT(n2->get_root() == n2); - enode * o2 = idl.mk_offset(n4, rational(1)); - SASSERT(n4->get_th_var(idl_id) != null_theory_var); - SASSERT(n2->get_th_var(idl_id) != null_theory_var); - SASSERT(n2->get_th_var(idl_id) != n4->get_th_var(idl_id)); - - t.pop_scope(1); - SASSERT(n2->get_th_var(idl_id) != null_theory_var); - SASSERT(n4->get_th_var(idl_id) != null_theory_var); - SASSERT(n4->get_th_var(idl_id) == n5->get_th_var(idl_id)); - - t.pop_scope(1); - SASSERT(n2->get_th_var(idl_id) != null_theory_var); - SASSERT(n4->get_th_var(idl_id) != null_theory_var); - SASSERT(n5->get_th_var(idl_id) == null_theory_var); - } - - static void tst23() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - enable_trace("th_diseq_prop_bug"); - enable_trace("add_eq"); - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_true_term(); - enode * d[2] = {n1, n2}; - t.assert_distinct_class(2, d); - enode * n3 = t.mk_const(); - enode * n4 = t.mk_const(); - - literal l1 = t.mk_eq(n3, n4); - literal l2 = t.mk_eq(n4, n1); - literal l3 = t.mk_eq(n3, n2); - t.push_scope(); - t.assign(l1, mk_axiom()); - t.propagate(); - SASSERT(n3->get_root() == n4->get_root()); - t.push_scope(); - t.assign(l2, mk_axiom()); - t.propagate(); - SASSERT(n3->get_root() == n1->get_root()); - SASSERT(t.is_diseq(n3, n2)); - SASSERT(t.get_assignment(l3) == l_false); - SASSERT(t.m_sat->m_explanation[l3.var()].kind() == EXPL_EXT); - literal_vector antecedents; - t.get_antecedents(~l3, t.m_sat->m_explanation[l3.var()].obj(), antecedents); - } - -public: - static void run_tests() { - tst1(); - tst2(); - tst3(); - tst8(); - tst9(); - tst10(); - tst11(); - tst12(); - tst13(); - tst14(); - tst15(); - tst16(false); - tst16(true); - tst17(); - tst18(); - tst19(); - tst20(); - tst21(); - tst22(); - tst23(); - } -}; - -struct foo { - bool_var m_var; // boolean variable associated with the equation - enode * m_lhs; - enode * m_rhs; -}; - -struct bar { - bool m_v1:1; - bool m_v2:1; - bool m_v3:1; - bool m_v4:1; - bool m_v5:1; - bool m_v6:1; - bool m_v7:1; - bool m_v8:1; -}; - -struct bar2 { - bool m_v1:1; - bool m_v2:1; - unsigned m_val:30; -}; - -void tst_core_theory() { - TRACE("core_theory", tout << "sizeof(equation): " << sizeof(equation) << "\n";); - TRACE("core_theory", tout << "sizeof(foo): " << sizeof(foo) << "\n";); - TRACE("core_theory", tout << "sizeof(bar): " << sizeof(bar) << "\n";); - TRACE("core_theory", tout << "sizeof(bar2): " << sizeof(bar2) << "\n";); - TRACE("core_theory", tout << "sizeof(theory_var_list): " << sizeof(theory_var_list) << "\n";); - TRACE("core_theory", tout << "sizeof(enode): " << sizeof(enode) << "\n";); - enable_debug("cg_bug"); - core_theory_tester::run_tests(); -} - diff --git a/src/test/dead/dimacs.cpp b/src/test/dead/dimacs.cpp deleted file mode 100644 index ca857be0e..000000000 --- a/src/test/dead/dimacs.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - tst_dimacs.cpp - -Abstract: - - Test dimacs parser - -Author: - - Leonardo de Moura (leonardo) 2006-10-02. - -Revision History: - ---*/ - -#include -#include -#ifdef _WINDOWS -#include -#include -#endif -#include"trace.h" -#include"dimacs_parser.h" - -class dummy_sat { - unsigned m_num_vars; -public: - dummy_sat():m_num_vars(0) {} - unsigned get_num_vars() { - return m_num_vars; - } - void mk_var() { - TRACE("dimacs", tout << "making variable: p" << m_num_vars << "\n";); - m_num_vars++; - } - void mk_clause(literal_vector & lits) { - TRACE("dimacs", tout << "making clause: " << lits << "\n";); - } -}; - -static void tst1() -{ -#ifdef _WINDOWS - dummy_sat solver; - const char * base = "."; - std::string pattern(base); - pattern += "\\*.cnf"; - - char buffer[MAX_PATH]; - - WIN32_FIND_DATAA data; - HANDLE h = FindFirstFileA(pattern.c_str(),&data); - - while (h != INVALID_HANDLE_VALUE) { - StringCchPrintfA(buffer, ARRAYSIZE(buffer), "%s\\%s", base, data.cFileName); - - TRACE("dimacs", tout << "Parsing: " << buffer << "\n";); - - std::ifstream s(buffer); - - parse_dimacs(s, solver); - - if (!FindNextFileA(h,&data)) - break; - } -#endif -} - -void tst_dimacs() { - tst1(); -} diff --git a/src/test/dead/distinct.cpp b/src/test/dead/distinct.cpp deleted file mode 100644 index e1595c37d..000000000 --- a/src/test/dead/distinct.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - distinct.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2006-11-03. - -Revision History: - ---*/ -#include"core_theory.h" - -class distinct_tester { - static void tst1() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - enode * d[3] = {n1, n2, n3}; - - enode * n4 = t.mk_const(); - enode * n5 = t.mk_const(); - enode * n6 = t.mk_const(); - - t.assert_distinct_class(3, d); - TRACE("distinct", t.display(tout);); - t.propagate(); - - t.push(); - - t.assert_lit(t.mk_eq(n1, n2)); - t.propagate(); - SASSERT(t.inconsistent()); - - t.pop(1); - SASSERT(!t.inconsistent()); - TRACE("distinct", t.display(tout);); - - t.push_scope(); - - t.assign(t.mk_eq(n1, n4), mk_axiom()); - t.assign(t.mk_eq(n2, n5), mk_axiom()); - t.assign(t.mk_eq(n2, n6), mk_axiom()); - t.propagate(); - SASSERT(!t.inconsistent()); - - t.assign(t.mk_eq(n4,n5), mk_axiom()); - t.propagate(); - TRACE("distinct", t.display(tout);); - SASSERT(t.inconsistent()); - } - - static void tst2() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - t.assert_lit(t.mk_eq(n1,n3)); - t.propagate(); - - enode * d[3] = {n1, n2, n3}; - - t.assert_distinct_class(3, d); - SASSERT(t.inconsistent()); - } - - static void tst3() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - t.assert_lit(t.mk_eq(n1,n3)); - - enode * d[3] = {n1, n2, n3}; - - t.assert_distinct_class(3, d); - - t.propagate(); - SASSERT(t.inconsistent()); - } - - static void tst4() { -#ifdef ENABLE_DISTINCT_CLASSES_SUPPORT - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - t.push(); - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - enode * d1[3] = {n1, n2, n3}; - - t.assert_distinct_class(3, d1); - - SASSERT(n1->get_distinct_classes() == 1); - SASSERT(n2->get_distinct_classes() == 1); - SASSERT(n3->get_distinct_classes() == 1); - - enode * n4 = t.mk_const(); - enode * n5 = t.mk_const(); - enode * n6 = t.mk_const(); - - enode * d2[3] = {n4, n5, n6}; - - t.assert_distinct_class(3, d2); - - SASSERT(n4->get_distinct_classes() == 2); - SASSERT(n5->get_distinct_classes() == 2); - SASSERT(n6->get_distinct_classes() == 2); - - enode * n7 = t.mk_const(); - enode * n8 = t.mk_const(); - enode * n9 = t.mk_const(); - - enode * d3[3] = {n7, n8, n9}; - - t.assert_distinct_class(3, d3); - - SASSERT(n7->get_distinct_classes() == 4); - SASSERT(n8->get_distinct_classes() == 4); - SASSERT(n9->get_distinct_classes() == 4); - - enode * n10 = t.mk_const(); - enode * n11 = t.mk_const(); - enode * n12 = t.mk_const(); - - enode * d4[3] = {n10, n11, n12}; - - t.assert_distinct_class(3, d4); - - SASSERT(n10->get_distinct_classes() == 8); - SASSERT(n11->get_distinct_classes() == 8); - SASSERT(n12->get_distinct_classes() == 8); - - t.push_scope(); - - t.assign(t.mk_eq(n7, n1), mk_axiom()); - t.propagate(); - SASSERT(!t.inconsistent()); - SASSERT(n1->get_root()->get_distinct_classes() == 5); - - t.push_scope(); - - t.assign(t.mk_eq(n11, n5), mk_axiom()); - t.propagate(); - SASSERT(!t.inconsistent()); - SASSERT(n5->get_root()->get_distinct_classes() == 10); - - t.push_scope(); - t.assign(t.mk_eq(n7, n3), mk_axiom()); - t.propagate(); - SASSERT(t.inconsistent()); - - t.pop_scope(1); - SASSERT(!t.inconsistent()); - - t.push_scope(); - - t.assign(t.mk_eq(n11, n1), mk_axiom()); - t.propagate(); - SASSERT(!t.inconsistent()); - SASSERT(n1->get_root()->get_distinct_classes() == 15); - - t.pop_scope(1); - - SASSERT(!t.inconsistent()); - SASSERT(n1->get_root()->get_distinct_classes() == 5); - SASSERT(n11->get_root()->get_distinct_classes() == 10); - SASSERT(n5->get_root()->get_distinct_classes() == 10); - - t.pop_scope(1); - SASSERT(n1->get_root()->get_distinct_classes() == 5); - SASSERT(n7->get_root()->get_distinct_classes() == 5); - SASSERT(n11->get_root()->get_distinct_classes() == 8); - SASSERT(n5->get_root()->get_distinct_classes() == 2); - - t.pop_scope(1); - SASSERT(n1->get_root()->get_distinct_classes() == 1); - SASSERT(n7->get_root()->get_distinct_classes() == 4); - SASSERT(n11->get_root()->get_distinct_classes() == 8); - SASSERT(n5->get_root()->get_distinct_classes() == 2); - - SASSERT(t.m_num_distinct_classes == 4); - - t.pop(1); - - SASSERT(t.m_num_distinct_classes == 0); -#endif - } - - static void tst5() { -#ifdef ENABLE_DISTINCT_CLASSES_SUPPORT - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - t.push(); - - enode * n1; - enode * n2; - enode * n3; - - for (unsigned i = 0; i < 40; i++) { - n1 = t.mk_const(); - n2 = t.mk_const(); - n3 = t.mk_const(); - - enode * d1[3] = {n1, n2, n3}; - - t.assert_distinct_class(3, d1); - } - - SASSERT(t.m_num_distinct_classes == 32); - SASSERT(n1->get_root()->get_distinct_classes() == 0); - - t.push_scope(); - t.assign(t.mk_eq(n1, n3), mk_axiom()); - t.propagate(); - - SASSERT(t.inconsistent()); - - t.pop_scope(1); - SASSERT(!t.inconsistent()); - - t.pop(1); - SASSERT(t.m_num_distinct_classes == 0); - - n1 = t.mk_const(); - n2 = t.mk_const(); - n3 = t.mk_const(); - - enode * d1[3] = {n1, n2, n3}; - - t.assert_distinct_class(3, d1); - SASSERT(n1->get_root()->get_distinct_classes() == 1); -#endif - } - - static void tst6() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - t.push_scope(); - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - enode * d1[3] = {n1, n2, n3}; - - t.assert_distinct_class(3, d1); - - SASSERT(t.m_num_distinct_classes == 0); - SASSERT(n1->get_root()->get_distinct_classes() == 0); - - t.assign(t.mk_eq(n1, n3), mk_axiom()); - t.propagate(); - - SASSERT(t.inconsistent()); - } - -public: - - static void run_tests() { - tst1(); - tst2(); - tst3(); - tst4(); - tst5(); - tst6(); - } -}; - - -void tst_distinct() { - enable_trace("core_theory_conflict"); - distinct_tester::run_tests(); -} - diff --git a/src/test/dead/expr_context_simplifier.cpp b/src/test/dead/expr_context_simplifier.cpp deleted file mode 100644 index bd512b426..000000000 --- a/src/test/dead/expr_context_simplifier.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "expr_context_simplifier.h" -#include "smtparser.h" -#include "ast_pp.h" -#include "reg_decl_plugins.h" - -static void check_equiv(ast_manager& m, expr* e1, expr* e2) { - front_end_params fp; - smt::solver solver(m, fp); - expr_ref equiv(m); - equiv = m.mk_not(m.mk_eq(e1,e2)); - solver.assert_expr(equiv); - lbool is_sat = solver.check(); - SASSERT(is_sat == l_false); -} - -static void simplify_formula(ast_manager& m, expr* e) { - expr_ref result(m); - expr_context_simplifier simp(m); - - simp(e, result); - - TRACE("expr_context_simplifier", - tout - << mk_pp(e, m) << "\n|->\n" - << mk_pp(result.get(), m) << "\n";); - - check_equiv(m, e, result); - -} - -void tst_expr_context_simplifier() { - ast_manager m; - - smtlib::parser* parser = smtlib::parser::create(m); - reg_decl_plugins(m); - - parser->initialize_smtlib(); - - parser->parse_string( - "(benchmark samples :logic QF_LIA \n" - " :extrafuns ((x Int) (y Int) (z Int) (u Int)) \n" - " :extrapreds ((p) (q) (r)) \n" - " :formula (and (<= 1 x) (or (<= 1 x) (<= x y))) \n" - " :formula (and (<= 2 (ite (<= z 1) (ite (<= z 1) x y) (* 2 x))) (<= x y)) \n" - " :formula (or (and (not p) q (or (not r) (and (or (not p) q) r)))\ - (and (not p) q (or (and p (not q) r) (and (or (not p) q) (not r)))) \ - (and (or (and p (not q)) (and p q))\ - (or (and p q r) (and (or (not p) (not q)) (not r))))\ - (and (not p) (not q) (or (and (not p) q r) (and (or p (not q)) (not r))))\ - (and (not p) (not q) (or (not r) (and (or p (not q)) r))))\n" - ")" - ); - - smtlib::benchmark* b = parser->get_benchmark(); - - smtlib::symtable const * table = b->get_symtable(); - - for (unsigned j = 0; j < b->get_num_formulas(); ++j) { - simplify_formula(m, b->begin_formulas()[j]); - } - - dealloc(parser); -} diff --git a/src/test/dead/fingerprint.cpp b/src/test/dead/fingerprint.cpp deleted file mode 100644 index 396009f0c..000000000 --- a/src/test/dead/fingerprint.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - fingerprint.cpp - -Abstract: - - Test fingerprint support - -Author: - - Leonardo de Moura (leonardo) 2006-10-29. - -Revision History: - ---*/ -#include"core_theory.h" - -bool add_fingerprint(core_theory & t, void * data, enode * n1) { - enode * c[1]; - c[0] = n1; - return t.add_fingerprint(data, 1, c); -} - -bool add_fingerprint(core_theory & t, void * data, enode * n1, enode * n2) { - enode * c[2]; - c[0] = n1; - c[1] = n2; - return t.add_fingerprint(data, 2, c); -} - -bool add_fingerprint(core_theory & t, void * data, enode * n1, enode * n2, enode * n3, enode * n4, enode * n5, enode * n6, enode * n7, enode * n8, enode * n9) { - enode * c[9]; - c[0] = n1; - c[1] = n2; - c[2] = n3; - c[3] = n4; - c[4] = n5; - c[5] = n6; - c[6] = n7; - c[7] = n8; - c[8] = n9; - return t.add_fingerprint(data, 9, c); -} - -class fingerprint_tester { - - static void tst1() { - core_theory t; - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - void * d1 = reinterpret_cast(1); - - SASSERT(add_fingerprint(t, 0, n1)); - SASSERT(!add_fingerprint(t, 0, n1)); - SASSERT(add_fingerprint(t, 0, n2)); - - SASSERT(add_fingerprint(t, d1, n1)); - SASSERT(!add_fingerprint(t, d1, n1)); - SASSERT(add_fingerprint(t, d1, n2)); - SASSERT(add_fingerprint(t, d1, n1, n2)); - SASSERT(add_fingerprint(t, d1, n2, n1)); - SASSERT(!add_fingerprint(t, d1, n1, n2)); - SASSERT(!add_fingerprint(t, d1, n2, n1)); - - t.push_scope(); - - SASSERT(add_fingerprint(t, 0, n3)); - SASSERT(add_fingerprint(t, d1, n3)); - SASSERT(add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n2)); - SASSERT(!add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n2)); - SASSERT(add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n1)); - SASSERT(!add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n1)); - - t.pop_scope(1); - - SASSERT(!add_fingerprint(t, 0, n1)); - SASSERT(!add_fingerprint(t, 0, n2)); - SASSERT(!add_fingerprint(t, d1, n1, n2)); - SASSERT(!add_fingerprint(t, d1, n2, n1)); - SASSERT(add_fingerprint(t, 0, n3)); - SASSERT(add_fingerprint(t, d1, n3)); - SASSERT(add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n2)); - SASSERT(!add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n2)); - SASSERT(add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n1)); - SASSERT(!add_fingerprint(t, d1, n1, n1, n1, n1, n1, n1, n2, n1, n1)); - } - -public: - - static void run_tests() { - tst1(); - } -}; - -void tst_fingerprint() { - fingerprint_tester::run_tests(); -} diff --git a/src/test/dead/gate.cpp b/src/test/dead/gate.cpp deleted file mode 100644 index 8acabc9ec..000000000 --- a/src/test/dead/gate.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - gate.cpp - -Abstract: - - Test SAT gates - -Author: - - Leonardo de Moura (leonardo) 2006-11-02. - -Revision History: - ---*/ -#include"sat_def.h" - -class gate_extension : public no_extension { -public: - bool relevancy_enabled() { - return true; - } - - bool gates_enabled() { - return true; - } -}; - - -class gate_no_rel_extension : public no_extension { -public: - bool relevancy_enabled() { - return false; - } - - bool gates_enabled() { - return true; - } -}; - -class sat_gate_tester { - - static void tst1() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - - SASSERT(solver.mk_or(l1, l2, l3) == solver.mk_or(l3, l1, l2)); - - SASSERT(solver.mk_or(l1, l1, l3) == solver.mk_or(l3, l1)); - - SASSERT(solver.mk_or(l1, l1, l1) == l1); - - SASSERT(solver.mk_or(l1, false_literal, l1) == l1); - - SASSERT(solver.mk_or(l1, true_literal, l1) == true_literal); - - solver.assert_lit(l1); - - SASSERT(solver.mk_or(l1, l2, l3) == true_literal); - - literal l4 = solver.mk_or(l2, l3); - - SASSERT(l4 != true_literal && l4 != false_literal); - - solver.push(); - - solver.assert_lit(l2); - - solver.propagate(); - - SASSERT(solver.get_assignment(l4) == l_true); - - solver.pop(1); - - SASSERT(solver.get_assignment(l4) == l_undef); - - solver.push(); - - solver.assert_lit(~l2); - - solver.assert_lit(~l3); - - solver.propagate(); - - SASSERT(solver.get_assignment(l4) == l_false); - - solver.pop(1); - - SASSERT(solver.get_assignment(l4) == l_undef); - - SASSERT(l4 == ~solver.mk_and(~l2, ~l3)); - } - - static void tst1a() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - - SASSERT(solver.mk_or(l1, l2, l3) == solver.mk_or(l3, l1, l2)); - - SASSERT(solver.mk_or(l1, l1, l3) == solver.mk_or(l3, l1)); - - SASSERT(solver.mk_or(l1, l1, l1) == l1); - - SASSERT(solver.mk_or(l1, false_literal, l1) == l1); - - SASSERT(solver.mk_or(l1, true_literal, l1) == true_literal); - - solver.assert_lit(l1); - - SASSERT(solver.mk_or(l1, l2, l3) != true_literal); - - literal l4 = solver.mk_or(l2, l3); - - SASSERT(l4 != true_literal && l4 != false_literal); - - solver.push(); - - solver.assert_lit(l2); - - solver.propagate(); - - SASSERT(solver.get_assignment(l4) == l_true); - - solver.pop(1); - - SASSERT(solver.get_assignment(l4) == l_undef); - - solver.push(); - - solver.assert_lit(~l2); - - solver.assert_lit(~l3); - - solver.propagate(); - - SASSERT(solver.get_assignment(l4) == l_false); - - solver.pop(1); - - SASSERT(solver.get_assignment(l4) == l_undef); - - SASSERT(l4 == ~solver.mk_and(~l2, ~l3)); - } - - static void tst2() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - - SASSERT(solver.mk_iff(l1, l2) == solver.mk_iff(l2, l1)); - - SASSERT(solver.mk_iff(l1, true_literal) == l1); - - SASSERT(solver.mk_iff(l1, false_literal) == ~l1); - - SASSERT(solver.mk_iff(true_literal, l2) == l2); - - SASSERT(solver.mk_iff(false_literal, l2) == ~l2); - - SASSERT(solver.mk_iff(l1, l1) == true_literal); - - SASSERT(solver.mk_iff(l1, ~l1) == false_literal); - } - - static void tst3() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - - solver.push(); - - literal l3 = solver.mk_or(l1, l2); - SASSERT(solver.m_ref_count[l3.var()] == 1); - - solver.pop(1); - } - - static void tst4() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - - literal l3 = solver.mk_or(l1, l2); - - solver.reset(); - - l1 = solver.mk_var(); - - } - - static void tst5() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - - solver.push_scope(); - - solver.assign(l1, mk_axiom()); - - solver.propagate(); - - solver.push_scope(); - - literal l4 = solver.mk_or(l1, l2); - - solver.mk_main_clause(l4, l3); - - SASSERT(solver.get_assignment(l4) == l_true); - - solver.pop_scope(1); - - SASSERT(solver.get_assignment(l4) == l_true); - } - - static void tst6() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - literal l4 = solver.mk_var(); - - SASSERT(solver.mk_ite(l1, l2, l3) == solver.mk_ite(~l1, l3, l2)); - - SASSERT(solver.mk_ite(l1, l2, l2) == l2); - - solver.assert_lit(l1); - - solver.push_scope(); - - SASSERT(solver.mk_ite(l1, l2, l3) == l2); - - SASSERT(solver.mk_ite(~l1, l2, l3) == l3); - } - - static void tst6a() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - literal l4 = solver.mk_var(); - - SASSERT(solver.mk_ite(l1, l2, l3) == solver.mk_ite(~l1, l3, l2)); - - SASSERT(solver.mk_ite(l1, l2, l2) == l2); - - solver.assert_lit(l1); - - solver.push_scope(); - - SASSERT(solver.mk_ite(l1, l2, l3) != l2); - - SASSERT(solver.mk_ite(~l1, l2, l3) != l3); - } - - static void tst7() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_uniq(l1); - SASSERT(l1 != l2); - - solver.push(); - - solver.assert_lit(l1); - solver.propagate(); - - SASSERT(solver.get_assignment(l1) == l_true); - SASSERT(solver.get_assignment(l2) == l_true); - - solver.pop(1); - solver.propagate(); - - SASSERT(solver.get_assignment(l1) == l_undef); - SASSERT(solver.get_assignment(l2) == l_undef); - - solver.assert_lit(~l1); - solver.propagate(); - - SASSERT(solver.get_assignment(l1) == l_false); - SASSERT(solver.get_assignment(l2) == l_false); - } - - static void tst8() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_uniq(l1); - SASSERT(l1 != l2); - - solver.push_scope(); - - solver.assert_lit(l1); - solver.propagate(); - - SASSERT(solver.get_assignment(l1) == l_true); - SASSERT(solver.get_assignment(l2) == l_true); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(solver.get_assignment(l1) == l_true); - SASSERT(solver.get_assignment(l2) == l_true); - } - - static void tst9() { - sat_solver s; - - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - literal l3 = s.mk_var(); - - s.push_scope(); - s.assign(l1, mk_axiom()); - s.push_scope(); - literal l4 = s.mk_var(); - literal l5 = s.mk_var(); - literal l6 = s.mk_or(l4, l5); - s.assign(l6, mk_axiom()); - s.mk_transient_clause(~l6, l3); - s.mk_transient_clause(~l6, l2); - s.mk_transient_clause(literal_vector(~l3, ~l1, ~l2)); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - s.resolve_conflict(); - SASSERT(r); - SASSERT(s.m_scope_lvl == 1); - SASSERT(s.m_ref_count[l4.var()] > 0); - SASSERT(s.m_ref_count[l5.var()] > 0); - SASSERT(s.m_ref_count[l6.var()] > 0); - s.pop_scope(1); - SASSERT(s.get_assignment(l1) == l_undef); - SASSERT(s.get_assignment(l4) == l_undef); - SASSERT(s.get_assignment(l5) == l_undef); - SASSERT(s.get_assignment(l6) == l_undef); - SASSERT(s.m_ref_count[l4.var()] > 0); - SASSERT(s.m_ref_count[l5.var()] > 0); - SASSERT(s.m_ref_count[l6.var()] > 0); - s.push_scope(); - s.assign(~l4, mk_axiom()); - s.propagate(); -#ifdef Z3DEBUG - s.del_learned_clauses(); -#endif - s.pop_scope(1); - } - - static void tst10() { - sat_solver s; - - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - literal l3 = s.mk_var(); - - s.push_scope(); - s.assign(l1, mk_axiom()); - s.push_scope(); - literal l4 = s.mk_var(); - literal l5 = s.mk_var(); - literal l6 = s.mk_iff(l4, l5); - literal l7 = s.mk_var(); - literal l8 = s.mk_or(l6, l7); - s.assign(l8, mk_axiom()); - s.mk_transient_clause(~l8, l3); - s.mk_transient_clause(~l8, l2); - s.mk_transient_clause(literal_vector(~l3, ~l1, ~l2)); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - s.resolve_conflict(); - SASSERT(r); - SASSERT(s.m_scope_lvl == 1); - s.pop_scope(1); - SASSERT(s.m_ref_count[l4.var()] > 0); - SASSERT(s.m_ref_count[l5.var()] > 0); - SASSERT(s.m_ref_count[l6.var()] > 0); - SASSERT(s.m_ref_count[l7.var()] > 0); - SASSERT(s.m_ref_count[l8.var()] > 0); - s.push_scope(); - s.assign(~l1, mk_axiom()); - s.push_scope(); - s.assign(l5, mk_axiom()); - s.mk_transient_clause(~l5, ~l4); - s.propagate(); - SASSERT(s.get_assignment(l6) == l_false); - SASSERT(s.get_assignment(l8) == l_undef); -#ifdef Z3DEBUG - s.del_learned_clauses(); - SASSERT(s.m_ref_count[l7.var()] == 0); - SASSERT(s.m_ref_count[l8.var()] == 0); - SASSERT(s.m_ref_count[l4.var()] > 0); - SASSERT(s.m_ref_count[l5.var()] > 0); - SASSERT(s.m_ref_count[l6.var()] > 0); -#endif - s.mk_transient_clause(l6, l3); - s.mk_transient_clause(l6, l2); - s.mk_transient_clause(literal_vector(~l3, l1, ~l2)); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - r = -#endif - s.resolve_conflict(); - SASSERT(r); - } - - static void tst11() { - sat_solver s; - - literal l0 = s.mk_var(); - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - - s.push_scope(); - s.assign(~l1, mk_axiom()); - s.assign(~l2, mk_axiom()); - s.push_scope(); - literal l3 = s.mk_or(l1, l2); - SASSERT(s.get_assignment(l3) == l_false); - s.mk_main_clause(l0, l1, l3); - SASSERT(s.m_ref_count[l3.var()] == 3); - s.pop_scope(1); - SASSERT(s.m_ref_count[l3.var()] == 2); - SASSERT(s.get_assignment(l3) == l_false); - s.assert_lit(l1); - s.propagate(); - SASSERT(s.inconsistent()); - } - -public: - static void run_tests() { - enable_trace("del_gate"); - enable_trace("sat_solver"); - enable_trace("gate"); - enable_trace("del_learned_clauses"); - tst1(); - tst1a(); - tst2(); - tst3(); - tst4(); - tst5(); - tst6(); - tst6a(); - tst7(); - tst8(); - tst9(); - tst10(); - tst11(); - } -}; - -void tst_gate() { - sat_gate_tester::run_tests(); -} diff --git a/src/test/dead/interval_arithmetic.cpp b/src/test/dead/interval_arithmetic.cpp deleted file mode 100644 index bffe3ea27..000000000 --- a/src/test/dead/interval_arithmetic.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - interval_arithmetic.cpp - -Abstract: - - Test interval arithmetic - -Author: - - Nikolaj Bjorner (nbjorner) 2006-12-05. - -Revision History: - ---*/ -#include -#include"interval_arithmetic.h" -#include"trace.h" - - -template -void tst_ext_number() { - typedef ext_number num; - num zero; - num one(1); - num eps(num::epsilon()); - num m_eps(num::epsilon().neg()); - num two(number(2)); - num half(number(1,2)); - num inf = num::infinity(); - num eps1 = num::epsilon(); - num three(number(3)); - num three_e = num::plus(three, num::epsilon()); - SASSERT(zero.get_sign() == num::ZERO); - SASSERT(one.get_sign() == num::POSITIVE); - SASSERT(m_eps.get_sign() == num::NEGATIVE); - SASSERT(inf.get_sign() == num::POSITIVE); - SASSERT(zero.is_zero()); - SASSERT(!one.is_zero()); - SASSERT(!inf.is_zero()); - SASSERT(inf.is_infinite()); - SASSERT(!one.is_infinite()); - SASSERT(one.is_pos()); - SASSERT(m_eps.is_neg()); - SASSERT(one != zero); - SASSERT(inf != one); - SASSERT(inf != zero); - SASSERT(zero == zero); - SASSERT(zero < one); - SASSERT(eps < two); - SASSERT(zero < eps); - SASSERT(zero < inf); - SASSERT(zero == min(zero, eps)); - SASSERT(zero == min(zero, inf)); - SASSERT(eps == max(zero, eps)); - SASSERT(inf == max(zero, inf)); - SASSERT(min(zero,eps) == min(eps,zero)); - SASSERT(num::plus(zero, eps) == eps); - SASSERT(num::plus(zero, one) == one); - SASSERT(num::plus(zero, inf) == inf); - SASSERT(num::plus(inf, inf) == inf); - SASSERT(inf.neg() < inf); - SASSERT(inf.neg() < zero); - SASSERT(num::minus(zero, one) == one.neg()); - SASSERT(num::minus(zero, eps) == eps.neg()); - SASSERT(num::minus(zero, inf) == inf.neg()); - SASSERT(num::minus(zero, inf.neg()) == inf); - SASSERT(num::minus(inf, inf.neg()) == inf); - - // sup_mult, inf_mult - SASSERT(sup_mult(zero, one) == zero); - SASSERT(sup_mult(one, one) == one); - SASSERT(sup_mult(one, one.neg()) == one.neg()); - SASSERT(inf_mult(zero, one) == zero); - SASSERT(inf_mult(one, one) == one); - SASSERT(inf_mult(one, one.neg()) == one.neg()); - - // sup_div, inf_div - SASSERT(one < sup_div(three_e, three)); - SASSERT(inf_div(three, three_e) < one); - SASSERT(inf_div(three_e, three) < two); - SASSERT(inf_div(three.neg(), three_e.neg()) < one); - SASSERT(one < sup_div(three_e.neg(), three.neg())); - SASSERT(inf_div(three_e.neg(), three.neg()) < two); - - // sup_power, inf_power - SASSERT(sup_power(one,3) == one); - SASSERT(sup_power(one,3) > zero); - SASSERT(sup_power(num::plus(one, num::epsilon()),3) > one); - - SASSERT(sup_power(one,2) == one); - SASSERT(sup_power(one,2) > zero); - SASSERT(sup_power(num::plus(one, num::epsilon()),2) > one); - - // sup_root, inf_root - SASSERT(sup_root(one,2) >= zero); - SASSERT(inf_root(one,2) <= one); - SASSERT(sup_root(zero,2) >= zero); - SASSERT(inf_root(zero,2) <= zero); - -} - -template -void tst_interval() -{ - typedef interval interval; - typedef ext_number ext_num; - ext_num m_inf(ext_num::infinity().neg()); - ext_num m_three(ext_num(3).neg()); - ext_num m_three_m_e(ext_num::plus(ext_num(3), ext_num::epsilon()).neg()); - ext_num m_three_p_e(ext_num::plus(ext_num(3), ext_num::epsilon().neg()).neg()); - ext_num m_eps(ext_num::epsilon().neg()); - ext_num zero(0); - ext_num eps(ext_num::epsilon()); - ext_num three(ext_num(3)); - ext_num three_m_e(ext_num::minus(ext_num(3), ext_num::epsilon())); - ext_num three_p_e(ext_num::plus(ext_num(3), ext_num::epsilon())); - ext_num inf(ext_num::infinity()); - ext_num nums[] = { m_inf, m_three_m_e, m_three, m_three_p_e, m_eps, zero, eps, three_m_e, three, three_p_e, inf }; - - unsigned n_nums = 11; - // - // add_lower - // add_upper - // - for (unsigned i = 0; i < n_nums; ++i) { - for (unsigned j = i+1; j < n_nums; ++j) { - - for (unsigned k = 0; k < n_nums; ++k) { - interval i1(nums[i], nums[j]); - bool ok = i1.add_lower(nums[k]); - TRACE("interval_arithmetic", tout << "lower: " << ok << " " - << nums[k] << " " << i1 << std::endl;); - } - - for (unsigned k = 0; k < n_nums; ++k) { - interval i1(nums[i], nums[j]); - bool ok = i1.add_upper(nums[k]); - TRACE("interval_arithmetic", tout << "upper: " << ok << " " - << nums[k] << " " << i1 << std::endl;); - } - } - } - - // - // + - // * - // - - // quotient - // - for (unsigned i = 0; i < n_nums; ++i) { - for (unsigned j = i+1; j < n_nums; ++j) { - interval i1(nums[i],nums[j]); - - interval x = i1.power(0); - interval y = i1.power(1); - interval z = i1.power(2); - interval x1 = i1.power(3); - - for (unsigned k = 0; k < n_nums; ++k) { - for (unsigned l = k+1; l < n_nums; ++l) { - interval i2(nums[k],nums[l]); - interval i3 = i1 + i2; - interval i4 = i1 - i2; - interval i5 = i1 * i2; - TRACE("interval_arithmetic", tout << i1 << " + " << i2 << " = " << i3 << std::endl;); - TRACE("interval_arithmetic", tout << i1 << " - " << i2 << " = " << i4 << std::endl;); - TRACE("interval_arithmetic", tout << i1 << " * " << i2 << " = " << i5 << std::endl;); - SASSERT(i5 == i2 * i1); - vector intervals; - interval::quotient(i1, i2, intervals); - TRACE("interval_arithmetic", - tout << i1 << " / " << i2 << " = " ; - for (unsigned idx = 0; idx < intervals.size(); ++idx) { - tout << intervals[idx] << " "; - } - tout << std::endl; - ); - - unsigned changed_bounds; - x = i1; - y = i2; - z = i3; - TRACE("interval_arithmetic", tout << "check: " << i1 << "=" << i2 << "*" << i3 << std::endl;); - if (interval::check_mult(x, y, z, changed_bounds)) { - TRACE("interval_arithmetic", tout << x << "=" << y << "*" << z << std::endl;); - SASSERT (!!(changed_bounds & 0x1) == (x.low() != i1.low())); - SASSERT (!!(changed_bounds & 0x2) == (x.high() != i1.high())); - SASSERT (!!(changed_bounds & 0x4) == (y.low() != i2.low())); - SASSERT (!!(changed_bounds & 0x8) == (y.high() != i2.high())); - SASSERT (!!(changed_bounds & 0x10) == (z.low() != i3.low())); - SASSERT (!!(changed_bounds & 0x20) == (z.high() != i3.high())); - } - else { - TRACE("interval_arithmetic", tout << "unsat" << std::endl;); - } - - x = i1; - y = i2; - if (interval::check_power(x, y, 3, changed_bounds)) { - TRACE("interval_arithmetic", - tout << "check: " << i1 << "=" << i2 << "^3" << " -> " - << x << " = " << y << "^3" << std::endl;); - } - else { - TRACE("interval_arithmetic", tout << "unsat: " << i1 << "=" << i2 << "^4" << std::endl;); - } - - - x = i1; - y = i2; - if (interval::check_power(x, y, 4, changed_bounds)) { - TRACE("interval_arithmetic", - tout << "check: " << i1 << "=" << i2 << "^4" << " -> " - << x << " = " << y << "^4" << std::endl;); - } - else { - TRACE("interval_arithmetic", tout << "unsat: " << i1 << "=" << i2 << "^4" << std::endl;); - } - } - } - } - } - - - // check_mult(i1, i2, i3, change_bounds); - - // check_power(i1, i2, power, changed_bounds); -} - -struct eps1 { rational operator()() { return rational(1); } }; -struct eps0 { inf_rational operator()() { return inf_rational(rational(0),true); } }; - -void tst_interval_arithmetic() { - TRACE("interval_arithmetic", tout << "starting interval_arithmetic test...\n";); - tst_ext_number(); - tst_ext_number(); - tst_interval(); - tst_interval(); -} diff --git a/src/test/dead/par_dll.cpp b/src/test/dead/par_dll.cpp deleted file mode 100644 index eb3a572e3..000000000 --- a/src/test/dead/par_dll.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "z3.h" -#include - -class thread_check { - - CRITICAL_SECTION m_cs; - - static DWORD __stdcall do_check(LPVOID _this) { - thread_check* th = static_cast(_this); - Z3_config cfg = Z3_mk_config(); - Z3_set_param_value(cfg,"MODEL","true"); - Z3_context ctx = Z3_mk_context(cfg); - Z3_parse_smtlib_string(ctx, "(benchmark b :logic QF_UF :extrafuns ((f U U) (x U)) :formula (= (f x) x))", 0, 0, 0, 0, 0, 0); - Z3_ast f = Z3_get_smtlib_formula(ctx, 0); - Z3_assert_cnstr(ctx, f); - Z3_model m = 0; - Z3_lbool r = Z3_check_and_get_model(ctx,&m); - EnterCriticalSection(&th->m_cs); - printf("%d\n", r); - LeaveCriticalSection(&th->m_cs); - if (m) { - Z3_del_model(ctx, m); - } - return 0; - } - - -public: - thread_check() { - InitializeCriticalSection(&m_cs); - } - - ~thread_check() { - DeleteCriticalSection(&m_cs); - } - - void do_checks(unsigned num_threads) { - HANDLE* handles = new HANDLE[num_threads]; - for (unsigned i = 0; i < num_threads; ++i) { - HANDLE hThread = CreateThread(NULL, 0, &thread_check::do_check, this, 0, 0); - handles[i] = hThread; - } - - WaitForMultipleObjects(num_threads, handles, TRUE, INFINITE); - - for (unsigned i = 0; i < num_threads; ++i) { - CloseHandle(handles[i]); - } - delete[] handles; - } -}; - -extern "C" -__declspec(dllexport) int ChessTestRun() { - thread_check tc; - tc.do_checks(2); - return 0; -} diff --git a/src/test/dead/parallel.cpp b/src/test/dead/parallel.cpp deleted file mode 100644 index c7471d472..000000000 --- a/src/test/dead/parallel.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifdef _WINDOWS - -#include "z3.h" -#include "z3_private.h" -#include -#include "util.h" -#include "trace.h" -#include -#include "trace.h" -#include "vector.h" -#include "buffer.h" -#undef ARRAYSIZE -#include - -class thread_check { - - CRITICAL_SECTION m_cs; - - static DWORD __stdcall do_check(LPVOID _this) { - thread_check* th = static_cast(_this); - Z3_config cfg = Z3_mk_config(); - Z3_set_param_value(cfg,"MODEL","true"); - Z3_context ctx = Z3_mk_context(cfg); - Z3_parse_smtlib_string(ctx, "(benchmark b :logic QF_UF :extrafuns ((f U U) (x U)) :formula (= (f x) x))", 0, 0, 0, 0, 0, 0); - Z3_ast f = Z3_get_smtlib_formula(ctx, 0); - Z3_assert_cnstr(ctx, f); - Z3_model m = 0; - Z3_lbool r = Z3_check_and_get_model(ctx,&m); - EnterCriticalSection(&th->m_cs); - printf("%d\n", r); - LeaveCriticalSection(&th->m_cs); - if (m) { - Z3_del_model(ctx, m); - } - return 0; - } - - -public: - thread_check() { - InitializeCriticalSection(&m_cs); - } - - ~thread_check() { - DeleteCriticalSection(&m_cs); - } - - void do_checks(unsigned num_threads) { - ptr_buffer handles; - for (unsigned i = 0; i < num_threads; ++i) { - HANDLE hThread = CreateThread(NULL, 0, &thread_check::do_check, this, 0, 0); - handles.push_back(hThread); - } - - WaitForMultipleObjects(handles.size(), handles.c_ptr(), TRUE, INFINITE); - - for (unsigned i = 0; i < handles.size(); ++i) { - CloseHandle(handles[i]); - } - } -}; - -void tst_parallel() { - thread_check tc; - tc.do_checks(2); -} -#else -void tst_parallel() { -} -#endif diff --git a/src/test/dead/quant_elim.cpp b/src/test/dead/quant_elim.cpp deleted file mode 100644 index e25e140a5..000000000 --- a/src/test/dead/quant_elim.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#include "ast.h" -#include "front_end_params.h" -#include "simplifier.h" -#include "qe.h" -#include "basic_simplifier_plugin.h" -#include "arith_simplifier_plugin.h" -#include "array_simplifier_plugin.h" -#include "bv_simplifier_plugin.h" -#include "ast_pp.h" -#include "smtlib.h" -#include "smtparser.h" -#include "lbool.h" -#include -#include "reg_decl_plugins.h" - - -static void test_qe(ast_manager& m, lbool expected_outcome, expr* fml, char const* option) { - - // enable_trace("bit2int"); - //enable_trace("gomory_cut"); - enable_trace("final_check_arith"); - enable_trace("arith_final_check"); - //enable_trace("arith_branching"); - enable_trace("theory_arith_int"); - enable_trace("presburger"); - enable_trace("quant_elim"); - // enable_trace("arith_simplifier_plugin"); - // enable_trace("non_linear"); - // enable_trace("gomory_cut_detail"); - // enable_trace("arith"); - // enable_trace("bv"); - // enable_trace("after_search"); - // enable_trace("bv_bit_prop"); - - simplifier simp(m); - front_end_params params; - params.m_quant_elim = true; - - std::cout << mk_pp(fml, m) << "\n"; - qe::expr_quant_elim qe(m, params); - expr_ref result(m); - qe(m.mk_true(), fml, result); - std::cout << " -> " << mk_pp(result, m) << " " << expected_outcome << "\n"; - if (expected_outcome == l_true && !m.is_true(result)) { - std::cout << "ERROR: expected true, instead got " << ast_pp(result, m).c_str() << "\n"; - //exit(-1); - } - if (expected_outcome == l_false && !m.is_false(result)) { - std::cout << "ERROR: expected false, instead got " << ast_pp(result, m).c_str() << "\n"; - //exit(-1); - } -} - -static void test_formula(lbool expected_outcome, char const* fml) { - ast_manager m; - reg_decl_plugins(m); - scoped_ptr parser = smtlib::parser::create(m); - parser->initialize_smtlib(); - - std::ostringstream buffer; - buffer << "(benchmark presburger :status unknown :logic AUFLIA :extrapreds ((p1) (p2) (p3)) " - << ":extrafuns ((a Int) (b Int))\n" - << ":extrapreds ((p) (q) (r))\n" - << ":datatypes ((list (nil) (cons (hd Int) (tl list))))\n" - << ":datatypes ((cell (cnil) (ccons (car cell) (cdr cell))))\n" - << ":extrasorts (U)\n" - << ":extrafuns ((f U U))\n" - << ":formula " << fml << ")"; - parser->parse_string(buffer.str().c_str()); - smtlib::benchmark* b = parser->get_benchmark(); - smtlib::theory::expr_iterator it = b->begin_formulas(); - smtlib::theory::expr_iterator end = b->end_formulas(); - for (; it != end; ++it) { - test_qe(m, expected_outcome, *it, 0); - } -} - -void tst_quant_elim() { - - test_formula(l_undef, "(exists ((p1 Bool) (q1 Bool) (r1 Bool))\ - (and (or (not p1) (not q1) r1)\ - (or (and (not p) (not q) (not p1) q1)\ - (and (not p) q p1 (not q1))\ - (and p (not q) p1 q1)\ - (and p q p1 q1))\ - (or (and (not r) (not r1))\ - (and (= p p1) (= q q1) r r1)\ - (and (not (and (= p p1) (= q q1))) (not (= r r1))))))"); - - - test_formula(l_false,"(forall (x Int) (y Int) (or (= x 0) (< (* 5 y) (* 6 x)) (> (* 5 y) (* 6 x))))"); - - test_formula(l_false, "(forall (a Int) (b Int) (exists (x Int) (and (< a (* 20 x)) (< (* 20 x) b))))"); - - test_formula(l_undef, "(exists (u U) (= (f u) u))"); - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 7 v))))))))"); - - - test_formula(l_true, "(forall (x Int) (y Int) (implies (= (* 6 x) (* 5 y)) (exists (d Int) (= y (* 3 d)))))"); - - test_formula(l_undef, "(exists (x Int) (= (- a (mod x 4)) 0))"); - // return; - - - // test_formula(l_true, "(exists (x Int) (y Int) (= 1 (+ (* 5 x) (* 3 y))))"); - - - test_formula(l_undef, "(exists (a Bool) (b Bool) (or (and p1 a) (and p2 (not b))))"); - - - - - test_formula(l_false, - "(forall (x Int) (q1 Int) (q2 Int) (r1 Int) (r2 Int) " - " (implies " - " (and (< x 4699) " - " (= (* 2622 x) (+ (* 65536 q1) r1)) " - " (<= 0 q1) " - " (<= 0 r1) " - " (< r1 65536) " - " (= x (+ (* 100 q2) r2)) " - " (<= 0 q2) " - " (<= 0 r2) " - " (< r2 100)) " - " (= q1 q2)))"); - - - - test_formula(l_undef, - "(forall (l list) (or (= l nil) (exists (x Int) (ll list) (= l (cons x ll)))))"); - - - - - - - test_formula(l_false, "(exists (x Real) (forall (y Real) (>= x y)))"); - test_formula(l_false, "(exists (x Real) (forall (y Real) (> x y)))"); - test_formula(l_false, "(exists (x Real) (forall (y Real) (< x y)))"); - test_formula(l_false, "(exists (x Real) (forall (y Real) (<= x y)))"); - - test_formula(l_true, "(exists (x Real) (exists (y Real) (< x y)))"); - test_formula(l_true, "(exists (x Real) (exists (y Real) (<= x y)))"); - test_formula(l_true, "(exists (x Real) (exists (y Real) (>= x y)))"); - test_formula(l_true, "(exists (x Real) (exists (y Real) (> x y)))"); - - test_formula(l_true, "(forall (x Real) (exists (y Real) (< x y)))"); - test_formula(l_true, "(forall (x Real) (exists (y Real) (<= x y)))"); - test_formula(l_true, "(forall (x Real) (exists (y Real) (>= x y)))"); - test_formula(l_true, "(forall (x Real) (exists (y Real) (> x y)))"); - - test_formula(l_false, "(forall (x Real) (forall (y Real) (< x y)))"); - test_formula(l_false, "(forall (x Real) (forall (y Real) (<= x y)))"); - test_formula(l_false, "(forall (x Real) (forall (y Real) (>= x y)))"); - test_formula(l_false, "(forall (x Real) (forall (y Real) (> x y)))"); - - - - - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 5 v))))))))"); - - - test_formula(l_false, "(forall (d Int) (implies (>= d 0) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= d (+ (* 3 x) (* 5 y)))))))"); - - test_formula(l_true, "(forall (y Int) (implies (exists (d Int) (= y (* 6 d))) (exists (d Int) (= y (* 2 d)))))"); - - test_formula(l_true, "(forall (y Int) (implies (exists (d Int) (= y (* 65 d))) (exists (d Int) (= y (* 5 d)))))"); - - - test_formula(l_true, - "(exists (z Int) (forall (w Int) (exists (x Int) (y Int) " - " (or (and (< (+ (* 3 x) w) 2) (< 1 (- (+ (* 2 x) z) w))) " - " (and (< z (* 2 y)) (> z y))))))"); - - - test_formula(l_true, "(exists (x Int) (y Int) (and (> x 0) (>= y 0) (= 1 (- (* 3 x) (* 5 y)))))"); - - - test_formula(l_true, - "(exists (a Int) (b Int) " - " (and (not (= a 1)) (= a b) (or (= a (* 2 b)) (= (* 2 b) (+ 1 (* 3 a))))))"); - - - - test_formula(l_true, - "(forall (x Int) (iff (and (not (= 0 (mod x 2))) (= 0 (mod (- x 1) 3))) " - " (or (= 0 (mod (- x 1) 12)) (= 0 (mod (- x 7) 12)))))"); - - - - - - - test_formula(l_false, "(exists (x Int) (and (< (* 3 x) 2) (< 1 (* 2 x))))"); - - - test_formula(l_true, "(forall (x Int) (y Int) (or (= 0 (mod x 5)) (not (= (* 6 x) (* 5 y)))))"); - - - test_formula(l_false, "(forall (x Int) (exists (y Int) (= x (* 2 y))))"); - test_formula(l_false, - "(forall (x Int) " - " (implies (not (= 0 (mod x 2))) " - " (or (= 0 (mod (- x 1) 4)) " - " (= 0 (mod (- x 1) 8)) " - " (= 0 (mod (- x 3) 8)) " - " (= 0 (mod (- x 1) 6)) " - " (= 0 (mod (- x 1) 14)) " - " (= 0 (mod (- x 9) 14)) " - " (= 0 (mod (- x 11) 14)) " - " (= 0 (mod (- x 5) 24)) " - " (= 0 (mod (- x 11) 24))))) "); - - test_formula(l_true, - "(forall (x Int) (iff (and (not (= 0 (mod x 2))) (= 0 (mod (- x 1) 3))) " - " (or (= 0 (mod (- x 1) 12)) (= 0 (mod (- x 7) 12)))))"); - - - - - test_formula(l_false, - "(forall (d Int) (c Int) (b Int) " - " (and (= c 0) (= d (* b c)) (= d 0)))"); - - - - - //return; - - test_formula(l_undef, "(exists (k!12 Int) (k!11 Int) (and (= (ite (= k!11 0) 0 k!11) k!11) (not (= (ite (= k!12 (+ 1)) 1 0) 0))))"); - //return; - - - - - - test_formula(l_false, - "(forall (a Int) (b Int) (x Int) (y Int) (z Int) " - " (implies (and (= (+ a 2) b) (= x (+ 1 (- b a))) (= y (- b 2)) (= z 3)) false))"); - - - - test_formula(l_false, - "(exists (a Int) (b Int) " - " (and (> a 1) (> b 1) (= a b) (or (= a (* 2 b)) (= (* 2 b) (+ 1 (* 3 a))))))"); - - - - test_formula(l_true, "(forall (d Int) (implies true (exists (x Int) (y Int) (and true true (= d (+ (* 3 x) (* 5 y)))))))"); - - // This one takes forever without bit-vectors - test_formula(l_true, "(forall (d Int) (implies (>= d 8) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= d (+ (* 3 x) (* 5 y)))))))"); - - test_formula(l_true, "(forall (d Int) (implies (>= d 0) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= d (- (* 3 x) (* 5 y)))))))"); - - - test_formula(l_false, "(exists (x Int) (y Int) (z Int) (= 1 (- (* 4 x) (* 6 y))))"); - - //return; - - - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 8 v))))))))"); - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 8 v))))))))"); - -#if 0 - - // too slow. - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 7 u) (* 8 v))))))))"); - - -#endif - - test_formula(l_true, "(forall (x Int) (exists (y Int) (and (<= (* 2 y) x) (< x (* 2 (+ y 1))))))"); - - - test_formula(l_false, "(exists (x Int) (y Int) (and (> y 0) (> y (* 2 x)) (< y (+ x 2)) (= 0 (mod y 2))))"); - - test_formula(l_false, "(exists (x Int) (and (< (* 3 x) 3) (< 1 (* 2 x))))"); - - - test_formula(l_true, "(exists (x Int) (and (< (* 3 x) 4) (< 1 (* 2 x))))"); - - test_formula(l_false, "(exists (x Int) (and (< (+ (* 3 x) 1) 10) (> (- (* 7 x) 6) 7) (= 0 (mod x 3))))"); - - - test_formula(l_false, "(exists (x Int) (y Int) (and (< (- 1 (* 5 y)) x) (< (+ 1 y) (* 13 x)) (< (+ x 2) 0) (> y 0)))"); - - test_formula(l_false, "(exists (x Int) (y Int) (and (< (- 1 (* 5 y)) x) (< (+ 1 y) (* 13 x)) (< x -2)))"); - - test_formula(l_true, "(exists (w Int) (z Int) (y Int) (x Int) (and (< (- 1 (* 5 y)) (+ x (* 2 z))) (< (+ 1 y w (* -4 z)) (* 13 x)) (< x -2) (> z 0)))"); - - - - test_formula(l_true, - "(forall (w Int) " - " (exists (z Int) (y Int) (x Int) " - " (and (< (- 1 (* 5 y)) (+ x (* 2 z))) " - " (< (- (+ 1 y) (* 4 z)) (* 13 x)) " - " (< x -2) (> z 0) (< x 10)))) "); - - - test_formula(l_false, - "(forall (d Int) (c Int) (b Int) " - " (and (= c 0) (= d (* b c)) (= d 4)))"); - - test_formula(l_undef, - "(exists (d Int) (c Int) (b Int) " - " (and (= c 0) (= d (* b c)) (= d 0)))"); - - test_formula(l_undef, - "(exists (d Int) (c Int) (b Int) " - " (and (= c 0) (= d (* b c)) (= d 4)))"); - - - - // Tests from Harrison's HOL-light version of Cooper. - - test_formula(l_true, "(forall (x Int) (y Int) (not (= (+ 1 (* 2 x)) (* 2 y))))"); - - - test_formula(l_false, "(exists (x Int) (y Int) (= 1 (- (* 4 x) (* 6 y))))"); - - - - // "(forall (x Int) (implies (< b x) (<= a x)))" - // "(forall (x Int) (implies (< b x) (< a x)))" - - - test_formula(l_false, "(forall (d Int) (implies (>= d 0) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= d (+ (* 3 x) (* 5 y)))))))"); - - test_formula(l_true, "(forall (d Int) (implies true (exists (x Int) (y Int) (and true true (= d (+ (* 3 x) (* 5 y)))))))"); - - // This one takes forever without bit-vectors - test_formula(l_true, "(forall (d Int) (implies (>= d 8) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= d (+ (* 3 x) (* 5 y)))))))"); - - test_formula(l_true, "(forall (d Int) (implies (>= d 0) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= d (- (* 3 x) (* 5 y)))))))"); - - test_formula(l_true, "(exists (x Int) (y Int) (and (> x 0) (>= y 0) (= 1 (- (* 3 x) (* 5 y)))))"); - - test_formula(l_false, "(exists (x Int) (y Int) (z Int) (= 1 (- (* 4 x) (* 6 y))))"); - - // "(forall (x Int) (implies (< b (* 3 x)) (a < (* 3 x))))" - - test_formula(l_false, "(forall (x Int) (y Int) (implies (<= x y) (< (+ 1 (* 2 x)) (* 2 y))))"); - - - test_formula(l_true, "(forall (x Int) (y Int) (z Int) (implies (= (+ 1 (* 2 x)) (* 2 y)) (> (+ x y z) 129)))"); - - // Formula examples from Cooper's paper. - - - test_formula(l_true, "(forall (a Int) (exists (b Int) (or (< a (+ (* 4 b) (* 3 a))) (and (not (< a b)) (> a (+ b 1))))))"); - - test_formula(l_false, "(exists (y Int) (forall (x Int) (and (> (+ x (* 5 y)) 1) (> (- (* 13 x) y) 1) (< (+ x 2) 0))))"); - - // Harrison's formulas: - - test_formula(l_false, "(forall (x Int) (y Int) (implies (and (>= x 0) (>= y 0)) (or (< (- (* 12 x) (* 8 y)) 0) (> (- (* 12 x) (* 8 y)) 2))))"); - - - // test_formula(l_true, "(exists (x Int) (y Int) (= 1 (+ (* 5 x) (* 3 y))))"); - - - test_formula(l_false, "(exists (x Int) (y Int) (= 1 (+ (* 5 x) (* 10 y))))"); - - test_formula(l_true, "(exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= 1 (- (* 5 x) (* 6 y)))))"); - - test_formula(l_true, "(exists (x Int) (y Int) (z Int) (w Int) (= 1 (+ (* 2 w) (* 3 x) (* 4 y) (* 5 z))))"); - - test_formula(l_true, "(exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= 1 (- (* 5 x) (* 3 y)))))"); - - test_formula(l_true, "(exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= 1 (- (* 3 x) (* 5 y)))))"); - - test_formula(l_false,"(exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= 1 (- (* 6 x) (* 3 y)))))"); - - test_formula(l_true, "(forall (x Int) (y Int) (or (= 0 (mod x 5)) (= 0 (mod y 6)) (not (= (* 6 x) (* 5 y)))))"); - - - test_formula(l_false,"(forall (x Int) (y Int) (or (not (= (* 6 x) (* 5 y)))))"); - - - - // Positive variant of the Bezout theorem (see the exercise). *) - - test_formula(l_true, "(forall (z Int) (implies (> z 7) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= (+ (* 3 x) (* 5 y)) z)))))"); - - test_formula(l_false,"(forall (z Int) (implies (> z 2) (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= (+ (* 3 x) (* 5 y)) z)))))"); - - test_formula(l_true, - "(forall (z Int) (implies (<= z 7) " - " (iff (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= z (+ (* 3 x) (* 5 y))))) " - " (not (exists (x Int) (y Int) (and (>= x 0) (>= y 0) (= (- 7 z) (+ (* 3 x) (* 5 y))))))))) "); - - // Basic result about congruences. - - test_formula(l_true, - "(forall (x Int) " - " (iff (and (not (exists (m Int) (= x (* 2 m)))) (exists (m Int) (= x (+ (* 3 m) 1)))) " - " (or (exists (m Int) (= x (+ (* 12 m) 1))) (exists (m Int) (= x (+ (* 12 m) 7))))))"); - - - - - - // Inspired by the Collatz conjecture. - - test_formula(l_false, - "(forall (a Int) (b Int) (x Int) (y Int) (z Int) " - " (implies (and (= (+ a 2) b) (= x (+ 1 (- b a))) (= y (- b 2)) (= z 3)) false))"); - - test_formula(l_true, - "(exists (a Int) (b Int) " - " (and (not (= a 1)) (= a b) (or (= a (* 2 b)) (= (* 2 b) (+ 1 (* 3 a))))))"); - - - test_formula(l_false, - "(exists (a Int) (b Int) " - " (and (> a 1) (> b 1) (= a b) (or (= a (* 2 b)) (= (* 2 b) (+ 1 (* 3 a))))))"); - - test_formula(l_false, - "(exists (a Int) (b Int) " - " (and (> a 1) (> b 1) " - " (or (= a (* 2 b)) (= (* 2 b) (+ 1 (* 3 a)))) " - " (or (= b (* 2 a)) (= (* 2 a) (+ 1 (* 3 b))))))"); - -#if 0 - // Bob Constable's "stamp problem". - - test_formula(l_true, - "(forall (x Int) (implies (>= x 8) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 5 v)))))))"); - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 5 v))))))))"); - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 7 v))))))))"); - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 3 u) (* 8 v))))))))"); - - test_formula(l_true, - "(exists (l Int) (forall (x Int) (implies (>= x l) " - " (exists (u Int) (v Int) (and (>= u 0) (>= v 0) (= x (+ (* 7 u) (* 8 v))))))))"); -#endif - - // Example from reciprocal mult: (2622 * x)>>16 = x/100 within a range. - - - test_formula(l_true, - "(forall (x Int) (y Int) " - " (iff (exists (d Int) (= (+ x y) (* 2 d))) " - " (iff (exists (d Int) (= x (* 2 d))) (exists (d Int) (= y (* 2 d))))))"); - - test_formula(l_true, - "(forall (n Int) " - " (implies (and (< 0 n) (< n 2400)) " - " (or (and (<= n 2) (<= 2 (* 2 n))) " - " (and (<= n 3) (<= 3 (* 2 n))) " - " (and (<= n 5) (<= 5 (* 2 n))) " - " (and (<= n 7) (<= 7 (* 2 n))) " - " (and (<= n 13) (<= 13 (* 2 n))) " - " (and (<= n 23) (<= 23 (* 2 n))) " - " (and (<= n 43) (<= 43 (* 2 n))) " - " (and (<= n 83) (<= 83 (* 2 n))) " - " (and (<= n 163) (<= 163 (* 2 n))) " - " (and (<= n 317) (<= 317 (* 2 n))) " - " (and (<= n 631) (<= 631 (* 2 n))) " - " (and (<= n 1259) (<= 1259 (* 2 n))) " - " (and (<= n 2503) (<= 2503 (* 2 n)))))) "); - - - - - memory::finalize(); -#ifdef _WINDOWS - _CrtDumpMemoryLeaks(); -#endif - exit(0); -} - - diff --git a/src/test/dead/relevancy.cpp b/src/test/dead/relevancy.cpp deleted file mode 100644 index 7a6ca016a..000000000 --- a/src/test/dead/relevancy.cpp +++ /dev/null @@ -1,653 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - relevancy.cpp - -Abstract: - - Test relevancy propagation. - -Author: - - Leonardo de Moura (leonardo) 2006-11-03. - -Revision History: - ---*/ -#include"sat_def.h" - -class relevancy_extension : public no_extension { -public: - bool relevancy_enabled() { - return true; - } - - bool gates_enabled() { - return true; - } -}; - -class sat_relevancy_tester { - - static void tst1() { - sat_solver solver; - - literal l1 = solver.mk_var(); - - SASSERT(!solver.is_relevant(l1.var())); - - solver.assert_lit(l1); - - SASSERT(solver.is_relevant(l1.var())); - } - - static void tst2() { - sat_solver solver; - - literal l1 = solver.mk_var(); - - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1.var())); - - solver.assert_lit(l1); - - SASSERT(solver.is_relevant(l1.var())); - - solver.pop_scope(1); - - SASSERT(solver.is_relevant(l1.var())); - } - - static void tst3() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - - literal l4 = solver.mk_ite(l1, l2, l3); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - - solver.mark_as_relevant(l4.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - - solver.push_scope(); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - - solver.assign(~l1, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - } - - static void tst4() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - literal l4 = solver.mk_ite(l1, l2, l3); - solver.propagate(); - - solver.push_scope(); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - - solver.mark_as_relevant(l4.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - - solver.assign(~l1, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - - solver.mark_as_relevant(l4.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - } - - static void tst5() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - - solver.push_scope(); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - literal l4 = solver.mk_ite(l1, l2, l3); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - - solver.mark_as_relevant(l4.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - } - - static void tst6() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_iff(l1, l2); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.push_scope(); - - solver.mark_as_relevant(l3.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.push_scope(); - - solver.mark_as_relevant(l2.var()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.pop_scope(1); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - } - - static void tst7() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_or(l1, l2); - - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.mark_as_relevant(l3.var()); - solver.assign(l3, mk_axiom()); - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.pop_scope(1); - solver.propagate(); - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.mark_as_relevant(l3.var()); - solver.assign(l3, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.pop_scope(1); - solver.propagate(); - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.assign(~l3, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.mark_as_relevant(l3.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.pop_scope(1); - solver.propagate(); - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.mark_as_relevant(l3.var()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(~l3, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - } - - static void tst8() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_or(l1, l2); - - solver.push_scope(); - - solver.mark_as_relevant(l3.var()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - } - - static void tst9() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_or(l1, l2); - - solver.mark_as_relevant(l3.var()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - - solver.assign(l1, mk_axiom()); - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1) || solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l1) != solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - } - - static void tst10() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_or(l1, l2); - - solver.assign(l1, mk_axiom()); - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - - solver.mark_as_relevant(l3.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1) || solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l1) != solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - } - - static void tst11() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_iff(l1, l2); - literal l4 = solver.mk_var(); - literal l5 = solver.mk_or(l3, l4); - - solver.propagate(); - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - SASSERT(!solver.is_relevant(l5)); - - solver.assign(l3, mk_axiom()); - solver.mark_as_relevant(l5.var()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.is_relevant(l2)); - SASSERT(solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - SASSERT(solver.is_relevant(l5)); - - solver.assign(l4, mk_axiom()); - solver.propagate(); - SASSERT(!solver.is_relevant(l4)); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(!solver.is_relevant(l4)); - SASSERT(!solver.is_relevant(l5)); - - solver.assign(l4, mk_axiom()); - solver.mark_as_relevant(l5.var()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - SASSERT(solver.is_relevant(l5)); - - solver.assign(l1, mk_axiom()); - solver.assign(l2, mk_axiom()); - solver.assign(l3, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - SASSERT(!solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l4)); - SASSERT(solver.is_relevant(l5)); - } - - static void tst12(clause_kind k) { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - - solver.mk_aux_clause(l1, l2, k); - - solver.push_scope(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - - solver.pop_scope(1); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - } - - static void tst13(clause_kind k) { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - - solver.mk_aux_clause(l1, l2, k); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - - solver.assign(l1, mk_axiom()); - solver.assign(l2, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - SASSERT(!solver.is_relevant(l2)); - } - - static void tst14() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - - solver.push_scope(); - - solver.assign(l1, mk_axiom()); - - solver.mk_aux_clause(l1, l2, CLS_MAIN); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - } - - static void tst15() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - - solver.push_scope(); - - solver.assign(l1, mk_axiom()); - solver.propagate(); - - SASSERT(!solver.is_relevant(l1)); - - solver.push_scope(); - - solver.mk_aux_clause(l1, l2, CLS_MAIN); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - - solver.pop_scope(1); - solver.propagate(); - - SASSERT(solver.is_relevant(l1)); - } - - static void tst16() { - sat_solver solver; - - literal l1 = solver.mk_var(); - - solver.push_scope(); - solver.assert_lit(l1); - solver.propagate(); - SASSERT(solver.is_relevant(l1)); - SASSERT(solver.get_assignment(l1) == l_true); - solver.assert_lit(l1); - solver.pop_scope(1); - SASSERT(solver.get_assignment(l1) == l_true); - SASSERT(solver.is_relevant(l1)); - } - - static void tst17() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - solver.assert_nonrelevant_lit(l1); - solver.mk_aux_clause(l1, l2, CLS_MAIN); - solver.check(); - SASSERT(solver.get_assignment(l1) == l_true || solver.get_assignment(l2) == l_true); - SASSERT(solver.is_relevant(l1) || solver.is_relevant(l2)); - } - - static void tst18() { - sat_solver solver; - - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - solver.assert_nonrelevant_lit(l1); - literal l3 = solver.mk_or(l1, l2); - SASSERT(l3 != true_literal); - solver.assert_lit(l3); - lbool r = solver.check(); - SASSERT(r == l_true); - SASSERT(solver.is_relevant(l3)); - SASSERT(solver.is_relevant(l1)); - } - -public: - - static void run_tests() { - tst1(); - tst2(); - tst3(); - tst4(); - tst5(); - tst6(); - tst7(); - tst8(); - tst9(); - tst10(); - tst11(); - tst12(CLS_MAIN); - tst12(CLS_TRANSIENT); - tst13(CLS_AUXILIARY); - tst13(CLS_EXT_LEMMA); - tst13(CLS_EXTERNAL); - tst14(); - tst15(); - tst16(); - tst17(); - tst18(); - } - -}; - -void tst_relevancy() { - sat_relevancy_tester::run_tests(); -} diff --git a/src/test/dead/sat.cpp b/src/test/dead/sat.cpp deleted file mode 100644 index 71cf6af40..000000000 --- a/src/test/dead/sat.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - tst_sat.cpp - -Abstract: - - Test SAT solver - -Author: - - Leonardo de Moura (leonardo) 2006-10-05. - -Revision History: - ---*/ - -#include"sat_def.h" - -class sat_tester { - - static void tst1() { - sat_solver solver; - solver.push_user_scope(); - solver.push_scope(); - literal l1 = solver.mk_var(); - SASSERT(solver.m_ref_count[l1.var()] == 1); - solver.assert_lit(l1); - SASSERT(solver.m_ref_count[l1.var()] == 2); - SASSERT(solver.m_weak_ref_count[l1.var()] == 1); - SASSERT(solver.get_assignment(l1) == l_true); - SASSERT(solver.m_level[l1.var()] == 1); - literal l2 = solver.mk_var(); - SASSERT(solver.m_ref_count[l2.var()] == 1); - SASSERT(solver.get_assignment(l2) == l_undef); - SASSERT(solver.m_level.size() == 3); - SASSERT(solver.m_free_var_indices.size() == 0); - solver.pop_scope(1); - SASSERT(solver.m_free_var_indices.size() == 2); - SASSERT(solver.m_ref_count[l1.var()] == 0); - } - - template - static void tst2() { - sat_solver solver; - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - literal l4 = solver.mk_var(); - solver.mk_aux_clause(~l1, ~l2, l3, CLS_MAIN); - solver.mk_aux_clause(~l3, ~l4, CLS_MAIN); - solver.push_scope(); - solver.assign(l1, mk_axiom()); - solver.assign(l2, mk_axiom()); - SASSERT(solver.get_assignment(l3) == l_undef); - SASSERT(solver.get_assignment(l4) == l_undef); - solver.propagate(); - SASSERT(solver.get_assignment(l3) == l_true); - SASSERT(solver.get_assignment(l4) == l_false); - solver.pop_scope(1); - SASSERT(solver.get_assignment(l1) == l_undef); - SASSERT(solver.get_assignment(l2) == l_undef); - SASSERT(solver.get_assignment(l3) == l_undef); - SASSERT(solver.get_assignment(l4) == l_undef); - } - - static void tst3() { - sat_solver solver; - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - solver.push_scope(); - SASSERT(solver.m_ref_count[l1.var()] == 1); - solver.mk_aux_clause(~l1, l2, CLS_TRANSIENT); - SASSERT(solver.m_ref_count[l1.var()] == 2); - solver.assign(l1, mk_axiom()); - solver.propagate(); - SASSERT(solver.get_assignment(l2) == l_true); - SASSERT(solver.m_transient_clauses.size() == 1); - TRACE("sat_ext", tout << "ref_count: " << solver.m_ref_count[l1.var()] << ", scope_lvl: " << solver.m_scope_lvl << "\n";); - SASSERT(solver.m_ref_count[l1.var()] == 3); - SASSERT(solver.m_ref_count[l2.var()] == 3); - solver.pop_scope(1); - solver.assign(l1, mk_axiom()); - solver.propagate(); - SASSERT(solver.get_assignment(l2) == l_undef); - SASSERT(solver.m_transient_clauses.size() == 0); - SASSERT(solver.m_ref_count[l1.var()] == 2); - SASSERT(solver.m_ref_count[l2.var()] == 1); - } - - static void tst4() { - sat_solver solver; - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - literal l4 = solver.mk_var(); - solver.push_user_scope(); - solver.mk_aux_clause(~l1, l2, l4, CLS_MAIN); - solver.push_user_scope(); - solver.mk_aux_clause(~l1, ~l2, l3, CLS_MAIN); - solver.push_scope(); - solver.mk_aux_clause(~l3, ~l4, CLS_TRANSIENT); - solver.mk_aux_clause(~l1, ~l4, CLS_MAIN); - SASSERT(solver.m_ref_count[l1.var()] == 4); - SASSERT(solver.m_ref_count[l2.var()] == 3); - SASSERT(solver.m_ref_count[l3.var()] == 3); - SASSERT(solver.m_ref_count[l4.var()] == 4); - SASSERT(solver.m_main_clauses.size() == 3); - SASSERT(solver.m_transient_clauses.size() == 1); - solver.pop_scope(2); - SASSERT(solver.m_ref_count[l1.var()] == 2); - SASSERT(solver.m_ref_count[l2.var()] == 2); - SASSERT(solver.m_ref_count[l3.var()] == 1); - SASSERT(solver.m_ref_count[l4.var()] == 2); - SASSERT(solver.m_main_clauses.size() == 1); - SASSERT(solver.m_transient_clauses.size() == 0); - solver.assign(l1, mk_axiom()); - SASSERT(solver.get_assignment(l4) == l_undef); - solver.pop_scope(1); - SASSERT(solver.m_main_clauses.size() == 0); - SASSERT(solver.m_ref_count[l1.var()] == 1); - SASSERT(solver.m_ref_count[l2.var()] == 1); - SASSERT(solver.m_ref_count[l3.var()] == 1); - SASSERT(solver.m_ref_count[l4.var()] == 1); - } - - template - static void tst5() { - sat_solver solver; - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - solver.push_scope(); - solver.assign(l1, mk_axiom()); - solver.push_scope(); - solver.mk_aux_clause(~l1, l2, CLS_MAIN); - SASSERT(solver.get_assignment(l2) == l_true); - solver.pop_scope(1); - SASSERT(solver.get_assignment(l2) == l_true); - solver.pop_scope(1); - SASSERT(solver.get_assignment(l2) == l_undef); - SASSERT(solver.m_main_clauses.size() == 1); - } - - static void tst6() { - sat_solver solver; - - literal l = solver.mk_var(); - solver.assert_lit(l); - SASSERT(!solver.inconsistent()); - solver.push_scope(); - solver.assign(~l, mk_axiom()); - SASSERT(solver.inconsistent()); - solver.pop_scope(1); - SASSERT(!solver.inconsistent()); - } - - class no_ref_count : public no_extension { - public: - static bool ref_counters_enabled() { - return false; - } - }; - - static void tst7() { - sat_solver solver; - literal l1 = solver.mk_var(); - solver.push_user_scope(); - literal l2 = solver.mk_var(); - SASSERT(solver.get_var_vector_size() == 3); - solver.pop_scope(1); - SASSERT(solver.get_var_vector_size() == 2); - } - - static void tst8() { - literal l[2]; - l[0] = true_literal; - l[1] = true_literal; - clause * cls = clause::mk_clause(2, l, CLS_EXTERNAL); - SASSERT(cls->kind() == CLS_EXTERNAL); - dealloc(cls); - } - - static void tst9() { - sat_solver solver; - - solver.push_scope(); - literal l1 = solver.mk_var(); - literal l2 = solver.mk_var(); - literal l3 = solver.mk_var(); - solver.mk_aux_clause(l1, l2, l3, CLS_MAIN); - solver.pop_scope(1); - SASSERT(solver.m_ref_count[l1.var()] == 1); - SASSERT(solver.get_assignment(l1) == l_undef); - solver.assert_lit(~l2); - solver.assert_lit(~l3); - solver.propagate(); - SASSERT(solver.get_assignment(l1) == l_true); - SASSERT(solver.m_main_clauses.size() == 1); - SASSERT(solver.m_ref_count[l1.var()] == 2); - solver.simplify_clauses(); - SASSERT(solver.m_main_clauses.size() == 0); - SASSERT(solver.m_ref_count[l1.var()] == 1); - SASSERT(solver.m_weak_ref_count[l1.var()] == 1); - SASSERT(solver.get_assignment(l1) == l_true); - } - - static void tst10() { - sat_solver s; - - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - literal l3 = s.mk_var(); - - s.push_scope(); - s.assign(l1, mk_axiom()); - s.push_scope(); - literal l4 = s.mk_var(); - s.assign(l4, mk_axiom()); - s.mk_aux_clause(~l4, l3, CLS_TRANSIENT); - s.mk_aux_clause(~l4, l2, CLS_TRANSIENT); - s.mk_aux_clause(~l3, ~l1, ~l2, CLS_TRANSIENT); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - s.resolve_conflict(); - SASSERT(r); - SASSERT(s.m_scope_lvl == 1); - SASSERT(s.m_ref_count[l4.var()] > 0); - s.pop_scope(1); - SASSERT(s.get_assignment(l1) == l_undef); - SASSERT(s.get_assignment(l4) == l_undef); - s.push_scope(); - s.assign(l4, mk_axiom()); -#ifdef Z3DEBUG - s.del_learned_clauses(); -#endif - s.pop_scope(1); - } - - static void tst11() { - // out-of-order conflict bug. - sat_solver s; - - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - s.push_scope(); - s.assign(l1, mk_axiom()); - s.assign(l2, mk_axiom()); - s.push_scope(); - s.mk_aux_clause(~l1, ~l2, CLS_TRANSIENT); - s.propagate(); - s.resolve_conflict(); - } - - static void tst12() { - // out-of-order conflict bug. - sat_solver s; - - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - literal l3 = s.mk_var(); - s.push_scope(); - s.assign(l1, mk_axiom()); - s.assign(l2, mk_axiom()); - s.push_scope(); - s.assign(l3, mk_axiom()); - s.mk_aux_clause(~l1, ~l2, CLS_TRANSIENT); - s.propagate(); - s.resolve_conflict(); - } - - static void tst13() { - sat_solver s; - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - literal l3 = s.mk_var(); - s.push_scope(); - s.assign(l1, mk_axiom()); - s.push_scope(); - s.assign(l2, mk_axiom()); - s.push_scope(); - s.mk_aux_clause(~l1, l3, CLS_MAIN); - s.propagate(); - SASSERT(!s.inconsistent()); - SASSERT(s.get_assignment(l3) == l_true); - s.mk_aux_clause(~l1, ~l2, CLS_TRANSIENT); - s.propagate(); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - s.resolve_conflict(); - SASSERT(r); - SASSERT(s.get_assignment(l3) == l_true); - TRACE("sat", tout << l3 << " : " << s.get_assignment(l3) << " : " << s.m_level[l3.var()] << " : " << s.m_scope_lvl << "\n";); - } - - static void tst14() { - sat_solver s; - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - s.push_scope(); - s.assign(~l1, mk_axiom()); - s.push_scope(); - s.assign(~l2, mk_axiom()); - s.assert_lit(l1); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - s.resolve_conflict(); - SASSERT(r); - SASSERT(s.get_assignment(l1) == l_true); - } - - static void tst15() { - sat_solver s; - literal l1 = s.mk_var(); - literal l2 = s.mk_var(); - s.push_scope(); - s.assign(~l1, mk_axiom()); - s.push_scope(); - s.assign(~l2, mk_axiom()); - s.assert_lit(l1); - SASSERT(s.inconsistent()); -#ifdef Z3DEBUG - bool r = -#endif - s.resolve_conflict(); - SASSERT(r); - SASSERT(s.get_assignment(l1) == l_true); - } - - static void tst16() { - sat_solver s; - s.push_scope(); - literal l1 = s.mk_var(); - bool_var v1 = l1.var(); - s.inc_weak_ref(v1); - s.pop_scope(1); - SASSERT(s.get_ref_count(v1) == 0); - literal l2 = s.mk_var(); - SASSERT(l2.var() != v1); - s.dec_weak_ref(v1); - literal l3 = s.mk_var(); - SASSERT(l3.var() == v1); - } - -public: - static void run_tests() { - enable_trace("sat_ext"); - enable_trace("backtrack"); - enable_trace("mk_clause"); - enable_debug("mk_clause"); - enable_trace("propagate"); - enable_trace("simplify"); - enable_trace("del_learned_clauses"); - enable_debug("sat_invariant"); - TRACE("sat_ext", tout << "running SAT solver tests...\n";); - tst1(); - tst2(); - tst2(); - tst3(); - tst4(); - tst5(); - tst5(); - tst6(); - tst7(); - tst8(); - tst9(); - tst10(); - tst11(); - tst12(); - tst13(); - tst14(); - tst15(); - tst16(); - } -}; - -void tst_sat() { - TRACE("sat", tout << "sizeof(clause): " << sizeof(clause) << "\n";); - sat_tester::run_tests(); -} - - diff --git a/src/test/dead/simplex_polynomial.cpp b/src/test/dead/simplex_polynomial.cpp deleted file mode 100644 index 2c4515f78..000000000 --- a/src/test/dead/simplex_polynomial.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "simplex_polynomial.h" - -void tst_simplex_polynomial() -{ - polynomial p1, p2, p3, p4; - simplex_variable v1(1), v2(2), v3(3), v4(4), v5(5); - monomial m1(v1), m2(v2), m3(v3), m4(v4); - - m1 = monomial(v1); - m1 *= monomial(v2); - m1 *= monomial(v1); - - m1.display(std::cout) << std::endl; - m1.normalize(); - m1.display(std::cout) << std::endl; - - m2 = m1; - SASSERT(m1 == m2); - - p1 = polynomial(rational(1,2)); - SASSERT(p1.is_const()); - - p1 += polynomial(v1); - SASSERT(!p1.is_const()); - - p1 += polynomial(v2); - p1 *= polynomial(v2); - p1 -= polynomial(v3); - p1 += polynomial(rational(2,3)); - - p1.normalize(); - p1.display(std::cout) << std::endl; - SASSERT(p1[0].size() == 0); // first element is a constant. - - - p1 = polynomial(v1); - p2 = polynomial(v2); - p3 = polynomial(v3); - p3 += p2; - p3 *= p1; - - p3.display(std::cout) << std::endl; // multiplication distributes. - SASSERT(p3.size() == 2); - -} diff --git a/src/test/dead/symmetry.cpp b/src/test/dead/symmetry.cpp deleted file mode 100644 index d296a346c..000000000 --- a/src/test/dead/symmetry.cpp +++ /dev/null @@ -1,1105 +0,0 @@ -#ifdef _WINDOWS -#include "vector.h" -#include "region.h" -#include "trail.h" -#include "nat_set.h" -#include "stream_buffer.h" -#include "obj_hashtable.h" -#include "reg_decl_plugins.h" - -class partition { -public: - class id { - friend class partition; - unsigned m_id; - id(unsigned idx): m_id(idx) {} - unsigned get_id() const { return m_id; } - public: - id() : m_id(0) {} - bool operator==(id const& other) const { return m_id == other.m_id; } - bool operator!=(id const& other) const { return m_id != other.m_id; } - std::ostream& display(std::ostream& out) const { - return out << "p" << m_id; - } - }; -private: - static const unsigned invalid_length = 0xFFFFFFFF; - - unsigned_vector m_vertices; // permutation of vertices - svector m_roots; // pointers to class roots, the position in m_vertices that contains the root. - unsigned_vector m_lengths; // length of equivalence class, valid at root position. - unsigned_vector m_length_trail; - unsigned_vector m_offset_trail; - unsigned_vector m_length_lim; - - bool invariant() const { - if (m_roots.size() != m_vertices.size()) { - return false; - } - if (m_roots.size() != m_lengths.size()) { - return false; - } - for (unsigned i = 0; i < m_roots.size(); ++i) { - if (!is_root(m_vertices[m_roots[m_vertices[i]].get_id()])) { - return false; - } - } - return true; - } - - bool is_root(id class_id) const { - return - class_id.m_id < m_vertices.size() && - m_roots[m_vertices[class_id.m_id]] == class_id; - } - -public: - - class mark { - partition& m_partition; - nat_set m_mark; - - public: - mark(partition& p): m_partition(p) { - m_mark.assure_domain(p.m_roots.size()); - } - - void reset() { - m_mark.reset(); - } - - bool test_and_set(id class_id0) { - if (m_mark.contains(class_id0.m_id)) { - return false; - } - m_mark.insert(class_id0.m_id); - return true; - } - }; - - partition(unsigned size) { - for (unsigned i = 0; i < size; ++i) { - m_vertices.push_back(i); - m_roots.push_back(id(0)); - m_lengths.push_back(invalid_length); - } - m_lengths[0] = size; - } - - void push_scope() { - SASSERT(invariant()); - m_length_lim.push_back(m_length_trail.size()); - } - - void pop_scope(unsigned num_scopes) { - if (num_scopes == 0) { - return; - } - unsigned lvl = m_length_lim.size(); - SASSERT(num_scopes <= lvl); - unsigned new_lvl = lvl - num_scopes; - unsigned old_size = m_length_lim[new_lvl]; - // - // NB. backtracking could be expensive in the case where - // we partition the same class multiple times during - // one level. Alternative is to maintain level indication - // together with length to avoid pushing redundant length - // constraints on the stack. - // - for (unsigned i = m_length_trail.size(); i > old_size; ) { - --i; - unsigned offset = m_offset_trail[i]; - unsigned length = m_length_trail[i]; - id class_id(offset); - if (length != invalid_length) { - for (unsigned j = 0; j < length; ++j) { - m_roots[m_vertices[offset + j]] = class_id; - } - } - m_lengths[offset] = length; - } - m_length_trail.shrink(old_size); - m_offset_trail.shrink(old_size); - m_length_lim.shrink(new_lvl); - SASSERT(invariant()); - } - - unsigned get_size(id class_id) const { - SASSERT(is_root(class_id)); - return m_lengths[class_id.m_id]; - } - - unsigned * get_elems(id class_id) { - SASSERT(is_root(class_id)); - return m_vertices.begin() + class_id.m_id; - } - - unsigned const * get_elems(id class_id) const { - return m_vertices.begin() + class_id.m_id; - } - - void mk_partition(unsigned length, unsigned const* vertices) { - SASSERT(m_vertices.begin() <= vertices); - SASSERT(vertices < m_vertices.begin() + m_vertices.size()); - unsigned offset = static_cast(vertices - m_vertices.begin()); - m_length_trail.push_back(m_lengths[offset]); - m_offset_trail.push_back(offset); - m_lengths[offset] = length; - id class_id(offset); - for (unsigned i = 0; i < length; ++i) { - m_roots[vertices[i]] = class_id; - } - } - - id operator[](unsigned v) const { - return m_roots[v]; - } - - void display(std::ostream& out) { - for (unsigned i = 0; i < m_vertices.size(); ++i) { - out << m_vertices[i] << " |-> " << m_roots[m_vertices[i]].m_id << "\n"; - } - } - - void copy_vertices(unsigned_vector& vertices) { - vertices = m_vertices; - } - - void split(id id, unsigned v, unsigned pos) { - // split class id into two parts. - // put var v at position pos in a singleton class. - // - // TBD: can swap into last place to save updates to ids. - // TBD: nothing ensures vertices are invariant under backtracking. - // TBD: the new partitions should be added to m_todo in - // the refiner. - // - unsigned offset = id.get_id(); - if (pos > offset) { - unsigned length = m_lengths[offset]; - std::swap(m_vertices.begin()[pos],m_vertices.begin()[offset]); - SASSERT(length > 1); - mk_partition(1, m_vertices.begin()+offset); - mk_partition(length-1,m_vertices.begin()+offset+1); - } - } - - bool next_split(id& class_id) { - // - // TBD: find first non-singleton partition that is not already - // split on. - // - return false; - } - -}; - -class graph { - // vertex adjacency graph: - vector > m_in; - vector > m_out; - unsigned m_max_degree; - - -public: - graph() : m_max_degree(0) {} - - void add_vertex(unsigned v) { - if (get_num_vertices() <= v) { - m_out.resize(v+1,vector()); - m_in.resize(v+1,vector()); - } - SASSERT(get_num_vertices() == m_in.size()); - SASSERT(get_num_vertices() == m_out.size()); - SASSERT(v < get_num_vertices()); - } - - - void add_edge(unsigned src, unsigned dst) { - SASSERT(src < get_num_vertices()); - SASSERT(dst < get_num_vertices()); - m_out[src].push_back(dst); - m_in[dst].push_back(src); - if (m_out[src].size() > m_max_degree) { - m_max_degree = m_out[src].size(); - } - } - - unsigned get_num_in(unsigned dst) const { - return m_in[dst].size(); - } - - unsigned get_src(unsigned dst, unsigned idx) const { - return m_in[dst][idx]; - } - - unsigned get_dst(unsigned src, unsigned idx) const { - return m_out[src][idx]; - } - - unsigned get_num_out(unsigned src) const { - return m_out[src].size(); - } - - unsigned get_num_vertices() const { - return m_in.size(); - } - - unsigned get_max_degree() const { - return m_max_degree; - } -}; - -class partition_refiner { - - partition& m_partition; - graph& m_graph; - partition::mark m_mark; - - - // - // Temporary variables. - // - svector m_todo; - svector m_inverse; - - // - // For bucketizing bisimilar nodes. - // - vector m_non_empty_buckets; - vector m_buckets; - - -public: - partition_refiner(partition& p, graph& g): m_partition(p), m_graph(g), m_mark(p) { - m_buckets.resize(m_graph.get_max_degree()+1); - } - - void add_refine_class(partition::id id) { - m_todo.push_back(id); - } - - // - // - // compute equivalence classes for vertices - // based on partition refinement. - // - // m_todo contains node classes to partition refine. - // - void partition_refinement() { - for (unsigned i = 0; i < m_todo.size(); ++i) { - partition_refinement(m_todo[i]); - } - m_todo.reset(); - } - - -private: - - // - // refine classes with vertices entering id_dst - // TBD: if we already refined id_dst, then avoid redundant re-refining? - // - void partition_refinement(partition::id id_dst) { - m_mark.reset(); - unsigned class_sz = m_partition.get_size(id_dst); - unsigned const* elems = m_partition.get_elems(id_dst); - for (unsigned j = 0; j < class_sz; ++j) { - unsigned dst = elems[j]; - unsigned in_degree = m_graph.get_num_in(dst); - for (unsigned k = 0; k < in_degree; ++k) { - unsigned src = m_graph.get_src(dst,k); - partition::id id_src = m_partition[src]; - if (m_mark.test_and_set(id_src)) { - partition_refinement(id_src, id_dst); - } - } - } - } - - // - // refined partition algorithm based on - // counting number of edges to id_dst. - // - void partition_refinement(partition::id id_src, partition::id id_dst) { - - unsigned src_sz = m_partition.get_size(id_src); - unsigned* src_elems = m_partition.get_elems(id_src); - // - // First pass: count number of connections to id_dst. - // Move vertices with 0 count into prefix. - // Count max-count - // - unsigned max_count = 0; - unsigned num_max_count = 0; - unsigned num_zeros = 0; - for (unsigned j = 0; j < src_sz; ++j) { - unsigned src = src_elems[j]; - unsigned count = 0; - unsigned out_degree = m_graph.get_num_out(src); - for (unsigned k = 0; k < out_degree; ++k) { - unsigned dst = m_graph.get_dst(src,k); - if (m_partition[dst] == id_src) { - ++count; - } - } - if (count > max_count) { - max_count = count; - num_max_count = 1; - } - else if (count == max_count) { - ++num_max_count; - } - if (count == 0) { - SASSERT(num_zeros <= j); - if (num_zeros < j) { - std::swap(src_elems[j],src_elems[num_zeros]); - } - ++num_zeros; - } - else { - m_buckets[count].push_back(src); - if (m_buckets[count].size() == 1) { - m_non_empty_buckets.push_back(count); - } - } - } - // - // All vertices have the same degree. - // - if (num_max_count == src_sz) { - reset_buckets(); - return; - } - - // - // at least two vertices have different counts - // reaching id_src. - // - - // - // Second pass: refine [src_elems+num_zeros..src_elems+src_size-1] based on count-sort. - // - - SASSERT(m_non_empty_buckets.size() >= 1); - - unsigned largest_bucket_pos = 0; - unsigned largest_bucket_sz = num_zeros; - unsigned pos = num_zeros; - if (num_zeros > 0) { - m_partition.mk_partition(num_zeros, src_elems); - } - for (unsigned i = 0; i < m_non_empty_buckets.size(); ++i) { - unsigned bucket_id = m_non_empty_buckets[i]; - unsigned_vector const& bucket = m_buckets[bucket_id]; - unsigned bucket_sz = bucket.size(); - SASSERT(bucket_sz > 0); - for (unsigned j = 0; j < bucket_sz; ++j) { - src_elems[pos+j] = bucket[j]; - } - if (largest_bucket_sz < bucket_sz) { - largest_bucket_sz = bucket_sz; - largest_bucket_pos = pos; - } - m_partition.mk_partition(bucket_sz, src_elems+pos); - pos += bucket_sz; - } - - // - // Insert all partitions except for largest_bucket_pos. - // - pos = 0; - if (num_zeros > 0 && largest_bucket_pos != 0) { - m_todo.push_back(m_partition[src_elems[0]]); - } - pos += num_zeros; - for (unsigned i = 0; i < m_non_empty_buckets.size(); ++i) { - unsigned sz = m_buckets[m_non_empty_buckets[i]].size(); - if (pos != largest_bucket_pos) { - m_todo.push_back(m_partition[src_elems[pos]]); - } - pos += sz; - } - - // reset buckets that were used. - reset_buckets(); - } - - void reset_buckets() { - for (unsigned i = 0; i < m_non_empty_buckets.size(); ++i) { - m_buckets[m_non_empty_buckets[i]].reset(); - } - m_non_empty_buckets.reset(); - } -}; - -class automorphism_search { - struct stats { - unsigned m_nodes; - unsigned m_max_level; - stats() : m_nodes(0), m_max_level(0) {} - }; - bool m_first; - unsigned_vector m_first_permutation; - partition_refiner m_refiner; - stats m_stats; - partition& m_partition; - graph& m_graph; - unsigned_vector m_num_elems; - ptr_vector m_elems; - -public: - - automorphism_search(partition& p, graph& g): - m_first(true), - m_refiner(p,g), - m_partition(p), - m_graph(g) - {} - - void search_main() { - search(); - } -private: - - bool propagate(partition::id& id) { - m_refiner.partition_refinement(); - - if (m_partition.next_split(id)) { - return true; - } - - if (m_first) { - m_first = false; - m_partition.copy_vertices(m_first_permutation); - pop_scope(1); - } - else { - // not the first node. - // process this. - // TBD - - } - return false; - } - - // - // enumerate elements from partition id: - // - - void search() { - partition::id id; - unsigned num_elems; - unsigned * elems; - - while (true) { - if (propagate(id)) { - push_scope(); - num_elems = m_partition.get_size(id); - elems = m_partition.get_elems(id); - SASSERT(num_elems > 0); - m_num_elems.push_back(num_elems); - m_elems.push_back(elems); - } - else if (get_level() == 0) { - return; - } - else { - num_elems = m_num_elems.back(); - elems = m_elems.back(); - } - - // TBD orbits. - - if (num_elems == 0) { - pop_scope(1); - } - else { - m_partition.split(id, elems[0], 0); // TBD - --m_num_elems.back(); - ++m_elems.back(); - } - } - } - - // TBD: - void push_scope() {} - - void pop_scope(unsigned num_scopes) {} - - unsigned get_level() { return 0; } - -}; - -void tst_symmetry0() { - graph g; - partition p(6); - for (unsigned i = 0; i < 6; ++i) { - g.add_vertex(i); - } - for (unsigned i = 0; i < 3; ++i) { - g.add_edge(i,i+3); - } - g.add_edge(0,1); - g.add_edge(1,2); - g.add_edge(2,0); - partition_refiner r(p,g); - r.add_refine_class(p[0]); - r.partition_refinement(); - p.display(std::cout); -} - -#include "ast.h" -#include "smtparser.h" -#include "array_decl_plugin.h" -#include "bv_decl_plugin.h" -#include "arith_decl_plugin.h" -#include "ast_pp.h" -#include "basic_simplifier_plugin.h" -#include "front_end_params.h" -#include "smt_context.h" - -class expr_symmetry_graph { - template - class labeling : public obj_map { - unsigned m_count; - u_map m_inverse; - public: - labeling() : m_count(0) {} - - unsigned get_count() const { return m_count; } - - unsigned get_label(T* e) { - unsigned lbl = 0; - if (!find(e, lbl)) { - insert(e, ++m_count); - lbl = m_count; - m_inverse.insert(lbl, e); - } - return lbl; - } - - unsigned get_existing_label(T* e) { - unsigned lbl = 0; - if (!find(e, lbl)) { - UNREACHABLE(); - } - return lbl; - } - - T* get_inverse(unsigned n) { - T* a = 0; - if (!m_inverse.find(n, a)) { - return 0; - } - return a; - } - }; - - ast_manager m_mgr; - labeling m_node_id; - expr_ref_vector m_formulas; - expr_ref_vector m_symmetry_breakers; - expr_ref_vector m_aux_preds; - - typedef obj_map func_decl_map; - - - bool is_labeled_function(func_decl* d) { - if (d->is_commutative() || d->get_arity() <= 1) { - return false; - } - if (m_mgr.is_distinct(d)) { - return false; - } - - return true; - } - - // TBD: we are not really interested in symmetries on unit literals. - - void print_graph(std::ostream& out, unsigned num_exprs, expr *const* exprs) { - ptr_vector todo; - ast_mark mark; - unsigned num_vertices = 0, num_edges = 0; - unsigned num_arity_colors = 0; - labeling node_color; - func_decl_map arity_color_map; - - todo.append(num_exprs, exprs); - while (!todo.empty()) { - expr* e = todo.back(); - todo.pop_back(); - if (m_node_id.contains(e)) { - continue; - } - m_node_id.get_label(e); - - ++num_vertices; - if (is_app(e)) { - app* a = to_app(e); - func_decl* d = a->get_decl(); - node_color.get_label(d); - unsigned arity = a->get_num_args(); - todo.append(arity, a->get_args()); - if (!is_labeled_function(d)) { - num_edges += arity; - } - else { - num_edges += 2*arity; - if (!arity_color_map.contains(d)) { - arity_color_map.insert(d,num_arity_colors); - num_arity_colors += arity; - } - } - } - } - num_vertices = m_node_id.get_count() + num_arity_colors; - - out << "p edge " << num_vertices << " " << num_edges << "\n"; - - // print graph - - // print nodes used for arities: - func_decl_map::iterator it = arity_color_map.begin(); - func_decl_map::iterator end = arity_color_map.end(); - for (; it != end; ++it) { - func_decl const* d = (*it).m_key; - unsigned offset = (*it).m_value; - for (unsigned i = 0; i < d->get_arity(); ++i) { - out << "n " << offset + m_node_id.get_count() + i << " " << i + 1 << "\n"; - } - } - - todo.append(num_exprs, exprs); - while (!todo.empty()) { - expr* e = todo.back(); - todo.pop_back(); - if (mark.is_marked(e)) { - continue; - } - mark.mark(e,true); - unsigned id = m_node_id.get_existing_label(e); - - if (is_app(e)) { - app* a = to_app(e); - func_decl* d = a->get_decl(); - unsigned arity = a->get_num_args(); - unsigned offset; - - todo.append(arity, a->get_args()); - out << "c " << d->get_name() << "\n"; - if(m_mgr.is_value(a) || arity > 0) { - out << "n " << id << " " << node_color.get_label(d) << "\n"; - } - else { - out << "n " << id << " 0\n"; - } - - if (is_labeled_function(d) && !arity_color_map.find(d,offset)) { - UNREACHABLE(); - } - for (unsigned i = 0; i < arity; ++i) { - unsigned id2 = m_node_id.get_existing_label(a->get_arg(i)); - if (!is_labeled_function(d)) { - out << "e " << id << " " << id2 << "\n"; - } - else { - unsigned color = offset + m_node_id.get_count() + i; - out << "e " << id << " " << color << "\n"; - out << "e " << color << " " << id2 << "\n"; - } - } - } - } - } - -public: - expr_symmetry_graph() : - m_formulas(m_mgr), - m_symmetry_breakers(m_mgr), - m_aux_preds(m_mgr) { - } - - void parse_file(char const* file_path, char const* file_tmp) { - - smtlib::parser* parser = smtlib::parser::create(m_mgr); - reg_decl_plugins(m_mgr); - parser->initialize_smtlib(); - - if (!parser->parse_file(file_path)) { - std::cout << "Could not parse file : " << file_path << std::endl; - dealloc(parser); - return; - } - - smtlib::benchmark* b = parser->get_benchmark(); - - smtlib::theory::expr_iterator it = b->begin_formulas(); - smtlib::theory::expr_iterator end = b->end_formulas(); - for (; it != end; ++it) { - m_formulas.push_back(*it); - } - it = b->begin_axioms(); - end = b->end_axioms(); - for (; it != end; ++it) { - m_formulas.push_back(*it); - } - - std::ofstream out(file_tmp); - - if (out.bad() || out.fail()) { - std::cerr << "Error: failed to open file \"" << file_tmp << "\" for writing.\n"; - exit(ERR_OPEN_FILE); - } - print_graph(out, m_formulas.size(), m_formulas.c_ptr()); - out.close(); - - dealloc(parser); - } - -private: - static void skip_blank(stream_buffer& inp) { - while (*inp == ' ' || *inp == '\t' || *inp == '\r') { - ++inp; - } - } - - - static bool read_line(stream_buffer& inp) { - while (*inp != EOF && *inp != '\n') { - ++inp; - } - if (*inp == EOF) { - return false; - } - ++inp; - return true; - } - - - enum token_type { - t_undef, - t_eof, - t_alpha, - t_digit, - t_special - }; - - static token_type get_token_type(int c) { - if ('0' <= c && c <= '9') { - return t_digit; - } - if ('a' <= c && c <= 'z') { - return t_alpha; - } - if ('A' <= c && c <= 'Z') { - return t_alpha; - } - return t_special; - } - - static bool read_token(stream_buffer& in, std::string& token, token_type& ty1) { - skip_blank(in); - ty1 = t_undef; - if (*in == EOF) { - ty1 = t_eof; - return false; - } - token.clear(); - while (*in != '\n' && - *in != ' ' && - *in != '\r' && - *in != '\t' && - *in != EOF) { - token_type ty2 = get_token_type(*in); - if (ty1 == t_undef) { - ty1 = ty2; - token.push_back(*in); - ++in; - } - else if (ty2 != t_special && ty1 == ty2) { - token.push_back(*in); - ++in; - } - else { - break; - } - } - return true; - } - - static bool read_token(stream_buffer& in, char const* token) { - token_type ty; - std::string s; - return - read_token(in, s, ty) && - 0 == strcmp(s.c_str(), token); - } - - static bool read_unsigned(char const* token, unsigned& u) { - u = 0; - while (*token) { - if ('0' <= *token && *token <= '9') { - u = 10*u + (*token - '0'); - ++token; - } - else { - return false; - } - } - return true; - } - - static bool read_unsigned(stream_buffer& in, unsigned& u) { - std::string token; - token_type ty = t_undef; - if (!(read_token(in, token, ty) && ty == t_digit)) { - return false; - } - return read_unsigned(token.c_str(), u); - } - - void print_cycle(unsigned_vector const& permutation) { - for (unsigned i = 0; i < permutation.size(); ++i) { - ast* a = m_node_id.get_inverse(permutation[i]); - if (a) { - std::cout << mk_pp(a, m_mgr) << " "; - } - } - std::cout << "\n"; - } - - - void mk_symmetry_breaker(vector const& permutation) { - expr_ref p(m_mgr); - p = m_mgr.mk_true(); - expr_ref_vector preds(m_mgr); - basic_simplifier_plugin util(m_mgr); - for (unsigned i = 0; i < permutation.size(); ++i) { - unsigned_vector const& cycle = permutation[i]; - if (cycle.size() <= 1) { - continue; - } - unsigned n = cycle[0]; - expr* first = m_node_id.get_inverse(n); - if (!first) { - continue; - } - - if (m_mgr.is_or(first) || m_mgr.is_not(first) || m_mgr.is_implies(first) || m_mgr.is_and(first)) { - continue; - } - if (!m_mgr.is_bool(first)) { - continue; - } - // cycle has at least 2 elements, all elements are predicates - // that are not Boolean connectives. - for (unsigned j = 0; j + 1 < cycle.size(); ++j) { - expr_ref q(m_mgr), a(m_mgr), b(m_mgr), ab(m_mgr), ba(m_mgr), e(m_mgr), abq(m_mgr); - if (j + 2 < cycle.size() || i + 1 < permutation.size()) { - q = m_mgr.mk_fresh_const("p",m_mgr.mk_bool_sort()); - m_aux_preds.push_back(q.get()); - } - else { - q = m_mgr.mk_true(); - } - a = m_node_id.get_inverse(cycle[j]); - b = m_node_id.get_inverse(cycle[j+1]); - util.mk_implies(a,b,ab); - util.mk_implies(b,a,ba); - util.mk_and(ab, q, abq); - util.mk_implies(p,abq,e); - m_symmetry_breakers.push_back(e.get()); - - util.mk_and(ba.get(),q.get(),p); - } - } - } - - - - bool read_cycle(stream_buffer& in, vector& permutation) { - unsigned_vector cycle; - unsigned n; - token_type ty; - std::string token; - if (!(read_token(in, token, ty) && ty == t_special && strcmp(token.c_str(),"(") == 0)) { - std::cout << "read (\n"; - return false; - } - if (!read_unsigned(in, n)) { - std::cout << "read unsigned\n"; - return false; - } - cycle.push_back(n); - while (true) { - if (!read_token(in, token, ty)) { - std::cout << "read next token\n"; - return false; - } - if (0 == strcmp(token.c_str(),")")) { - break; - } - if (0 != strcmp(token.c_str(),",")) { - std::cout << "read ,\n"; - return false; - } - if (!read_token(in, token, ty)) { - std::cout << "read next token\n"; - return false; - } - if (!read_unsigned(token.c_str(), n)) { - std::cout << "read number\n"; - return false; - } - cycle.push_back(n); - } - // print_cycle(cycle); - permutation.push_back(cycle); - return true; - } - - bool read_permutation(stream_buffer& in) { - vector permutation; - while (*in != '\n') { - if (!read_cycle(in, permutation)) { - return false; - } - } - ++in; - mk_symmetry_breaker(permutation); - return true; - } - -public: - void parse_generators(char const* symmetry_file) { - std::fstream in(symmetry_file); - if (in.bad() || in.fail()) { - std::cerr << "Error: failed to open file \"" << symmetry_file << "\" for reading.\n"; - exit(ERR_OPEN_FILE); - } - { - stream_buffer in_buf(in); - - while (true) { - if (!read_token(in_buf, "Generator")) { - if (read_line(in_buf)) { - continue; - } - break; - } - if (!read_token(in_buf, ":")) { - break; - } - if (!read_permutation(in_buf)) { - std::cout << "Could not read generator\n"; - char buffer[2] = { *in_buf, 0 }; - std::cout << buffer << "\n"; - break; - } - std::cout << "Read generator\n"; - // convert back to symmetry breaking. - } - } - - in.close(); - - } - -public: - static void run_bliss(char const* file_in, char const* file_out) { - char const* bliss_exe = "C:\\users\\nbjorner\\Documents\\Downloads\\bliss-0.50\\bliss-0.50\\bliss.exe"; - char buffer[4024]; -#if _WINDOWS - sprintf_s(buffer, ARRAYSIZE(buffer), "%s -directed %s > %s", bliss_exe, file_in, file_out); -#else - sprintf(buffer, "%s -directed %s > %s", bliss_exe, file_in, file_out); -#endif - system(buffer); - } - - void print_symmetry_breakers(const char* out_file) { - std::ofstream out(out_file); - if (out.bad() || out.fail()) { - std::cerr << "Error: failed to open file \"" << out_file << "\" for writing.\n"; - exit(ERR_OPEN_FILE); - } - out << ":extrapreds ("; - for (unsigned i = 0; i < m_aux_preds.size(); ++i) { - out << "(" << mk_pp(m_aux_preds[i].get(), m_mgr) << ") "; - } - out << ")\n"; - for (unsigned i = 0; i < m_symmetry_breakers.size(); ++i) { - out << ":assumption " << mk_pp(m_symmetry_breakers[i].get(), m_mgr) << "\n"; - } - out.close(); - } - - - void prove_with_symmetry_breakers() { - front_end_params params; - smt::context ctx(m_mgr, params); - for (unsigned i = 0; i < m_formulas.size(); ++i) { - ctx.assert_expr(m_formulas[i].get()); - } - for (unsigned i = 0; i < m_symmetry_breakers.size(); ++i) { - ctx.assert_expr(m_symmetry_breakers[i].get()); - } - lbool result = ctx.setup_and_check(); - std::cout << result << "\n"; - ctx.display_statistics(std::cout); - } - -}; - -void tst_symmetry_parse(char** argv, int argc, int& i) { - if (i+2 < argc) { - char const* file_in = argv[i+1]; - char const* file_tmp1 = "C:\\tmp\\bliss_in.txt"; - char const* file_tmp2 = "C:\\tmp\\bliss_out.txt"; - char const* file_out = argv[i+2]; - expr_symmetry_graph graph; - graph.parse_file(file_in, file_tmp1); - graph.run_bliss(file_tmp1, file_tmp2); - graph.parse_generators(file_tmp2); - graph.print_symmetry_breakers(file_out); - i += 2; - } - else { - std::cout << "usage .smt .smt \n"; - } -} - -void tst_symmetry_prove(char** argv, int argc, int& i) { - if (i+1 < argc) { - char const* file_in = argv[i+1]; - char const* file_tmp1 = "C:\\tmp\\bliss_in.txt"; - char const* file_tmp2 = "C:\\tmp\\bliss_out.txt"; - expr_symmetry_graph graph; - graph.parse_file(file_in, file_tmp1); - graph.run_bliss(file_tmp1, file_tmp2); - graph.parse_generators(file_tmp2); - graph.prove_with_symmetry_breakers(); - i += 1; - } - else { - std::cout << "usage .smt\n"; - } -} - -void tst_symmetry() { - char const* arg = "C:\\tvm\\src\\benchmarks\\zap\\smt-lib\\QF_IDL\\queens_bench\\toroidal_bench\\toroidal_queen2-1.smt"; - expr_symmetry_graph graph; - graph.parse_file(arg, 0); -} -#else -void tst_symmetry_parse(char** argv, int argc, int& i) { -} - -void tst_symmetry_prove(char** argv, int argc, int& i) { -} - -void tst_symmetry() { -} -#endif diff --git a/src/test/dead/template_models.cpp b/src/test/dead/template_models.cpp deleted file mode 100644 index eb4c52dd0..000000000 --- a/src/test/dead/template_models.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "ast_fm.h" -#include "smtparser.h" -#include "ast_pp.h" - -static void -simplify_formula( - ast_manager& ast_manager, - smtlib::symtable* table, - smtlib::parser* parser, - ast* formula - ) -{ -// front_end_params params; -// std::cout << std::make_pair(&ast_manager, formula) << std::endl; - -// const_decl_ast *le_decl = 0, *add_decl = 0, *mul_decl = 0; -// const_decl_ast *lt_decl = 0, *gt_decl = 0, *f_decl = 0; -// type_decl_ast* int_decl = 0; -// type_ast* int_type = 0; - -// table->find1("<=", le_decl); -// table->find1("+", add_decl); -// table->find1("*", mul_decl); -// table->find1("f", f_decl); -// table->find1("<", lt_decl); -// table->find1(">", gt_decl); -// table->find("Int", int_decl); -// int_type = ast_manager.mk_type(int_decl); - - -// ast_simplifier simplifier(ast_manager, params); - -// #if 0 -// iast_arith_simplifier* arith = -// simplifier.add_arithmetic( -// null_theory_id, // TBD -// add_decl, -// mul_decl, -// le_decl, -// false -// ); - -// arith->register_lt(lt_decl); -// arith->register_gt(gt_decl); -// #endif -// ast_fm fm(ast_manager, simplifier, le_decl, add_decl, mul_decl); - -// ast_function_replace replace(ast_manager); - -// ast_ref<> templ(ast_manager); -// templ = ast_manager.mk_const(add_decl, -// ast_manager.mk_var(0,int_type), -// ast_manager.mk_numeral(rational(2), int_type)); - -// ast_ref<> result(ast_manager); - -// // -// // Replace f by \lambda x . x + 2 in formula. -// // - -// replace(formula, f_decl, 1, templ.get(), result); - -// std::cout << "substituted:" -// << std::make_pair(&ast_manager, result.get()) << std::endl; - -// // -// // Eliminate quantified variables from the formula. -// // -// fm.eliminate(result.get(), result); - -// std::cout << "projected:" -// << std::make_pair(&ast_manager, result.get()) << std::endl; - -} - -void tst_template_models() -{ - const char* spec = - "(benchmark template_models :logic QF_LIA \n" - ":extrafuns ((f Int Int) (b Int) (c Int))\n" - ":formula (forall (x Int) (and (< (f x) (f (+ x 1))) (> (f b) b) (> (f c) b))))"; - - ast_manager ast_manager; - smtlib::parser* parser = smtlib::parser::create(ast_manager); - - parser->initialize_smtlib(); - - parser->parse_string(spec); - - smtlib::benchmark* b = parser->get_benchmark(); - - smtlib::symtable* table = b->get_symtable(); - vector formulas; - b->get_formulas(formulas); - for (unsigned j = 0; j < formulas.size(); ++j) { - simplify_formula(ast_manager, table, - parser, formulas[j].m_formula); - } - - dealloc(parser); -} diff --git a/src/test/dead/th_propagation.cpp b/src/test/dead/th_propagation.cpp deleted file mode 100644 index b57e1e9b3..000000000 --- a/src/test/dead/th_propagation.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - th_propagation.cpp - -Abstract: - - Test theory propagation. - -Author: - - Leonardo de Moura (leonardo) 2006-11-07. - -Revision History: - ---*/ -#include"core_theory.h" - -class th_propagation_tester { - static void tst1() { - core_theory t; - t.m_params.m_relevancy_lvl = 0; - - enode * n1 = t.mk_const(); - enode * n2 = t.mk_const(); - enode * n3 = t.mk_const(); - - literal eq1 = t.mk_eq(n1,n2); - literal eq2 = t.mk_eq(n2,n3); - literal eq3 = t.mk_eq(n1,n3); - - literal l1 = t.mk_lit(); - literal l2 = t.mk_lit(); - t.mk_main_clause(l1, l2, ~eq3); - t.mk_main_clause(~l2, ~eq3); - t.mk_main_clause(~l1, ~eq2); - - t.push_scope(); - t.assign(eq1, mk_axiom()); - t.propagate(); - - t.push_scope(); - t.assign(eq2, mk_axiom()); - t.propagate(); - SASSERT(t.get_assignment(eq3) == l_true); - SASSERT(t.inconsistent()); - bool r = t.m_sat->resolve_conflict(); - SASSERT(r); - } - -public: - static void run_tests() { - enable_trace("th_prop"); - enable_trace("scope"); - enable_trace("conflict"); - tst1(); - } -}; - -void tst_th_propagation() { - th_propagation_tester::run_tests(); -} - diff --git a/src/test/dead/trail.cpp b/src/test/dead/trail.cpp deleted file mode 100644 index c883c7558..000000000 --- a/src/test/dead/trail.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - trail.cpp - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2007-02-26. - -Revision History: - ---*/ -#include"core_theory.h" - -void tst_trail() { - core_theory t; - bvalue v(10); - t.push(); - v.set(t, 20); - v.set(t, 30); - SASSERT(v.get() == 30); - t.pop(1); - SASSERT(v.get() == 10); - t.push(); - t.push(); - v.set(t, 100); - SASSERT(v.get() == 100); - t.pop(2); - SASSERT(v.get() == 10); - t.push(); - t.push(); - v.set(t, 40); - SASSERT(v.get() == 40); - t.pop(1); - SASSERT(v.get() == 10); -} diff --git a/src/test/dead/watch_list.cpp b/src/test/dead/watch_list.cpp deleted file mode 100644 index 163edae0f..000000000 --- a/src/test/dead/watch_list.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - tst_watch_list.cpp - -Abstract: - - Test watch list data structure. - -Author: - - Leonardo de Moura (leonardo) 2006-10-02. - -Revision History: - ---*/ -#include"vector.h" -#include"sat_types.h" - -static void tst1() { - watch_list wl; - for(unsigned i = 0; i < 10; i++) - wl.insert_clause(reinterpret_cast(static_cast(i+1))); -} - -static void tst2() { - ptr_vector clause_list; - vector lit_list; - watch_list wl; - unsigned n = rand()%1000; - for (unsigned i = 0; i < n; i++) { - unsigned op = rand()%7; - if (op <= 1) { - clause * c = reinterpret_cast(static_cast(rand())); - wl.insert_clause(c); - clause_list.push_back(c); - } - else if (op <= 3) { - literal l = to_literal(rand()); - wl.insert_literal(l); - lit_list.push_back(l); - } - else if (op <= 4) { - if (!clause_list.empty()) { - int idx = rand() % (clause_list.size()); - clause * c = clause_list[idx]; - wl.remove_clause(c); - ptr_vector::iterator it = std::find(clause_list.begin(), clause_list.end(), c); - SASSERT(it); - clause_list.erase(it); - } - } - else if (op <= 5) { - ptr_vector::iterator it = clause_list.begin(); - ptr_vector::iterator end = clause_list.end(); - watch_list::clause_iterator it2 = wl.begin_clause(); - watch_list::clause_iterator end2 = wl.end_clause(); - for (; it != end; ++it, ++it2) { - SASSERT(it2 != end2); - SASSERT(*it == *it2); - } - } - else if (op <= 6) { - vector::iterator begin = lit_list.begin(); - vector::iterator it = lit_list.end(); - watch_list::literal_iterator it2 = wl.begin_literals(); - watch_list::literal_iterator end2 = wl.end_literals(); - while (it != begin) { - --it; - SASSERT(it2 != end2); - SASSERT(*it == *it2); - ++it2; - } - } - } -} - -static void tst3() { - for (unsigned i = 0; i < 1000; i++) - tst2(); -} - -void tst_watch_list() { - tst1(); - tst3(); -} -