3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-03-04 12:40:23 +00:00
z3/src/smt/smt_setup.cpp
Nikolaj Bjorner 939bf1c725 wip - alpha support for polymorphism
An initial update to support polymorphism from SMTLIB3 and the API (so far C, Python).

The WIP SMTLIB3 format is assumed to be supporting the following declaration

```
(declare-type-var A)
```
Whenever A is used in a type signature of a function/constant or bound quantified variable, it is taken to mean that all instantiations of A are included in the signature and assertions.
For example, if the function f is declared with signature A -> A, then there is a version of f for all instances of A.
The semantics of polymorphism appears to follow previous proposals: the instances are effectively different functions.
This may clash with some other notions, such as the type signature forall 'a . 'a -> 'a would be inhabited by a unique function (the identity), while this is not enforced in this version (and hopefully never because it is more busy work).

The C API has the function 'Z3_mk_type_variable' to create a type variable and applying functions modulo polymorphic type signatures is possible.
The kind Z3_TYPE_VAR is added to sort discriminators.

This version is considered as early alpha. It passes a first rudimentary unit test involving quantified axioms, declare-fun, define-fun, and define-fun-rec.
2023-07-12 18:09:02 -07:00

923 lines
32 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smt_setup.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-06-24.
Revision History:
--*/
#include "smt/smt_context.h"
#include "smt/smt_setup.h"
#include "ast/static_features.h"
#include "smt/theory_arith.h"
#include "smt/theory_lra.h"
#include "smt/theory_dense_diff_logic.h"
#include "smt/theory_diff_logic.h"
#include "smt/theory_utvpi.h"
#include "smt/theory_array.h"
#include "smt/theory_array_full.h"
#include "smt/theory_bv.h"
#include "smt/theory_datatype.h"
#include "smt/theory_recfun.h"
#include "smt/theory_dummy.h"
#include "smt/theory_dl.h"
#include "smt/theory_seq_empty.h"
#include "smt/theory_seq.h"
#include "smt/theory_char.h"
#include "smt/theory_special_relations.h"
#include "smt/theory_pb.h"
#include "smt/theory_fpa.h"
#include "smt/theory_str.h"
#include "smt/theory_polymorphism.h"
namespace smt {
setup::setup(context & c, smt_params & params):
m_context(c),
m_manager(c.get_manager()),
m_params(params),
m_already_configured(false) {
}
void setup::operator()(config_mode cm) {
TRACE("internalize", tout << "setup " << &m_context << "\n";);
SASSERT(m_context.get_scope_level() == 0);
SASSERT(!m_already_configured);
// if (m_params.m_mbqi && m_params.m_model_compact) {
// warning_msg("ignoring MODEL_COMPACT=true because it cannot be used with MBQI=true");
// m_params.m_model_compact = false;
// }
TRACE("setup", tout << "configuring logical context, logic: " << m_logic << " " << cm << "\n";);
m_already_configured = true;
switch (cm) {
case CFG_BASIC: setup_unknown(); break;
case CFG_LOGIC: setup_default(); break;
case CFG_AUTO: setup_auto_config(); break;
}
setup_card();
}
void setup::setup_default() {
if (m_logic == "QF_UF")
setup_QF_UF();
else if (m_logic == "QF_RDL")
setup_QF_RDL();
else if (m_logic == "QF_IDL")
setup_QF_IDL();
else if (m_logic == "QF_UFIDL")
setup_QF_UFIDL();
else if (m_logic == "QF_LRA")
setup_QF_LRA();
else if (m_logic == "QF_LIA")
setup_QF_LIA();
else if (m_logic == "QF_UFLIA")
setup_QF_UFLIA();
else if (m_logic == "QF_UFLRA")
setup_QF_UFLRA();
else if (m_logic == "QF_AX")
setup_QF_AX();
else if (m_logic == "QF_AUFLIA")
setup_QF_AUFLIA();
else if (m_logic == "QF_BV")
setup_QF_BV();
else if (m_logic == "QF_AUFBV")
setup_QF_AUFBV();
else if (m_logic == "QF_ABV")
setup_QF_AUFBV();
else if (m_logic == "QF_UFBV")
setup_QF_AUFBV();
else if (m_logic == "QF_BVRE")
setup_QF_BVRE();
else if (m_logic == "AUFLIA")
setup_AUFLIA();
else if (m_logic == "AUFLIRA")
setup_AUFLIRA();
else if (m_logic == "AUFNIRA")
setup_AUFNIRA();
else if (m_logic == "AUFLIA+")
setup_AUFLIA();
else if (m_logic == "AUFLIA-")
setup_AUFLIA();
else if (m_logic == "AUFLIRA+")
setup_AUFLIRA();
else if (m_logic == "AUFLIRA-")
setup_AUFLIRA();
else if (m_logic == "AUFNIRA+")
setup_AUFLIRA();
else if (m_logic == "AUFNIRA-")
setup_AUFLIRA();
else if (m_logic == "UFNIA")
setup_UFNIA();
else if (m_logic == "UFLRA")
setup_UFLRA();
else if (m_logic == "LRA")
setup_LRA();
else if (m_logic == "QF_FP")
setup_QF_FP();
else if (m_logic == "QF_FPBV" || m_logic == "QF_BVFP")
setup_QF_FPBV();
else if (m_logic == "QF_S" || m_logic == "QF_SLIA")
setup_QF_S();
else if (m_logic == "QF_DT")
setup_QF_DT();
else
setup_unknown();
}
void setup::setup_auto_config() {
static_features st(m_manager);
IF_VERBOSE(100, verbose_stream() << "(smt.configuring)\n";);
TRACE("setup", tout << "setup, logic: " << m_logic << "\n";);
// HACK: do not collect features for QF_BV and QF_AUFBV... since they do not use them...
if (m_logic == "QF_BV") {
setup_QF_BV();
}
else if (m_logic == "QF_AUFBV" || m_logic == "QF_ABV" || m_logic == "QF_UFBV") {
setup_QF_AUFBV();
}
else {
IF_VERBOSE(100, verbose_stream() << "(smt.collecting-features)\n";);
ptr_vector<expr> fmls;
m_context.get_asserted_formulas(fmls);
st.collect(fmls.size(), fmls.data());
TRACE("setup", st.display_primitive(tout););
IF_VERBOSE(1000, st.display_primitive(verbose_stream()););
if (m_logic == "QF_UF")
setup_QF_UF(st);
else if (m_logic == "QF_RDL")
setup_QF_RDL(st);
else if (m_logic == "QF_IDL")
setup_QF_IDL(st);
else if (m_logic == "QF_UFIDL")
setup_QF_UFIDL(st);
else if (m_logic == "QF_LRA")
setup_QF_LRA(st);
else if (m_logic == "QF_LIA")
setup_QF_LIA(st);
else if (m_logic == "QF_UFLIA")
setup_QF_UFLIA(st);
else if (m_logic == "QF_UFLRA")
setup_QF_UFLRA();
else if (m_logic == "QF_AX")
setup_QF_AX(st);
else if (m_logic == "QF_BVRE")
setup_QF_BVRE();
else if (m_logic == "QF_AUFLIA")
setup_QF_AUFLIA(st);
else if (m_logic == "QF_S" || m_logic == "QF_SLIA")
setup_QF_S();
else if (m_logic == "AUFLIA")
setup_AUFLIA(st);
else if (m_logic == "AUFLIRA")
setup_AUFLIRA();
else if (m_logic == "AUFNIRA")
setup_AUFNIRA();
else if (m_logic == "AUFLIA+")
setup_AUFLIA();
else if (m_logic == "AUFLIA-")
setup_AUFLIA();
else if (m_logic == "AUFLIRA+")
setup_AUFLIRA();
else if (m_logic == "AUFLIRA-")
setup_AUFLIRA();
else if (m_logic == "AUFNIRA+")
setup_AUFLIRA();
else if (m_logic == "AUFNIRA-")
setup_AUFLIRA();
else if (m_logic == "UFNIA")
setup_UFNIA();
else if (m_logic == "QF_DT")
setup_QF_DT();
else if (m_logic == "LRA")
setup_LRA();
else
setup_unknown(st);
}
}
static void check_no_arithmetic(static_features const & st, char const * logic) {
if (st.m_num_arith_ineqs > 0 || st.m_num_arith_terms > 0 || st.m_num_arith_eqs > 0)
throw default_exception("Benchmark constrains arithmetic, but specified logic does not support it.");
}
void setup::setup_QF_UF() {
m_params.setup_QF_UF();
}
void setup::setup_QF_DT() {
setup_QF_UF();
setup_datatypes();
setup_recfuns();
}
void setup::setup_QF_BVRE() {
setup_QF_BV();
setup_QF_LIA();
setup_seq();
}
void setup::setup_QF_UF(static_features const & st) {
check_no_arithmetic(st, "QF_UF");
setup_QF_UF();
TRACE("setup",
tout << "st.m_num_theories: " << st.m_num_theories << "\n";
tout << "st.m_num_uninterpreted_functions: " << st.m_num_uninterpreted_functions << "\n";);
}
void setup::setup_QF_RDL() {
m_params.setup_QF_RDL();
setup_mi_arith();
}
static bool is_in_diff_logic(static_features const & st) {
return
st.m_num_arith_eqs == st.m_num_diff_eqs &&
st.m_num_arith_terms == st.m_num_diff_terms &&
st.m_num_arith_ineqs == st.m_num_diff_ineqs;
}
static bool is_diff_logic(static_features const & st) {
return
is_in_diff_logic(st) &&
(st.m_num_diff_ineqs > 0 || st.m_num_diff_eqs > 0 || st.m_num_diff_terms > 0)
;
}
static void check_no_uninterpreted_functions(static_features const & st, char const * logic) {
if (st.m_num_uninterpreted_functions != 0)
throw default_exception("Benchmark contains uninterpreted function symbols, but specified logic does not support them.");
}
void setup::setup_QF_RDL(static_features & st) {
if (!is_in_diff_logic(st))
throw default_exception("Benchmark is not in QF_RDL (real difference logic).");
if (st.m_has_int)
throw default_exception("Benchmark has integer variables but it is marked as QF_RDL (real difference logic).");
TRACE("setup", tout << "setup_QF_RDL(st)\n";);
check_no_uninterpreted_functions(st, "QF_RDL");
m_params.m_relevancy_lvl = 0;
m_params.m_arith_eq2ineq = true;
m_params.m_arith_reflect = false;
m_params.m_arith_propagate_eqs = false;
m_params.m_nnf_cnf = false;
if (st.is_dense()) {
m_params.m_restart_strategy = RS_GEOMETRIC;
m_params.m_restart_adaptive = false;
m_params.m_phase_selection = PS_CACHING;
}
// The smi theories use fixed size integers instead of rationals.
// They have support for epsilons for modeling strict inequalities, but they
// cannot handle rational numbers.
// It is only safe to use them when the input does not contain rational numbers.
// Moreover, if model construction is enabled, then rational numbers may be needed
// to compute the actual value of epsilon even if the input does not have rational numbers.
// Example: (x < 1) and (x > 0)
if (m_manager.proofs_enabled()) {
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
}
else {
if (m_params.m_arith_auto_config_simplex || st.m_num_uninterpreted_constants > 4 * st.m_num_bool_constants
|| st.m_num_ite_terms > 0 /* theory_rdl and theory_frdl do not support ite-terms */) {
// if (!st.m_has_rational && !m_params.m_model && st.arith_k_sum_is_small()) {
// TRACE("rdl_bug", tout << "using theory_smi_arith\n";);
// m_context.register_plugin(alloc(smt::theory_smi_arith, m_context));
// }
// else {
TRACE("rdl_bug", tout << "using theory_mi_arith\n";);
//setup_lra_arith();
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
// }
}
else {
m_params.m_arith_bound_prop = bound_prop_mode::BP_NONE;
m_params.m_arith_propagation_strategy = arith_prop_strategy::ARITH_PROP_AGILITY;
m_params.m_arith_add_binary_bounds = true;
if (!st.m_has_rational && !m_params.m_model && st.arith_k_sum_is_small())
m_context.register_plugin(alloc(smt::theory_frdl, m_context));
else
m_context.register_plugin(alloc(smt::theory_rdl, m_context));
}
}
}
void setup::setup_QF_IDL() {
TRACE("setup", tout << "setup_QF_IDL()\n";);
m_params.setup_QF_IDL();
setup_lra_arith();
}
void setup::setup_QF_IDL(static_features & st) {
if (!is_in_diff_logic(st))
throw default_exception("Benchmark is not in QF_IDL (integer difference logic).");
if (st.m_has_real)
throw default_exception("Benchmark has real variables but it is marked as QF_IDL (integer difference logic).");
TRACE("setup", tout << "setup QF_IDL, m_arith_k_sum: " << st.m_arith_k_sum << " m_num_diff_terms: " << st.m_num_arith_terms << "\n";
st.display_primitive(tout););
TRACE("setup", tout << "setup_QF_IDL(st)\n";);
check_no_uninterpreted_functions(st, "QF_IDL");
m_params.m_relevancy_lvl = 0;
m_params.m_arith_eq2ineq = true;
m_params.m_arith_reflect = false;
m_params.m_arith_propagate_eqs = false;
m_params.m_arith_small_lemma_size = 30;
m_params.m_nnf_cnf = false;
if (st.m_num_uninterpreted_constants > 5000)
m_params.m_relevancy_lvl = 2;
else if (st.m_cnf && !st.is_dense())
m_params.m_phase_selection = PS_CACHING_CONSERVATIVE2;
else
m_params.m_phase_selection = PS_CACHING;
if (st.is_dense() && st.m_num_bin_clauses + st.m_num_units == st.m_num_clauses) {
m_params.m_restart_adaptive = false;
m_params.m_restart_strategy = RS_GEOMETRIC;
}
if (st.m_cnf && st.m_num_units == st.m_num_clauses) {
// the problem is just a big conjunction... using randomization to deal with crafted benchmarks
m_params.m_random_initial_activity = IA_RANDOM;
}
TRACE("setup",
tout << "RELEVANCY: " << m_params.m_relevancy_lvl << "\n";
tout << "ARITH_EQ_BOUNDS: " << m_params.m_arith_eq_bounds << "\n";);
if (m_manager.proofs_enabled()) {
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
}
else if (!m_params.m_arith_auto_config_simplex && st.is_dense()) {
TRACE("setup", tout << "using dense diff logic...\n";);
m_params.m_phase_selection = PS_CACHING_CONSERVATIVE;
if (st.arith_k_sum_is_small())
m_context.register_plugin(alloc(smt::theory_dense_si, m_context));
else
m_context.register_plugin(alloc(smt::theory_dense_i, m_context));
}
else {
// if (st.arith_k_sum_is_small()) {
// TRACE("setup", tout << "using small integer simplex...\n";
// m_context.register_plugin(alloc(smt::theory_si_arith, m_context));
// }
// else {
TRACE("setup", tout << "using big integer simplex...\n";);
m_context.register_plugin(alloc(smt::theory_i_arith, m_context));
// }
}
}
void setup::setup_QF_UFIDL() {
TRACE("setup", tout << "setup_QF_UFIDL()\n";);
m_params.setup_QF_UFIDL();
setup_lra_arith();
}
void setup::setup_QF_UFIDL(static_features & st) {
TRACE("setup", tout << "setup_QF_UFIDL(st)\n";);
if (st.m_has_real)
throw default_exception("Benchmark has real variables but it is marked as QF_UFIDL (uninterpreted functions and difference logic).");
m_params.m_relevancy_lvl = 0;
m_params.m_arith_reflect = false;
m_params.m_nnf_cnf = false;
if (st.m_num_uninterpreted_functions == 0) {
m_params.m_arith_eq2ineq = true;
m_params.m_arith_propagate_eqs = false;
if (st.is_dense()) {
m_params.m_arith_small_lemma_size = 128;
m_params.m_lemma_gc_half = true;
m_params.m_restart_strategy = RS_GEOMETRIC;
if (m_manager.proofs_enabled()) {
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
}
else if (st.arith_k_sum_is_small())
m_context.register_plugin(alloc(smt::theory_dense_si, m_context));
else
m_context.register_plugin(alloc(smt::theory_dense_i, m_context));
return;
}
}
m_params.m_arith_eq_bounds = true;
// m_params.m_phase_selection = PS_THEORY;
m_params.m_restart_strategy = RS_GEOMETRIC;
m_params.m_restart_factor = 1.5;
m_params.m_restart_adaptive = false;
if (m_manager.proofs_enabled()) {
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
}
// else if (st.arith_k_sum_is_small())
// m_context.register_plugin(alloc(smt::theory_dense_si, m_context));
else
m_context.register_plugin(alloc(smt::theory_i_arith, m_context));
}
void setup::setup_QF_LRA() {
TRACE("setup", tout << "setup_QF_LRA()\n";);
m_params.setup_QF_LRA();
setup_lra_arith();
}
void setup::setup_QF_LRA(static_features const & st) {
check_no_uninterpreted_functions(st, "QF_LRA");
m_params.setup_QF_LRA(st);
setup_lra_arith();
}
void setup::setup_QF_LIRA(static_features const& st) {
setup_mi_arith();
}
void setup::setup_QF_LIA() {
TRACE("setup", tout << "setup_QF_LIA(st)\n";);
m_params.setup_QF_LIA();
setup_lra_arith();
}
void setup::setup_QF_LIA(static_features const & st) {
check_no_uninterpreted_functions(st, "QF_LIA");
TRACE("setup", tout << "QF_LIA setup\n";);
m_params.setup_QF_LIA(st);
setup_lra_arith();
}
void setup::setup_QF_UFLIA() {
setup_lra_arith();
m_params.setup_QF_UFLIA();
}
void setup::setup_QF_UFLIA(static_features & st) {
if (st.m_has_real)
throw default_exception("Benchmark has real variables but it is marked as QF_UFLIA (uninterpreted functions and linear integer arithmetic).");
setup_QF_UFLIA();
if (st.m_has_bv)
setup_QF_BV();
}
void setup::setup_QF_UFLRA() {
m_params.setup_QF_UFLRA();
setup_lra_arith();
}
void setup::setup_QF_BV() {
TRACE("setup", tout << "qf-bv\n";);
m_params.setup_QF_BV();
m_context.register_plugin(alloc(smt::theory_bv, m_context));
}
void setup::setup_QF_AUFBV() {
m_params.setup_QF_AUFBV();
m_context.register_plugin(alloc(smt::theory_bv, m_context));
setup_arrays();
}
void setup::setup_QF_AX() {
TRACE("setup", tout << "QF_AX\n";);
m_params.setup_QF_AX();
setup_arrays();
}
void setup::setup_QF_AX(static_features const & st) {
m_params.setup_QF_AX(st);
setup_arrays();
}
void setup::setup_QF_AUFLIA() {
TRACE("QF_AUFLIA", tout << "no static features\n";);
m_params.setup_QF_AUFLIA();
setup_i_arith();
setup_arrays();
}
void setup::setup_QF_AUFLIA(static_features const & st) {
m_params.setup_QF_AUFLIA(st);
setup_i_arith();
setup_arrays();
}
void setup::setup_AUFLIA(bool simple_array) {
TRACE("setup", tout << "AUFLIA\n";);
m_params.setup_AUFLIA(simple_array);
TRACE("setup", tout << "max_eager_multipatterns: " << m_params.m_qi_max_eager_multipatterns << "\n";);
m_context.register_plugin(alloc(smt::theory_i_arith, m_context));
setup_arrays();
}
void setup::setup_AUFLIA(static_features const & st) {
if (st.m_has_real)
throw default_exception("Benchmark has real variables but it is marked as AUFLIA (arrays, uninterpreted functions and linear integer arithmetic).");
m_params.setup_AUFLIA(st);
setup_AUFLIA();
}
void setup::setup_AUFLIRA(bool simple_array) {
TRACE("setup", tout << "AUFLIRA\n";);
m_params.setup_AUFLIRA(simple_array);
setup_mi_arith();
setup_arrays();
}
void setup::setup_UFNIA() {
setup_AUFLIA();
}
void setup::setup_UFLRA() {
setup_AUFLIRA();
}
void setup::setup_AUFLIAp() {
setup_AUFLIA();
}
void setup::setup_AUFNIRA() {
setup_AUFLIRA();
}
void setup::setup_LRA() {
m_params.setup_LRA();
setup_mi_arith();
}
void setup::setup_QF_FP() {
setup_QF_BV();
m_context.register_plugin(alloc(smt::theory_fpa, m_context));
}
void setup::setup_QF_FPBV() {
setup_QF_BV();
m_context.register_plugin(alloc(smt::theory_fpa, m_context));
}
void setup::setup_QF_S() {
if (m_params.m_string_solver == "z3str3") {
setup_str();
}
else if (m_params.m_string_solver == "seq") {
setup_unknown();
}
else if (m_params.m_string_solver == "char") {
setup_QF_BV();
setup_char();
}
else if (m_params.m_string_solver == "auto") {
setup_unknown();
}
else if (m_params.m_string_solver == "empty") {
setup_seq();
}
else if (m_params.m_string_solver == "none") {
// don't register any solver.
}
else {
throw default_exception("invalid parameter for smt.string_solver, valid options are 'z3str3', 'seq', 'auto'");
}
}
bool is_arith(static_features const & st) {
return st.m_num_arith_ineqs > 0 || st.m_num_arith_terms > 0 || st.m_num_arith_eqs > 0;
}
void setup::setup_i_arith() {
if (arith_solver_id::AS_OLD_ARITH == m_params.m_arith_mode) {
m_context.register_plugin(alloc(smt::theory_i_arith, m_context));
}
else {
setup_lra_arith();
}
}
void setup::setup_lra_arith() {
if (m_params.m_arith_mode == arith_solver_id::AS_OLD_ARITH)
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
else
m_context.register_plugin(alloc(smt::theory_lra, m_context));
}
void setup::setup_mi_arith() {
switch (m_params.m_arith_mode) {
case arith_solver_id::AS_OPTINF:
m_context.register_plugin(alloc(smt::theory_inf_arith, m_context));
break;
case arith_solver_id::AS_NEW_ARITH:
setup_lra_arith();
break;
default:
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
break;
}
}
void setup::setup_arith() {
static_features st(m_manager);
IF_VERBOSE(100, verbose_stream() << "(smt.collecting-features)\n";);
ptr_vector<expr> fmls;
m_context.get_asserted_formulas(fmls);
st.collect(fmls.size(), fmls.data());
IF_VERBOSE(1000, st.display_primitive(verbose_stream()););
bool fixnum = st.arith_k_sum_is_small() && m_params.m_arith_fixnum;
bool int_only = !st.m_has_rational && !st.m_has_real && m_params.m_arith_int_only;
auto mode = m_params.m_arith_mode;
if (m_logic == "QF_LIA") {
mode = arith_solver_id::AS_NEW_ARITH;
}
switch(mode) {
case arith_solver_id::AS_NO_ARITH:
m_context.register_plugin(alloc(smt::theory_dummy, m_context, m_manager.mk_family_id("arith"), "no arithmetic"));
break;
case arith_solver_id::AS_DIFF_LOGIC:
m_params.m_arith_eq2ineq = true;
if (fixnum) {
if (int_only)
m_context.register_plugin(alloc(smt::theory_fidl, m_context));
else
m_context.register_plugin(alloc(smt::theory_frdl, m_context));
}
else {
if (int_only)
m_context.register_plugin(alloc(smt::theory_idl, m_context));
else
m_context.register_plugin(alloc(smt::theory_rdl, m_context));
}
break;
case arith_solver_id::AS_DENSE_DIFF_LOGIC:
m_params.m_arith_eq2ineq = true;
if (fixnum) {
if (int_only)
m_context.register_plugin(alloc(smt::theory_dense_si, m_context));
else
m_context.register_plugin(alloc(smt::theory_dense_smi, m_context));
}
else {
if (int_only)
m_context.register_plugin(alloc(smt::theory_dense_i, m_context));
else
m_context.register_plugin(alloc(smt::theory_dense_mi, m_context));
}
break;
case arith_solver_id::AS_UTVPI:
m_params.m_arith_eq2ineq = true;
if (int_only)
m_context.register_plugin(alloc(smt::theory_iutvpi, m_context));
else
m_context.register_plugin(alloc(smt::theory_rutvpi, m_context));
break;
case arith_solver_id::AS_OPTINF:
m_context.register_plugin(alloc(smt::theory_inf_arith, m_context));
break;
case arith_solver_id::AS_OLD_ARITH:
if (m_params.m_arith_int_only && int_only)
m_context.register_plugin(alloc(smt::theory_i_arith, m_context));
else
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
break;
case arith_solver_id::AS_NEW_ARITH:
setup_lra_arith();
break;
default:
m_context.register_plugin(alloc(smt::theory_mi_arith, m_context));
break;
}
}
void setup::setup_bv() {
family_id bv_fid = m_manager.mk_family_id("bv");
if (m_context.get_theory(bv_fid))
return;
switch(m_params.m_bv_mode) {
case BS_NO_BV:
m_context.register_plugin(alloc(smt::theory_dummy, m_context, bv_fid, "no bit-vector"));
break;
case BS_BLASTER:
m_context.register_plugin(alloc(smt::theory_bv, m_context));
break;
}
}
void setup::setup_arrays() {
switch(m_params.m_array_mode) {
case AR_NO_ARRAY:
m_context.register_plugin(alloc(smt::theory_dummy, m_context, m_manager.mk_family_id("array"), "no array"));
break;
case AR_SIMPLE:
m_context.register_plugin(alloc(smt::theory_array, m_context));
break;
case AR_MODEL_BASED:
throw default_exception("The model-based array theory solver is deprecated");
break;
case AR_FULL:
m_context.register_plugin(alloc(smt::theory_array_full, m_context));
break;
}
}
void setup::setup_datatypes() {
TRACE("datatype", tout << "registering theory datatype...\n";);
m_context.register_plugin(alloc(theory_datatype, m_context));
}
void setup::setup_recfuns() {
TRACE("recfun", tout << "registering theory recfun...\n";);
theory_recfun * th = alloc(theory_recfun, m_context);
m_context.register_plugin(th);
}
void setup::setup_dl() {
m_context.register_plugin(mk_theory_dl(m_context));
}
void setup::setup_seq_str(static_features const & st) {
// check params for what to do here when it's ambiguous
if (m_params.m_string_solver == "z3str3") {
setup_str();
}
else if (m_params.m_string_solver == "seq") {
setup_seq();
}
else if (m_params.m_string_solver == "empty") {
setup_seq();
}
else if (m_params.m_string_solver == "none") {
// don't register any solver.
}
else if (m_params.m_string_solver == "auto") {
if (st.m_has_seq_non_str) {
setup_seq();
}
else {
setup_str();
}
}
else {
throw default_exception("invalid parameter for smt.string_solver, valid options are 'z3str3', 'seq', 'auto'");
}
}
void setup::setup_card() {
m_context.register_plugin(alloc(theory_pb, m_context));
}
void setup::setup_fpa() {
setup_bv();
m_context.register_plugin(alloc(theory_fpa, m_context));
}
void setup::setup_str() {
setup_arith();
m_context.register_plugin(alloc(theory_str, m_context, m_manager, m_params));
}
void setup::setup_seq() {
m_context.register_plugin(alloc(smt::theory_seq, m_context));
setup_char();
}
void setup::setup_char() {
m_context.register_plugin(alloc(smt::theory_char, m_context));
}
void setup::setup_special_relations() {
m_context.register_plugin(alloc(smt::theory_special_relations, m_context, m_manager));
}
void setup::setup_polymorphism() {
if (m_manager.has_type_vars())
m_context.register_plugin(alloc(theory_polymorphism, m_context));
}
void setup::setup_unknown() {
static_features st(m_manager);
ptr_vector<expr> fmls;
m_context.get_asserted_formulas(fmls);
st.collect(fmls.size(), fmls.data());
TRACE("setup", tout << "setup_unknown\n";);
setup_arith();
setup_arrays();
setup_bv();
setup_datatypes();
setup_recfuns();
setup_dl();
setup_seq_str(st);
setup_fpa();
setup_special_relations();
setup_polymorphism();
}
void setup::setup_unknown(static_features & st) {
TRACE("setup", tout << "setup_unknown\n";);
if (st.m_num_quantifiers > 0) {
if (st.m_has_real)
setup_AUFLIRA(false);
else
setup_AUFLIA(false);
setup_datatypes();
setup_bv();
setup_dl();
setup_seq_str(st);
setup_fpa();
setup_recfuns();
setup_special_relations();
setup_polymorphism();
return;
}
TRACE("setup",
tout << "num non UF theories: " << st.num_non_uf_theories() << "\n";
tout << "num theories: " << st.num_theories() << "\n";
tout << "is_diff_logic: " << is_diff_logic(st) << "\n";
tout << "is_arith: " << is_arith(st) << "\n";
tout << "has UF: " << st.has_uf() << "\n";
tout << "has real: " << st.m_has_real << "\n";
tout << "has int: " << st.m_has_int << "\n";
tout << "has bv: " << st.m_has_bv << "\n";
tout << "has fpa: " << st.m_has_fpa << "\n";
tout << "has arrays: " << st.m_has_arrays << "\n";);
if (st.num_non_uf_theories() == 0) {
setup_QF_UF(st);
return;
}
if (st.num_theories() == 1 && is_diff_logic(st)) {
if (st.m_has_real && !st.m_has_int)
setup_QF_RDL(st);
else if (!st.m_has_real && st.m_has_int)
setup_QF_IDL(st);
else
setup_unknown();
return;
}
if (st.num_theories() == 2 && st.has_uf() && is_diff_logic(st)) {
if (!st.m_has_real && st.m_has_int)
setup_QF_UFIDL(st);
else
setup_unknown();
return;
}
if (st.num_theories() == 1 && is_arith(st)) {
if ((st.m_has_int && st.m_has_real) || (st.m_num_non_linear != 0))
setup_QF_LIRA(st);
else if (st.m_has_real)
setup_QF_LRA(st);
else
setup_QF_LIA(st);
return;
}
if (st.num_theories() == 2 && st.has_uf() && is_arith(st)) {
if (!st.m_has_real && st.m_num_non_linear == 0)
setup_QF_UFLIA(st);
else if (!st.m_has_int && st.m_num_non_linear == 0)
setup_QF_UFLRA();
else
setup_unknown();
return;
}
if (st.num_theories() == 1 && st.m_has_bv) {
setup_QF_BV();
return;
}
if (st.num_theories() == 1 && st.m_has_fpa) {
setup_QF_FP();
return;
}
if (st.num_theories() == 2 && st.m_has_fpa && st.m_has_bv) {
setup_QF_FPBV();
return;
}
if (st.num_theories() == 1 && st.m_has_arrays) {
setup_QF_AX(st);
return;
}
if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && !st.m_has_ext_arrays && st.m_has_bv) {
setup_QF_AUFBV();
return;
}
if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_int) {
setup_QF_AUFLIA(st);
return;
}
setup_unknown();
}
};