From 4e37821dde621e243d3a86be3fcd1d99ce6ac70a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Feb 2016 13:52:43 +0000 Subject: [PATCH] "canceled" -> Z3_CANCELED_MSG Relates to #431 --- src/ast/expr2polynomial.cpp | 61 +- src/math/interval/interval_def.h | 209 +++--- src/math/polynomial/algebraic_numbers.cpp | 383 +++++----- src/math/polynomial/polynomial.cpp | 719 ++++++++++--------- src/math/polynomial/upolynomial.cpp | 315 ++++---- src/math/realclosure/realclosure.cpp | 589 +++++++-------- src/math/subpaving/subpaving_t_def.h | 126 ++-- src/math/subpaving/tactic/expr2subpaving.cpp | 47 +- src/muz/bmc/dl_bmc_engine.cpp | 324 ++++----- src/muz/duality/duality_dl_interface.cpp | 52 +- src/muz/pdr/pdr_context.cpp | 390 +++++----- src/smt/tactic/smt_tactic.cpp | 40 +- src/tactic/nlsat_smt/nl_purify_tactic.cpp | 2 +- 13 files changed, 1632 insertions(+), 1625 deletions(-) diff --git a/src/ast/expr2polynomial.cpp b/src/ast/expr2polynomial.cpp index 097d77cbc..a06ce7e2a 100644 --- a/src/ast/expr2polynomial.cpp +++ b/src/ast/expr2polynomial.cpp @@ -8,8 +8,8 @@ Module Name: Abstract: Translator from Z3 expressions into multivariate polynomials (and back). - - + + Author: Leonardo (leonardo) 2011-12-23 @@ -23,6 +23,7 @@ Notes: #include"ast_smt2_pp.h" #include"z3_exception.h" #include"cooperate.h" +#include"common_msgs.h" struct expr2polynomial::imp { struct frame { @@ -31,7 +32,7 @@ struct expr2polynomial::imp { frame():m_curr(0), m_idx(0) {} frame(app * t):m_curr(t), m_idx(0) {} }; - + expr2polynomial & m_wrapper; ast_manager & m_am; arith_util m_autil; @@ -39,7 +40,7 @@ struct expr2polynomial::imp { expr2var * m_expr2var; bool m_expr2var_owner; expr_ref_vector m_var2expr; - + obj_map m_cache; expr_ref_vector m_cached_domain; polynomial::polynomial_ref_vector m_cached_polynomials; @@ -52,7 +53,7 @@ struct expr2polynomial::imp { bool m_use_var_idxs; volatile bool m_cancel; - + imp(expr2polynomial & w, ast_manager & am, polynomial::manager & pm, expr2var * e2v, bool use_var_idxs): m_wrapper(w), m_am(am), @@ -94,7 +95,7 @@ struct expr2polynomial::imp { void checkpoint() { if (m_cancel) - throw default_exception("canceled"); + throw default_exception(Z3_CANCELED_MSG); cooperate("expr2polynomial"); } @@ -114,7 +115,7 @@ struct expr2polynomial::imp { SASSERT(!m_cache.contains(t)); SASSERT(m_cached_denominators.size() == m_cached_polynomials.size()); SASSERT(m_cached_denominators.size() == m_cached_domain.size()); - if (t->get_ref_count() <= 1) + if (t->get_ref_count() <= 1) return; unsigned idx = m_cached_polynomials.size(); m_cache.insert(t, idx); @@ -176,7 +177,7 @@ struct expr2polynomial::imp { case OP_NUM: store_const_poly(t); return true; - case OP_ADD: case OP_SUB: case OP_MUL: case OP_UMINUS: case OP_TO_REAL: + case OP_ADD: case OP_SUB: case OP_MUL: case OP_UMINUS: case OP_TO_REAL: push_frame(t); return false; case OP_POWER: { @@ -215,7 +216,7 @@ struct expr2polynomial::imp { store_var_poly(t); return true; } - + SASSERT(is_app(t)); if (!m_autil.is_arith_expr(t)) { if (m_use_var_idxs) @@ -223,7 +224,7 @@ struct expr2polynomial::imp { store_var_poly(t); return true; } - + return visit_arith_app(to_app(t)); } @@ -237,7 +238,7 @@ struct expr2polynomial::imp { polynomial::polynomial * const * polynomial_args(unsigned num_args) { SASSERT(m_presult_stack.size() >= num_args); return m_presult_stack.c_ptr() + m_presult_stack.size() - num_args; - } + } polynomial::numeral const * denominator_args(unsigned num_args) { SASSERT(m_dresult_stack.size() >= num_args); @@ -330,34 +331,34 @@ struct expr2polynomial::imp { // do nothing cache_result(t); } - + void process_app(app * t) { SASSERT(m_presult_stack.size() == m_dresult_stack.size()); - + switch (t->get_decl_kind()) { - case OP_ADD: + case OP_ADD: process_add(t); return; case OP_SUB: process_sub(t); return; - case OP_MUL: + case OP_MUL: process_mul(t); return; case OP_POWER: process_power(t); return; - case OP_UMINUS: + case OP_UMINUS: process_uminus(t); return; - case OP_TO_REAL: + case OP_TO_REAL: process_to_real(t); return; default: UNREACHABLE(); } } - + bool to_polynomial(expr * t, polynomial::polynomial_ref & p, polynomial::scoped_numeral & d) { if (!is_int_real(t)) return false; @@ -373,7 +374,7 @@ struct expr2polynomial::imp { while (fr.m_idx < num_args) { expr * arg = a->get_arg(fr.m_idx); fr.m_idx++; - if (!visit(arg)) + if (!visit(arg)) goto begin_loop; } process_app(a); @@ -470,12 +471,12 @@ expr2polynomial::~expr2polynomial() { dealloc(m_imp); } -ast_manager & expr2polynomial::m() const { - return m_imp->m_am; +ast_manager & expr2polynomial::m() const { + return m_imp->m_am; } -polynomial::manager & expr2polynomial::pm() const { - return m_imp->m_pm; +polynomial::manager & expr2polynomial::pm() const { + return m_imp->m_pm; } bool expr2polynomial::to_polynomial(expr * t, polynomial::polynomial_ref & p, polynomial::scoped_numeral & d) { @@ -486,14 +487,14 @@ void expr2polynomial::to_expr(polynomial::polynomial_ref const & p, bool use_pow m_imp->to_expr(p, use_power, r); } -bool expr2polynomial::is_var(expr * t) const { +bool expr2polynomial::is_var(expr * t) const { SASSERT(!m_imp->m_use_var_idxs); - return m_imp->m_expr2var->is_var(t); + return m_imp->m_expr2var->is_var(t); } - -expr2var const & expr2polynomial::get_mapping() const { + +expr2var const & expr2polynomial::get_mapping() const { SASSERT(!m_imp->m_use_var_idxs); - return *(m_imp->m_expr2var); + return *(m_imp->m_expr2var); } void expr2polynomial::set_cancel(bool f) { @@ -511,8 +512,8 @@ bool default_expr2polynomial::is_int(polynomial::var x) const { return m_is_int[x]; } -polynomial::var default_expr2polynomial::mk_var(bool is_int) { - polynomial::var x = pm().mk_var(); +polynomial::var default_expr2polynomial::mk_var(bool is_int) { + polynomial::var x = pm().mk_var(); m_is_int.reserve(x+1, false); m_is_int[x] = is_int; return x; diff --git a/src/math/interval/interval_def.h b/src/math/interval/interval_def.h index 9d720f6c5..43bf9f91a 100644 --- a/src/math/interval/interval_def.h +++ b/src/math/interval/interval_def.h @@ -24,14 +24,15 @@ Revision History: #include"trace.h" #include"scoped_numeral.h" #include"cooperate.h" +#include"common_msgs.h" #define DEFAULT_PI_PRECISION 2 // #define TRACE_NTH_ROOT template -interval_manager::interval_manager(reslimit& lim, C const & c): m_limit(lim), m_c(c) { - m().set(m_minus_one, -1); +interval_manager::interval_manager(reslimit& lim, C const & c): m_limit(lim), m_c(c) { + m().set(m_minus_one, -1); m().set(m_one, 1); m_pi_n = 0; } @@ -63,7 +64,7 @@ void interval_manager::del(interval & a) { template void interval_manager::checkpoint() { if (!m_limit.inc()) - throw default_exception("canceled"); + throw default_exception(Z3_CANCELED_MSG); cooperate("interval"); } @@ -82,7 +83,7 @@ void interval_manager::nth_root_slow(numeral const & a, unsigned n, numeral c static unsigned counter = 0; static unsigned loop_counter = 0; counter++; - if (counter % 1000 == 0) + if (counter % 1000 == 0) std::cerr << "[nth-root] " << counter << " " << loop_counter << " " << ((double)loop_counter)/((double)counter) << std::endl; #endif @@ -163,7 +164,7 @@ void interval_manager::nth_root_slow(numeral const & a, unsigned n, numeral c /** \brief Store in o a rough approximation of a^1/n. - + It uses 2^Floor[Floor(Log2(a))/n] \pre is_pos(a) @@ -179,7 +180,7 @@ void interval_manager::rough_approx_nth_root(numeral const & a, unsigned n, n } /* - Compute the n-th root of \c a with (suggested) precision p. + Compute the n-th root of \c a with (suggested) precision p. The only guarantee provided by this method is that a^(1/n) is in [lo, hi]. If n is even, then a is assumed to be nonnegative. @@ -202,8 +203,8 @@ void interval_manager::nth_root(numeral const & a, unsigned n, numeral const m().abs(A); nth_root_pos(A, n, p, lo, hi); - STRACE("nth_root_trace", - tout << "[nth-root] ("; m().display(tout, A); tout << ")^(1/" << n << ") >= "; m().display(tout, lo); tout << "\n"; + STRACE("nth_root_trace", + tout << "[nth-root] ("; m().display(tout, A); tout << ")^(1/" << n << ") >= "; m().display(tout, lo); tout << "\n"; tout << "[nth-root] ("; m().display(tout, A); tout << ")^(1/" << n << ") <= "; m().display(tout, hi); tout << "\n";); if (is_neg) { m().swap(lo, hi); @@ -214,7 +215,7 @@ void interval_manager::nth_root(numeral const & a, unsigned n, numeral const /** r <- A/(x^n) - + If to_plus_inf, then r >= A/(x^n) If not to_plus_inf, then r <= A/(x^n) @@ -251,7 +252,7 @@ void interval_manager::A_div_x_n(numeral const & A, numeral const & x, unsign The computation stops when the difference between current and new x is less than p. The procedure may not terminate if m() is not precise and p is very small. - + */ template void interval_manager::approx_nth_root(numeral const & A, unsigned n, numeral const & p, numeral & x) { @@ -261,18 +262,18 @@ void interval_manager::approx_nth_root(numeral const & A, unsigned n, numeral static unsigned counter = 0; static unsigned loop_counter = 0; counter++; - if (counter % 1000 == 0) + if (counter % 1000 == 0) std::cerr << "[nth-root] " << counter << " " << loop_counter << " " << ((double)loop_counter)/((double)counter) << std::endl; #endif - + _scoped_numeral x_prime(m()), d(m()); - + m().set(d, 1); - if (m().lt(A, d)) + if (m().lt(A, d)) m().set(x, A); else rough_approx_nth_root(A, n, x); - + round_to_minus_inf(); if (n == 2) { @@ -297,8 +298,8 @@ void interval_manager::approx_nth_root(numeral const & A, unsigned n, numeral _scoped_numeral _n(m()), _n_1(m()); m().set(_n, n); // _n contains n m().set(_n_1, n); - m().dec(_n_1); // _n_1 contains n-1 - + m().dec(_n_1); // _n_1 contains n-1 + while (true) { checkpoint(); #ifdef TRACE_NTH_ROOT @@ -311,7 +312,7 @@ void interval_manager::approx_nth_root(numeral const & A, unsigned n, numeral m().div(x_prime, _n, x_prime); m().sub(x_prime, x, d); m().abs(d); - TRACE("nth_root", + TRACE("nth_root", tout << "A: "; m().display(tout, A); tout << "\n"; tout << "x: "; m().display(tout, x); tout << "\n"; tout << "x_prime: "; m().display(tout, x_prime); tout << "\n"; @@ -340,7 +341,7 @@ void interval_manager::nth_root_pos(numeral const & A, unsigned n, numeral co else { // Check if hi is really a upper bound for A^(n-1) A_div_x_n(A, hi, n-1, true /* lo will be greater than the actual lower bound */, lo); - TRACE("nth_root_bug", + TRACE("nth_root_bug", tout << "Assuming upper\n"; tout << "A: "; m().display(tout, A); tout << "\n"; tout << "hi: "; m().display(tout, hi); tout << "\n"; @@ -397,12 +398,12 @@ template void interval_manager::sine_series(numeral const & a, unsigned k, bool upper, numeral & o) { SASSERT(k % 2 == 1); // Compute sine using taylor series up to k - // x - x^3/3! + x^5/5! - x^7/7! + ... + // x - x^3/3! + x^5/5! - x^7/7! + ... // The result should be greater than or equal to the actual value if upper == true // Otherwise it must be less than or equal to the actual value. // The argument upper only matter if the numeral_manager is not precise. - // Taylor series up to k with rounding to + // Taylor series up to k with rounding to _scoped_numeral f(m()); _scoped_numeral aux(m()); m().set(o, a); @@ -412,7 +413,7 @@ void interval_manager::sine_series(numeral const & a, unsigned k, bool upper, TRACE("sine_bug", tout << "[begin-loop] o: " << m().to_rational_string(o) << "\ni: " << i << "\n"; tout << "upper: " << upper << ", upper_factor: " << upper_factor << "\n"; tout << "o (default): " << m().to_string(o) << "\n";); - set_rounding(upper_factor); + set_rounding(upper_factor); m().power(a, i, f); TRACE("sine_bug", tout << "a^i " << m().to_rational_string(f) << "\n";); set_rounding(!upper_factor); @@ -441,15 +442,15 @@ void interval_manager::sine(numeral const & a, unsigned k, numeral & lo, nume m().reset(hi); return; } - + // Compute sine using taylor series // x - x^3/3! + x^5/5! - x^7/7! + ... // // Note that, the coefficient of even terms is 0. // So, we force k to be odd to make sure the error is minimized. if (k % 2 == 0) - k++; - + k++; + // Taylor series error = |x|^(k+1)/(k+1)! _scoped_numeral error(m()); _scoped_numeral aux(m()); @@ -466,7 +467,7 @@ void interval_manager::sine(numeral const & a, unsigned k, numeral & lo, nume m().div(error, aux, error); TRACE("sine", tout << "error: " << m().to_rational_string(error) << "\n";); - // Taylor series up to k with rounding to -oo + // Taylor series up to k with rounding to -oo sine_series(a, k, false, lo); if (m().precise()) { @@ -508,7 +509,7 @@ void interval_manager::cosine_series(numeral const & a, unsigned k, bool uppe // The argument upper only matter if the numeral_manager is not precise. - // Taylor series up to k with rounding to -oo + // Taylor series up to k with rounding to -oo _scoped_numeral f(m()); _scoped_numeral aux(m()); m().set(o, 1); @@ -527,7 +528,7 @@ void interval_manager::cosine_series(numeral const & a, unsigned k, bool uppe else m().add(o, f, o); sign = !sign; - upper_factor = !upper_factor; + upper_factor = !upper_factor; } } @@ -540,15 +541,15 @@ void interval_manager::cosine(numeral const & a, unsigned k, numeral & lo, nu m().set(hi, 1); return; } - + // Compute cosine using taylor series // 1 - x^2/2! + x^4/4! - x^6/6! + ... // // Note that, the coefficient of odd terms is 0. // So, we force k to be even to make sure the error is minimized. if (k % 2 == 1) - k++; - + k++; + // Taylor series error = |x|^(k+1)/(k+1)! _scoped_numeral error(m()); _scoped_numeral aux(m()); @@ -563,9 +564,9 @@ void interval_manager::cosine(numeral const & a, unsigned k, numeral & lo, nu m().div(error, aux, error); TRACE("sine", tout << "error: "; m().display_decimal(tout, error, 32); tout << "\n";); - // Taylor series up to k with rounding to -oo + // Taylor series up to k with rounding to -oo cosine_series(a, k, false, lo); - + if (m().precise()) { m().set(hi, lo); m().sub(lo, error, lo); @@ -614,12 +615,12 @@ void interval_manager::reset(interval & a) { template bool interval_manager::contains_zero(interval const & n) const { - return + return (lower_is_neg(n) || (lower_is_zero(n) && !lower_is_open(n))) && (upper_is_pos(n) || (upper_is_zero(n) && !upper_is_open(n))); } - + template bool interval_manager::contains(interval const & n, numeral const & v) const { if (!lower_is_inf(n)) { @@ -688,7 +689,7 @@ void interval_manager::set(interval & t, interval const & s) { template bool interval_manager::eq(interval const & a, interval const & b) const { - return + return ::eq(m(), lower(a), lower_kind(a), lower(b), lower_kind(b)) && ::eq(m(), upper(a), upper_kind(a), upper(b), upper_kind(b)) && lower_is_open(a) == lower_is_open(b) && @@ -792,7 +793,7 @@ void interval_manager::add(interval const & a, interval const & b, interval & add_jst(a, b, c_deps); add(a, b, c); } - + template void interval_manager::add(interval const & a, interval const & b, interval & c) { ext_numeral_kind new_l_kind, new_u_kind; @@ -869,7 +870,7 @@ void interval_manager::div_mul(numeral const & k, interval const & a, interva round_to_minus_inf(); m().inv(k, m_inv_k); ::mul(m(), l, l_k, m_inv_k, EN_NUMERAL, new_l_val, new_l_kind); - + round_to_plus_inf(); m().inv(k, m_inv_k); ::mul(m(), u, u_k, m_inv_k, EN_NUMERAL, new_u_val, new_u_kind); @@ -975,7 +976,7 @@ void interval_manager::mul_jst(interval const & i1, interval const & i2, inte } } else { - SASSERT(is_P(i1)); + SASSERT(is_P(i1)); if (is_N(i2)) { // 0 <= a <= x <= b, c <= y <= d <= 0 --> x*y <= b*c (uses the fact that x is pos (a is not neg) or y is neg (d is not pos)) // 0 <= a <= x, y <= d <= 0 --> a*d <= x*y @@ -990,7 +991,7 @@ void interval_manager::mul_jst(interval const & i1, interval const & i2, inte } else { SASSERT(is_P(i2)); - // 0 <= a <= x, 0 <= c <= y --> a*c <= x*y + // 0 <= a <= x, 0 <= c <= y --> a*c <= x*y // x <= b, y <= d --> x*y <= b*d (uses the fact that x is pos (a is not negative) or y is pos (c is not negative)) r_deps.m_lower_deps = DEP_IN_LOWER1 | DEP_IN_LOWER2; r_deps.m_upper_deps = DEP_IN_UPPER1 | DEP_IN_UPPER2 | DEP_IN_LOWER1; // we can replace DEP_IN_LOWER1 with DEP_IN_LOWER2 @@ -1075,11 +1076,11 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval // x <= b <= 0, 0 <= c <= y --> x*y <= b*c TRACE("interval_bug", tout << "(N, P) #" << call_id << "\n";); SASSERT(is_P(i2)); - - // must update upper_is_open first, since value of is_N0(i1) and is_P0(i2) may be affected by update + + // must update upper_is_open first, since value of is_N0(i1) and is_P0(i2) may be affected by update set_upper_is_open(r, (is_N0(i1) || is_P0(i2)) ? false : (b_o || c_o)); set_lower_is_open(r, a_o || d_o); - + round_to_minus_inf(); ::mul(m(), a, a_k, d, d_k, new_l_val, new_l_kind); round_to_plus_inf(); @@ -1093,7 +1094,7 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval TRACE("interval_bug", tout << "(M, N) #" << call_id << "\n";); set_lower_is_open(r, b_o || c_o); - set_upper_is_open(r, a_o || c_o); + set_upper_is_open(r, a_o || c_o); round_to_minus_inf(); ::mul(m(), b, b_k, c, c_k, new_l_val, new_l_kind); @@ -1110,7 +1111,7 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval bool bc_o = b_o || c_o; bool ac_o = a_o || c_o; bool bd_o = b_o || d_o; - + round_to_minus_inf(); ::mul(m(), a, a_k, d, d_k, ad, ad_k); ::mul(m(), b, b_k, c, c_k, bc, bc_k); @@ -1129,7 +1130,7 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval set_lower_is_open(r, bc_o); } - + if (::gt(m(), ac, ac_k, bd, bd_k) || (::eq(m(), ac, ac_k, bd, bd_k) && !ac_o && bd_o)) { m().swap(new_u_val, ac); new_u_kind = ac_k; @@ -1148,7 +1149,7 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval SASSERT(is_P(i2)); set_lower_is_open(r, a_o || d_o); - set_upper_is_open(r, b_o || d_o); + set_upper_is_open(r, b_o || d_o); round_to_minus_inf(); ::mul(m(), a, a_k, d, d_k, new_l_val, new_l_kind); @@ -1157,13 +1158,13 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval } } else { - SASSERT(is_P(i1)); + SASSERT(is_P(i1)); if (is_N(i2)) { // 0 <= a <= x <= b, c <= y <= d <= 0 --> x*y <= b*c (uses the fact that x is pos (a is not neg) or y is neg (d is not pos)) // 0 <= a <= x, y <= d <= 0 --> a*d <= x*y TRACE("interval_bug", tout << "(P, N) #" << call_id << "\n";); - - // must update upper_is_open first, since value of is_P0(i1) and is_N0(i2) may be affected by update + + // must update upper_is_open first, since value of is_P0(i1) and is_N0(i2) may be affected by update set_upper_is_open(r, (is_P0(i1) || is_N0(i2)) ? false : a_o || d_o); set_lower_is_open(r, b_o || c_o); @@ -1187,7 +1188,7 @@ void interval_manager::mul(interval const & i1, interval const & i2, interval } else { SASSERT(is_P(i2)); - // 0 <= a <= x, 0 <= c <= y --> a*c <= x*y + // 0 <= a <= x, 0 <= c <= y --> a*c <= x*y // x <= b, y <= d --> x*y <= b*d (uses the fact that x is pos (a is not negative) or y is pos (c is not negative)) TRACE("interval_bug", tout << "(P, P) #" << call_id << "\n";); @@ -1232,7 +1233,7 @@ void interval_manager::power_jst(interval const & a, unsigned n, interval_dep else if (upper_is_neg(a)) { // [l, u]^n = [u^n, l^n] if u < 0 // l <= x <= u < 0 --> x^n <= l^n (use lower and upper bound -- need the fact that x is negative) - // x <= u < 0 --> u^n <= x^n + // x <= u < 0 --> u^n <= x^n b_deps.m_lower_deps = DEP_IN_UPPER1; if (lower_is_inf(a)) b_deps.m_upper_deps = 0; @@ -1252,7 +1253,7 @@ void interval_manager::power_jst(interval const & a, unsigned n, interval_dep b_deps.m_lower_deps = 0; else b_deps.m_lower_deps = DEP_IN_LOWER1; - + if (upper_is_inf(a)) b_deps.m_upper_deps = 0; else @@ -1298,15 +1299,15 @@ void interval_manager::power(interval const & a, unsigned n, interval & b) { else if (upper_is_neg(a)) { // [l, u]^n = [u^n, l^n] if u < 0 // l <= x <= u < 0 --> x^n <= l^n (use lower and upper bound -- need the fact that x is negative) - // x <= u < 0 --> u^n <= x^n + // x <= u < 0 --> u^n <= x^n SASSERT(!upper_is_inf(a)); bool lower_a_open = lower_is_open(a), upper_a_open = upper_is_open(a); bool lower_a_inf = lower_is_inf(a); - + m().set(lower(b), lower(a)); m().set(upper(b), upper(a)); m().swap(lower(b), upper(b)); // we use a swap because a and b can be aliased - + round_to_minus_inf(); m().power(lower(b), n, lower(b)); @@ -1337,7 +1338,7 @@ void interval_manager::power(interval const & a, unsigned n, interval & b) { round_to_plus_inf(); ::power(m(), un1, un1_kind, n); ::power(m(), un2, un2_kind, n); - + if (::gt(m(), un1, un1_kind, un2, un2_kind) || (::eq(m(), un1, un1_kind, un2, un2_kind) && !lower_is_open(a) && upper_is_open(a))) { m().swap(upper(b), un1); set_upper_is_inf(b, un1_kind == EN_PLUS_INFINITY); @@ -1348,7 +1349,7 @@ void interval_manager::power(interval const & a, unsigned n, interval & b) { set_upper_is_inf(b, un2_kind == EN_PLUS_INFINITY); set_upper_is_open(b, upper_is_open(a)); } - + m().reset(lower(b)); set_lower_is_inf(b, false); set_lower_is_open(b, false); @@ -1359,8 +1360,8 @@ void interval_manager::power(interval const & a, unsigned n, interval & b) { if (lower_is_inf(a)) { reset_lower(b); } - else { - m().power(lower(a), n, lower(b)); + else { + m().power(lower(a), n, lower(b)); set_lower_is_inf(b, false); set_lower_is_open(b, lower_is_open(a)); } @@ -1409,7 +1410,7 @@ void interval_manager::nth_root(interval const & a, unsigned n, numeral const set_lower_is_open(b, lower_is_open(a) && m().eq(lo, hi)); m().set(lower(b), lo); } - + if (upper_is_inf(a)) { m().reset(upper(b)); set_upper_is_inf(b, true); @@ -1423,7 +1424,7 @@ void interval_manager::nth_root(interval const & a, unsigned n, numeral const set_upper_is_open(b, upper_is_open(a) && m().eq(lo, hi)); m().set(upper(b), hi); } - TRACE("interval_nth_root", display(tout, a); tout << " --> "; display(tout, b); tout << "\n";); + TRACE("interval_nth_root", display(tout, a); tout << " --> "; display(tout, b); tout << "\n";); } template @@ -1523,17 +1524,17 @@ void interval_manager::inv(interval const & a, interval & b) { numeral & new_l_val = m_result_lower; numeral & new_u_val = m_result_upper; ext_numeral_kind new_l_kind, new_u_kind; - + if (is_P1(a)) { // 0 < l <= x --> 1/x <= 1/l // 0 < l <= x <= u --> 1/u <= 1/x (use lower and upper bounds) - + round_to_minus_inf(); m().set(new_l_val, upper(a)); new_l_kind = upper_kind(a); ::inv(m(), new_l_val, new_l_kind); SASSERT(new_l_kind == EN_NUMERAL); bool new_l_open = upper_is_open(a); - + if (lower_is_zero(a)) { SASSERT(lower_is_open(a)); m().reset(upper(b)); @@ -1542,15 +1543,15 @@ void interval_manager::inv(interval const & a, interval & b) { } else { round_to_plus_inf(); - m().set(new_u_val, lower(a)); + m().set(new_u_val, lower(a)); m().inv(new_u_val); m().swap(upper(b), new_u_val); set_upper_is_inf(b, false); set_upper_is_open(b, lower_is_open(a)); } - - m().swap(lower(b), new_l_val); - set_lower_is_inf(b, false); + + m().swap(lower(b), new_l_val); + set_lower_is_inf(b, false); set_lower_is_open(b, new_l_open); } else if (is_N1(a)) { @@ -1577,8 +1578,8 @@ void interval_manager::inv(interval const & a, interval & b) { set_lower_is_inf(b, false); set_lower_is_open(b, upper_is_open(a)); } - - m().swap(upper(b), new_u_val); + + m().swap(upper(b), new_u_val); set_upper_is_inf(b, false); set_upper_is_open(b, new_u_open); } @@ -1610,12 +1611,12 @@ void interval_manager::div_jst(interval const & i1, interval const & i2, inte // x <= b <= 0, c <= y <= d < 0 --> b/c <= x/y // a <= x <= b <= 0, y <= d < 0 --> x/y <= a/d r_deps.m_lower_deps = DEP_IN_UPPER1 | DEP_IN_LOWER2 | DEP_IN_UPPER2; - r_deps.m_upper_deps = DEP_IN_LOWER1 | DEP_IN_UPPER2; + r_deps.m_upper_deps = DEP_IN_LOWER1 | DEP_IN_UPPER2; } else { // a <= x, a < 0, 0 < c <= y --> a/c <= x/y // x <= b <= 0, 0 < c <= y <= d --> x/y <= b/d - r_deps.m_lower_deps = DEP_IN_LOWER1 | DEP_IN_LOWER2; + r_deps.m_lower_deps = DEP_IN_LOWER1 | DEP_IN_LOWER2; r_deps.m_upper_deps = DEP_IN_UPPER1 | DEP_IN_LOWER2 | DEP_IN_UPPER2; } } @@ -1634,7 +1635,7 @@ void interval_manager::div_jst(interval const & i1, interval const & i2, inte } } else { - SASSERT(is_P(i1)); + SASSERT(is_P(i1)); if (is_N1(i2)) { // b > 0, x <= b, c <= y <= d < 0 --> b/d <= x/y // 0 <= a <= x, c <= y <= d < 0 --> x/y <= a/c @@ -1665,7 +1666,7 @@ void interval_manager::div(interval const & i1, interval const & i2, interval #endif SASSERT(!contains_zero(i2)); SASSERT(&i1 != &r); - + if (is_zero(i1)) { TRACE("interval_bug", tout << "div #" << call_id << "\n"; display(tout, i1); tout << "\n"; display(tout, i2); tout << "\n";); @@ -1682,12 +1683,12 @@ void interval_manager::div(interval const & i1, interval const & i2, interval numeral const & b = upper(i1); ext_numeral_kind b_k = upper_kind(i1); numeral const & c = lower(i2); ext_numeral_kind c_k = lower_kind(i2); numeral const & d = upper(i2); ext_numeral_kind d_k = upper_kind(i2); - + bool a_o = lower_is_open(i1); bool b_o = upper_is_open(i1); bool c_o = lower_is_open(i2); bool d_o = upper_is_open(i2); - + numeral & new_l_val = m_result_lower; numeral & new_u_val = m_result_upper; ext_numeral_kind new_l_kind, new_u_kind; @@ -1698,7 +1699,7 @@ void interval_manager::div(interval const & i1, interval const & i2, interval tout << "c: "; m().display(tout, c); tout << "\n"; tout << "d: "; m().display(tout, d); tout << "\n"; ); - + if (is_N(i1)) { if (is_N1(i2)) { // x <= b <= 0, c <= y <= d < 0 --> b/c <= x/y @@ -1707,7 +1708,7 @@ void interval_manager::div(interval const & i1, interval const & i2, interval set_lower_is_open(r, is_N0(i1) ? false : b_o || c_o); set_upper_is_open(r, a_o || d_o); - + round_to_minus_inf(); ::div(m(), b, b_k, c, c_k, new_l_val, new_l_kind); if (m().is_zero(d)) { @@ -1725,10 +1726,10 @@ void interval_manager::div(interval const & i1, interval const & i2, interval // x <= b <= 0, 0 < c <= y <= d --> x/y <= b/d TRACE("interval_bug", tout << "(N, P) #" << call_id << "\n";); SASSERT(is_P1(i2)); - + set_upper_is_open(r, is_N0(i1) ? false : (b_o || d_o)); set_lower_is_open(r, a_o || c_o); - + if (m().is_zero(c)) { SASSERT(c_o); m().reset(new_l_val); @@ -1747,10 +1748,10 @@ void interval_manager::div(interval const & i1, interval const & i2, interval // 0 < a <= x <= b < 0, y <= d < 0 --> b/d <= x/y // 0 < a <= x <= b < 0, y <= d < 0 --> x/y <= a/d TRACE("interval_bug", tout << "(M, N) #" << call_id << "\n";); - + set_lower_is_open(r, b_o || d_o); - set_upper_is_open(r, a_o || d_o); - + set_upper_is_open(r, a_o || d_o); + if (m().is_zero(d)) { SASSERT(d_o); m().reset(new_l_val); m().reset(new_u_val); @@ -1771,10 +1772,10 @@ void interval_manager::div(interval const & i1, interval const & i2, interval TRACE("interval_bug", tout << "(M, P) #" << call_id << "\n";); SASSERT(is_P1(i2)); - + set_lower_is_open(r, a_o || c_o); - set_upper_is_open(r, b_o || c_o); - + set_upper_is_open(r, b_o || c_o); + if (m().is_zero(c)) { SASSERT(c_o); m().reset(new_l_val); m().reset(new_u_val); @@ -1790,15 +1791,15 @@ void interval_manager::div(interval const & i1, interval const & i2, interval } } else { - SASSERT(is_P(i1)); + SASSERT(is_P(i1)); if (is_N1(i2)) { // b > 0, x <= b, c <= y <= d < 0 --> b/d <= x/y // 0 <= a <= x, c <= y <= d < 0 --> x/y <= a/c TRACE("interval_bug", tout << "(P, N) #" << call_id << "\n";); - + set_upper_is_open(r, is_P0(i1) ? false : a_o || c_o); set_lower_is_open(r, b_o || d_o); - + if (m().is_zero(d)) { SASSERT(d_o); m().reset(new_l_val); @@ -1816,10 +1817,10 @@ void interval_manager::div(interval const & i1, interval const & i2, interval // 0 <= a <= x, 0 < c <= y <= d --> a/d <= x/y // b > 0 x <= b, 0 < c <= y --> x/y <= b/c TRACE("interval_bug", tout << "(P, P) #" << call_id << "\n";); - + set_lower_is_open(r, is_P0(i1) ? false : a_o || d_o); set_upper_is_open(r, b_o || c_o); - + round_to_minus_inf(); ::div(m(), a, a_k, d, d_k, new_l_val, new_l_kind); if (m().is_zero(c)) { @@ -1833,7 +1834,7 @@ void interval_manager::div(interval const & i1, interval const & i2, interval } } } - + m().swap(lower(r), new_l_val); m().swap(upper(r), new_u_val); set_lower_is_inf(r, new_l_kind == EN_MINUS_INFINITY); @@ -1851,16 +1852,16 @@ void interval_manager::pi_series(int x, numeral & r, bool up) { _scoped_numeral f(m()); set_rounding(up); m().set(r, 4, 8*x + 1); - set_rounding(!up); + set_rounding(!up); m().set(f, 2, 8*x + 4); set_rounding(up); m().sub(r, f, r); - set_rounding(!up); + set_rounding(!up); m().set(f, 1, 8*x + 5); set_rounding(up); m().sub(r, f, r); set_rounding(!up); - m().set(f, 1, 8*x + 6); + m().set(f, 1, 8*x + 6); set_rounding(up); m().sub(r, f, r); m().set(f, 1, 16); @@ -1870,16 +1871,16 @@ void interval_manager::pi_series(int x, numeral & r, bool up) { template void interval_manager::pi(unsigned n, interval & r) { - // Compute an interval that contains pi using the series + // Compute an interval that contains pi using the series // P[0] + P[1] + ... + P[n] // where // P[n] := 1/16^x (4/(8x + 1) - 2/(8x + 4) - 1/(8x + 5) - 1/(8x + 6)) - // + // // The size of the interval is 1/15 * 1/(16^n) // // Lower is P[0] + P[1] + ... + P[n] // Upper is Lower + 1/15 * 1/(16^n) - + // compute size of the resulting interval round_to_plus_inf(); // overestimate size of the interval _scoped_numeral len(m()); @@ -1888,7 +1889,7 @@ void interval_manager::pi(unsigned n, interval & r) { m().power(len, n, len); m().set(p, 1, 15); m().mul(p, len, len); - + // compute lower bound numeral & l_val = m_result_lower; m().reset(l_val); @@ -1897,7 +1898,7 @@ void interval_manager::pi(unsigned n, interval & r) { round_to_minus_inf(); m().add(l_val, p, l_val); } - + // computer upper bound numeral & u_val = m_result_upper; if (m().precise()) { @@ -1959,7 +1960,7 @@ void interval_manager::e_series(unsigned k, bool upper, numeral & o) { template void interval_manager::e(unsigned k, interval & r) { // Store in r lower and upper bounds for Euler's constant. - // + // // The procedure uses the series // // V = 1 + 1/1 + 1/2! + 1/3! + ... + 1/k! @@ -1976,9 +1977,9 @@ void interval_manager::e(unsigned k, interval & r) { fact(k+1, error); round_to_plus_inf(); m().inv(error); // error == 1/(k+1)! - m().set(aux, 4); + m().set(aux, 4); m().mul(aux, error, error); // error == 4/(k+1)! - + if (m().precise()) { m().set(hi, lo); m().add(hi, error, hi); diff --git a/src/math/polynomial/algebraic_numbers.cpp b/src/math/polynomial/algebraic_numbers.cpp index 5d6779d21..e00c1f29f 100644 --- a/src/math/polynomial/algebraic_numbers.cpp +++ b/src/math/polynomial/algebraic_numbers.cpp @@ -26,6 +26,7 @@ Notes: #include"mpbqi.h" #include"timeit.h" #include"algebraic_params.hpp" +#include"common_msgs.h" namespace algebraic_numbers { @@ -36,9 +37,9 @@ namespace algebraic_numbers { // Each algebraic number is associated with two // isolating (refinable) intervals. The second // interval just caches refinements of the first one. - + struct algebraic_cell { - // polynomial + // polynomial unsigned m_p_sz; mpz * m_p; mpbqi m_interval; // isolating/refinable interval @@ -61,7 +62,7 @@ namespace algebraic_numbers { algebraic_params::collect_param_descrs(r); } - struct manager::imp { + struct manager::imp { reslimit& m_limit; manager & m_wrapper; small_object_allocator & m_allocator; @@ -72,9 +73,9 @@ namespace algebraic_numbers { upoly_manager m_upmanager; mpq m_zero; scoped_mpz m_is_rational_tmp; - scoped_upoly m_isolate_tmp1; - scoped_upoly m_isolate_tmp2; - scoped_upoly m_isolate_tmp3; + scoped_upoly m_isolate_tmp1; + scoped_upoly m_isolate_tmp2; + scoped_upoly m_isolate_tmp3; scoped_upoly m_eval_sign_tmp; factors m_isolate_factors; scoped_mpbq_vector m_isolate_roots; @@ -83,14 +84,14 @@ namespace algebraic_numbers { scoped_upoly m_add_tmp; polynomial::var m_x; polynomial::var m_y; - + // configuration int m_min_magnitude; bool m_factor; polynomial::factor_params m_factor_params; int m_zero_accuracy; - // statistics + // statistics unsigned m_compare_cheap; unsigned m_compare_sturm; unsigned m_compare_refine; @@ -123,10 +124,10 @@ namespace algebraic_numbers { ~imp() { } - + void checkpoint() { if (!m_limit.inc()) - throw algebraic_exception("canceled"); + throw algebraic_exception(Z3_CANCELED_MSG); cooperate("algebraic"); } @@ -156,10 +157,10 @@ namespace algebraic_numbers { m_zero_accuracy = -static_cast(p.zero_accuracy()); } - unsynch_mpq_manager & qm() { - return m_qmanager; + unsynch_mpq_manager & qm() { + return m_qmanager; } - + mpbq_manager & bqm() { return m_bqmanager; } @@ -204,7 +205,7 @@ namespace algebraic_numbers { return; if (a.is_basic()) del(a.to_basic()); - else + else del(a.to_algebraic()); a.m_cell = 0; } @@ -212,7 +213,7 @@ namespace algebraic_numbers { void reset(numeral & a) { del(a); } - + bool is_zero(numeral const & a) { return a.m_cell == 0; } @@ -220,14 +221,14 @@ namespace algebraic_numbers { bool is_pos(numeral const & a) { if (a.is_basic()) return qm().is_pos(basic_value(a)); - else + else return bqim().is_pos(a.to_algebraic()->m_interval); } bool is_neg(numeral const & a) { if (a.is_basic()) return qm().is_neg(basic_value(a)); - else + else return bqim().is_neg(a.to_algebraic()->m_interval); } @@ -238,26 +239,26 @@ namespace algebraic_numbers { else return a.to_basic()->m_value; } - + bool is_int(numeral & a) { if (a.is_basic()) return qm().is_int(basic_value(a)); if (a.to_algebraic()->m_not_rational) return false; // we know for sure a is not a rational (and consequently an integer) - // make sure the isolating interval has at most one integer + // make sure the isolating interval has at most one integer if (!refine_until_prec(a, 1)) { SASSERT(a.is_basic()); // a became basic return qm().is_int(basic_value(a)); } - + // Find unique integer in the isolating interval algebraic_cell * c = a.to_algebraic(); scoped_mpz candidate(qm()); bqm().floor(qm(), upper(c), candidate); - + SASSERT(bqm().ge(upper(c), candidate)); - + if (bqm().lt(lower(c), candidate) && upm().eval_sign_at(c->m_p_sz, c->m_p, candidate) == 0) { m_wrapper.set(a, candidate); return true; @@ -272,10 +273,10 @@ namespace algebraic_numbers { Thus, we can find whether a non-basic number is actually a rational by using the Rational root theorem. - + p/q is a root of a_n * x^n + ... + a_0 If p is a factor of a_0, and q is a factor of a_n. - + If the isolating interval (lower, upper) has size less than 1/a_n, then (a_n*lower, a_n*upper) contains at most one integer. Let u be this integer, then the non-basic number is a rational iff @@ -297,7 +298,7 @@ namespace algebraic_numbers { // 1/2^{log2(a_n)+1} <= 1/a_n unsigned k = qm().log2(abs_a_n); k++; - + TRACE("algebraic_bug", tout << "abs(an): " << qm().to_string(abs_a_n) << ", k: " << k << "\n";); // make sure the isolating interval size is less than 1/2^k @@ -319,7 +320,7 @@ namespace algebraic_numbers { scoped_mpq candidate(qm()); qm().set(candidate, zcandidate, abs_a_n); SASSERT(bqm().ge(upper(c), candidate)); - + // Find if candidate is an actual root if (bqm().lt(lower(c), candidate) && upm().eval_sign_at(c->m_p_sz, c->m_p, candidate) == 0) { saved_a.restore_if_too_small(); @@ -378,7 +379,7 @@ namespace algebraic_numbers { mpbq & upper(algebraic_cell * c) { return c->m_interval.upper(); } - + void update_sign_lower(algebraic_cell * c) { int sl = upm().eval_sign_at(c->m_p_sz, c->m_p, lower(c)); // The isolating intervals are refinable. Thus, the polynomial has opposite signs at lower and upper. @@ -417,7 +418,7 @@ namespace algebraic_numbers { normalize_coeffs(c); return c; } - + void set(numeral & a, mpq & n) { if (qm().is_zero(n)) { reset(a); @@ -441,7 +442,7 @@ namespace algebraic_numbers { qm().set(tmp, n); set(a, tmp); } - + void copy_poly(algebraic_cell * c, unsigned sz, mpz const * p) { SASSERT(c->m_p == 0); SASSERT(c->m_p_sz == 0); @@ -461,7 +462,7 @@ namespace algebraic_numbers { bqim().set(c->m_interval, l, u); } - // Copy fields from source to target. + // Copy fields from source to target. // It assumes that fields target->m_p is NULL or was deleted. void copy(algebraic_cell * target, algebraic_cell const * source) { copy_poly(target, source->m_p_sz, source->m_p); @@ -543,7 +544,7 @@ namespace algebraic_numbers { return upm().factor(up, r, m_factor_params); } else { - scoped_upoly & up_sqf = m_isolate_tmp3; + scoped_upoly & up_sqf = m_isolate_tmp3; up_sqf.reset(); upm().square_free(up.size(), up.c_ptr(), up_sqf); TRACE("anum_bug", upm().display(tout, up_sqf.size(), up_sqf.c_ptr()); tout << "\n";); @@ -563,7 +564,7 @@ namespace algebraic_numbers { void sort_roots(numeral_vector & r) { std::sort(r.begin(), r.end(), lt_proc(m_wrapper)); } - + void isolate_roots(scoped_upoly const & up, numeral_vector & roots) { if (up.empty()) return; // ignore the zero polynomial @@ -572,7 +573,7 @@ namespace algebraic_numbers { bool full_fact; if (upm().has_zero_roots(up.size(), up.c_ptr())) { roots.push_back(numeral()); - scoped_upoly & nz_up = m_isolate_tmp2; + scoped_upoly & nz_up = m_isolate_tmp2; upm().remove_zero_roots(up.size(), up.c_ptr(), nz_up); full_fact = factor(nz_up, fs); } @@ -594,7 +595,7 @@ namespace algebraic_numbers { // set r <- -b/a qm().set(r, f[0]); qm().div(r, f[1], r); - qm().neg(r); + qm().neg(r); roots.push_back(numeral(mk_basic_cell(r))); continue; } @@ -628,7 +629,7 @@ namespace algebraic_numbers { } sort_roots(roots); } - + void isolate_roots(polynomial_ref const & p, numeral_vector & roots) { SASSERT(is_univariate(p)); TRACE("algebraic", tout << "isolating roots of: " << p << "\n";); @@ -705,7 +706,7 @@ namespace algebraic_numbers { return bqm().magnitude_ub(l); if (bqm().is_nonneg(l)) return qm().log2(u.numerator()) - qm().log2(l.numerator()) - u_k + l_k - u_k; - else + else return qm().mlog2(u.numerator()) - qm().mlog2(l.numerator()) - u_k + l_k - u_k; } @@ -719,7 +720,7 @@ namespace algebraic_numbers { /** \brief Refine isolating interval associated with algebraic number. The new interval will half of the size of the original one. - + Return TRUE, if interval was refined Return FALSE, if actual root was found. */ @@ -736,7 +737,7 @@ namespace algebraic_numbers { Remark: a root object may become basic when invoking this method, since we may find the actual rational root. - This can only happen when non minimal polynomials are used to + This can only happen when non minimal polynomials are used to encode root objects. */ bool refine(numeral & a) { @@ -777,12 +778,12 @@ namespace algebraic_numbers { } /** - Functor for computing the polynomial + Functor for computing the polynomial resultant_y(pa(x-y), pb(y)) where pa and pb are the polynomials for algebraic cells: a and b. - - Remark: If alpha and beta are roots of pa and pb, then + + Remark: If alpha and beta are roots of pa and pb, then alpha + beta is a root of the new polynomial. Remark: If the argument IsAdd == false, then the @@ -791,9 +792,9 @@ namespace algebraic_numbers { template struct mk_add_polynomial { imp & m; - + mk_add_polynomial(imp & _m):m(_m) {} - + void operator()(algebraic_cell * a, algebraic_cell * b, scoped_upoly & r) const { polynomial_ref pa_x(m.pm()); // pa(x) polynomial_ref pa_x_y(m.pm()); // pa(x-y) for addition and pa(x+y) for subtraction @@ -811,7 +812,7 @@ namespace algebraic_numbers { }; /** - Functor for computing the polynomial + Functor for computing the polynomial resultant_y(y^n * pa(x/y), pb(y)) where pa and pb are the polynomials for algebraic cells: a and b. @@ -819,12 +820,12 @@ namespace algebraic_numbers { */ struct mk_mul_polynomial { imp & m; - + mk_mul_polynomial(imp & _m):m(_m) {} - + void operator()(algebraic_cell * a, algebraic_cell * b, scoped_upoly & r) const { polynomial_ref pa_x(m.pm()); // pa(x) - polynomial_ref pa_x_div_y(m.pm()); // y^n * pa(x/y) + polynomial_ref pa_x_div_y(m.pm()); // y^n * pa(x/y) polynomial_ref pb_y(m.pm()); // pb(y) polynomial_ref r_x(m.pm()); // r(x) = resultant_y(y^n * pa(x/y), pb(y)) pa_x = m.pm().to_polynomial(a->m_p_sz, a->m_p, m.m_x); @@ -842,9 +843,9 @@ namespace algebraic_numbers { struct add_interval_proc { imp & m; add_interval_proc(imp & _m):m(_m) {} - + void operator()(algebraic_cell * a, algebraic_cell * b, mpbqi & r) const { - if (IsAdd) + if (IsAdd) m.bqim().add(a->m_interval, b->m_interval, r); else m.bqim().sub(a->m_interval, b->m_interval, r); @@ -857,7 +858,7 @@ namespace algebraic_numbers { struct mul_interval_proc { imp & m; mul_interval_proc(imp & _m):m(_m) {} - + void operator()(algebraic_cell * a, algebraic_cell * b, mpbqi & r) const { m.bqim().mul(a->m_interval, b->m_interval, r); } @@ -904,13 +905,13 @@ namespace algebraic_numbers { SASSERT(!num.is_basic()); m_owner.bqim().set(m_old_interval, num.to_algebraic()->m_interval); } - + ~save_intervals() { if (!m_restore_invoked) restore_if_too_small(); m_owner.bqim().del(m_old_interval); } - + // Restore the intervals of m_cell, if its current magnitude is too small void restore_if_too_small() { m_restore_invoked = true; @@ -960,7 +961,7 @@ namespace algebraic_numbers { } SASSERT(bqm().lt(r_i.lower(), r_i.upper())); } - + // make sure 0 is not a root of p scoped_upoly & nz_p = m_add_tmp; if (upm().has_zero_roots(p.size(), p.c_ptr())) { @@ -970,7 +971,7 @@ namespace algebraic_numbers { else { p.swap(nz_p); } - + if (!upm().isolating2refinable(nz_p.size(), nz_p.c_ptr(), bqm(), r_i.lower(), r_i.upper())) { // found actual root scoped_mpq r(qm()); @@ -985,7 +986,7 @@ namespace algebraic_numbers { /** \brief Apply a binary operation on the given algebraic numbers. - + \pre !a.is_basic() and !b.is_basic() The template arguments: @@ -1019,17 +1020,17 @@ namespace algebraic_numbers { seqs.push_back(seq); } SASSERT(seqs.size() == num_fs); - + save_intervals saved_a(*this, a); save_intervals saved_b(*this, b); scoped_mpbqi r_i(bqim()); - + while (true) { checkpoint(); SASSERT(!a.is_basic()); SASSERT(!b.is_basic()); mk_interval(cell_a, cell_b, r_i); - + unsigned num_rem = 0; // number of remaining sequences unsigned target_i = UINT_MAX; // index of sequence that is isolating int target_lV, target_uV; @@ -1059,7 +1060,7 @@ namespace algebraic_numbers { num_rem++; } } - + if (num_rem == 1 && target_i != UINT_MAX) { // found isolating interval TRACE("anum_mk_binary", tout << "target_i: " << target_i << "\n";); @@ -1069,7 +1070,7 @@ namespace algebraic_numbers { set_core(c, f, r_i, *(seqs[target_i]), target_lV, target_uV, full_fact); return; } - + if (!refine(a) || !refine(b)) { // a or b became basic SASSERT(a.is_basic() || b.is_basic()); @@ -1102,12 +1103,12 @@ namespace algebraic_numbers { save_intervals saved_a(*this, a); scoped_mpbqi r_i(bqim()); - + while (true) { checkpoint(); SASSERT(!a.is_basic()); mk_interval(cell_a, r_i); - + unsigned num_rem = 0; // number of remaining sequences unsigned target_i = UINT_MAX; // index of sequence that is isolating int target_lV, target_uV; @@ -1154,7 +1155,7 @@ namespace algebraic_numbers { } /** - Functor for computing the polynomial + Functor for computing the polynomial resultant_y(x^k - y, pa(y)) where pa is the polynomial for algebraic cell: a. @@ -1169,17 +1170,17 @@ namespace algebraic_numbers { void operator()(algebraic_cell * a, scoped_upoly & r) const { // Let p be the polynomial associated with a. // Then, r(x) := Resultant(x^k - y, p(y), y) - // is a polynomial s.t. a^{1/k} is a root of r(x). - + // is a polynomial s.t. a^{1/k} is a root of r(x). + // Create r(x) polynomial_ref p_y(m.pm()); polynomial_ref xk_y(m.pm()); polynomial_ref y(m.pm()); polynomial_ref r_x(m.pm()); p_y = m.pm().to_polynomial(a->m_p_sz, a->m_p, m.m_y); - y = m.pm().mk_polynomial(m.m_y); + y = m.pm().mk_polynomial(m.m_y); xk_y = m.pm().mk_polynomial(m.m_x, k); - xk_y = xk_y - y; + xk_y = xk_y - y; m.pm().resultant(xk_y, p_y, m.m_y, r_x); m.upm().to_numeral_vector(r_x, r); } @@ -1192,13 +1193,13 @@ namespace algebraic_numbers { imp & m; unsigned k; root_interval_proc(imp & _m, unsigned _k):m(_m), k(_k) {} - + void operator()(algebraic_cell * a, mpbqi & r) const { m.bqm().root_lower(m.lower(a), k, r.lower()); m.bqm().root_upper(m.upper(a), k, r.upper()); } }; - + /** \brief Functor for b <- a^{1/k} */ @@ -1206,13 +1207,13 @@ namespace algebraic_numbers { imp & m; unsigned k; root_proc(imp & _m, unsigned _k):m(_m), k(_k) {} - void operator()(numeral & a, numeral & b) const { - return m.root(a, k, b); + void operator()(numeral & a, numeral & b) const { + return m.root(a, k, b); } }; - + /** - Functor for computing the polynomial + Functor for computing the polynomial resultant_y(x - y^k, pa(y)) where pa is the polynomial for algebraic cell: a. @@ -1230,7 +1231,7 @@ namespace algebraic_numbers { polynomial_ref x_yk(m.pm()); polynomial_ref r_x(m.pm()); p_y = m.pm().to_polynomial(a->m_p_sz, a->m_p, m.m_y); - x = m.pm().mk_polynomial(m.m_x); + x = m.pm().mk_polynomial(m.m_x); x_yk = m.pm().mk_polynomial(m.m_y, k); x_yk = x - x_yk; m.pm().resultant(x_yk, p_y, m.m_y, r_x); @@ -1245,7 +1246,7 @@ namespace algebraic_numbers { imp & m; unsigned k; power_interval_proc(imp & _m, unsigned _k):m(_m), k(_k) {} - + void operator()(algebraic_cell * a, mpbqi & r) const { m.bqim().power(a->m_interval, k, r); } @@ -1259,18 +1260,18 @@ namespace algebraic_numbers { unsigned k; power_proc(imp & _m, unsigned _k):m(_m), k(_k) {} - void operator()(numeral & a, numeral & b) const { - return m.power(a, k, b); + void operator()(numeral & a, numeral & b) const { + return m.power(a, k, b); } }; - + void root_core(basic_cell * a, unsigned k, numeral & b) { SASSERT(!qm().is_zero(a->m_value)); SASSERT(k > 1); mpq & a_val = a->m_value; scoped_mpq r_a_val(qm()); - + if (qm().root(a_val, k, r_a_val)) { // the result is rational TRACE("root_core", tout << "r_a_val: " << r_a_val << " a_val: "; qm().display(tout, a_val); tout << "\n";); @@ -1280,18 +1281,18 @@ namespace algebraic_numbers { // Let a_val be of the form n/d // create polynomial p: d*x^k - n - // a_val > 0 --> (0, a_val+1) is an isolating interval + // a_val > 0 --> (0, a_val+1) is an isolating interval // a_val < 0 --> (a_val-1, 0) is an isolating interval - + // Create p scoped_upoly p(upm()); p.push_back(mpz()); qm().set(p.back(), a_val.numerator()); qm().neg(p.back()); - for (unsigned i = 0; i < k; i++) + for (unsigned i = 0; i < k; i++) p.push_back(mpz()); qm().set(p.back(), a_val.denominator()); - + // Create isolating interval scoped_mpbq lower(bqm()); scoped_mpbq upper(bqm()); @@ -1329,12 +1330,12 @@ namespace algebraic_numbers { } if (is_neg(a) && k % 2 == 0) { - // Remark: some computer algebra systems (e.g., Mathematica) define the + // Remark: some computer algebra systems (e.g., Mathematica) define the // k-th root of a negative number as a complex number for any k. // We should check if our definition will not confuse users. throw algebraic_exception("even root of negative number is not real"); } - + if (a.is_basic()) root_core(a.to_basic(), k, b); else @@ -1367,11 +1368,11 @@ namespace algebraic_numbers { qm().power(basic_value(a), k, r); set(b, r); } - else { + else { mk_unary(a, b, mk_power_polynomial(*this, k), power_interval_proc(*this, k), power_proc(*this, k)); } } - + void add(basic_cell * a, basic_cell * b, numeral & c) { scoped_mpq r(qm()); qm().add(basic_value(a), basic_value(b), r); @@ -1393,12 +1394,12 @@ namespace algebraic_numbers { tout << "b: "; qm().display(tout, b->m_value); tout << "\n";); scoped_mpq nbv(qm()); qm().set(nbv, b->m_value); - if (IsAdd) + if (IsAdd) qm().neg(nbv); m_add_tmp.reset(); upm().translate_q(a->m_p_sz, a->m_p, nbv, m_add_tmp); mpbqi const & i = a->m_interval; - scoped_mpbq l(bqm()); + scoped_mpbq l(bqm()); scoped_mpbq u(bqm()); qm().neg(nbv); if (bqm().to_mpbq(nbv, l)) { @@ -1411,7 +1412,7 @@ namespace algebraic_numbers { scoped_mpq iu(qm()); to_mpq(qm(), i.lower(), il); to_mpq(qm(), i.upper(), iu); - TRACE("algebraic", + TRACE("algebraic", tout << "nbv: " << nbv << "\n"; tout << "il: " << il << ", iu: " << iu << "\n";); qm().add(il, nbv, il); @@ -1419,7 +1420,7 @@ namespace algebraic_numbers { // (il, iu) is an isolating refinable (rational) interval for the new polynomial. upm().convert_q2bq_interval(m_add_tmp.size(), m_add_tmp.c_ptr(), il, iu, bqm(), l, u); } - TRACE("algebraic", + TRACE("algebraic", upm().display(tout, m_add_tmp.size(), m_add_tmp.c_ptr()); tout << ", l: " << l << ", u: " << u << "\n"; tout << "l_sign: " << upm().eval_sign_at(m_add_tmp.size(), m_add_tmp.c_ptr(), l) << "\n"; @@ -1441,7 +1442,7 @@ namespace algebraic_numbers { } if (a.is_basic()) { - if (b.is_basic()) + if (b.is_basic()) add(a.to_basic(), b.to_basic(), c); else add(b.to_algebraic(), a.to_basic(), c); @@ -1467,7 +1468,7 @@ namespace algebraic_numbers { } if (a.is_basic()) { - if (b.is_basic()) + if (b.is_basic()) sub(a.to_basic(), b.to_basic(), c); else { // c <- b - a @@ -1503,7 +1504,7 @@ namespace algebraic_numbers { upm().set(a->m_p_sz, a->m_p, mulp); upm().compose_p_q_x(mulp.size(), mulp.c_ptr(), nbv); mpbqi const & i = a->m_interval; - scoped_mpbq l(bqm()); + scoped_mpbq l(bqm()); scoped_mpbq u(bqm()); qm().inv(nbv); bool is_neg = qm().is_neg(nbv); @@ -1519,7 +1520,7 @@ namespace algebraic_numbers { scoped_mpq iu(qm()); to_mpq(qm(), i.lower(), il); to_mpq(qm(), i.upper(), iu); - TRACE("algebraic", + TRACE("algebraic", tout << "nbv: " << nbv << "\n"; tout << "il: " << il << ", iu: " << iu << "\n";); qm().mul(il, nbv, il); @@ -1529,7 +1530,7 @@ namespace algebraic_numbers { // (il, iu) is an isolating refinable (rational) interval for the new polynomial. upm().convert_q2bq_interval(mulp.size(), mulp.c_ptr(), il, iu, bqm(), l, u); } - TRACE("algebraic", + TRACE("algebraic", upm().display(tout, mulp.size(), mulp.c_ptr()); tout << ", l: " << l << ", u: " << u << "\n"; tout << "l_sign: " << upm().eval_sign_at(mulp.size(), mulp.c_ptr(), l) << "\n"; @@ -1546,13 +1547,13 @@ namespace algebraic_numbers { } if (a.is_basic()) { - if (b.is_basic()) + if (b.is_basic()) mul(a.to_basic(), b.to_basic(), c); else mul(b.to_algebraic(), a.to_basic(), c); } else { - if (b.is_basic()) + if (b.is_basic()) mul(a.to_algebraic(), b.to_basic(), c); else mk_binary(a, b, c, mk_mul_polynomial(*this), mul_interval_proc(*this), mul_proc(*this)); @@ -1572,7 +1573,7 @@ namespace algebraic_numbers { update_sign_lower(c); } } - + /** Make sure lower != 0 and upper != 0 if a is non-basic algebraic number. */ @@ -1587,7 +1588,7 @@ namespace algebraic_numbers { int sign_l = sign_lower(cell_a); SASSERT(sign_l != 0); int sign_u = -sign_l; - + #define REFINE_LOOP(BOUND, TARGET_SIGN) \ while (true) { \ bqm().div2(BOUND); \ @@ -1628,9 +1629,9 @@ namespace algebraic_numbers { algebraic_cell * cell_a = a.to_algebraic(); upm().p_1_div_x(cell_a->m_p_sz, cell_a->m_p); // convert binary rational bounds into rational bounds - scoped_mpq inv_lower(qm()), inv_upper(qm()); - to_mpq(qm(), lower(cell_a), inv_lower); - to_mpq(qm(), upper(cell_a), inv_upper); + scoped_mpq inv_lower(qm()), inv_upper(qm()); + to_mpq(qm(), lower(cell_a), inv_lower); + to_mpq(qm(), upper(cell_a), inv_upper); // (1/upper, 1/lower) is an isolating interval for the new polynomial qm().inv(inv_lower); qm().inv(inv_upper); @@ -1652,8 +1653,8 @@ namespace algebraic_numbers { // It is also useful to allow users to evaluate expressions containing algebraic numbers. // // We can avoid computing invb, by having a procedure similar to mul - // that uses - // Resultant(pa(xy), pb(y), y) instead of + // that uses + // Resultant(pa(xy), pb(y), y) instead of // Resultant(y^n * pa(x/y), pb(y), y) // scoped_anum invb(m_wrapper); @@ -1679,7 +1680,7 @@ namespace algebraic_numbers { p(b) < 0 --> If p(l) < 0 then c > b else c < b p(b) == 0 --> c = b p(b) > 0 --> if p(l) < 0 then c < b else c > b - + We can simplify the rules above as: p(b) == 0 then c == b (p(b) < 0) == (p(l) < 0) then c > b else c < b @@ -1697,7 +1698,7 @@ namespace algebraic_numbers { return 0; return sign_b == sign_lower(c) ? 1 : -1; } - + // Return true if the polynomials of cell_a and cell_b are the same. bool compare_p(algebraic_cell const * cell_a, algebraic_cell const * cell_b) { return upm().eq(cell_a->m_p_sz, cell_a->m_p, cell_b->m_p_sz, cell_b->m_p); @@ -1723,7 +1724,7 @@ namespace algebraic_numbers { } COMPARE_INTERVAL(); - + // if cell_a and cell_b, contain the same polynomial, // and the intervals are overlaping, then they are // the same root. @@ -1733,19 +1734,19 @@ namespace algebraic_numbers { } TRACE("algebraic", tout << "comparing\n"; - tout << "a: "; upm().display(tout, cell_a->m_p_sz, cell_a->m_p); tout << "\n"; bqim().display(tout, cell_a->m_interval); + tout << "a: "; upm().display(tout, cell_a->m_p_sz, cell_a->m_p); tout << "\n"; bqim().display(tout, cell_a->m_interval); tout << "\ncell_a->m_minimal: " << cell_a->m_minimal << "\n"; - tout << "b: "; upm().display(tout, cell_b->m_p_sz, cell_b->m_p); tout << "\n"; bqim().display(tout, cell_b->m_interval); + tout << "b: "; upm().display(tout, cell_b->m_p_sz, cell_b->m_p); tout << "\n"; bqim().display(tout, cell_b->m_interval); tout << "\ncell_b->m_minimal: " << cell_b->m_minimal << "\n";); - + if (cell_a->m_minimal && cell_b->m_minimal) { // Minimal polynomial special case. // This branch is only executed when polynomial // factorization is turned on. // If a and b are defined by minimal distinct polynomials, - // then they MUST BE DIFFERENT. - // Thus, if we keep refining the interval of a and b, + // then they MUST BE DIFFERENT. + // Thus, if we keep refining the interval of a and b, // eventually they will not overlap while (true) { checkpoint(); @@ -1760,7 +1761,7 @@ namespace algebraic_numbers { COMPARE_INTERVAL(); } } - + // make sure that intervals of a and b have the same magnitude int a_m = magnitude(a_lower, a_upper); int b_m = magnitude(b_lower, b_upper); @@ -1777,7 +1778,7 @@ namespace algebraic_numbers { m_compare_refine += a_m - target_m; COMPARE_INTERVAL(); } - + if (target_m > m_min_magnitude) { int num_refinements = target_m - m_min_magnitude; for (int i = 0; i < num_refinements; i++) { @@ -1787,9 +1788,9 @@ namespace algebraic_numbers { COMPARE_INTERVAL(); } } - + // EXPENSIVE CASE - // Let seq be the Sturm-Tarski sequence for + // Let seq be the Sturm-Tarski sequence for // p_a, p_a' * p_b // Let s_l be the number of sign variations at a_lower. // Let s_u be the number of sign variations at a_upper. @@ -1798,14 +1799,14 @@ namespace algebraic_numbers { // Since there is only one root of p_a in (a_lower, b_lower), // we are evaluating the sign of p_b at a. // That is V is the sign of p_b at a. - // + // // We have // V < 0 -> p_b(a) < 0 -> if p_b(b_lower) < 0 then b > a else b < a // V == 0 -> p_b(a) == 0 -> a = b // V > 0 -> p_b(a) > 0 -> if p_b(b_lower) > 0 then b > a else b < a // Simplifying we have: // V == 0 --> a = b - // if (V < 0) == (p_b(b_lower) < 0) then b > a else b < a + // if (V < 0) == (p_b(b_lower) < 0) then b > a else b < a // m_compare_sturm++; upolynomial::scoped_upolynomial_sequence seq(upm()); @@ -1819,9 +1820,9 @@ namespace algebraic_numbers { return -1; else return 1; - + // Here is an unexplored option for comparing numbers. - // + // // The isolating intervals of a and b are still overlaping // Then we compute // r(x) = Resultant(x - y1 + y2, p1(y1), p2(y2)) @@ -1837,23 +1838,23 @@ namespace algebraic_numbers { // 3) If 0 is not a root of r(x), then a != b (by remark 2) // // 4) Let (l1, u1) and (l2, u2) be the intervals of a and b. - // Then, a - b must be in (l1 - u2, u1 - l2) - // + // Then, a - b must be in (l1 - u2, u1 - l2) + // // 5) Assume a != b, then if we keep refining the isolating intervals for a and b, // then eventually, (l1, u1) and (l2, u2) will not overlap. - // Thus, if 0 is not a root of r(x), we can keep refining until + // Thus, if 0 is not a root of r(x), we can keep refining until // the intervals do not overlap. // // 6) If 0 is a root of r(x), we have two possibilities: // a) Isolate roots of r(x) in the interval (l1 - u2, u1 - l2), // and then keep refining (l1, u1) and (l2, u2) until they // (l1 - u2, u1 - l2) "convers" only one root. - // + // // b) Compute the sturm sequence for r(x), // keep refining the (l1, u1) and (l2, u2) until // (l1 - u2, u1 - l2) contains only one root of r(x) } - + int compare(numeral & a, numeral & b) { TRACE("algebraic", tout << "comparing: "; display_interval(tout, a); tout << " "; display_interval(tout, b); tout << "\n";); if (a.is_basic()) { @@ -1863,13 +1864,13 @@ namespace algebraic_numbers { return -compare(b.to_algebraic(), basic_value(a)); } else { - if (b.is_basic()) + if (b.is_basic()) return compare(a.to_algebraic(), basic_value(b)); else return compare_core(a, b); } } - + bool eq(numeral & a, numeral & b) { return compare(a, b) == 0; } @@ -1921,7 +1922,7 @@ namespace algebraic_numbers { } /** - \brief "Optimistic" mapping: it assumes all variables are mapped to + \brief "Optimistic" mapping: it assumes all variables are mapped to basic_values (rationals). Throws an exception if that is not the case. */ struct opt_var2basic : public polynomial::var2mpq { @@ -1955,7 +1956,7 @@ namespace algebraic_numbers { return m_imp.basic_value(v); } }; - + /** \brief Reduced mapping which contains only the non-basic values as intervals */ @@ -1989,24 +1990,24 @@ namespace algebraic_numbers { catch (opt_var2basic::failed) { // continue } - + // Eliminate rational values from p polynomial_ref p_prime(ext_pm); var2basic x2v_basic(*this, x2v); p_prime = ext_pm.substitute(p, x2v_basic); TRACE("anum_eval_sign", tout << "p after eliminating rationals: " << p_prime << "\n";); - + if (ext_pm.is_zero(p_prime)) { // polynomial vanished after substituting rational values. return 0; } - + if (is_const(p_prime)) { // polynomial became the constant polynomial after substitution. SASSERT(size(p_prime) == 1); return ext_pm.m().sign(ext_pm.coeff(p_prime, 0)); } - + // Try to find sign using intervals polynomial::var_vector & xs = m_eval_sign_vars; xs.reset(); @@ -2014,7 +2015,7 @@ namespace algebraic_numbers { SASSERT(!xs.empty()); var2interval x2v_interval(*this, x2v); scoped_mpbqi ri(bqim()); - + while (true) { checkpoint(); ext_pm.eval(p_prime, x2v_interval, ri); @@ -2047,7 +2048,7 @@ namespace algebraic_numbers { break; } } - + if (restart) { // Some non-basic value became basic. // So, restarting the whole process @@ -2056,7 +2057,7 @@ namespace algebraic_numbers { } // At this point, we are almost sure that p is zero at x2n - // That is, rin is probably a very small interval that contains zero. + // That is, rin is probably a very small interval that contains zero. // Remark: m_zero_accuracy == 0 means use precise computation. if (m_zero_accuracy > 0) { @@ -2074,19 +2075,19 @@ namespace algebraic_numbers { #else // Evaluating the sign using Resultants // Basic idea: - // We want to evaluate the sign of + // We want to evaluate the sign of // p(x_1, ..., x_n) // at x_1 -> v_1, ..., x_n -> v_n // - // Let v be p(v_1, ..., v_n). + // Let v be p(v_1, ..., v_n). // We want to know the sign of v. - // + // // Assume v_i's are defined by the polynomials q_i(x_i) // Then, we have that // the polynomials // y - p(x_1, ..., x_n), q_1(x_1), ..., q_n(x_n) - // are zero at y -> v, x_1 -> v_1, ..., x_n -> v_n - // + // are zero at y -> v, x_1 -> v_1, ..., x_n -> v_n + // // Thus, by resultant theory, v is also a root of // R(y) = Resultant(p(x_1, ..., x_n), q_1(x_1), ..., q_n(x_n)) // Remark: R(y) is not the zero polynomial, since @@ -2095,7 +2096,7 @@ namespace algebraic_numbers { // // Now, let L be a lower bound on the nonzero roots of R(y). // Thus, any root alpha of R(y) is zero or |alpha| > L - // + // // Therefore, we have that |v| > L // Now, using L, we can keep refining the interval ri which contains v. // Eventually, ri will not contain zero (and consequently v != 0), @@ -2165,7 +2166,7 @@ namespace algebraic_numbers { if (bqm().lt(mL, ri.lower()) && bqm().lt(ri.upper(), L)) return 0; - + for (unsigned i = 0; i < xs.size(); i++) { polynomial::var x = xs[i]; SASSERT(x2v.contains(x)); @@ -2188,12 +2189,12 @@ namespace algebraic_numbers { struct var_degree_lt { imp & m_imp; polynomial::var2anum const & m_x2v; - + var_degree_lt(imp & i, polynomial::var2anum const & x2v): - m_imp(i), + m_imp(i), m_x2v(x2v) { } - + unsigned degree(polynomial::var x) const { if (!m_x2v.contains(x)) return UINT_MAX; @@ -2212,14 +2213,14 @@ namespace algebraic_numbers { polynomial::var m_x; anum const & m_v; ext_var2num(manager & am, polynomial::var2anum const & x2v, polynomial::var x, anum const & v): - m_am(am), - m_x2v(x2v), - m_x(x), + m_am(am), + m_x2v(x2v), + m_x(x), m_v(v) { } virtual manager & m() const { return m_am; } virtual bool contains(polynomial::var x) const { return x == m_x || m_x2v.contains(x); } - virtual anum const & operator()(polynomial::var x) const { + virtual anum const & operator()(polynomial::var x) const { if (x == m_x) return m_v; else @@ -2233,7 +2234,7 @@ namespace algebraic_numbers { for (unsigned i = 0; i < roots.size(); i++) { display_root(tout, roots[i]); tout << "\n"; }); - + unsigned sz = roots.size(); unsigned j = 0; // std::cout << "p: " << p << "\n"; @@ -2255,7 +2256,7 @@ namespace algebraic_numbers { for (unsigned i = j; i < sz; i++) del(roots[i]); roots.shrink(j); - + TRACE("isolate_roots", tout << "after filtering roots:\n"; for (unsigned i = 0; i < roots.size(); i++) { display_root(tout, roots[i]); tout << "\n"; @@ -2279,7 +2280,7 @@ namespace algebraic_numbers { pm().mk_var(); SASSERT(pm().num_vars() >= sz); } - + polynomial::var_vector m_isolate_roots_vars; void isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots, bool nested_call = false) { TRACE("isolate_roots", tout << "isolating roots of: " << p << "\n";); @@ -2312,24 +2313,24 @@ namespace algebraic_numbers { if (x2v.contains(x)) { // The remaining variable is assigned, the actual unassigned variable vanished when we replaced rational values. // So, the polynomial does not have any roots - return; + return; } TRACE("isolate_roots", tout << "p is univariate after applying (rational fragment of) x2v... using univariate procedure\n";); isolate_roots(p_prime, roots); return; } - + polynomial::var_vector & xs = m_isolate_roots_vars; xs.reset(); ext_pm.vars(p_prime, xs); SASSERT(xs.size() > 1); - + // sort variables by the degree of the values std::stable_sort(xs.begin(), xs.end(), var_degree_lt(*this, x2v)); TRACE("isolate_roots", tout << "there are " << (xs.size() - 1) << " variables assigned to nonbasic numbers...\n";); - + // last variables is the one not assigned by x2v, or the unassigned variable vanished - polynomial::var x = xs.back(); + polynomial::var x = xs.back(); if (x2v.contains(x)) { // all remaining variables are assigned. // the unassigned variable vanished when we replaced the rational values. @@ -2361,13 +2362,13 @@ namespace algebraic_numbers { break; } } - + if (ext_pm.is_zero(q)) { TRACE("isolate_roots", tout << "q vanished\n";); // q may vanish at some of the other roots of the polynomial defining the values. // To decide if p_prime vanishes at x2v or not, we start evaluating each coefficient of p_prime at x2v // until we find one that is not zero at x2v. - // In the process we will copy p_prime to the local polynomial manager, since we will need to create + // In the process we will copy p_prime to the local polynomial manager, since we will need to create // an auxiliary variable. SASSERT(!nested_call); unsigned n = ext_pm.degree(p_prime, x); @@ -2417,7 +2418,7 @@ namespace algebraic_numbers { // z * x^i + c_{i-1} * x^{i-1} + ... + c_1 * x + c_0 // where c's are the coefficients of p_prime. // Then we invoke isolate_roots with q2 and x2v extended with z->a. - // The resultant will not vanish again because + // The resultant will not vanish again because // 0 is not a root of the polynomial defining a. polynomial_ref q2(pm()); polynomial_ref z_p(pm()); // z poly @@ -2517,7 +2518,7 @@ namespace algebraic_numbers { // Select a numeral between prev and curr. // Pre: prev < curr void select(numeral & prev, numeral & curr, numeral & result) { - TRACE("algebraic_select", + TRACE("algebraic_select", tout << "prev: "; display_interval(tout, prev); tout << "\n"; tout << "curr: "; display_interval(tout, curr); tout << "\n";); SASSERT(lt(prev, curr)); @@ -2526,13 +2527,13 @@ namespace algebraic_numbers { if (prev.is_basic()) { if (curr.is_basic()) bqm().select_small_core(qm(), basic_value(prev), basic_value(curr), w); - else + else bqm().select_small_core(qm(), basic_value(prev), lower(curr.to_algebraic()), w); } else { - if (curr.is_basic()) + if (curr.is_basic()) bqm().select_small_core(qm(), upper(prev.to_algebraic()), basic_value(curr), w); - else + else bqm().select_small_core(upper(prev.to_algebraic()), lower(curr.to_algebraic()), w); } scoped_mpq qw(qm()); @@ -2546,13 +2547,13 @@ namespace algebraic_numbers { polynomial::var2anum const & m_x2v; anum const & m_v; ext2_var2num(manager & am, polynomial::var2anum const & x2v, anum const & v): - m_am(am), - m_x2v(x2v), + m_am(am), + m_x2v(x2v), m_v(v) { } virtual manager & m() const { return m_am; } virtual bool contains(polynomial::var x) const { return true; } - virtual anum const & operator()(polynomial::var x) const { + virtual anum const & operator()(polynomial::var x) const { if (m_x2v.contains(x)) return m_x2v(x); else @@ -2572,12 +2573,12 @@ namespace algebraic_numbers { signs.push_back(s); } else { - TRACE("isolate_roots_bug", tout << "p: " << p << "\n"; + TRACE("isolate_roots_bug", tout << "p: " << p << "\n"; polynomial::var_vector xs; p.m().vars(p, xs); for (unsigned i = 0; i < xs.size(); i++) { if (x2v.contains(xs[i])) { - tout << "x" << xs[i] << " -> "; + tout << "x" << xs[i] << " -> "; display_root(tout, x2v(xs[i])); tout << " "; display_interval(tout, x2v(xs[i])); @@ -2589,7 +2590,7 @@ namespace algebraic_numbers { }); for (unsigned i = 0; i < num_roots; i++) refine_until_prec(roots[i], DEFAULT_PRECISION); - + scoped_anum w(m_wrapper); int_lt(roots[0], w); TRACE("isolate_roots_bug", tout << "w: "; display_root(tout, w); tout << "\n";); @@ -2654,7 +2655,7 @@ namespace algebraic_numbers { } else { algebraic_cell * c = a.to_algebraic(); - out << "Root["; + out << "Root["; upm().display(out, c->m_p_sz, c->m_p, "#1", true); if (c->m_i == 0) { // undefined @@ -2663,7 +2664,7 @@ namespace algebraic_numbers { SASSERT(c->m_i > 0); out << " &, " << c->m_i << "]"; } - + } void display_root_smt2(std::ostream & out, numeral const & a) { @@ -2696,10 +2697,10 @@ namespace algebraic_numbers { void display_interval(std::ostream & out, numeral const & a) { if (a.is_basic()) { - out << "["; - qm().display(out, basic_value(a)); + out << "["; + qm().display(out, basic_value(a)); out << ", "; - qm().display(out, basic_value(a)); + qm().display(out, basic_value(a)); out << "]"; } else { @@ -2716,7 +2717,7 @@ namespace algebraic_numbers { // the precision on refine is base 2 return upm().refine(c->m_p_sz, c->m_p, bqm(), l, u, precision * 4); } - + void display_decimal(std::ostream & out, numeral const & a, unsigned precision) { if (a.is_basic()) { qm().display_decimal(out, basic_value(a), precision); @@ -2733,7 +2734,7 @@ namespace algebraic_numbers { } } } - + void get_lower(numeral const & a, mpq & l, unsigned precision) { if (a.is_basic()) { qm().set(l, basic_value(a)); @@ -2755,7 +2756,7 @@ namespace algebraic_numbers { to_mpq(qm(), _u, u); } } - + }; manager::manager(reslimit& lim, unsynch_mpq_manager & m, params_ref const & p, small_object_allocator * a) { @@ -2788,11 +2789,11 @@ namespace algebraic_numbers { void manager::del(numeral & a) { return m_imp->del(a); } - + void manager::reset(numeral & a) { return m_imp->reset(a); } - + bool manager::is_zero(numeral const & a) { return m_imp->is_zero(const_cast(a)); } @@ -2824,7 +2825,7 @@ namespace algebraic_numbers { void manager::to_rational(numeral const & a, rational & r) { return m_imp->to_rational(const_cast(a), r); } - + void manager::swap(numeral & a, numeral & b) { return m_imp->swap(a, b); } @@ -2843,7 +2844,7 @@ namespace algebraic_numbers { void manager::set(numeral & a, int n) { scoped_mpq _n(qm()); - qm().set(_n, n); + qm().set(_n, n); set(a, _n); } @@ -2852,7 +2853,7 @@ namespace algebraic_numbers { qm().set(_n, n); set(a, _n); } - + void manager::set(numeral & a, mpq const & n) { m_imp->set(a, n); } @@ -2860,7 +2861,7 @@ namespace algebraic_numbers { void manager::set(numeral & a, numeral const & n) { m_imp->set(a, n); } - + void manager::isolate_roots(polynomial_ref const & p, numeral_vector & roots) { m_imp->isolate_roots(p, roots); } @@ -2880,7 +2881,7 @@ namespace algebraic_numbers { void manager::mk_root(sexpr const * p, unsigned i, numeral & r) { m_imp->mk_root(p, i, r); } - + void manager::root(numeral const & a, unsigned k, numeral & b) { m_imp->root(const_cast(a), k, b); } @@ -2934,7 +2935,7 @@ namespace algebraic_numbers { bool manager::eq(numeral const & a, numeral const & b) { return m_imp->eq(const_cast(a), const_cast(b)); } - + bool manager::eq(numeral const & a, mpq const & b) { return m_imp->eq(const_cast(a), b); } @@ -2948,7 +2949,7 @@ namespace algebraic_numbers { bool manager::lt(numeral const & a, numeral const & b) { return m_imp->lt(const_cast(a), const_cast(b)); } - + bool manager::lt(numeral const & a, mpq const & b) { return m_imp->lt(const_cast(a), b); } @@ -2972,7 +2973,7 @@ namespace algebraic_numbers { void manager::get_polynomial(numeral const & a, svector & r) { m_imp->get_polynomial(a, r); } - + void manager::get_lower(numeral const & a, mpbq & l) { SASSERT(!is_rational(a)); bqm().set(l, a.to_algebraic()->m_interval.lower()); @@ -3055,7 +3056,7 @@ namespace algebraic_numbers { void manager::reset_statistics() { m_imp->reset_statistics(); } - + void manager::collect_statistics(statistics & st) const { m_imp->collect_statistics(st); } diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index 4a12249e1..93858b6be 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -34,6 +34,7 @@ Notes: #include"linear_eq_solver.h" #include"scoped_numeral_buffer.h" #include"ref_buffer.h" +#include"common_msgs.h" namespace polynomial { @@ -48,21 +49,21 @@ namespace polynomial { m_p_trials(p_trials), m_max_search_size(max_search_size) { } - + void factor_params::updt_params(params_ref const & p) { m_max_p = p.get_uint("max_prime", UINT_MAX); m_p_trials = p.get_uint("num_primes", 1); m_max_search_size = p.get_uint("max_search_size", UINT_MAX); } - + void factor_params::get_param_descrs(param_descrs & r) { - r.insert("max_search_size", CPK_UINT, "(default: infty) Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. This parameter can be used to limit the search space."); + r.insert("max_search_size", CPK_UINT, "(default: infty) Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. This parameter can be used to limit the search space."); r.insert("max_prime", CPK_UINT, "(default: infty) Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. This parameter limits the maximum prime number p to be used in the first step."); r.insert("num_primes", CPK_UINT, "(default: 1) Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. The search space may be reduced by factoring the polynomial in different GF(p)'s. This parameter specify the maximum number of finite factorizations to be considered, before lifiting and searching."); } typedef ptr_vector monomial_vector; - + void var2degree::display(std::ostream & out) const { bool first = true; out << "["; @@ -85,7 +86,7 @@ namespace polynomial { // Monomials // // ----------------------------------- - + /** \brief power: var + exponent */ @@ -97,14 +98,14 @@ namespace polynomial { unsigned degree() const { return second; } unsigned & degree() { return second; } void set_var(var x) { first = x; } - + struct lt_var { - bool operator()(power const & p1, power const & p2) { - // CMW: The assertion below does not hold on OSX, because + bool operator()(power const & p1, power const & p2) { + // CMW: The assertion below does not hold on OSX, because // their implementation of std::sort will try to compare // two items at the same index instead of comparing // the indices directly. I suspect that the purpose of - // this assertion was to make sure that there are + // this assertion was to make sure that there are // no duplicates, so I replaced it with a new assertion at // the end of var_degrees(...). @@ -139,7 +140,7 @@ namespace polynomial { } return true; } - + /** \brief Return total degree of the given power product. */ @@ -150,7 +151,7 @@ namespace polynomial { return r; } - + /** \brief Monomials (power products) */ @@ -173,10 +174,10 @@ namespace polynomial { struct hash_proc { unsigned operator()(monomial const * m) const { - return m->m_hash; + return m->m_hash; } }; - + struct eq_proc { bool operator()(monomial const * m1, monomial const * m2) const { if (m1->size() != m2->size() || m1->hash() != m2->hash()) @@ -186,13 +187,13 @@ namespace polynomial { if (m1->get_power(i) != m2->get_power(i)) return false; } - + return true; } }; static unsigned get_obj_size(unsigned sz) { return sizeof(monomial) + sz * sizeof(power); } - + monomial(unsigned id, unsigned sz, power const * pws, unsigned h): m_ref_count(0), m_id(id), @@ -204,16 +205,16 @@ namespace polynomial { m_powers[i] = pw; SASSERT(i == 0 || get_var(i) > get_var(i-1)); SASSERT(degree(i) > 0); - m_total_degree += degree(i); + m_total_degree += degree(i); } } unsigned hash() const { return m_hash; } unsigned ref_count() const { return m_ref_count; } - + void inc_ref() { m_ref_count++; } - + void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; } bool is_valid() const { @@ -221,21 +222,21 @@ namespace polynomial { } unsigned id() const { return m_id; } - + unsigned size() const { return m_size; } - + unsigned total_degree() const { return m_total_degree; } - + power const & get_power(unsigned idx) const { SASSERT(idx < size()); return m_powers[idx]; } - + power const * get_powers() const { return m_powers; } - + var get_var(unsigned idx) const { return get_power(idx).get_var(); } - + unsigned degree(unsigned idx) const { return get_power(idx).degree(); } var max_var() const { - if (m_size == 0) + if (m_size == 0) return null_var; return get_var(m_size - 1); } @@ -358,7 +359,7 @@ namespace polynomial { var max_smaller_than(var x) const { SASSERT(x != null_var); var y = max_smaller_than_core(x); - DEBUG_CODE({ + DEBUG_CODE({ bool found = false; for (unsigned i = 0; i < m_size; i++) { if (get_var(i) < x) { @@ -377,7 +378,7 @@ namespace polynomial { }); return y; } - + void display(std::ostream & out, display_var_proc const & proc = display_var_proc(), bool use_star = false) const { if (m_size == 0) { out << "1"; @@ -417,7 +418,7 @@ namespace polynomial { } out << ")"; } - + bool is_unit() const { return m_size == 0; } /** @@ -452,7 +453,7 @@ namespace polynomial { inline void swap(monomial * & m1, monomial * & m2) { std::swap(m1, m2); } typedef chashtable monomial_table; - + /** \brief Mapping from monomials to positions. */ @@ -470,14 +471,14 @@ namespace polynomial { SASSERT(id < m_m2pos.size()); m_m2pos[id] = UINT_MAX; } - + void set(monomial const * m, unsigned pos) { unsigned id = m->id(); m_m2pos.reserve(id+1, UINT_MAX); SASSERT(m_m2pos[id] == UINT_MAX); m_m2pos[id] = pos; } - + /** \brief Save the position of the monomials in p. */ @@ -510,7 +511,7 @@ namespace polynomial { class tmp_monomial { monomial * m_ptr; unsigned m_capacity; //!< maximum number of arguments supported by m_ptr; - + monomial * allocate(unsigned capacity) { void * mem = memory::allocate(monomial::get_obj_size(capacity)); return new (mem) monomial(UINT_MAX, 0, 0, 0); @@ -541,36 +542,36 @@ namespace polynomial { m_ptr(allocate(TMP_INITIAL_CAPACITY)), m_capacity(TMP_INITIAL_CAPACITY) { } - + ~tmp_monomial() { deallocate(m_ptr, m_capacity); } - + void init(unsigned sz, power const * pws) { - if (sz > m_capacity) + if (sz > m_capacity) increase_capacity(sz * 2); SASSERT(sz < m_capacity); m_ptr->m_size = sz; if (sz == 0) return; memcpy(m_ptr->m_powers, pws, sizeof(power) * sz); } - - void reset() { - m_ptr->m_size = 0; + + void reset() { + m_ptr->m_size = 0; } - unsigned size() const { - return m_ptr->m_size; + unsigned size() const { + return m_ptr->m_size; } - - void push_back(power const & pw) { - if (m_ptr->m_size >= m_capacity) + + void push_back(power const & pw) { + if (m_ptr->m_size >= m_capacity) expand_capacity(m_ptr->m_size * 2); m_ptr->m_powers[m_ptr->m_size] = pw; m_ptr->m_size++; } - - monomial * get_ptr() { + + monomial * get_ptr() { unsigned sz = m_ptr->m_size; m_ptr->m_hash = monomial::hash_core(sz, m_ptr->m_powers); return m_ptr; @@ -593,15 +594,15 @@ namespace polynomial { power const & get_power(unsigned idx) const { return m_ptr->m_powers[idx]; } - power const * get_powers() const { return m_ptr->m_powers; } + power const * get_powers() const { return m_ptr->m_powers; } }; /** \brief Compare m1 and m2 using a lexicographical order - - Return - - -1 if m1 <_lex m2, - - 0 if m1 = m2, + + Return + - -1 if m1 <_lex m2, + - 0 if m1 = m2, - 1 if m1 >_lex m2 The biggest variable dominates @@ -675,7 +676,7 @@ namespace polynomial { } if (idx1 == idx2) { SASSERT(min_var_degree1 != min_var_degree2); - return min_var_degree1 < min_var_degree2 ? -1 : 1; + return min_var_degree1 < min_var_degree2 ? -1 : 1; } return idx1 < 0 ? -1 : 1; } @@ -683,15 +684,15 @@ namespace polynomial { struct lex_lt2 { var m_min; lex_lt2(var m):m_min(m) {} - bool operator()(monomial * m1, monomial * m2) const { + bool operator()(monomial * m1, monomial * m2) const { TRACE("lex_bug", tout << "min: x" << m_min << "\n"; m1->display(tout); tout << "\n"; m2->display(tout); tout << "\n";); - return lex_compare2(m1, m2, m_min) < 0; + return lex_compare2(m1, m2, m_min) < 0; } }; /** \brief Compare m1 and m2 using a graded lexicographical order - + \see lex_compare */ int graded_lex_compare(monomial const * m1, monomial const * m2) { @@ -702,7 +703,7 @@ namespace polynomial { else return t1 < t2 ? -1 : 1; } - + /** \brief Compare submonomials m1[start1, end1) and m2[start2, end2) using reverse lexicographical order */ @@ -732,7 +733,7 @@ namespace polynomial { SASSERT(idx2 == start2 && idx1 != start1); return 1; } - + /** \brief Compare m1 and m2 using reverse lexicographical order. @@ -763,7 +764,7 @@ namespace polynomial { }; /** - \brief + \brief */ class monomial_manager { unsigned m_ref_count; @@ -796,7 +797,7 @@ namespace polynomial { ~monomial_manager() { dec_ref(m_unit); - CTRACE("polynomial", !m_monomials.empty(), + CTRACE("polynomial", !m_monomials.empty(), tout << "monomials leaked\n"; monomial_table::iterator it = m_monomials.begin(); monomial_table::iterator end = m_monomials.end(); for (; it != end; ++it) { @@ -806,7 +807,7 @@ namespace polynomial { if (m_own_allocator) dealloc(m_allocator); } - + void inc_ref() { m_ref_count++; } @@ -819,7 +820,7 @@ namespace polynomial { } small_object_allocator & allocator() { return *m_allocator; } - + var mk_var() { var r = m_next_var; m_next_var++; @@ -830,8 +831,8 @@ namespace polynomial { return m_next_var; } - bool is_valid(var x) const { - return x < m_next_var; + bool is_valid(var x) const { + return x < m_next_var; } void del(monomial * m) { @@ -841,11 +842,11 @@ namespace polynomial { m_allocator->deallocate(obj_sz, m); } - void inc_ref(monomial * m) { + void inc_ref(monomial * m) { m->inc_ref(); } - - void dec_ref(monomial * m) { + + void dec_ref(monomial * m) { m->dec_ref(); if (m->ref_count() == 0) del(m); @@ -961,26 +962,26 @@ namespace polynomial { j++; } product_tmp.set_size(j); - TRACE("monomial_mul_bug", + TRACE("monomial_mul_bug", tout << "before mk_monomial\n"; tout << "pws1: "; for (unsigned i = 0; i < sz1; i++) tout << pws1[i] << " "; tout << "\n"; tout << "pws2: "; for (unsigned i = 0; i < sz2; i++) tout << pws2[i] << " "; tout << "\n"; - tout << "product_tmp: "; for (unsigned i = 0; i < product_tmp.size(); i++) tout << product_tmp.get_power(i) << " "; + tout << "product_tmp: "; for (unsigned i = 0; i < product_tmp.size(); i++) tout << product_tmp.get_power(i) << " "; tout << "\n";); monomial * r = mk_monomial(product_tmp); - TRACE("monomial_mul_bug", + TRACE("monomial_mul_bug", tout << "j: " << j << "\n"; tout << "r: "; r->display(tout); tout << "\n"; tout << "pws1: "; for (unsigned i = 0; i < sz1; i++) tout << pws1[i] << " "; tout << "\n"; tout << "pws2: "; for (unsigned i = 0; i < sz2; i++) tout << pws2[i] << " "; tout << "\n"; - tout << "product_tmp: "; for (unsigned i = 0; i < product_tmp.size(); i++) tout << product_tmp.get_power(i) << " "; + tout << "product_tmp: "; for (unsigned i = 0; i < product_tmp.size(); i++) tout << product_tmp.get_power(i) << " "; tout << "\n";); SASSERT(r->is_valid()); SASSERT(r->total_degree() == power_product_total_degree(sz1, pws1) + power_product_total_degree(sz2, pws2)); return r; } - - monomial * mul(monomial const * m1, monomial const * m2) { + + monomial * mul(monomial const * m1, monomial const * m2) { if (m1 == m_unit) return const_cast(m2); if (m2 == m_unit) @@ -996,12 +997,12 @@ namespace polynomial { unsigned i1 = 0; unsigned i2 = 0; unsigned j = 0; - if (sz1 < sz2) - return false; // pws2 does not divide pws1 + if (sz1 < sz2) + return false; // pws2 does not divide pws1 while (true) { if (i2 == sz2) { if (STORE_RESULT) { - for (; i1 < sz1; i1++, j++) + for (; i1 < sz1; i1++, j++) r.set_power(j, pws1[i1]); r.set_size(j); } @@ -1064,7 +1065,7 @@ namespace polynomial { return false; } - /** + /** \brief Compute the gcd of pws1 and pws2, store it in g, and pws1/g in r1, and pws2/g in r2 Return true if the gcd is not 1. If the result is false, then g, r1 and r2 should not be used. */ @@ -1081,7 +1082,7 @@ namespace polynomial { while (true) { if (i1 == sz1) { if (found) { - for (; i2 < sz2; i2++, j2++) + for (; i2 < sz2; i2++, j2++) r2.set_power(j2, pws2[i2]); r1.set_size(j1); r2.set_size(j2); @@ -1092,7 +1093,7 @@ namespace polynomial { } if (i2 == sz2) { if (found) { - for (; i1 < sz1; i1++, j1++) + for (; i1 < sz1; i1++, j1++) r1.set_power(j1, pws1[i1]); r1.set_size(j1); r2.set_size(j2); @@ -1172,7 +1173,7 @@ namespace polynomial { if (k == 1) return const_cast(m); unsigned sz = m->size(); - tmp_monomial & pw_tmp = m_tmp1; + tmp_monomial & pw_tmp = m_tmp1; pw_tmp.reserve(sz); for (unsigned i = 0; i < sz; i++) pw_tmp.set_power(i, power(m->get_var(i), m->degree(i)*k)); @@ -1224,9 +1225,9 @@ namespace polynomial { elim_tmp.set_size(j); return mk_monomial(elim_tmp); } - + /** - \brief Return m/x^n where n == m->degree_of(x) + \brief Return m/x^n where n == m->degree_of(x) */ monomial * div_x(monomial const * m, var x) { SASSERT(is_valid(x)); @@ -1295,10 +1296,10 @@ namespace polynomial { } m_monomials.swap(new_table); } - + }; - + /** We maintain the following invariant: The first monomial m of every non-zero polynomial p contains: @@ -1375,12 +1376,12 @@ namespace polynomial { void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; } static unsigned get_obj_size(unsigned n) { return sizeof(polynomial) + n * (sizeof(numeral) + sizeof(monomial*)); } - + /** \brief Partial order used to implement the polynomial invariant that guarantees that the first monomial contains the maximal variable in the polynomial, and it occurs with maximal degree. - + Return true if m1 > m2 in this partial order. */ static bool po_gt(monomial const * m1, monomial const * m2) { @@ -1436,7 +1437,7 @@ namespace polynomial { return max; } - bool lex_sorted() const { + bool lex_sorted() const { return m_lex_sorted; } @@ -1527,7 +1528,7 @@ namespace polynomial { _scoped_numeral abs_a_i(nm); nm.set(abs_a_i, a_i); nm.abs(abs_a_i); - + numeral const & a_prime = abs_a_i; if (i > 0) { if (nm.is_neg(a_i)) @@ -1539,7 +1540,7 @@ namespace polynomial { if (nm.is_neg(a_i)) out << "- "; } - + if (m(i)->is_unit()) { out << nm.to_string(a_prime); } @@ -1570,7 +1571,7 @@ namespace polynomial { nm.display(out, a); } } - + void display_mon_smt2(std::ostream & out, mpzzp_manager & nm, display_var_proc const & proc, unsigned i) const { SASSERT(i < m_size); monomial const * m_i = m(i); @@ -1612,10 +1613,10 @@ namespace polynomial { }; - manager::factors::factors(manager & _m):m_manager(_m), m_total_factors(0) { - m().m().set(m_constant, 1); + manager::factors::factors(manager & _m):m_manager(_m), m_total_factors(0) { + m().m().set(m_constant, 1); } - + manager::factors::~factors() { reset(); m().m().del(m_constant); @@ -1628,9 +1629,9 @@ namespace polynomial { m_factors.reset(); m_degrees.reset(); m_total_factors = 0; - m().m().set(m_constant, 1); + m().m().set(m_constant, 1); } - + void manager::factors::push_back(polynomial * p, unsigned degree) { SASSERT(p != 0 && degree > 0); m_factors.push_back(p); @@ -1638,7 +1639,7 @@ namespace polynomial { m_total_factors += degree; m().inc_ref(p); } - + void manager::factors::multiply(polynomial_ref & out) const { if (m_factors.empty()) { out = m().mk_const(m_constant); @@ -1649,18 +1650,18 @@ namespace polynomial { polynomial_ref current(m_factors[i], m()); if (m_degrees[i] > 1) { m().pw(current, m_degrees[i], current); - } + } if (i == 0) { out = current; } else { - out = m().mul(out, current); + out = m().mul(out, current); } } // multiply the constant out = m().mul(m_constant, out); } } - + void manager::factors::display(std::ostream & out) const { out << m().m().to_string(get_constant()); for (unsigned i = 0; i < m_factors.size(); ++ i) { @@ -1670,20 +1671,20 @@ namespace polynomial { } } - void manager::factors::set_constant(numeral const & constant) { - m().m().set(m_constant, constant); - } - - void manager::factors::set_degree(unsigned i, unsigned degree) { - SASSERT(i > 0); - m_total_factors -= m_degrees[i]; - m_total_factors += m_degrees[i] = degree; + void manager::factors::set_constant(numeral const & constant) { + m().m().set(m_constant, constant); + } + + void manager::factors::set_degree(unsigned i, unsigned degree) { + SASSERT(i > 0); + m_total_factors -= m_degrees[i]; + m_total_factors += m_degrees[i] = degree; + } + + polynomial_ref manager::factors::operator[](unsigned i) const { + return polynomial_ref(m_factors[i], m()); } - polynomial_ref manager::factors::operator[](unsigned i) const { - return polynomial_ref(m_factors[i], m()); - } - unsigned manager::id(monomial const * m) { return m->id(); } @@ -1691,7 +1692,7 @@ namespace polynomial { unsigned manager::id(polynomial const * p) { return p->id(); } - + bool manager::is_unit(monomial const * m) { return m->size() == 0; } @@ -1699,7 +1700,7 @@ namespace polynomial { bool manager::is_zero(polynomial const * p) { return p->size() == 0; } - + bool manager::is_const(polynomial const * p) { return is_zero(p) || (p->size() == 1 && is_unit(p->m(0))); } @@ -1724,7 +1725,7 @@ namespace polynomial { } return true; } - + unsigned manager::size(polynomial const * p) { return p->size(); } @@ -1755,11 +1756,11 @@ namespace polynomial { unsigned manager::size(monomial const * m) { return m->size(); } - + var manager::get_var(monomial const * m, unsigned i) { return m->get_var(i); } - + unsigned manager::degree(monomial const * m, unsigned i) { return m->degree(i); } @@ -1802,7 +1803,7 @@ namespace polynomial { } return r; } - + var manager::max_var(polynomial const * p) { if (p->size() == 0) return null_var; @@ -1859,7 +1860,7 @@ namespace polynomial { } return true; } - + /** \brief Divide as by the GCD of as. Return true, if the GCD is not 1. @@ -1882,7 +1883,7 @@ namespace polynomial { /** \brief Som-of-monomials buffer. This a temporary datastructure for building polynomials. - + The following idiom should be used: Invoke add(...), addmul(...) several times, and then invoke mk() to obtain the final polynomial. */ @@ -1956,7 +1957,7 @@ namespace polynomial { bool empty() const { return m_tmp_ms.empty(); } monomial * m(unsigned i) const { return m_tmp_ms[i]; } - + numeral const & a(unsigned i) const { return m_tmp_as[i]; } /** @@ -1986,7 +1987,7 @@ namespace polynomial { /** \brief Store a*m*p into the buffer. m_m2pos is updated with the position of the monomials in m_tmp_ms. - + The reference counter of new monomials added into the buffer is increased. */ template @@ -2025,7 +2026,7 @@ namespace polynomial { void addmul(numeral const & a, monomial const * m, som_buffer const & p) { return addmul(a, m, &p); } - + void addmul(numeral const & a, som_buffer const * p) { return addmul(a, m_owner->mk_unit(), p); } @@ -2046,7 +2047,7 @@ namespace polynomial { /** \brief Store p into the buffer. m_m2pos is updated with the position of the monomials in m_tmp_ms. - + The reference counter of new monomials added into the buffer is increased. */ void add(polynomial const * p) { @@ -2067,11 +2068,11 @@ namespace polynomial { } } } - + /** \brief Add 'a*m' into m_tmp_as and m_tmp_ms. m_m2pos is updated with the position of the monomials in m_tmp_ms. - + The reference counter of m is increased. */ void add(numeral const & a, monomial * m) { @@ -2090,11 +2091,11 @@ namespace polynomial { mng.add(m_tmp_as[pos], a, m_tmp_as[pos]); } } - + /** - \brief Add 'a' (that is, a*m_unit) into m_tmp_as and m_tmp_ms. + \brief Add 'a' (that is, a*m_unit) into m_tmp_as and m_tmp_ms. m_m2pos is updated with the position of the monomials in m_tmp_ms. - + The reference counter of m_unit is increased. */ void add(numeral const & a) { @@ -2209,7 +2210,7 @@ namespace polynomial { for (unsigned i = 0; i < sz; i++) { m_buffers[i]->reset(); } - } + } void reset() { reset(m_buffers.size()); @@ -2358,7 +2359,7 @@ namespace polynomial { m_mgcd_iterpolators.flush(); m_mgcd_skeletons.reset(); DEBUG_CODE({ - TRACE("polynomial", + TRACE("polynomial", tout << "leaked polynomials\n"; for (unsigned i = 0; i < m_polynomials.size(); i++) { if (m_polynomials[i] != 0) { @@ -2374,13 +2375,13 @@ namespace polynomial { void checkpoint() { if (!m_limit.inc()) { - throw polynomial_exception("canceled"); + throw polynomial_exception(Z3_CANCELED_MSG); } cooperate("polynomial"); } mpzzp_manager & m() const { return const_cast(this)->m_manager; } - manager & pm() const { return m_wrapper; } + manager & pm() const { return m_wrapper; } up_manager & upm() { return m_upm; } monomial_manager & mm() const { return *m_monomial_manager; } @@ -2392,7 +2393,7 @@ namespace polynomial { return mm().num_vars(); } - bool is_valid(var x) const { + bool is_valid(var x) const { return mm().is_valid(x); } @@ -2442,11 +2443,11 @@ namespace polynomial { mm().allocator().deallocate(obj_sz, p); } - void inc_ref(monomial * m) { + void inc_ref(monomial * m) { mm().inc_ref(m); } - - void dec_ref(monomial * m) { + + void dec_ref(monomial * m) { mm().dec_ref(m); } @@ -2459,7 +2460,7 @@ namespace polynomial { if (p->ref_count() == 0) del(p); } - + vector m_lex_sort_buckets; unsigned_vector m_lex_sort_permutation; void lex_sort(polynomial const * p) { @@ -2468,12 +2469,12 @@ namespace polynomial { struct poly_khasher { unsigned operator()(polynomial const * p) const { return 17; } }; - struct poly_chasher { - unsigned operator()(polynomial const * p, unsigned idx) const { + struct poly_chasher { + unsigned operator()(polynomial const * p, unsigned idx) const { return hash_u_u(p->m(idx)->hash(), numeral_manager::hash(p->a(idx))); } }; - + unsigned hash(polynomial const * p) { if (p->size() == 0) return 31; @@ -2513,7 +2514,7 @@ namespace polynomial { monomial * mk_monomial(unsigned sz, var * xs) { return mm().mk_monomial(sz, xs); } monomial * mk_monomial(unsigned sz, power const * pws) { return mm().mk_monomial(sz, pws); } - + monomial * convert(monomial const * src) { return mm().convert(src); } polynomial * mk_const_core(numeral & a) { @@ -2521,7 +2522,7 @@ namespace polynomial { inc_ref(u); return mk_polynomial_core(1, &a, &u); } - + polynomial * mk_const(numeral & a) { if (m_manager.is_zero(a)) return mk_zero(); @@ -2602,7 +2603,7 @@ namespace polynomial { polynomial * p = mk_univariate(x, n, m_rat2numeral.c_ptr()); reset_tmp_as2(); return p; - } + } polynomial * mk_linear(unsigned sz, numeral * as, var const * xs, numeral & c) { SASSERT(m_tmp_linear_as.empty()); @@ -2635,16 +2636,16 @@ namespace polynomial { reset_tmp_as2(); return p; } - - - monomial * mul(monomial const * m1, monomial const * m2) { + + + monomial * mul(monomial const * m1, monomial const * m2) { return mm().mul(m1, m2); } bool div(monomial const * m1, monomial const * m2) { return mm().div(m1, m2); } - + bool div(monomial const * m1, monomial const * m2, monomial * & r) { return mm().div(m1, m2, r); } @@ -2680,7 +2681,7 @@ namespace polynomial { polynomial * addmul(polynomial const * p1, numeral const & a2, polynomial const * p2) { return addmul(p1, a2, mk_unit(), p2); } - + polynomial * add(polynomial const * p1, polynomial const * p2) { numeral one(1); return addmul(one, mk_unit(), p1, one, mk_unit(), p2); @@ -2703,7 +2704,7 @@ namespace polynomial { m_som_buffer.reset(); unsigned sz1 = p1->size(); for (unsigned i = 0; i < sz1; i++) { - checkpoint(); + checkpoint(); numeral const & a1 = p1->a(i); monomial * m1 = p1->m(i); m_som_buffer.addmul(a1, m1, p2); @@ -2746,7 +2747,7 @@ namespace polynomial { m_som_buffer.reset(); unsigned sz1 = p1->size(); for (unsigned i = 0; i < sz1; i++) { - checkpoint(); + checkpoint(); numeral const & a1 = p1->a(i); m_manager.mul(a, a1, new_a1); monomial * m1 = p1->m(i); @@ -2754,7 +2755,7 @@ namespace polynomial { } return m_som_buffer.mk(); } - + // Divide coefficients of p by d. // This methods assumes that all coefficients of p are divisible by d. polynomial * div(polynomial * p, numeral const & d) { @@ -2775,7 +2776,7 @@ namespace polynomial { polynomial * new_p = mul(tmp, p); return new_p; } - + /** \brief Return m/x^k */ @@ -2784,7 +2785,7 @@ namespace polynomial { } /** - \brief Return m/x^n where n == m->degree_of(x) + \brief Return m/x^n where n == m->degree_of(x) */ monomial * div_x(monomial const * m, var x) { return mm().div_x(m, x); @@ -2799,7 +2800,7 @@ namespace polynomial { /** \brief (Incremental) Newton interpolation for multivariate polynomials. - Creates a polynomial on x of degree at most d with coefficients in Z[y1, ..., ym], + Creates a polynomial on x of degree at most d with coefficients in Z[y1, ..., ym], using d+1 sample points. Sample points are provided using the method add, and the interpolating polynomial is created using mk() method. @@ -2817,18 +2818,18 @@ namespace polynomial { newton_interpolator(imp & _pm):pm(_pm), m_inputs(m()), m_invs(m()), m_vs(pm.m_wrapper) { m_invs.push_back(numeral(0)); } - - void reset() { + + void reset() { m_inputs.reset(); - m_invs.shrink(1); - m_vs.reset(); - SASSERT(m().is_zero(m_invs[0])); + m_invs.shrink(1); + m_vs.reset(); + SASSERT(m().is_zero(m_invs[0])); } scoped_numeral_vector const & inputs() const { return m_inputs; } unsigned num_sample_points() const { return m_inputs.size(); } - + /** \brief Add a new datapoint */ @@ -2878,7 +2879,7 @@ namespace polynomial { m_vs.push_back(const_cast(output)); } } - + // Convert newton form to standard form void mk(var x, polynomial_ref & r) { SASSERT(m().modular()); @@ -2905,13 +2906,13 @@ namespace polynomial { r = u; } }; - + /** \brief Newton interpolation for multivariate polynomials. - Creates a polynomial on x of degree at most d with coefficients in Z[y1, ..., ym], + Creates a polynomial on x of degree at most d with coefficients in Z[y1, ..., ym], using d+1 sample points. The sample points are store in the vectors inputs and outputs. Both must have size d+1. - + \pre manager must be configured in Zp (modular) mode. We need this requeriment because we use the inverse operation. */ @@ -2973,11 +2974,11 @@ namespace polynomial { }; imp & pm; var m_x; - svector m_entries; + svector m_entries; unsigned_vector m_powers; ptr_vector m_orig_monomials; - unsigned m_max_powers; // maximal number of powers associated with an entry - + unsigned m_max_powers; // maximal number of powers associated with an entry + skeleton(imp & _pm, polynomial * p, var x):pm(_pm), m_x(x) { m_max_powers = 0; ptr_buffer ms; @@ -2991,7 +2992,7 @@ namespace polynomial { monomial * orig_m = ms[i]; monomial * m; unsigned k = orig_m->degree_of(x); - if (k > 0) + if (k > 0) m = pm.div_x(orig_m, x); else m = orig_m; @@ -3012,7 +3013,7 @@ namespace polynomial { m_orig_monomials.push_back(orig_m); m_powers.push_back(k); } - TRACE("skeleton", + TRACE("skeleton", tout << "x: x" << m_x << "\n"; tout << "max: " << m_max_powers << "\n"; tout << "p: "; p->display(tout, pm.m()); tout << "\n"; @@ -3050,7 +3051,7 @@ namespace polynomial { entry const & operator[](unsigned idx) const { return m_entries[idx]; } unsigned ith_power(entry const & e, unsigned i) const { SASSERT(i < e.m_num_powers); return m_powers[e.m_first_power_idx + i]; } - + monomial * ith_orig_monomial(entry const & e, unsigned i) const { SASSERT(i < e.m_num_powers); return m_orig_monomials[e.m_first_power_idx + i]; } unsigned max_num_powers() const { return m_max_powers; } @@ -3089,7 +3090,7 @@ namespace polynomial { } } } - + ~sparse_interpolator() { if (m_skeleton) { numeral_manager & m = m_skeleton->pm.m(); @@ -3099,7 +3100,7 @@ namespace polynomial { m.del(m_outputs[i]); } } - + void reset() { numeral_manager & m = m_skeleton->pm.m(); for (unsigned i = 0; i < m_inputs.size(); i++) { @@ -3133,7 +3134,7 @@ namespace polynomial { } return true; } - + bool mk(polynomial_ref & r) { SASSERT(m_skeleton); numeral_manager & m = m_skeleton->pm.m(); @@ -3164,14 +3165,14 @@ namespace polynomial { tout << "\n";); solver.add(i, cs.c_ptr(), m_outputs[output_idx]); } - TRACE("sparse_interpolator", + TRACE("sparse_interpolator", tout << "find coefficients of:\n"; for (unsigned i = 0; i < num_pws; i++) { m_skeleton->ith_orig_monomial(e, i)->display(tout); tout << "\n"; } tout << "system of equations:\n"; solver.display(tout);); - if (!solver.solve(new_as.c_ptr())) + if (!solver.solve(new_as.c_ptr())) return false; for (unsigned i = 0; i < num_pws; i++) { if (!m.is_zero(new_as[i])) { @@ -3210,7 +3211,7 @@ namespace polynomial { typedef sbuffer power_buffer; typedef sbuffer unsigned_buffer; typedef sbuffer var_buffer; - + /** Store in pws the variables occuring in p and their (minimal or maximal) degrees. */ @@ -3220,7 +3221,7 @@ namespace polynomial { pws.reset(); unsigned_vector & var2pos = m_var_degrees_tmp; var2pos.reserve(num_vars(), UINT_MAX); - + unsigned sz = p->size(); for (unsigned i = 0; i < sz; i++) { monomial * m = p->m(i); @@ -3241,7 +3242,7 @@ namespace polynomial { } } } - + sz = pws.size(); for (unsigned i = 0; i < sz; i++) { SASSERT(var2pos[pws[i].get_var()] != UINT_MAX); @@ -3288,7 +3289,7 @@ namespace polynomial { for (unsigned i = 0; i < sz; i++) { monomial * m = p->m(i); unsigned d = m->degree_of(x); - som_buffer * c = cs[d]; + som_buffer * c = cs[d]; c->add(p->a(i), div_x(m, x)); } } @@ -3313,7 +3314,7 @@ namespace polynomial { reduct = m_cheap_som_buffer2.mk(); return m_cheap_som_buffer.mk(); } - + /** \brief Return true if the coefficient of x^k is just a constant. Store it in c. @@ -3391,7 +3392,7 @@ namespace polynomial { int sz = p->size(); if (sz == 0) { return m_zero_numeral; - } + } else { monomial * u = mk_unit(); for (int i = 0; i < sz; ++ i) { @@ -3422,7 +3423,7 @@ namespace polynomial { if (m_manager.is_one(a)) { c = const_cast(p); return; - } + } m_cheap_som_buffer.reset(); scoped_numeral ai(m_manager); for (unsigned i = 0; i < sz; i++) { @@ -3441,14 +3442,14 @@ namespace polynomial { SASSERT(glex_max_pos != UINT_MAX); if (m_manager.is_neg(p->a(glex_max_pos))) return neg(p); - else + else return const_cast(p); } void flip_sign_if_lm_neg(polynomial_ref & p) { p = flip_sign_if_lm_neg_core(p); } - + /** \brief Extract the integer content, content and primitive part of p with respect to variable x. @@ -3488,7 +3489,7 @@ namespace polynomial { iccp_filter.resize(d+1, 0); iccp_powers.reset(); for (unsigned j = 0; j <= d; j++) - iccp_filter[j] = 0; + iccp_filter[j] = 0; unsigned sz = p->size(); for (unsigned j = 0; j < sz; j++) { monomial * m = p->m(j); @@ -3496,7 +3497,7 @@ namespace polynomial { TRACE("polynomial", tout << "degree of x" << x << " at "; m->display(tout); tout << " is " << k << "\n";); if (iccp_filter[k] == 0) iccp_powers.push_back(k); - if (m->size() == (k > 0 ? 1 : 0)) + if (m->size() == (k > 0 ? 1 : 0)) iccp_filter[k]++; else iccp_filter[k]+=2; @@ -3514,7 +3515,7 @@ namespace polynomial { // Extract integer content ic(p, i, pp); TRACE("polynomial", tout << "p: "; p->display(tout, m_manager); tout << "\ni: " << m_manager.to_string(i) << "\npp: " << pp << "\n";); - // Compute c using the gcd of coeffs of x^k for k's in iccp_powers + // Compute c using the gcd of coeffs of x^k for k's in iccp_powers polynomial_ref ci(pm()); c = coeff(pp, x, iccp_powers[0]); for (unsigned j = 1; j < num_powers; j++) { @@ -3531,7 +3532,7 @@ namespace polynomial { TRACE("polynomial", tout << "pp: " << pp << "\nc: " << c << "\n";); pp = exact_div(pp, c); } - + void iccp(polynomial const * p, numeral & i, polynomial_ref & c, polynomial_ref & pp) { iccp(p, max_var(p), i, c, pp); } @@ -3555,7 +3556,7 @@ namespace polynomial { } void gcd_prs(polynomial const * u, polynomial const * v, var x, polynomial_ref & r) { - TRACE("polynomial_gcd", tout << "gcd prs with x" << x << " for\nu: "; + TRACE("polynomial_gcd", tout << "gcd prs with x" << x << " for\nu: "; u->display(tout, m_manager); tout << "\nv: "; v->display(tout, m_manager); tout << "\n";); if (degree(u, x) < degree(v, x)) std::swap(u, v); @@ -3565,13 +3566,13 @@ namespace polynomial { scoped_numeral d_a(m_manager); polynomial_ref d_r(pm()); polynomial_ref g(pm()), h(pm()), rem(pm()), new_h(pm()); - + iccp(u, x, i_u, c_u, pp_u); iccp(v, x, i_v, c_v, pp_v); - + gcd(c_u, c_v, d_r); m_manager.gcd(i_u, i_v, d_a); - TRACE("polynomial_gcd_detail", + TRACE("polynomial_gcd_detail", tout << "After GCD of the content\n"; tout << "u: "; u->display(tout, m_manager); tout << "\n"; tout << "v: "; v->display(tout, m_manager); tout << "\n"; @@ -3582,15 +3583,15 @@ namespace polynomial { tout << "pp_u: " << pp_u << "\n"; tout << "pp_v: " << pp_v << "\n"; tout << "d_r: " << d_r << "\nd_a: " << d_a << "\n";); - + g = mk_one(); h = mk_one(); - + unsigned counter = 0; while (true) { SASSERT(degree(pp_u, x) >= degree(pp_v, x)); unsigned delta = degree(pp_u, x) - degree(pp_v, x); - TRACE("polynomial_gcd_detail", + TRACE("polynomial_gcd_detail", tout << "iteration: " << counter << "\n"; tout << "gcd loop\npp_u: " << pp_u << "\npp_v: " << pp_v << "\ndelta: " << delta << "\n";); counter++; @@ -3624,14 +3625,14 @@ namespace polynomial { } h = new_h; } - } + } // Store in r <- gcd(content(u, x), v) void gcd_content(polynomial const * u, var x, polynomial const * v, polynomial_ref & r) { scoped_numeral i_u(m_manager); polynomial_ref c_u(pm()); polynomial_ref pp_u(pm()); - + iccp(u, x, i_u, c_u, pp_u); c_u = mul(i_u, c_u); gcd(c_u, v, r); @@ -3645,7 +3646,7 @@ namespace polynomial { SASSERT(is_univariate(u)); SASSERT(is_univariate(v)); if (is_zero(u)) { - r = const_cast(v); + r = const_cast(v); flip_sign_if_lm_neg(r); return; } @@ -3659,7 +3660,7 @@ namespace polynomial { flip_sign_if_lm_neg(r); return; } - if (is_const(u) || is_const(v)) { + if (is_const(u) || is_const(v)) { scoped_numeral i_u(m_manager), i_v(m_manager); ic(v, i_v); ic(u, i_u); @@ -3697,15 +3698,15 @@ namespace polynomial { scoped_numeral a1(m()); scoped_numeral a2(m()); m().mul(b2, inv2, a1); // a1 is the multiplicator for coefficients of C1 - m().mul(b1, inv1, a2); // a2 is the multiplicator for coefficients of C2 + m().mul(b1, inv1, a2); // a2 is the multiplicator for coefficients of C2 TRACE("CRA", tout << "a1: " << a1 << ", a2: " << a2 << "\n";); // new bound scoped_numeral new_bound(m()); - m().mul(b1, b2, new_bound); + m().mul(b1, b2, new_bound); scoped_numeral lower(m()); scoped_numeral upper(m()); scoped_numeral new_a(m()), tmp1(m()), tmp2(m()), tmp3(m()); - m().div(new_bound, 2, upper); + m().div(new_bound, 2, upper); m().set(lower, upper); m().neg(lower); TRACE("CRA", tout << "lower: " << lower << ", upper: " << upper << "\n";); @@ -3719,7 +3720,7 @@ namespace polynomial { m().sub(new_a, new_bound, new_a); \ R.add(new_a, M); \ } - + numeral zero(0); unsigned i1 = 0; unsigned i2 = 0; @@ -3747,7 +3748,7 @@ namespace polynomial { int s = lex_compare(m1, m2); if (s == 0) { ADD(C1->a(i1), C2->a(i2), m1); - TRACE("CRA", + TRACE("CRA", tout << "C1->a(i1): " << m().to_string(C1->a(i1)) << ", C2->a(i2): " << m().to_string(C2->a(i2)) << ", new_a: " << new_a << "\n"; tout << "tmp1: " << tmp1 << ", tmp2: " << tmp2 << ", tmp3: " << tmp3 << "\n";); i1++; @@ -3779,10 +3780,10 @@ namespace polynomial { polynomial_ref pp_u(pm()), pp_v(pm()); ic(u, c_u, pp_u); ic(v, c_v, pp_v); - + scoped_numeral d_a(m()); m_manager.gcd(c_u, c_v, d_a); - + scoped_numeral lc_u(m()); scoped_numeral lc_v(m()); unsigned d_u = degree(pp_u, x); @@ -3791,7 +3792,7 @@ namespace polynomial { lc_v = univ_coeff(pp_v, d_v); scoped_numeral lc_g(m()); m().gcd(lc_u, lc_v, lc_g); - + polynomial_ref u_Zp(m_wrapper); polynomial_ref v_Zp(m_wrapper); @@ -3853,8 +3854,8 @@ namespace polynomial { TRACE("mgcd", tout << "candidate:\n" << candidate << "\n";); scoped_numeral lc_candidate(m()); lc_candidate = univ_coeff(candidate, degree(candidate, x)); - if (m().divides(lc_candidate, lc_g) && - divides(candidate, pp_u) && + if (m().divides(lc_candidate, lc_g) && + divides(candidate, pp_u) && divides(candidate, pp_v)) { TRACE("mgcd", tout << "found GCD\n";); r = mul(d_a, candidate); @@ -3938,8 +3939,8 @@ namespace polynomial { for (unsigned i = 0; i < sz; i++) { monomial * m = p->m(i); unsigned k = m->degree_of(x); - if (k == 0) - continue; + if (k == 0) + continue; tmp_m = div_x(m, x); SASSERT(tmp_m != m); // since x is in m, but not in tmp_m if (m_m2pos.get(tmp_m) == 1) { @@ -3951,7 +3952,7 @@ namespace polynomial { SASSERT(num_unmarked <= num_marked); if (num_unmarked < num_marked) { // reset remaining marks - for (unsigned i = 0; i < num_marked; i++) + for (unsigned i = 0; i < num_marked; i++) m_m2pos.reset(no_x_ms[i]); TRACE("mgcd_detail", tout << "iccp_ZpX, cheap case... invoking ic\n";); ic(p, ci, pp); @@ -3961,7 +3962,7 @@ namespace polynomial { // 3) expensive case // Basic idea: separate a*m*x^k into a*x^k and m, put a*x^k into the som_buffer associated with m. // The mapping between m is som_buffers is given by m_m2pos - + // Extract integer content ic(p, ci, pp); no_x_ms.reset(); @@ -3984,7 +3985,7 @@ namespace polynomial { som->add(pp->a(i), mk_monomial(x, k)); } unsigned num_ms = no_x_ms.size(); - for (unsigned i = 0; i < num_ms; i++) + for (unsigned i = 0; i < num_ms; i++) m_m2pos.reset(no_x_ms[i]); SASSERT(num_ms > 0); // Compute GCD of all som_buffers @@ -3997,7 +3998,7 @@ namespace polynomial { SASSERT(is_univariate(a)); euclid_gcd(g, a, new_g); g = new_g; - if (is_const(g)) + if (is_const(g)) break; } if (!is_const(g)) { @@ -4014,7 +4015,7 @@ namespace polynomial { som_buffers.reset(num_ms); } - // Return the leading coefficient (with respect to glex) of p when + // Return the leading coefficient (with respect to glex) of p when // p is viewed as a multivariate polynomial Zp[y_1, ..., y_n] with coefficients in Zp[x]. polynomial * lc_glex_ZpX(polynomial const * p, var x) { // collect a*x^k of maximal monomial with respect to glex @@ -4023,7 +4024,7 @@ namespace polynomial { monomial_ref tmp_m(m_wrapper); unsigned sz = p->size(); for (unsigned i = 0; i < sz; i++) { - monomial * m = p->m(i); + monomial * m = p->m(i); unsigned k = m->degree_of(x); if (k != 0) { tmp_m = div_x(m, x); @@ -4071,11 +4072,11 @@ namespace polynomial { newton_interpolator_vector m_mgcd_iterpolators; scoped_ptr_vector m_mgcd_skeletons; - + struct sparse_mgcd_failed {}; - + // Auxiliary recursive function used in multivariate modular GCD - void mod_gcd_rec(polynomial const * u, polynomial const * v, unsigned p, + void mod_gcd_rec(polynomial const * u, polynomial const * v, unsigned p, unsigned idx, var_buffer const & vars, polynomial_ref & r) { TRACE("mgcd", tout << "mod_gcd_rec\nu: "; u->display(tout, m_manager, true); tout << "\nv: "; v->display(tout, m_manager, true); tout << "\n";); unsigned num_vars = vars.size(); @@ -4099,7 +4100,7 @@ namespace polynomial { scoped_numeral ci_g(m()); polynomial_ref c_g(m_wrapper); polynomial_ref lc_g(m_wrapper); - TRACE("mgcd_detail", + TRACE("mgcd_detail", tout << "idx: " << idx << "\n"; tout << "x" << x << "\n"; tout << "pp_u = "; pp_u->display(tout, m_manager, true); tout << "\n"; @@ -4113,11 +4114,11 @@ namespace polynomial { m().gcd(ci_u, ci_v, ci_g); euclid_gcd(c_u, c_v, c_g); euclid_gcd(lc_u, lc_v, lc_g); - TRACE("mgcd_detail", + TRACE("mgcd_detail", tout << "c_g = "; c_g->display(tout, m_manager, true); tout << "\n"; tout << "lc_g = "; lc_g->display(tout, m_manager, true); tout << "\n"; tout << "ci_g = " << ci_g << "\n";); - + skeleton * sk = m_mgcd_skeletons[idx]; // use dense interpolation if skeleton is not available @@ -4148,16 +4149,16 @@ namespace polynomial { q = mul(lc_g_val, q); var q_var = max_var(q); unsigned deg_q = q_var == null_var ? 0 : degree(q, q_var); - TRACE("mgcd_detail", tout << "counter: " << counter << "\nidx: " << idx << "\nq: " << q << "\ndeg_q: " << deg_q << "\nmin_deg_q: " << + TRACE("mgcd_detail", tout << "counter: " << counter << "\nidx: " << idx << "\nq: " << q << "\ndeg_q: " << deg_q << "\nmin_deg_q: " << min_deg_q << "\nnext_x: x" << vars[idx+1] << "\nmax_var(q): " << q_var << "\n";); if (deg_q < min_deg_q) { - TRACE("mgcd_detail", tout << "reseting...\n";); + TRACE("mgcd_detail", tout << "reseting...\n";); counter = 0; min_deg_q = deg_q; // start from scratch if (sk == 0) { interpolator.reset(); - interpolator.add(val, q); + interpolator.add(val, q); } else { sinterpolator.reset(); @@ -4166,9 +4167,9 @@ namespace polynomial { } } else if (deg_q == min_deg_q) { - TRACE("mgcd_detail", tout << "adding sample point...\n";); + TRACE("mgcd_detail", tout << "adding sample point...\n";); if (sk == 0) { - interpolator.add(val, q); + interpolator.add(val, q); } else { if (!sinterpolator.add(val, q)) @@ -4197,10 +4198,10 @@ namespace polynomial { found_candidate = true; } } - + bool done = false; if (found_candidate) { - if (degree(H, x) > 0) + if (degree(H, x) > 0) primitive_ZpX(H, x, C); else C = normalize(H); @@ -4220,7 +4221,7 @@ namespace polynomial { throw sparse_mgcd_failed(); } } - + if (done) { TRACE("mgcd", tout << "idx: " << idx << "\nresult: " << r << "\n";); if (sk == 0 && m_use_sparse_gcd) { @@ -4234,8 +4235,8 @@ namespace polynomial { } // Multivariate modular GCD algorithm - void mod_gcd(polynomial const * u, polynomial const * v, - power_buffer const & u_var_degrees, power_buffer const & v_var_degrees, + void mod_gcd(polynomial const * u, polynomial const * v, + power_buffer const & u_var_degrees, power_buffer const & v_var_degrees, polynomial_ref & r) { m_mgcd_iterpolators.set_owner(this); TRACE("mgcd", tout << "mod_gcd\nu: "; u->display(tout, m_manager, true); tout << "\nv: "; v->display(tout, m_manager, true); tout << "\n";); @@ -4264,10 +4265,10 @@ namespace polynomial { polynomial_ref pp_u(pm()), pp_v(pm()); ic(u, c_u, pp_u); ic(v, c_v, pp_v); - + scoped_numeral d_a(m()); m_manager.gcd(c_u, c_v, d_a); - + unsigned mm_u_pos = pp_u->graded_lex_max_pos(); // position of the maximal monomial in u unsigned mm_v_pos = pp_v->graded_lex_max_pos(); // position of the maximal monomial in v scoped_numeral lc_u(m()); @@ -4284,7 +4285,7 @@ namespace polynomial { polynomial_ref q(m_wrapper); polynomial_ref candidate(m_wrapper); scoped_numeral p(m()); - + for (unsigned i = 0; i < NUM_BIG_PRIMES; i++) { m().set(p, g_big_primes[i]); TRACE("mgcd", tout << "trying prime: " << p << "\n";); @@ -4336,8 +4337,8 @@ namespace polynomial { TRACE("mgcd", tout << "candidate:\n" << candidate << "\n";); scoped_numeral lc_candidate(m()); lc_candidate = candidate->a(candidate->graded_lex_max_pos()); - if (m().divides(lc_candidate, lc_g) && - divides(candidate, pp_u) && + if (m().divides(lc_candidate, lc_g) && + divides(candidate, pp_u) && divides(candidate, pp_v)) { TRACE("mgcd", tout << "found GCD\n";); r = mul(d_a, candidate); @@ -4350,18 +4351,18 @@ namespace polynomial { // fallback to prs gcd_prs(u, v, max_var(u), r); } - + void gcd(polynomial const * u, polynomial const * v, polynomial_ref & r) { power_buffer u_var_degrees; power_buffer v_var_degrees; TRACE("gcd_calls", tout << "gcd\nu: "; u->display(tout, m_manager); tout << "\nv: "; v->display(tout, m_manager); tout << "\n";); - TRACE("polynomial_gcd", + TRACE("polynomial_gcd", tout << "gcd\nu: "; u->display(tout, m_manager); tout << "\nv: "; v->display(tout, m_manager); tout << "\nis_zero(u): " << is_zero(u) << ", is_const(u): " << is_const(u) << "\n"; tout << "is_zero(v): " << is_zero(v) << ", is_const(v): " << is_const(v) << "\n"; tout << "modular: " << m().modular() << "\n";); if (is_zero(u)) { - r = const_cast(v); + r = const_cast(v); flip_sign_if_lm_neg(r); return; } @@ -4375,7 +4376,7 @@ namespace polynomial { flip_sign_if_lm_neg(r); return; } - if (is_const(u) || is_const(v)) { + if (is_const(u) || is_const(v)) { scoped_numeral i_u(m_manager), i_v(m_manager); ic(v, i_v); ic(u, i_u); @@ -4384,12 +4385,12 @@ namespace polynomial { r = mk_const(a); return; } - + // Search for a variable x that occurs only in u or v. var_max_degrees(u, u_var_degrees); std::sort(u_var_degrees.begin(), u_var_degrees.end(), power::lt_var()); var_max_degrees(v, v_var_degrees); std::sort(v_var_degrees.begin(), v_var_degrees.end(), power::lt_var()); - TRACE("polynomial_gcd", + TRACE("polynomial_gcd", tout << "u var info\n"; for (unsigned i = 0; i < u_var_degrees.size(); i++) tout << u_var_degrees[i] << " "; tout << "\n"; tout << "v var info\n"; for (unsigned i = 0; i < v_var_degrees.size(); i++) tout << v_var_degrees[i] << " "; tout << "\n";); var x = null_var; @@ -4451,7 +4452,7 @@ namespace polynomial { SASSERT(max_var(u) == x); #if 0 unsigned min_k = std::max(m_u_var_degrees[sz - 1].degree(), m_v_var_degrees[sz - 1].degree()); - unsigned max_var_bias = 2; // the basic procedures are optimized for operating on the maximal variable. So, we have a bias to select the maximal one + unsigned max_var_bias = 2; // the basic procedures are optimized for operating on the maximal variable. So, we have a bias to select the maximal one if (min_k > max_var_bias) { min_k -= max_var_bias; i = sz - 1; @@ -4484,7 +4485,7 @@ namespace polynomial { #endif mod_gcd(u, v, u_var_degrees, v_var_degrees, r); - + #ifdef Z3DEBUG if (is_debug_enabled("mgcd_check")) { polynomial_ref r2(m_wrapper); @@ -4538,7 +4539,7 @@ namespace polynomial { r = const_cast(p); return; } - + var x = max_var(p); scoped_numeral i(m_manager); polynomial_ref c(pm()), pp(pm()); @@ -4579,7 +4580,7 @@ namespace polynomial { r = const_cast(p); return; } - + polynomial_ref p_prime(pm()); p_prime = derivative(p, x); polynomial_ref g(pm()); @@ -4713,7 +4714,7 @@ namespace polynomial { monomial * m = p->m(i); SASSERT(m->size() <= 1); monomial * new_m; - if (m->size() == 0) + if (m->size() == 0) new_m = m; else new_m = mk_monomial(y, m->degree(0)); @@ -4780,7 +4781,7 @@ namespace polynomial { // on exit. struct scoped_degree2pos { imp& pm; - polynomial const* p; + polynomial const* p; scoped_degree2pos(imp& pm, polynomial const* p): pm(pm), p(p) @@ -4804,7 +4805,7 @@ namespace polynomial { return; } var x = max_var(p); - unsigned d = degree(p, x); + unsigned d = degree(p, x); scoped_degree2pos _sd2pos(*this, p); scoped_numeral a(m()); m_manager.set(a, p->a(m_degree2pos[d])); @@ -4815,7 +4816,7 @@ namespace polynomial { m_manager.set(a, p->a(pos)); else m_manager.reset(a); - r = muladd(q, r, a); + r = muladd(q, r, a); } } @@ -4828,13 +4829,13 @@ namespace polynomial { var xs[2] = { x, y }; return mk_linear(2, as, xs, zero); } - + void compose_x_minus_y(polynomial const * p, var y, polynomial_ref & r) { SASSERT(is_valid(y)); SASSERT(is_univariate(p)); var x = max_var(p); if (y == max_var(p)) { - r = coeff(p, x, 0); + r = coeff(p, x, 0); return; } polynomial_ref x_minus_y(pm()); @@ -4887,7 +4888,7 @@ namespace polynomial { /** \brief Template for computing several variations of pseudo division algorithm. If degree(p) < degree(q) --> Q = m_zero, d = 0, R = p - + The following property is guaranteed by this method l(q)^d * p = Q * q + R @@ -4897,20 +4898,20 @@ namespace polynomial { Possible configurations: Exact_d == true, then d = degree(p) - degree(q) + 1. If Exact_d == false, then d <= degree(p) - degree(q) + 1. - + If Quotient == false, Q is not computed. If ModD == true, then x2d must be different from 0. - Moreover, p and q are assumed to be normalized modulo x2d. + Moreover, p and q are assumed to be normalized modulo x2d. For all x, x2d->degree(x) > 0 implies degree(p, x) < x2d->degree(x) and degree(q, x) < x2d->degree(x) Moreover, the division algorithm will compute Q and R modulo x2d. */ template - void pseudo_division_core(polynomial const * p, polynomial const * q, var x, unsigned & d, polynomial_ref & Q, polynomial_ref & R, + void pseudo_division_core(polynomial const * p, polynomial const * q, var x, unsigned & d, polynomial_ref & Q, polynomial_ref & R, var2degree const * x2d = 0) { SASSERT(is_valid(x)); SASSERT(!ModD || x2d != 0); - TRACE("polynomial", tout << "pseudo_division\np: "; p->display(tout, m_manager); + TRACE("polynomial", tout << "pseudo_division\np: "; p->display(tout, m_manager); tout << "\nq: "; q->display(tout, m_manager); tout << "\nx: " << x << "\n";); polynomial * A = const_cast(p); polynomial * B = const_cast(q); @@ -4960,7 +4961,7 @@ namespace polynomial { tout << "A: "; A->display(tout, m_manager); tout << "\n"; tout << "B: "; B->display(tout, m_manager); tout << "\n"; tout << "l_B: "; l_B->display(tout, m_manager); tout << "\n"; - tout << "r_B: "; r_B->display(tout, m_manager); tout << "\n"; + tout << "r_B: "; r_B->display(tout, m_manager); tout << "\n"; tout << "Q: "; Q->display(tout, m_manager); tout << "\n"; tout << "R: "; R->display(tout, m_manager); tout << "\n"; tout << "d: " << d << "\n";); @@ -4977,7 +4978,7 @@ namespace polynomial { TRACE("polynomial", tout << "l_B_e: " << l_B_e << "\n";); if (Quotient) { Q = mul(l_B_e, Q); - if (ModD) + if (ModD) Q = mod_d(Q, *x2d); } R = mul(l_B_e, R); @@ -4992,19 +4993,19 @@ namespace polynomial { // Note that the goal is to cancel x^deg_R in R. // m_som_buffer will contain the new monomials of R. m_som_buffer.reset(); - // We can accomplish that by traversing the current R, and + // We can accomplish that by traversing the current R, and // - For each monomial a * m * x^deg_R --> m_som_buffer.addmul(-a, m * x^(deg_R - deg_B), r_B) // Note that m*x^(deg_R - deg_B) is div_x_k(m*x^deg_R, deg_B) - // - For other monomials a*m, ---> m_som_buffer.addmul(a, m, l_B) + // - For other monomials a*m, ---> m_som_buffer.addmul(a, m, l_B) // Note that, with this trick and don't need to create the temporary polynomials l_B * R and S * B // // If the quotient needs to be computed, we have that // S <- l_R * x^(deg_R - deg_B) // Q <- l_B * Q + S // The new monomials of Q are stored in m_som_buffer2 - // When traversing R, for each monomial a*m*x^deg_R we add m_som_buffer2.add(a, m*x^(deg_R - deg_B)) + // When traversing R, for each monomial a*m*x^deg_R we add m_som_buffer2.add(a, m*x^(deg_R - deg_B)) m_som_buffer2.reset(); - // + // unsigned sz = R->size(); for (unsigned i = 0; i < sz; i++) { monomial * m = R->m(i); @@ -5012,7 +5013,7 @@ namespace polynomial { if (m->degree_of(x) == deg_R) { monomial_ref m_prime(pm()); m_prime = div_x_k(m, x, deg_B); - CTRACE("polynomial", m->degree_of(x) != deg_R - deg_B, + CTRACE("polynomial", m->degree_of(x) != deg_R - deg_B, tout << "deg_R: " << deg_R << ", deg_B: " << deg_B << ", x: " << x << "\n"; m->display(tout); tout << ", "; m_prime->display(tout); tout << "\n";); SASSERT(m->degree_of(x) == deg_R); @@ -5073,7 +5074,7 @@ namespace polynomial { rhs = mul(Q, old_q); rhs = add(rhs, R); bool is_eq = eq(lhs, rhs); - TRACE("pseudo_remainder", + TRACE("pseudo_remainder", tout << "pseudo_division bug\n"; tout << "p: "; old_p->display(tout, m_manager); tout << "\n"; tout << "q: "; old_q->display(tout, m_manager); tout << "\n"; @@ -5097,7 +5098,7 @@ namespace polynomial { polynomial * exact_div(polynomial const * p, numeral const & c) { SASSERT(!m().is_zero(c)); - + som_buffer & R = m_som_buffer; R.reset(); @@ -5153,7 +5154,7 @@ namespace polynomial { R.addmul(a_r_q, m_r_q, q); // R <- R - (a_r/a_q)*(m_r/m_q)*Q } } - + // Return true if q divides p. bool divides(polynomial const * q, polynomial const * p) { TRACE("polynomial", tout << "divides\nq: "; q->display(tout, m_manager); tout << "\np: "; p->display(tout, m_manager); tout << "\n";); @@ -5197,21 +5198,21 @@ namespace polynomial { void quasi_resultant(polynomial const * p, polynomial const * q, var x, polynomial_ref & r) { // For h_0 = p and h_1 = q, we compute the following sequence // using the pseudo remainder procedure - // + // // l(h_1)^d_1 * h_0 = q_1 * h_1 + h_2 // l(h_2)^d_2 * h_1 = q_2 * h_2 + h_3 // l(h_3)^d_3 * h_2 = q_3 * h_3 + h_4 // ... // l(h_n)^d_n * h_{n-1} = q_n * h_n + h_{n+1} // - // where + // where // degree(h_i, x) > 0 for all i in [0, n], and // degree(h_{n+1}, x) == 0 // // l(h_i) is the leading coefficient of h_i with respect to variable x. // l(h_i) is in general a polynomial. // For example, l( y*x^2 + x^2 + y^2 x + 1 ) = y + 1 - // + // // d^i is an unsigned integer. It is introduce by the pseudo remainder procedure // because the coefficients of x^k do not form a field. That is, they are elements of a polynomial ring Q[y_1, ..., y_n]. // Their values are irrelevant for the correctness of this procedure. @@ -5225,20 +5226,20 @@ namespace polynomial { // if h_0(a_1, ..., a_n, b) = h_1(a_1, ..., a_n, b) = 0 // then for any h_i in the sequence, h_i(a_1, ..., a_n, b) = 0. // In particular, h_{n+1}(a_1, ..., a_n) = 0 - // + // // Observation 3: - // The procedure terminates because degree(h_i, x) > degree(h_{i+1}, x) + // The procedure terminates because degree(h_i, x) > degree(h_{i+1}, x) // for all i >= 1 // // Observation 4: - // If h_{n+1} is the zero polynomial, then + // If h_{n+1} is the zero polynomial, then // For any complex numbers a_1, ..., a_n // the univariate polynomials p(a_1, ..., a_n, x) and q(a_1, ..., a_n, x) in C[x] // have a common root. - // Reason: + // Reason: // If h_n(a_1, ..., a_n, x) is not the zero polynomial, then it is the GCD of p(a_1, ..., a_n, x) and q(a_1, ..., a_n, x), // and it contains the common roots. - // If h_n(a_1, ..., a_n, x) is the zero polynomial, then + // If h_n(a_1, ..., a_n, x) is the zero polynomial, then // we consider h_{n-1}(a_1, ..., a_n, x). If it is not the zero polynomial then it is the GCD and we are done, // otherwise we consider h_{n-2}(a_1, ..., a_n, x), and we continue the same process. // Thus, eventually we find a h_i(a_1, ..., a_n, x) for i > 1 that is the GCD, or q(a_1, ..., a_n, x) is the zero polynomial, @@ -5274,7 +5275,7 @@ namespace polynomial { // degree(h_2, x) < degree(h_1, x) } } - + // sign = sign * (-1)^(deg_A * deg_B) static void update_sign(unsigned deg_A, unsigned deg_B, bool & sign) { if (deg_A % 2 == 0 || deg_B % 2 == 0) @@ -5290,14 +5291,14 @@ namespace polynomial { the coefficients of p and q with respect to x. Given p and q polynomials in Q[y_1, ..., y_n, x], r is a polynomial in Q[y_1, ..., y_n]. - + Property 1) If p and q can be written as p = a_m * (x - alpha_1) * ... * (x - alpha_m) q = b_n * (x - beta_1) * ... * (x - beta_n) - Then, + Then, Res(p, q, x) = a_m^n * b_n^m * Product_{i in [1,m], j in [1, n]} (alpha_i - beta_j) - + Remark: if p and q are univariate polynomials, then alpha_i's and beta_j's are the roots of p and q, then Res(p, q, x) is the product of the differences of their roots modulo a constant. @@ -5307,10 +5308,10 @@ namespace polynomial { if p(a_1, ..., a_n, b) = q(a_1, ..., a_n, b) = 0, then r(a_1, ..., b_n) = 0 Property 3) - There are polynomials U and V in Q[y_1, ..., y_n, x] s.t. + There are polynomials U and V in Q[y_1, ..., y_n, x] s.t. p*U + q*V = r s.t. - deg(U, x) < deg(q, x) + deg(U, x) < deg(q, x) and deg(V, x) < deg(p, x) @@ -5318,7 +5319,7 @@ namespace polynomial { Property 4) (follows from 1) If Res(p, q, x) = 0, then p and q have a common divisor. - + Resultant Calculus: Let A and B be two polynomials of degree m and n on variable x. Let c and d be numerals. @@ -5330,7 +5331,7 @@ namespace polynomial { Res(c, d, x) = 1 Res(A, B1*B2, x) = Res(A, B1, x)*Res(A, B2, x) Res(A, A*Q + B, x) = coeff(A, x)^(l-n) * Res(A, B, x) where l = deg(A*Q + R) - + The last equation suggests an approach for computing the Resultant using pseudo-division instead of determinants. @@ -5340,7 +5341,7 @@ namespace polynomial { pseudo_division(A, B, x, d, Q, R); r = degree(R) Then we have: - (lc^d)^n * Res(A, B) = Res(A * l^d, B) = Res(Q * B + R, B) = (-1)^(m*n) * Res(B, Q * B + R) = (-1)^(m*n) * lc^(m-r) * Res(B, R) + (lc^d)^n * Res(A, B) = Res(A * l^d, B) = Res(Q * B + R, B) = (-1)^(m*n) * Res(B, Q * B + R) = (-1)^(m*n) * lc^(m-r) * Res(B, R) So, lc^(d*n) * Res(A, B) = (-1)^(m*n) * lc^(m-r) * Res(B, R) @@ -5351,7 +5352,7 @@ namespace polynomial { d*n >= m >= m-r - So, if d*n == m-r + So, if d*n == m-r Res(A, B) = (-1)^(m*n) * Res(R, B) if d*n > m-r Res(A, B) = (-1)^(m*n) * exact_div(Res(R, B), lc^(d*n - m + r)) @@ -5383,7 +5384,7 @@ namespace polynomial { pw(B, degree(A, x), result); return; } - + // decompose A and B into // A = iA*cA*ppA // B = iB*cB*ppB @@ -5402,7 +5403,7 @@ namespace polynomial { t = mul(cA, cB); A = ppA; B = ppB; - // + // TRACE("resultant", tout << "resultant(A, B, x) after normalization\nA: " << A << "\nB: " << B << "\nx: " << x << "\n"; tout << "t: " << t << "\n";); @@ -5509,7 +5510,7 @@ namespace polynomial { std::swap(deg_p, deg_q); } SASSERT(deg_p > 0); - unsigned n = deg_p; + unsigned n = deg_p; sRes.reset(); sRes.resize(n + 1); // the sequence is from 0 ... n sRes.set(n, const_cast(p)); @@ -5522,17 +5523,17 @@ namespace polynomial { unsigned j = n - 1; while (j > 0) { SASSERT(degree(sRes.get(j+1), x) == j+1); // sRes_{j+1} is regular - if (j == n-1) + if (j == n-1) R_j_plus_1 = mk_one(); // by definition of PSC chain else R_j_plus_1 = coeff(sRes.get(j+1), x, j+1); unsigned r = degree(sRes.get(j), x); if (r == j) { // sRes_j is regular - + exact_pseudo_remainder(sRes.get(j+1), sRes.get(j), x, prem); TRACE("psc", tout << "j: " << j << "\nsRes_j+1: "; sRes.get(j+1)->display(tout, m_manager); - tout << "\nsRes_j: "; sRes.get(j)->display(tout, m_manager); + tout << "\nsRes_j: "; sRes.get(j)->display(tout, m_manager); tout << "\nprem: " << prem << "\n";); // sRes_{j-1} = prem/R_j_plus_1^2 newS = exact_div(prem, R_j_plus_1); @@ -5543,7 +5544,7 @@ namespace polynomial { else { SASSERT(r < j); // sRes_j is defective - + // sRes_{j-1} = sRes_{j-2} = ... = sRes_{r+1} = 0 for (int i = j-1; i >= static_cast(r+1); i--) sRes.set(i, mk_zero()); @@ -5555,7 +5556,7 @@ namespace polynomial { for (unsigned i = 0; i < j-r; i++) newS = exact_div(newS, R_j_plus_1); sRes.set(r, newS); - + // If r > 0, we also compute sRes_{r-1} if (r > 0) { exact_pseudo_remainder(sRes.get(j+1), sRes.get(j), x, prem); @@ -5578,7 +5579,7 @@ namespace polynomial { void psc_chain1(polynomial const * p, polynomial const * q, var x, polynomial_ref_vector & S) { subresultant_chain(p, q, x, S); unsigned sz = S.size(); - TRACE("psc", tout << "subresultant_chain\n"; + TRACE("psc", tout << "subresultant_chain\n"; for (unsigned i = 0; i < sz; i++) { tout << "i: " << i << " "; S.get(i)->display(tout, m_manager); tout << "\n"; }); for (unsigned i = 0; i < sz - 1; i++) { S.set(i, coeff(S.get(i), x, i)); @@ -5599,27 +5600,27 @@ namespace polynomial { unsigned n2 = degree(B, x); if (n1 > n2) { G1 = const_cast(A); - G2 = const_cast(B); + G2 = const_cast(B); } else { G1 = const_cast(B); - G2 = const_cast(A); + G2 = const_cast(A); std::swap(n1, n2); } unsigned d0 = 0; unsigned d1 = n1 - n2; unsigned i = 1; - unsigned n3; + unsigned n3; S.reset(); while (true) { // Compute Gh_{i+2} if (!is_zero(G2)) { exact_pseudo_remainder(G1, G2, x, Gh3); n3 = degree(Gh3, x); - if (!is_zero(Gh3) && d1%2 == 0) + if (!is_zero(Gh3) && d1%2 == 0) Gh3 = neg(Gh3); } - + // Compute hi if (i > 1) { g1 = lc(G1, x); @@ -5632,9 +5633,9 @@ namespace polynomial { std::reverse(S.c_ptr(), S.c_ptr() + S.size()); return; } - } + } } - + // Compute G_{i+2} if (i == 1 || is_zero(Gh3)) { G3 = Gh3; @@ -5643,9 +5644,9 @@ namespace polynomial { pw(h1, d1, hs1); hs1 = mul(g1, hs1); G3 = exact_div(Gh3, hs1); - hs1 = 0; + hs1 = 0; } - + // prepare for next iteration n1 = n2; n2 = n3; @@ -5659,7 +5660,7 @@ namespace polynomial { } } - // Optimized calculation of S_e using "Dichotomous Lazard" + // Optimized calculation of S_e using "Dichotomous Lazard" void Se_Lazard(unsigned d, polynomial const * lc_S_d, polynomial const * S_d_1, var x, polynomial_ref & S_e) { unsigned n = d - degree(S_d_1, x) - 1; TRACE("Lazard", tout << "lc_S_d: "; lc_S_d->display(tout, m_manager); tout << "\nS_d_1: "; S_d_1->display(tout, m_manager); @@ -5673,7 +5674,7 @@ namespace polynomial { polynomial const * Y = lc_S_d; unsigned a = 1 << log2(n); TRACE("Lazard", tout << "a: " << a << "\n";); - SASSERT(a <= n); + SASSERT(a <= n); SASSERT(n < 2*a); polynomial_ref C(pm()); C = X; @@ -5698,7 +5699,7 @@ namespace polynomial { } // Optimized calculation of S_{e-1} for optimized psc_chain - void optimized_S_e_1(unsigned d, unsigned e, polynomial const * A, polynomial const * S_d_1, polynomial const * S_e, polynomial const * s, + void optimized_S_e_1(unsigned d, unsigned e, polynomial const * A, polynomial const * S_d_1, polynomial const * S_e, polynomial const * s, var x, polynomial_ref & S_e_1) { SASSERT(d == degree(A, x)); SASSERT(e == degree(S_d_1, x)); @@ -5750,7 +5751,7 @@ namespace polynomial { S_e_1 = exact_div(S_e_1, s); if ((d-e+1) % 2 == 1) S_e_1 = neg(S_e_1); - } + } void psc_chain_optimized_core(polynomial const * P, polynomial const * Q, var x, polynomial_ref_vector & S) { TRACE("psc_chain_classic", tout << "P: "; P->display(tout, m_manager); tout << "\nQ: "; Q->display(tout, m_manager); tout << "\n";); @@ -5758,7 +5759,7 @@ namespace polynomial { unsigned degQ = degree(Q, x); SASSERT(degP >= degQ); polynomial_ref A(pm()), B(pm()), C(pm()), minus_Q(pm()), lc_Q(pm()), ps(pm()); - + lc_Q = lc(Q, x); polynomial_ref s(pm()); // s <- lc(Q)^(deg(P)-deg(Q)) @@ -5812,7 +5813,7 @@ namespace polynomial { if (degree(P, x) >= degree(Q, x)) psc_chain_optimized_core(P, Q, x, S); else - psc_chain_optimized_core(Q, P, x, S); + psc_chain_optimized_core(Q, P, x, S); if (S.empty()) S.push_back(mk_zero()); std::reverse(S.c_ptr(), S.c_ptr() + S.size()); @@ -5825,7 +5826,7 @@ namespace polynomial { SASSERT(degP >= degQ); polynomial_ref A(pm()), B(pm()), C(pm()), minus_Q(pm()), lc_Q(pm()), lc_B(pm()), lc_A(pm()); polynomial_ref tmp1(pm()), tmp2(pm()), s_delta(pm()), minus_B(pm()), ps(pm()); - + lc_Q = lc(Q, x); polynomial_ref s(pm()); // s <- lc(Q)^(deg(P)-deg(Q)) @@ -5862,7 +5863,7 @@ namespace polynomial { ps = coeff(C, x, e); if (!is_zero(ps)) S.push_back(ps); - + } else { SASSERT(delta == 0 || delta == 1); @@ -5892,7 +5893,7 @@ namespace polynomial { if (degree(P, x) >= degree(Q, x)) psc_chain_classic_core(P, Q, x, S); else - psc_chain_classic_core(Q, P, x, S); + psc_chain_classic_core(Q, P, x, S); if (S.empty()) S.push_back(mk_zero()); std::reverse(S.c_ptr(), S.c_ptr() + S.size()); @@ -5958,7 +5959,7 @@ namespace polynomial { bool is_perfect_square(polynomial const * p, unsigned i, numeral & sqrt_a) { monomial * m = p->m(i); if (!m->is_square()) - return false; + return false; numeral const & a = p->a(i); if (!m_manager.is_perfect_square(a, sqrt_a)) return false; @@ -5972,7 +5973,7 @@ namespace polynomial { return true; } scoped_numeral a(m_manager); - TRACE("sqrt_bug", + TRACE("sqrt_bug", tout << "sqrt: "; p->display(tout, m_manager); tout << "\n"; tout << "min pos: " << p->graded_lex_min_pos() << "\n"; tout << "max pos: " << p->graded_lex_max_pos() << "\n";); @@ -6010,7 +6011,7 @@ namespace polynomial { SASSERT(m1 != 0); som_buffer & R = m_som_buffer; som_buffer & C = m_som_buffer2; - R.reset(); + R.reset(); C.reset(); numeral two; m_manager.set(two, 2); @@ -6024,7 +6025,7 @@ namespace polynomial { if (i == max_pos) continue; C.add(p->a(i), p->m(i)); - } + } scoped_numeral a_i(m_manager); scoped_numeral aux(m_manager); monomial_ref m_aux(pm()); @@ -6050,7 +6051,7 @@ namespace polynomial { if (!m_manager.divides(two_a, C.a(curr_max))) return false; m_manager.div(C.a(curr_max), two_a, a_i); - + // C <- C - 2*R*a_i*m_i - a_i*a_i*m_i*m_i unsigned R_sz = R.size(); for (unsigned j = 0; j < R_sz; j++) { @@ -6076,7 +6077,7 @@ namespace polynomial { tout << "polynomials before rename\n"; for (unsigned i = 0; i < m_polynomials.size(); i++) { if (m_polynomials[i] == 0) - continue; + continue; m_polynomials[i]->display(tout, m_manager); tout << "\n"; }); @@ -6092,7 +6093,7 @@ namespace polynomial { p->make_first_maximal(); SASSERT(p->size() <= 1 || !p->lex_sorted()); } - TRACE("rename", + TRACE("rename", tout << "polynomials after rename\n"; for (unsigned i = 0; i < m_polynomials.size(); i++) { if (m_polynomials[i] == 0) @@ -6129,7 +6130,7 @@ namespace polynomial { } return found_unit; } - + bool is_nonpos(polynomial const * p) { unsigned sz = p->size(); for (unsigned i = 0; i < sz; i++) { @@ -6151,10 +6152,10 @@ namespace polynomial { } return true; } - + // Functor used to compute the maximal degree of each variable in a polynomial p. class var_max_degree { - unsigned_vector m_max_degree; + unsigned_vector m_max_degree; var_vector m_xs; public: void init(polynomial const * p) { @@ -6174,7 +6175,7 @@ namespace polynomial { } } } - + void reset() { unsigned sz = m_xs.size(); for (unsigned i = 0; i < sz; i++) { @@ -6188,7 +6189,7 @@ namespace polynomial { } unsigned num_vars() const { return m_xs.size(); } - + var const * vars() const { return m_xs.c_ptr(); } }; @@ -6230,7 +6231,7 @@ namespace polynomial { m_found_vars.reserve(num_vars(), false); m_som_buffer.reset(); som_buffer & R = m_som_buffer; - tmp_monomial & new_m = m_tmp1; + tmp_monomial & new_m = m_tmp1; unsigned sz = p->size(); for (unsigned i = 0; i < sz; i++) { monomial * m = p->m(i); @@ -6284,14 +6285,14 @@ namespace polynomial { struct var_pos { unsigned_vector m_pos; - + void init(unsigned sz, var const * xs) { for (unsigned i = 0; i < sz; i++) { SASSERT(m_pos.get(xs[i], UINT_MAX) == UINT_MAX); m_pos.setx(xs[i], i, UINT_MAX); } } - + void reset(unsigned sz, var const * xs) { for (unsigned i = 0; i < sz; i++) { SASSERT(m_pos.get(xs[i], UINT_MAX) != UINT_MAX); @@ -6330,8 +6331,8 @@ namespace polynomial { virtual unsynch_mpq_manager & m() const { UNREACHABLE(); static unsynch_mpq_manager m; return m; } virtual bool contains(var x) const { return m_var_pos(x) != UINT_MAX; } virtual mpq const & operator()(var x) const { return m_vs[m_var_pos(x)]; } - }; - + }; + polynomial * substitute(polynomial const * p, unsigned xs_sz, var const * xs, mpq const * vs) { var2mpq_wrapper x2v(xs_sz, xs, vs, m_var_pos); return substitute(p, x2v); @@ -6345,7 +6346,7 @@ namespace polynomial { scoped_numeral tmp(m_manager); m_som_buffer.reset(); som_buffer & R = m_som_buffer; - tmp_monomial & new_m = m_tmp1; + tmp_monomial & new_m = m_tmp1; unsigned sz = p->size(); for (unsigned i = 0; i < sz; i++) { monomial * m = p->m(i); @@ -6375,7 +6376,7 @@ namespace polynomial { return R.mk(); } - + /** Auxiliary method used to implement t_eval. If evaluates the sub-polynomial p composed of the monomials at positions [start, end) @@ -6420,7 +6421,7 @@ namespace polynomial { var y = p->max_smaller_than(i, end, x); if (y == null_var) { SASSERT(end == i+1); - vm.add(r, p->a(i), r); + vm.add(r, p->a(i), r); } else { t_eval_core(p, vm, x2v, i, end, y, aux.get()); @@ -6472,7 +6473,7 @@ namespace polynomial { lex_sort(p); // lex_sort just reorders the monomials of p. That is, p still represents the same polynomial t_eval_core(p, vm, x2v, 0, p->size(), max_var(p), r); } - + class single_var2value : public var2value { numeral_manager & m_manager; var m_x; @@ -6486,14 +6487,14 @@ namespace polynomial { void univ_eval(polynomial const * p, var x, numeral const & val, numeral & r) { SASSERT(is_univariate(p)); - if (is_zero(p)) + if (is_zero(p)) m().set(r, 0); - else if (is_const(p)) + else if (is_const(p)) m().set(r, p->a(0)); else t_eval(const_cast(p), single_var2value(m(),x, val), r); } - + void eval(polynomial const * p, var2mpbqi const & x2v, mpbqi & r) { t_eval(const_cast(p), x2v, r); } @@ -6583,7 +6584,7 @@ namespace polynomial { m_manager.set(m_four, -4); disc = addmul(b2, m_four, mk_unit(), ac); // discriminant must be different from 0, since p is square free - SASSERT(!is_zero(disc)); + SASSERT(!is_zero(disc)); polynomial_ref disc_sqrt(pm()); TRACE("factor", tout << "disc: " << disc << "\n";); if (!sqrt(disc, disc_sqrt)) { @@ -6632,14 +6633,14 @@ namespace polynomial { r.push_back(f1, k); r.push_back(f2, k); } - + void factor_sqf_pp_univ(polynomial const * p, factors & r, unsigned k, factor_params const & params) { SASSERT(is_univariate(p)); SASSERT(is_square_free(p, max_var(p))); SASSERT(is_primitive(p, max_var(p))); SASSERT(!is_zero(p)); TRACE("factor", tout << "factor square free univariate:\n"; p->display(tout, m_manager); tout << "\n";); - + // Convert polynomial into a upolynomial, and execute univariate factorization. var x = max_var(p); up_manager::scoped_numeral_vector p1(upm().m()); @@ -6664,7 +6665,7 @@ namespace polynomial { numeral_vector const & f1 = fs[i]; unsigned k1 = fs.get_degree(i); f = to_polynomial(f1.size(), f1.c_ptr(), x); - TRACE("factor_bug", + TRACE("factor_bug", tout << "uni-factor:\n"; upm().display(tout, f1); tout << "\n"; tout << "factor:\n" << f << "\n";); r.push_back(f, k*k1); @@ -6681,7 +6682,7 @@ namespace polynomial { SASSERT(is_primitive(p, x)); SASSERT(is_square_free(p, x)); TRACE("factor", tout << "factor square free (degree > 2):\n"; p->display(tout, m_manager); tout << "\n";); - + // TODO: invoke Dejan's procedure r.push_back(const_cast(p), k); } @@ -6721,14 +6722,14 @@ namespace polynomial { TRACE("factor", tout << "i: " << i << "\n";); acc_constant(r, i); factor_core(c, r, params); - + polynomial_ref C(pm()); C = pp; // Let C be a primitive polynomial of the form: P_1^1 * P_2^2 * ... * P_k^k, where each P_i is square free - polynomial_ref C_prime(pm()); + polynomial_ref C_prime(pm()); C_prime = derivative(C, x); polynomial_ref B(pm()), A(pm()), D(pm()); - gcd(C, C_prime, B); + gcd(C, C_prime, B); if (is_const(B)) { // C must be of the form P_1 (square free) SASSERT(degree(C, x) > 0); @@ -6736,7 +6737,7 @@ namespace polynomial { } else { // B is of the form P_2 * P_3^2 * ... * P_k^{k-1} - A = exact_div(C, B); + A = exact_div(C, B); // A is of the form P_1 * P_2 * ... * P_k unsigned j = 1; while (!is_const(A)) { @@ -6922,7 +6923,7 @@ namespace polynomial { small_object_allocator & manager::allocator() const { return m_imp->mm().allocator(); } - + void manager::add_del_eh(del_eh * eh) { m_imp->add_del_eh(eh); } @@ -6930,7 +6931,7 @@ namespace polynomial { void manager::remove_del_eh(del_eh * eh) { m_imp->remove_del_eh(eh); } - + var manager::mk_var() { return m_imp->mk_var(); } @@ -6970,7 +6971,7 @@ namespace polynomial { unsigned manager::hash(polynomial const * p) { return m_imp->hash(p); } - + polynomial * manager::coeff(polynomial const * p, var x, unsigned k) { return m_imp->coeff(p, x, k); } @@ -7038,7 +7039,7 @@ namespace polynomial { polynomial * manager::mk_zero() { return m_imp->mk_zero(); } - + polynomial * manager::mk_const(numeral & a) { return m_imp->mk_const(a); } @@ -7083,7 +7084,7 @@ namespace polynomial { return m_imp->sub(p1, p2); } - polynomial * manager::addmul(numeral const & a1, monomial const * m1, polynomial const * p1, + polynomial * manager::addmul(numeral const & a1, monomial const * m1, polynomial const * p1, numeral const & a2, monomial const * m2, polynomial const * p2) { return m_imp->addmul(a1, m1, p1, a2, m2, p2); } @@ -7099,11 +7100,11 @@ namespace polynomial { polynomial * manager::mul(numeral const & a, polynomial const * p) { return m_imp->mul(a, p); } - + polynomial * manager::mul(rational const & a, polynomial const * p) { return m_imp->mul(a, p); } - + polynomial * manager::mul(polynomial const * p1, polynomial const * p2) { return m_imp->mul(p1, p2); } @@ -7115,7 +7116,7 @@ namespace polynomial { polynomial * manager::mul(monomial const * m, polynomial const * p) { return m_imp->mul(m, p); } - + void manager::pw(polynomial const * p, unsigned k, polynomial_ref & r) { m_imp->pw(p, k, r); } @@ -7160,7 +7161,7 @@ namespace polynomial { polynomial * manager::flip_sign_if_lm_neg(polynomial const * p) { return m_imp->flip_sign_if_lm_neg_core(p); } - + void manager::gcd(polynomial const * p, polynomial const * q, polynomial_ref & g) { m_imp->gcd(p, q, g); } @@ -7168,7 +7169,7 @@ namespace polynomial { polynomial * manager::derivative(polynomial const * p, var x) { return m_imp->derivative(p, x); } - + void manager::square_free(polynomial const * p, var x, polynomial_ref & r) { m_imp->square_free(p, x, r); } @@ -7252,7 +7253,7 @@ namespace polynomial { polynomial * manager::exact_div(polynomial const * p, numeral const & c) { return m_imp->exact_div(p, c); } - + bool manager::divides(polynomial const * q, polynomial const * p) { return m_imp->divides(q, p); } @@ -7333,7 +7334,7 @@ namespace polynomial { return m_imp->mod_d(p, x2d); } - void manager::exact_pseudo_division_mod_d(polynomial const * p, polynomial const * q, var x, var2degree const & x2d, + void manager::exact_pseudo_division_mod_d(polynomial const * p, polynomial const * q, var x, var2degree const & x2d, polynomial_ref & Q, polynomial_ref & R) { m_imp->exact_pseudo_division_mod_d(p, q, x, x2d, Q, R); } @@ -7345,7 +7346,7 @@ namespace polynomial { void manager::eval(polynomial const * p, var2mpq const & x2v, mpq & r) { return m_imp->eval(p, x2v, r); } - + void manager::eval(polynomial const * p, var2anum const & x2v, algebraic_numbers::anum & r) { return m_imp->eval(p, x2v, r); } @@ -7364,7 +7365,7 @@ namespace polynomial { } }; -polynomial::polynomial * convert(polynomial::manager & sm, polynomial::polynomial * p, polynomial::manager & tm, +polynomial::polynomial * convert(polynomial::manager & sm, polynomial::polynomial * p, polynomial::manager & tm, polynomial::var x, unsigned max_d) { ptr_buffer ms; polynomial::numeral_manager & nm = tm.m(); diff --git a/src/math/polynomial/upolynomial.cpp b/src/math/polynomial/upolynomial.cpp index 3068df33c..78ce912f4 100644 --- a/src/math/polynomial/upolynomial.cpp +++ b/src/math/polynomial/upolynomial.cpp @@ -8,12 +8,12 @@ Module Name: Abstract: Goodies for creating and handling univariate polynomials. - - A dense representation is much better for Root isolation algorithms, + + A dense representation is much better for Root isolation algorithms, encoding algebraic numbers, factorization, etc. We also use integers as the coefficients of univariate polynomials. - + Author: Leonardo (leonardo) 2011-11-29 @@ -26,21 +26,22 @@ Notes: #include"polynomial_primes.h" #include"buffer.h" #include"cooperate.h" +#include"common_msgs.h" namespace upolynomial { - core_manager::factors::factors(core_manager & upm): - m_upm(upm), - m_total_factors(0), - m_total_degree(0) { - nm().set(m_constant, 1); + core_manager::factors::factors(core_manager & upm): + m_upm(upm), + m_total_factors(0), + m_total_degree(0) { + nm().set(m_constant, 1); } - + core_manager::factors::~factors() { clear(); nm().del(m_constant); } - + void core_manager::factors::clear() { for (unsigned i = 0; i < m_factors.size(); ++ i) { m_upm.reset(m_factors[i]); @@ -104,19 +105,19 @@ namespace upolynomial { } } - numeral_manager & core_manager::factors::nm() const { - return m_upm.m(); - } + numeral_manager & core_manager::factors::nm() const { + return m_upm.m(); + } - void core_manager::factors::set_constant(numeral const & constant) { - nm().set(m_constant, constant); - } + void core_manager::factors::set_constant(numeral const & constant) { + nm().set(m_constant, constant); + } - void core_manager::factors::set_degree(unsigned i, unsigned degree) { + void core_manager::factors::set_degree(unsigned i, unsigned degree) { m_total_degree -= m_upm.degree(m_factors[i])*m_degrees[i]; - m_total_factors -= m_degrees[i]; - m_degrees[i] = degree; - m_total_factors += degree; + m_total_factors -= m_degrees[i]; + m_degrees[i] = degree; + m_total_factors += degree; m_total_degree += m_upm.degree(m_factors[i])*degree; } @@ -125,7 +126,7 @@ namespace upolynomial { m_total_degree += m_upm.degree(p)*m_degrees[i]; m_factors[i].swap(p); } - + void core_manager::factors::swap(factors & other) { m_factors.swap(other.m_factors); m_degrees.swap(other.m_degrees); @@ -154,8 +155,8 @@ namespace upolynomial { } void core_manager::checkpoint() { - if (!m_limit.inc()) - throw upolynomial_exception("canceled"); + if (!m_limit.inc()) + throw upolynomial_exception(Z3_CANCELED_MSG); cooperate("upolynomial"); } @@ -209,7 +210,7 @@ namespace upolynomial { set_size(sz, buffer); } - void core_manager::get_primitive_and_content(unsigned f_sz, numeral const * f, numeral_vector & pp, numeral & cont) { + void core_manager::get_primitive_and_content(unsigned f_sz, numeral const * f, numeral_vector & pp, numeral & cont) { SASSERT(f_sz > 0); m().gcd(f_sz, f, cont); SASSERT(m().is_pos(cont)); @@ -221,7 +222,7 @@ namespace upolynomial { for (unsigned i = 0; i < f_sz; i++) { if (!m().is_zero(f[i])) { m().div(f[i], cont, pp[i]); - } + } else { m().set(pp[i], 0); } @@ -252,7 +253,7 @@ namespace upolynomial { neg_core(sz, p, m_basic_tmp); buffer.swap(m_basic_tmp); } - + // buffer := p1 + p2 void core_manager::add_core(unsigned sz1, numeral const * p1, unsigned sz2, numeral const * p2, numeral_vector & buffer) { SASSERT(!is_alias(p1, buffer)); @@ -334,7 +335,7 @@ namespace upolynomial { numeral const & b_j = p2[j]; if (m().is_zero(b_j)) continue; - m().addmul(buffer[i+j], a_i, b_j, buffer[i+j]); + m().addmul(buffer[i+j], a_i, b_j, buffer[i+j]); } } set_size(new_sz, buffer); @@ -378,7 +379,7 @@ namespace upolynomial { return; for (unsigned i = 0; i < sz; i++) { #ifdef Z3DEBUG - scoped_numeral old_p_i(m()); + scoped_numeral old_p_i(m()); old_p_i = p[i]; #endif // Actual code @@ -387,7 +388,7 @@ namespace upolynomial { #ifdef Z3DEBUG scoped_numeral tmp(m()); m().mul(g, p[i], tmp); - CTRACE("div_bug", !m().eq(tmp, old_p_i), tout << "old(p[i]): " << m().to_string(old_p_i) << ", g: " << m().to_string(g) << ", p[i]: " << + CTRACE("div_bug", !m().eq(tmp, old_p_i), tout << "old(p[i]): " << m().to_string(old_p_i) << ", g: " << m().to_string(g) << ", p[i]: " << m().to_string(p[i]) << ", tmp: " << m().to_string(tmp) << "\n";); SASSERT(tmp == old_p_i); #endif @@ -428,7 +429,7 @@ namespace upolynomial { } // Pseudo division - void core_manager::div_rem_core(unsigned sz1, numeral const * p1, unsigned sz2, numeral const * p2, + void core_manager::div_rem_core(unsigned sz1, numeral const * p1, unsigned sz2, numeral const * p2, unsigned & d, numeral_vector & q, numeral_vector & r) { SASSERT(!is_alias(p1, q)); SASSERT(!is_alias(p2, q)); SASSERT(!is_alias(p1, r)); SASSERT(!is_alias(p2, r)); @@ -438,7 +439,7 @@ namespace upolynomial { set(sz1, p1, q); if (field()) { div(q, *p2); - } + } reset(r); return; } @@ -464,7 +465,7 @@ namespace upolynomial { set_size(qsz, q); return; } - unsigned m_n = sz1 - sz2; // m-n + unsigned m_n = sz1 - sz2; // m-n if (field()) { numeral & ratio = a_m; m().div(r[sz1 - 1], b_n, ratio); @@ -492,7 +493,7 @@ namespace upolynomial { } // Pseudo division - void core_manager::div_rem(unsigned sz1, numeral const * p1, unsigned sz2, numeral const * p2, unsigned & d, + void core_manager::div_rem(unsigned sz1, numeral const * p1, unsigned sz2, numeral const * p2, unsigned & d, numeral_vector & q, numeral_vector & r) { numeral_vector & _r = m_div_tmp1; numeral_vector & _q = m_div_tmp2; @@ -677,15 +678,15 @@ namespace upolynomial { scoped_numeral a1(m()); scoped_numeral a2(m()); m().mul(b2, inv2, a1); // a1 is the multiplicator for coefficients of C1 - m().mul(b1, inv1, a2); // a2 is the multiplicator for coefficients of C2 + m().mul(b1, inv1, a2); // a2 is the multiplicator for coefficients of C2 TRACE("CRA", tout << "a1: " << a1 << ", a2: " << a2 << "\n";); // new bound scoped_numeral new_bound(m()); - m().mul(b1, b2, new_bound); + m().mul(b1, b2, new_bound); scoped_numeral lower(m()); scoped_numeral upper(m()); scoped_numeral new_a(m()), tmp1(m()), tmp2(m()), tmp3(m()); - m().div(new_bound, 2, upper); + m().div(new_bound, 2, upper); m().set(lower, upper); m().neg(lower); TRACE("CRA", tout << "lower: " << lower << ", upper: " << upper << "\n";); @@ -700,7 +701,7 @@ namespace upolynomial { R.push_back(numeral()); \ m().set(R.back(), new_a); \ } - + numeral zero(0); unsigned i = 0; unsigned sz1 = C1.size(); @@ -718,7 +719,7 @@ namespace upolynomial { m().set(b2, new_bound); R.swap(C2); } - + void core_manager::mod_gcd(unsigned sz_u, numeral const * u, unsigned sz_v, numeral const * v, numeral_vector & result) { @@ -726,8 +727,8 @@ namespace upolynomial { SASSERT(sz_u > 0 && sz_v > 0); SASSERT(!m().modular()); scoped_numeral c_u(m()), c_v(m()); - numeral_vector & pp_u = m_mgcd_tmp[0]; - numeral_vector & pp_v = m_mgcd_tmp[1]; + numeral_vector & pp_u = m_mgcd_tmp[0]; + numeral_vector & pp_v = m_mgcd_tmp[1]; get_primitive_and_content(sz_u, u, pp_u, c_u); get_primitive_and_content(sz_v, v, pp_v, c_v); scoped_numeral c_g(m()); @@ -745,7 +746,7 @@ namespace upolynomial { numeral_vector & v_Zp = m_mgcd_tmp[3]; numeral_vector & q = m_mgcd_tmp[4]; numeral_vector & C = m_mgcd_tmp[5]; - + for (unsigned i = 0; i < NUM_BIG_PRIMES; i++) { m().set(p, polynomial::g_big_primes[i]); TRACE("mgcd", tout << "trying prime: " << p << "\n";); @@ -797,8 +798,8 @@ namespace upolynomial { TRACE("mgcd", tout << "candidate:\n"; display_star(tout, candidate); tout << "\n";); SASSERT(candidate.size() > 0); numeral const & lc_candidate = candidate[candidate.size() - 1]; - if (m().divides(lc_candidate, lc_g) && - divides(pp_u, candidate) && + if (m().divides(lc_candidate, lc_g) && + divides(pp_u, candidate) && divides(pp_v, candidate)) { TRACE("mgcd", tout << "found GCD\n";); mul(candidate, c_g); @@ -845,9 +846,9 @@ namespace upolynomial { else { flip_sign_if_lm_neg(buffer); } - TRACE("upolynomial", tout << "GCD\n"; display(tout, sz1, p1); tout << "\n"; display(tout, sz2, p2); tout << "\n--->\n"; + TRACE("upolynomial", tout << "GCD\n"; display(tout, sz1, p1); tout << "\n"; display(tout, sz2, p2); tout << "\n--->\n"; display(tout, buffer); tout << "\n";); - return; + return; } rem(A.size(), A.c_ptr(), B.size(), B.c_ptr(), R); normalize(R); @@ -868,7 +869,7 @@ namespace upolynomial { flip_sign_if_lm_neg(buffer); return; } - if (!modular()) + if (!modular()) mod_gcd(sz1, p1, sz2, p2, buffer); else euclid_gcd(sz1, p1, sz2, p2, buffer); @@ -913,9 +914,9 @@ namespace upolynomial { else { flip_sign_if_lm_neg(buffer); } - TRACE("upolynomial", tout << "subresultant GCD\n"; display(tout, sz1, p1); tout << "\n"; display(tout, sz2, p2); tout << "\n--->\n"; + TRACE("upolynomial", tout << "subresultant GCD\n"; display(tout, sz1, p1); tout << "\n"; display(tout, sz2, p2); tout << "\n--->\n"; display(tout, buffer); tout << "\n";); - return; + return; } rem(A.size(), A.c_ptr(), B.size(), B.c_ptr(), d, R); unsigned pseudo_div_d = A.size() - B.size(); @@ -928,7 +929,7 @@ namespace upolynomial { m().power(B[B.size() - 1], pseudo_div_d + 1 - d, aux); mul(R, aux); } - d = pseudo_div_d; + d = pseudo_div_d; TRACE("upolynomial", tout << "R: "; display(tout, R); tout << "\nd: " << d << "\n";); // aux <- g*h^d m().power(h, d, aux); @@ -961,7 +962,7 @@ namespace upolynomial { // buffer := square-free(p) void core_manager::square_free(unsigned sz, numeral const * p, numeral_vector & buffer) { - SASSERT(!is_alias(p, buffer)); + SASSERT(!is_alias(p, buffer)); if (sz <= 1) { set(sz, p, buffer); return; @@ -1000,11 +1001,11 @@ namespace upolynomial { return; } - if (k == 1 || sz == 0 || (sz == 1 && m().is_one(p[0]))) { + if (k == 1 || sz == 0 || (sz == 1 && m().is_one(p[0]))) { set(sz, p, r); return; } - + numeral_vector & result = m_pw_tmp; set(sz, p, result); for (unsigned i = 1; i < k; i++) @@ -1039,18 +1040,18 @@ namespace upolynomial { m().mul(p[d], lc_inv, p[d]); } - } + } } - + // Extended GCD - void core_manager::ext_gcd(unsigned szA, numeral const * A, unsigned szB, numeral const * B, + void core_manager::ext_gcd(unsigned szA, numeral const * A, unsigned szB, numeral const * B, numeral_vector & U, numeral_vector & V, numeral_vector & D) { SASSERT(!is_alias(A, U)); SASSERT(!is_alias(A, V)); SASSERT(!is_alias(A, D)); SASSERT(!is_alias(B, U)); SASSERT(!is_alias(B, V)); SASSERT(!is_alias(B, D)); SASSERT(field()); scoped_numeral_vector V1(m()), V3(m()), Q(m()), R(m()), T(m()), V1Q(m()); - + // since we are in a field define gcd(A, B) to be monic // if AU + BV = D and D is not monic we make it monic, and then divide U and V by the same inverse @@ -1058,13 +1059,13 @@ namespace upolynomial { // U <- 1 reset(U); U.push_back(numeral()); m().set(U.back(), 1); // D <- A - set(szA, A, D); + set(szA, A, D); mk_monic(szA, D.c_ptr()); // V1 <- 0 - reset(V1); + reset(V1); // V3 <- B - set(szB, B, V3); - + set(szB, B, V3); + while (true) { if (V3.empty()) { // V3 is the zero polynomial @@ -1088,10 +1089,10 @@ namespace upolynomial { mul(V, lc_inv); return; } - + // D = QV3 + R div_rem(D.size(), D.c_ptr(), V3.size(), V3.c_ptr(), Q, R); - + // T <- U - V1Q mul(V1.size(), V1.c_ptr(), Q.size(), Q.c_ptr(), V1Q); sub(U.size(), U.c_ptr(), V1Q.size(), V1Q.c_ptr(), T); @@ -1104,8 +1105,8 @@ namespace upolynomial { // V3 <- R V3.swap(R); } - } - + } + // Display p void core_manager::display(std::ostream & out, unsigned sz, numeral const * p, char const * var_name, bool use_star) const { bool displayed = false; @@ -1144,7 +1145,7 @@ namespace upolynomial { if (!displayed) out << "0"; } - + static void display_smt2_mumeral(std::ostream & out, numeral_manager & m, mpz const & n) { if (m.is_neg(n)) { out << "(- "; @@ -1172,7 +1173,7 @@ namespace upolynomial { out << "(^ " << var_name << " " << k << ")"; } else { - out << "(* "; + out << "(* "; display_smt2_mumeral(out, m, n); out << " "; if (k == 1) @@ -1189,12 +1190,12 @@ namespace upolynomial { out << "0"; return; } - + if (sz == 1) { display_smt2_mumeral(out, m(), p[0]); return; } - + unsigned non_zero_idx = UINT_MAX; unsigned num_non_zeros = 0; for (unsigned i = 0; i < sz; i++) { @@ -1208,7 +1209,7 @@ namespace upolynomial { SASSERT(non_zero_idx != UINT_MAX && non_zero_idx >= 1); display_smt2_monomial(out, m(), p[non_zero_idx], non_zero_idx, var_name); } - + out << "(+"; unsigned i = sz; while (i > 0) { @@ -1230,7 +1231,7 @@ namespace upolynomial { } return true; } - + void upolynomial_sequence::push(unsigned sz, numeral * p) { m_begins.push_back(m_seq_coeffs.size()); m_szs.push_back(sz); @@ -1253,8 +1254,8 @@ namespace upolynomial { _scoped_numeral_vector(m.m()) { } - scoped_upolynomial_sequence::~scoped_upolynomial_sequence() { - m_manager.reset(*this); + scoped_upolynomial_sequence::~scoped_upolynomial_sequence() { + m_manager.reset(*this); } manager::~manager() { @@ -1355,7 +1356,7 @@ namespace upolynomial { return r; } - + // Return the descartes bound for (0, +oo) unsigned manager::descartes_bound(unsigned sz, numeral const * p) { return sign_changes(sz, p); @@ -1382,9 +1383,9 @@ namespace upolynomial { unsigned num_vars = 0; // a0 a1 a2 a3 // a0 a0+a1 a0+a1+a2 a0+a1+a2+a3 - // a0 2a0+a1 3a0+2a1+a2 - // a0 3a0+a1 - // a0 + // a0 2a0+a1 3a0+2a1+a2 + // a0 3a0+a1 + // a0 for (unsigned i = 0; i < sz; i++) { checkpoint(); unsigned k; @@ -1496,12 +1497,12 @@ namespace upolynomial { } // Given b of the form c/(2^k) - // p(x) := (2^k)^n * p(x + c/(2^k)) where b = c/2^k + // p(x) := (2^k)^n * p(x + c/(2^k)) where b = c/2^k // // Given p: a_n * x^n + ... + a_0 - // + // // buffer := a_n * (2^k * x + c)^n + a_{n-1} * 2^k * (2^k * x + c)^{n-1} + ... + a_1 * (2^k)^{n-1} * (2^k * x + c) + a_0 * (2^k)^n - // + // // We perform the transformation in two steps: // 1) a_n * x^n + a_{n-1} * 2^k * x^{n-1} + ... + a_1 * (2^k)^{n-1} + a_0 * (2^k)^n // Let d_n, ..., d_0 be the coefficients after this step @@ -1509,33 +1510,33 @@ namespace upolynomial { // d_n * x^n + ... + d_0 // 2) d_n * (2^k * x + c)^n + ... + d_0 // This step is like the translation with integers, but the coefficients must be adjusted by 2^k in each iteration. - // + // // That is, it is a special translation such as: // a_n*(b*x + c)^n + a_{n-1}*(b*x + c)^{n-1} + ... + a_1*(b*x + c) + a_0 // This kind of translation can be computed by applying the following recurrence: // To simplify the notation, we fix n = 4 // Moreover we use a_i[k] to represent the coefficient a_i at iteration k // a_i[0] = a_i - // + // // a_4*(b*x + c)^4 + a_3*(b*x + c)^3 + a_2*(b*x + c)^2 + a_1*(b*x + c) + a_0 // --> // a_4*b*x*(b*x + c)^3 + (a_3 + a_4*c)*(b*x + c)^3 + a_2*(b*x + c)^2 + a_1*(b*x + c) + a_0 // Thus a_4[1] = a_4[0]*b, a_3[1] = a_3[0] + a_4[0]*c, a_2[1] = a_2[0], a_1[1] = a_1[0], a_0[1] = a_0[0] - // + // // a_4[1]*x*(b*x + c)^3 + a_3[1]*(b*x + c)^3 + a_2[1]*(b*x + c)^2 + a_1[1]*(b*x + c) + a_0[1] // --> // a_4[1]*b*x^2*(b*x + c)^2 + (a_3[1]*b + a_4[1]*c)*x*(b*x + c)^2 + (a_2[1] + a_3[1]*c)*(b*x + c)^2 + a_1[1]*(b*x + c) + a_0[1] // Thus a_4[2] = a_4[1]*b, a_3[2] = a_3[1]*b + a_4[1]*c, a_2[2] = a_2[1] + a_3[1]*c, a_1[2] = a_1[1], a_0[2] = a_0[1] - // + // // a_4[2]*x^2*(b*x + c)^2 + a_3[2]*x*(b*x + c)^2 + a_2[2]*(b*x + c)^2 + a_1[2]*(b*x + c) + a_0[2] // --> // a_4[2]*b*x^3*(b*x + c) + (a_3[2]*b + a_4[2]*c)*x^2*(b*x + c) + (a_2[2]*b + a_3[2]*c)*x*(b*x + c) + (a_1[2] + a_2[2]*c)*(b*x + c) + a_0[2] // Thus a_4[3] = a_4[2]*b, a_3[3] = a_3[2]*b + a_4[2]*c, a_2[3] = a_2[2]*b + a_3[2]*c, a_1[3] = a_1[2] + a_2[2]*c, a_0[3] = a_1[3] - // + // // a_4[3]*x^3*(b*x + c) + a_3[3]*x^2*(b*x + c) + a_2[3]*x*(b*x + c) + a_1[3]*(b*x + c) + a_0[3] // ---> - // a_4[3]*b*x^4 + (a_3[3]*b + a_4[3]*c)*x^3 + (a_2[3]*b + a_3[3]*c)*x^2 + (a_1[3]*b + a_2[3]*c)*x + (a_0[3] + a_1[3]*c) - // + // a_4[3]*b*x^4 + (a_3[3]*b + a_4[3]*c)*x^3 + (a_2[3]*b + a_3[3]*c)*x^2 + (a_1[3]*b + a_2[3]*c)*x + (a_0[3] + a_1[3]*c) + // void manager::translate_bq(unsigned sz, numeral * p, mpbq const & b) { if (sz <= 1) return; @@ -1617,7 +1618,7 @@ namespace upolynomial { } } - // p(x) := p(2^k * x) + // p(x) := p(2^k * x) void manager::compose_p_2k_x(unsigned sz, numeral * p, unsigned k) { // (2^k)^n*a_n*x^n + (2^k)^(n-1)*x^{n-1} + ... + a_0 if (sz <= 1) @@ -1629,11 +1630,11 @@ namespace upolynomial { } } - // p(x) := (2^k)^n * p(x/2^k) + // p(x) := (2^k)^n * p(x/2^k) // // Let old(p) be of the form: // a_n * x^n + a_{n-1}*x^{n-1} + ... + a_1 * x + a_0 - // + // // Then p is of the form: // a_n * x^n + a_{n-1} * 2^k * x^{n-1} + a_{n-2} * (2^k)^2 * x^{n-2} + ... + a_0 * (2^k)^n void manager::compose_2kn_p_x_div_2k(unsigned sz, numeral * p, unsigned k) { @@ -1646,7 +1647,7 @@ namespace upolynomial { m().mul2k(p[i], k_i); } } - + // p(x) := a^n * p(x/a) // See compose_2kn_p_x_div_2k void manager::compose_an_p_x_div_a(unsigned sz, numeral * p, numeral const & a) { @@ -1675,13 +1676,13 @@ namespace upolynomial { m().mul(b_i, b, b_i); } } - + // Let b be of the form c/(2^k), then this operation is equivalent to: // (2^k)^n*p(c*x/(2^k)) - // + // // Let old(p) be of the form: // a_n * x^n + a_{n-1}*x^{n-1} + ... + a_1 * x + a_0 - // + // // Then p is of the form: // a_n * c^n * x^n + a_{n-1} * c^{n-1} * 2^k * x^{n-1} + ... + a_1 * c * (2^k)^(n-1) * x + a_0 * (2^k)^n void manager::compose_p_b_x(unsigned sz, numeral * p, mpbq const & b) { @@ -1705,12 +1706,12 @@ namespace upolynomial { // Let q be of the form b/c, then this operation is equivalent to: // p(x) := c^n*p(b*x/c) - // + // // If u is a root of old(p), then u*(c/b) is a root of new p. - // + // // Let old(p) be of the form: // a_n * x^n + a_{n-1}*x^{n-1} + ... + a_1 * x + a_0 - // + // // Then p is of the form: // a_n * b^n * x^n + a_{n-1} * b^{n-1} * c * x^{n-1} + ... + a_1 * b * c^(n-1) * x + a_0 * c^n void manager::compose_p_q_x(unsigned sz, numeral * p, mpq const & q) { @@ -1730,14 +1731,14 @@ namespace upolynomial { } } } - + // Evaluate the sign of p(b) int manager::eval_sign_at(unsigned sz, numeral const * p, mpbq const & b) { // Actually, given b = c/2^k, we compute the sign of (2^k)^n*p(b) // Original Horner Sequence // ((a_n * b + a_{n-1})*b + a_{n-2})*b + a_{n-3} ... // Variation of the Horner Sequence for (2^k)^n*p(b) - // ((a_n * c + a_{n-1}*2_k)*c + a_{n-2}*(2_k)^2)*c + a_{n-3}*(2_k)^3 ... + a_0*(2_k)^n + // ((a_n * c + a_{n-1}*2_k)*c + a_{n-2}*(2_k)^2)*c + a_{n-3}*(2_k)^3 ... + a_0*(2_k)^n if (sz == 0) return 0; if (sz == 1) @@ -1770,7 +1771,7 @@ namespace upolynomial { // Original Horner Sequence // ((a_n * b + a_{n-1})*b + a_{n-2})*b + a_{n-3} ... // Variation of the Horner Sequence for (d^n)*p(b) - // ((a_n * c + a_{n-1}*d)*c + a_{n-2}*d^2)*c + a_{n-3}*d^3 ... + a_0*d^n + // ((a_n * c + a_{n-1}*d)*c + a_{n-2}*d^2)*c + a_{n-3}*d^3 ... + a_0*d^n if (sz == 0) return 0; if (sz == 1) @@ -1797,7 +1798,7 @@ namespace upolynomial { } return sign_of(r); } - + // Evaluate the sign of p(b) int manager::eval_sign_at(unsigned sz, numeral const * p, mpz const & b) { // Using Horner Sequence @@ -1906,7 +1907,7 @@ namespace upolynomial { void manager::root_upper_bound(unsigned sz, numeral const * p, numeral & r) { // Using Cauchy's Inequality - // We have that any root u of p must satisfy + // We have that any root u of p must satisfy // |u| < (max(p) + min(p))/min(p) // |u| < (max(p) + |a_n|)/|a_n| // where: max(p) is the maximum coefficient in absolute value. @@ -1932,7 +1933,7 @@ namespace upolynomial { init = true; continue; } - if (m().gt(c, max)) + if (m().gt(c, max)) m().set(max, c); if (m().lt(c, min)) m().set(min, c); @@ -1946,26 +1947,26 @@ namespace upolynomial { m().div(r2, a_n, r2); m().add(r2, numeral(1), r2); // use the best bound - if (m().lt(r2, r)) + if (m().lt(r2, r)) swap(r, r2); SASSERT(m().le(r, r2)); } /** \brief Find positive root upper bound using Knuth's approach. - + Given p(x) = a_n * x^n + a_{n-1} * x^{n-1} + ... + a_0 - + If a_n is positive, Let B = max({ (-a_{n-k}/a_n)^{1/k} | 1 <= k <= n, a_{n-k} < 0 }) Then, 2*B is a bound for the positive roots - + Similarly, if a_n is negative Let B = max({ (-a_{n-k}/a_n)^{1/k} | 1 <= k <= n, a_{n-k} > 0 }) Then, 2*B is a bound for the positive roots This procedure returns a k s.t. 2*B <= 2^k - + The procedure actually computes max of log2(abs(a_{n-k})) + 1 - log2(abs(a_n))/k @@ -1974,12 +1975,12 @@ namespace upolynomial { Let u > 0 be a root of p(x). If u <= B, then we are done. So, let us assume u > B - + Assume, a_n > 0 (the proof is similar for a_n < 0) Then: a_n * u^n + a_{n-1} * u^{n-1} + ... + a0 = 0 u^n = 1/a_n (-a_{n-1} * u^{n-1} - ... - a_0) - Note that, if we remove the monomials s.t. a_i is positive, then + Note that, if we remove the monomials s.t. a_i is positive, then we are increasing the value of (-a_{n-1} * u^{n-1} - ... - a_0). Thus, u^n <= 1/a_n(SUM_{a_i < 0, 0 <= i < n} (-a_i * u^i)) @@ -1990,7 +1991,7 @@ namespace upolynomial { 1 <= 1/a_n(SUM_{a_{n-k} < 0, n >= k > 0} (-a_{n-k} * u^{n-k})) = 1/a_n(SUM_{a_{n-k} < 0, 1 <= k <= n} (-a_i * u^{n-k})) < Sum_{1 <= k < +oo}(B/u)^k Since u > B, we have that Sum_{1 <= k < +oo}(B/u)^k = B/(u - B) Thus, we have - 1 < B/(u - B) + 1 < B/(u - B) and u < 2B */ unsigned manager::knuth_positive_root_upper_bound(unsigned sz, numeral const * p) { @@ -2044,14 +2045,14 @@ namespace upolynomial { We essentially compute the upper bound for the roots of x^n*p(1/x) where n is the degree of p. Remark: alpha is a nonzero root of p(x) iff 1/alpha is a root of x^n*p(1/x). Thus, if 2^k is upper bound for the root of x^n*p(1/x). Then we have that - -2^k < 1/alpha < 2^k + -2^k < 1/alpha < 2^k and consequently alpha < -1/2^k or 1/2^k < alpha /pre p is not the zero polynomial. */ unsigned manager::nonzero_root_lower_bound(unsigned sz, numeral const * p) { - SASSERT(sz > 0); + SASSERT(sz > 0); // consume zeros unsigned i = 0; while (true) { @@ -2082,7 +2083,7 @@ namespace upolynomial { struct manager::drs_frame { unsigned m_parent_idx; // position of the parent frame, UINT_MAX if it doesn't have a parent frame unsigned m_size:30; // size of the polynomial associated with this frame - unsigned m_first:1; // first time visiting the frame? + unsigned m_first:1; // first time visiting the frame? unsigned m_left:1; // true if the frame is the left child of the parent frame. drs_frame(unsigned pidx, unsigned sz, bool left): m_parent_idx(pidx), @@ -2115,14 +2116,14 @@ namespace upolynomial { // I don't really need the following test, because 0 - 1 == UINT_MAX unsigned parent_idx = frame_stack.empty() ? UINT_MAX : frame_stack.size() - 1; numeral_vector & p_aux = m_push_tmp; - + // Possible optimization: the coefficients of the parent frame are not needed anymore. // So, we could reuse/steal them. // left child set(sz, p, p_aux); compose_2n_p_x_div_2(p_aux.size(), p_aux.c_ptr()); - normalize(p_aux); + normalize(p_aux); for (unsigned i = 0; i < sz; i++) { p_stack.push_back(numeral()); m().set(p_stack.back(), p_aux[i]); @@ -2149,7 +2150,7 @@ namespace upolynomial { unsigned idx = frame_stack.size() - 1; while (idx != UINT_MAX) { drs_frame const & fr = frame_stack[idx]; - TRACE("upolynomial", + TRACE("upolynomial", tout << "normalizing...\n"; tout << "idx: " << idx << ", left: " << fr.m_left << ", l: " << bqm.to_string(l) << ", u: " << bqm.to_string(u) << "\n";); if (fr.m_left) { @@ -2170,7 +2171,7 @@ namespace upolynomial { swap(lowers.back(), l); swap(uppers.back(), u); } - + // 1/2 is a root of the polynomial associated with the top frame. // Apply transformations for obtaining root of the original polynomial: // We use the following transformations: @@ -2259,7 +2260,7 @@ namespace upolynomial { push_child_frames(q.size(), q.c_ptr(), p_stack, frame_stack); } else { - push_child_frames(sz, p, p_stack, frame_stack); + push_child_frames(sz, p, p_stack, frame_stack); } } } @@ -2314,7 +2315,7 @@ namespace upolynomial { TRACE("upolynomial", tout << "searching at (-1, 0) using:\n"; display(tout, sz, p); tout << "\n";); old_roots_sz = roots.size(); old_lowers_sz = lowers.size(); - drs_isolate_0_1_roots(sz, p, bqm, roots, lowers, uppers); + drs_isolate_0_1_roots(sz, p, bqm, roots, lowers, uppers); SASSERT(lowers.size() == uppers.size()); adjust_neg(bqm, roots, old_roots_sz, neg_k); adjust_neg(bqm, lowers, old_lowers_sz, neg_k); @@ -2390,7 +2391,7 @@ namespace upolynomial { } // Isolate roots in an interval (-2^neg_k, 2^pos_k) using an approach based on Descartes rule of signs. - void manager::sturm_isolate_roots_core(unsigned sz, numeral * p, unsigned neg_k, unsigned pos_k, + void manager::sturm_isolate_roots_core(unsigned sz, numeral * p, unsigned neg_k, unsigned pos_k, mpbq_manager & bqm, mpbq_vector & roots, mpbq_vector & lowers, mpbq_vector & uppers) { SASSERT(!has_zero_roots(sz, p)); scoped_upolynomial_sequence seq(*this); @@ -2450,10 +2451,10 @@ namespace upolynomial { bqm.swap(curr_lower, f.m_lower); bqm.swap(curr_upper, f.m_upper); pop_ss_frame(bqm, s); - SASSERT(lower_sv > upper_sv + 1); + SASSERT(lower_sv > upper_sv + 1); bqm.add(curr_lower, curr_upper, mid); bqm.div2(mid); - TRACE("upolynomial", + TRACE("upolynomial", tout << "depth: " << s.size() << "\n"; tout << "lower_sv: " << lower_sv << "\n"; tout << "upper_sv: " << upper_sv << "\n"; @@ -2492,8 +2493,8 @@ namespace upolynomial { } void manager::sqf_isolate_roots(unsigned sz, numeral const * p, mpbq_manager & bqm, mpbq_vector & roots, mpbq_vector & lowers, mpbq_vector & uppers) { - bqm.reset(roots); - bqm.reset(lowers); + bqm.reset(roots); + bqm.reset(lowers); bqm.reset(uppers); if (has_zero_roots(sz, p)) { roots.push_back(mpbq(0)); @@ -2516,10 +2517,10 @@ namespace upolynomial { TRACE("upolynomial", tout << "square free part:\n"; display(tout, sqf_p); tout << "\n";); sqf_isolate_roots(sqf_p.size(), sqf_p.c_ptr(), bqm, roots, lowers, uppers); } - + // Keep expanding the Sturm sequence starting at seq void manager::sturm_seq_core(upolynomial_sequence & seq) { - scoped_numeral_vector r(m()); + scoped_numeral_vector r(m()); while (true) { unsigned sz = seq.size(); srem(seq.size(sz-2), seq.coeffs(sz-2), seq.size(sz-1), seq.coeffs(sz-1), r); @@ -2539,7 +2540,7 @@ namespace upolynomial { void manager::sturm_seq(unsigned sz, numeral const * p, upolynomial_sequence & seq) { reset(seq); - scoped_numeral_vector p_prime(m()); + scoped_numeral_vector p_prime(m()); seq.push(m(), sz, p); derivative(sz, p, p_prime); seq.push(p_prime.size(), p_prime.c_ptr()); @@ -2548,7 +2549,7 @@ namespace upolynomial { void manager::sturm_tarski_seq(unsigned sz1, numeral const * p1, unsigned sz2, numeral const * p2, upolynomial_sequence & seq) { reset(seq); - scoped_numeral_vector p1p2(m()); + scoped_numeral_vector p1p2(m()); seq.push(m(), sz1, p1); derivative(sz1, p1, p1p2); mul(p1p2.size(), p1p2.c_ptr(), sz2, p2, p1p2); @@ -2558,7 +2559,7 @@ namespace upolynomial { void manager::fourier_seq(unsigned sz, numeral const * p, upolynomial_sequence & seq) { reset(seq); - scoped_numeral_vector p_prime(m()); + scoped_numeral_vector p_prime(m()); seq.push(m(), sz, p); if (sz == 0) return; @@ -2570,16 +2571,16 @@ namespace upolynomial { seq.push(p_prime.size(), p_prime.c_ptr()); } } - + /** - We say an interval (a, b) of a polynomial p is ISOLATING if p has only one root in the + We say an interval (a, b) of a polynomial p is ISOLATING if p has only one root in the interval (a, b). We say an isolating interval (a, b) of a square free polynomial p is REFINEABLE if sign(p(a)) = -sign(p(b)) - + Not every isolating interval (a, b) of a square free polynomial p is refineable, because - sign(p(a)) or sign(p(b)) may be zero. + sign(p(a)) or sign(p(b)) may be zero. Refinable intervals of square free polynomials are useful, because we can increase precision ("squeeze" the interval) by just evaluating p at (a+b)/2 @@ -2590,7 +2591,7 @@ namespace upolynomial { The method returns TRUE if it produced a REFINABLE interval (a', b'). The new interval is stored in input variables a and b. - The method returns FALSE if it found the root a' in the interval (a, b). The root is + The method returns FALSE if it found the root a' in the interval (a, b). The root is stored in the input variable a. \pre p MUST BE SQUARE FREE. @@ -2631,7 +2632,7 @@ namespace upolynomial { } } } - if (sign_a != 0 && sign_b == 0 ) { + if (sign_a != 0 && sign_b == 0 ) { // CASE 3 scoped_mpbq new_b(bqm); // new_b <- (a+b)/2 @@ -2671,7 +2672,7 @@ namespace upolynomial { // b1 <- (a+b)/2 bqm.add(a, b, b1); bqm.div2(b1); - // a2 <- (a+b)/2 + // a2 <- (a+b)/2 bqm.set(a2, b1); int sign_b1 = eval_sign_at(sz, p, b1); int sign_a2 = sign_b1; @@ -2691,13 +2692,13 @@ namespace upolynomial { bqm.div2(new_b2); while (true) { - TRACE("upolynomial", + TRACE("upolynomial", tout << "CASE 4\na1: " << bqm.to_string(a1) << ", b1: " << bqm.to_string(b1) << ", new_a1: " << bqm.to_string(new_a1) << "\n"; tout << "a2: " << bqm.to_string(a2) << ", b2: " << bqm.to_string(b2) << ", new_b2: " << bqm.to_string(new_b2) << "\n";); int sign_new_a1 = eval_sign_at(sz, p, new_a1); if (sign_new_a1 == 0) { // found root - swap(new_a1, a); + swap(new_a1, a); result = false; goto end; } @@ -2716,7 +2717,7 @@ namespace upolynomial { result = false; goto end; } - + if (sign_new_b2 == -sign_a2) { // found interval swap(a2, a); @@ -2739,7 +2740,7 @@ namespace upolynomial { bqm.add(b2, a2, new_b2); bqm.div2(new_b2); } - + end: return result; } @@ -2748,11 +2749,11 @@ namespace upolynomial { Given a square-free polynomial p, and a refinable interval (a,b), then "squeeze" (a,b). That is, return a new interval (a',b') s.t. b' - a' = (b - a)/2 See isolating2refinable for a definition of refinable interval. - + Return TRUE, if interval was squeezed, and new interval is stored in (a,b). Return FALSE, if the actual root was found, it is stored in a. - The arguments sign_a and sign_b must contain the values returned by + The arguments sign_a and sign_b must contain the values returned by eval_sign_at(sz, p, a) and eval_sign_at(sz, p, b). */ bool manager::refine_core(unsigned sz, numeral const * p, int sign_a, mpbq_manager & bqm, mpbq & a, mpbq & b) { @@ -2786,7 +2787,7 @@ namespace upolynomial { } // Keeps reducing the interval until b - a < 1/2^k or a root is found. - // See comments in refine_core above. + // See comments in refine_core above. // // Return TRUE, if interval was squeezed, and new interval is stored in (a,b). // Return FALSE, if the actual root was found, it is stored in a. @@ -2821,7 +2822,7 @@ namespace upolynomial { SASSERT(sign_a != 0 && sign_b != 0); SASSERT(sign_a == -sign_b); bool found_d = false; - TRACE("convert_bug", + TRACE("convert_bug", tout << "a: " << m().to_string(a.numerator()) << "/" << m().to_string(a.denominator()) << "\n"; tout << "b: " << m().to_string(b.numerator()) << "/" << m().to_string(b.denominator()) << "\n"; tout << "sign_a: " << sign_a << "\n"; @@ -2839,7 +2840,7 @@ namespace upolynomial { bqm.mul2(upper); if (m_manager.is_neg(a.numerator())) ::swap(lower, upper); - TRACE("convert_bug", + TRACE("convert_bug", tout << "a: "; m().display(tout, a.numerator()); tout << "/"; m().display(tout, a.denominator()); tout << "\n"; tout << "lower: "; bqm.display(tout, lower); tout << ", upper: "; bqm.display(tout, upper); tout << "\n";); SASSERT(bqm.lt(lower, a)); @@ -2848,7 +2849,7 @@ namespace upolynomial { bqm.refine_upper(a, lower, upper); } SASSERT(bqm.lt(upper, b)); - while (true) { + while (true) { int sign_upper = eval_sign_at(sz, p, upper); if (sign_upper == 0) { // found root @@ -2872,7 +2873,7 @@ namespace upolynomial { bqm.refine_upper(a, lower, upper); } } - + if (!found_d) { if (bqm.to_mpbq(b, lower)) { // found d @@ -2893,7 +2894,7 @@ namespace upolynomial { SASSERT(bqm.lt(c, lower)); SASSERT(bqm.lt(lower, upper)); SASSERT(bqm.lt(lower, b)); - while (true) { + while (true) { int sign_lower = eval_sign_at(sz, p, lower); if (sign_lower == 0) { // found root @@ -2946,8 +2947,8 @@ namespace upolynomial { bool manager::normalize_interval(unsigned sz, numeral const * p, mpbq_manager & m, mpbq & a, mpbq & b) { return normalize_interval_core(sz, p, INT_MIN, m, a, b); - } - + } + unsigned manager::get_root_id(unsigned sz, numeral const * p, mpbq const & l) { scoped_upolynomial_sequence seq(*this); sturm_seq(sz, p, seq); @@ -2963,7 +2964,7 @@ namespace upolynomial { m_manager.neg(new_c); r.set_constant(new_c); } - + void manager::factor_2_sqf_pp(numeral_vector & p, factors & r, unsigned k) { SASSERT(p.size() == 3); // p has degree 2 TRACE("factor", tout << "factor square free (degree == 2):\n"; display(tout, p); tout << "\n";); @@ -2980,7 +2981,7 @@ namespace upolynomial { m().mul(a, c, ac); m().addmul(b2, numeral(-4), ac, disc); // discriminant must be different from 0, since p is square free - SASSERT(!m().is_zero(disc)); + SASSERT(!m().is_zero(disc)); scoped_numeral disc_sqrt(m()); if (!m().is_perfect_square(disc, disc_sqrt)) { // p is irreducible @@ -3053,13 +3054,13 @@ namespace upolynomial { scoped_numeral_vector pp(m()); get_primitive_and_content(sz, p, pp, content); r.set_constant(content); - // + // scoped_numeral_vector & C = pp; // Let C be a primitive polynomial of the form: P_1^1 * P_2^2 * ... * P_k^k, where each P_i is square free scoped_numeral_vector C_prime(m()); derivative(C, C_prime); scoped_numeral_vector A(m()), B(m()), D(m()); - gcd(C, C_prime, B); + gcd(C, C_prime, B); bool result = true; if (is_const(B)) { @@ -3071,7 +3072,7 @@ namespace upolynomial { } else { // B is of the form P_2 * P_3^2 * ... * P_k^{k-1} - VERIFY(exact_div(C, B, A)); + VERIFY(exact_div(C, B, A)); TRACE("factor_bug", tout << "C: "; display(tout, C); tout << "\nB: "; display(tout, B); tout << "\nA: "; display(tout, A); tout << "\n";); // A is of the form P_1 * P_2 * ... * P_k unsigned j = 1; @@ -3084,7 +3085,7 @@ namespace upolynomial { // D is of the form P_{j+1} * P_{j+2} * ... * P_k VERIFY(exact_div(A, D, C)); // C is of the form P_j - if (!is_const(C)) { + if (!is_const(C)) { flip_factor_sign_if_lm_neg(C, r, j); if (!factor_sqf_pp(C, r, j, params)) result = false; @@ -3111,7 +3112,7 @@ namespace upolynomial { bool manager::factor(unsigned sz, numeral const * p, factors & r, factor_params const & params) { bool result = factor_core(sz, p, r, params); -#ifndef _EXTERNAL_RELEASE +#ifndef _EXTERNAL_RELEASE IF_VERBOSE(FACTOR_VERBOSE_LVL, verbose_stream() << "(polynomial-factorization :distinct-factors " << r.distinct_factors() << ")" << std::endl;); #endif return result; diff --git a/src/math/realclosure/realclosure.cpp b/src/math/realclosure/realclosure.cpp index a9ce346b9..0268470f7 100644 --- a/src/math/realclosure/realclosure.cpp +++ b/src/math/realclosure/realclosure.cpp @@ -29,6 +29,7 @@ Notes: #include"ref_vector.h" #include"ref_buffer.h" #include"cooperate.h" +#include"common_msgs.h" #ifndef REALCLOSURE_INI_BUFFER_SIZE #define REALCLOSURE_INI_BUFFER_SIZE 32 @@ -43,7 +44,7 @@ Notes: #endif namespace realclosure { - + // --------------------------------- // // Intervals with binary rational endpoints @@ -58,7 +59,7 @@ namespace realclosure { static bool field() { return true; } unsigned m_div_precision; bool m_to_plus_inf; - + numeral_manager(unsynch_mpq_manager & qm):mpbq_manager(qm), m_div_precision(REALCLOSURE_INI_DIV_PRECISION), m_to_plus_inf(true) { } @@ -106,7 +107,7 @@ namespace realclosure { void set_rounding(bool to_plus_inf) { m_manager.m_to_plus_inf = to_plus_inf; } void round_to_minus_inf() { set_rounding(false); } void round_to_plus_inf() { set_rounding(true); } - + // Getters numeral const & lower(interval const & a) const { return a.m_lower; } numeral const & upper(interval const & a) const { return a.m_upper; } @@ -116,7 +117,7 @@ namespace realclosure { bool upper_is_open(interval const & a) const { return a.upper_is_open(); } bool lower_is_inf(interval const & a) const { return a.lower_is_inf(); } bool upper_is_inf(interval const & a) const { return a.upper_is_inf(); } - + // Setters void set_lower(interval & a, numeral const & n) { m_manager.set(a.m_lower, n); } void set_upper(interval & a, numeral const & n) { m_manager.set(a.m_upper, n); } @@ -124,13 +125,13 @@ namespace realclosure { void set_upper_is_open(interval & a, bool v) { a.m_upper_open = v; } void set_lower_is_inf(interval & a, bool v) { a.m_lower_inf = v; } void set_upper_is_inf(interval & a, bool v) { a.m_upper_inf = v; } - + // Reference to numeral manager numeral_manager & m() const { return m_manager; } - + mpbq_config(numeral_manager & m):m_manager(m) {} }; - + typedef interval_manager mpbqi_manager; typedef mpbqi_manager::interval mpbqi; @@ -160,7 +161,7 @@ namespace realclosure { // This unnecessary precision will only slowdown the subsequent operations that do not need it. // To cope with this issue, we cache the value m_interval in m_old_interval whenever the width of m_interval is below // a give threshold. Then, after finishing OP, we restore the old_interval. - mpbqi * m_old_interval; + mpbqi * m_old_interval; value(bool rat):m_ref_count(0), m_rational(rat), m_old_interval(0) {} bool is_rational() const { return m_rational; } mpbqi const & interval() const { return m_interval; } @@ -173,7 +174,7 @@ namespace realclosure { }; typedef ptr_array polynomial; - + struct extension; bool rank_lt(extension * r1, extension * r2); @@ -183,7 +184,7 @@ namespace realclosure { extension * m_ext; bool m_depends_on_infinitesimals; //!< True if the polynomial expression depends on infinitesimal values. rational_function_value(extension * ext):value(false), m_ext(ext), m_depends_on_infinitesimals(false) {} - + polynomial const & num() const { return m_numerator; } polynomial & num() { return m_numerator; } polynomial const & den() const { return m_denominator; } @@ -199,7 +200,7 @@ namespace realclosure { // Field Extensions // // --------------------------------- - + typedef int sign; typedef std::pair p2s; @@ -217,7 +218,7 @@ namespace realclosure { unsigned m_kind:2; unsigned m_idx:30; mpbqi m_interval; - mpbqi * m_old_interval; + mpbqi * m_old_interval; extension(kind k, unsigned idx):m_ref_count(0), m_kind(k), m_idx(idx), m_old_interval(0) {} @@ -233,11 +234,11 @@ namespace realclosure { }; bool rank_lt(extension * r1, extension * r2) { - return r1->knd() < r2->knd() || (r1->knd() == r2->knd() && r1->idx() < r2->idx()); + return r1->knd() < r2->knd() || (r1->knd() == r2->knd() && r1->idx() < r2->idx()); } bool rank_eq(extension * r1, extension * r2) { - return r1->knd() == r2->knd() && r1->idx() == r2->idx(); + return r1->knd() == r2->knd() && r1->idx() == r2->idx(); } struct rank_lt_proc { @@ -245,7 +246,7 @@ namespace realclosure { return rank_lt(r1, r2); } }; - + /** \brief Sign condition object, it encodes one conjunct of a sign assignment. If has to keep following m_prev to obtain the whole sign condition @@ -271,7 +272,7 @@ namespace realclosure { array m_sign_conditions; // Sign conditions associated with the columns of M array m_qs; // Polynomials used in the sign conditions. sign_det():m_ref_count(0) {} - + array const & qs() const { return m_qs; } sign_condition * sc(unsigned idx) const { return m_sign_conditions[idx]; } unsigned num_roots() const { return m_prs.size(); } @@ -281,7 +282,7 @@ namespace realclosure { struct algebraic : public extension { polynomial m_p; - mpbqi m_iso_interval; + mpbqi m_iso_interval; sign_det * m_sign_det; //!< != 0 if m_iso_interval constains more than one root of m_p. unsigned m_sc_idx; //!< != UINT_MAX if m_sign_det != 0, in this case m_sc_idx < m_sign_det->m_sign_conditions.size() bool m_depends_on_infinitesimals; //!< True if the polynomial p depends on infinitesimal extensions. @@ -301,22 +302,22 @@ namespace realclosure { symbol m_pp_name; unsigned m_k; mk_interval & m_proc; - + transcendental(unsigned idx, symbol const & n, symbol const & pp_n, mk_interval & p): extension(TRANSCENDENTAL, idx), m_name(n), m_pp_name(pp_n), m_k(0), m_proc(p) {} void display(std::ostream & out, bool pp = false) const { - if (pp) + if (pp) out << m_pp_name; else out << m_name; } }; - + struct infinitesimal : public extension { symbol m_name; symbol m_pp_name; - + infinitesimal(unsigned idx, symbol const & n, symbol const & pp_n):extension(INFINITESIMAL, idx), m_name(n), m_pp_name(pp_n) {} void display(std::ostream & out, bool pp = false) const { @@ -325,7 +326,7 @@ namespace realclosure { out << "ε" << m_pp_name.get_num() << ""; else out << m_pp_name; - + } else { if (m_name.is_numerical()) @@ -341,7 +342,7 @@ namespace realclosure { // Predefined transcendental mk_interval procs // // --------------------------------- - + struct mk_pi_interval : public mk_interval { virtual void operator()(unsigned k, mpqi_manager & im, mpqi_manager::interval & r) { im.pi(k, r); @@ -368,7 +369,7 @@ namespace realclosure { typedef _scoped_interval scoped_mpbqi; typedef sbuffer int_buffer; typedef sbuffer unsigned_buffer; - + reslimit& m_limit; small_object_allocator * m_allocator; bool m_own_allocator; @@ -385,10 +386,10 @@ namespace realclosure { value * m_e; ptr_vector m_to_restore; //!< Set of values v s.t. v->m_old_interval != 0 ptr_vector m_ex_to_restore; - + // Parameters bool m_use_prem; //!< use pseudo-remainder when computing sturm sequences - bool m_clean_denominators; + bool m_clean_denominators; unsigned m_ini_precision; //!< initial precision for transcendentals, infinitesimals, etc. unsigned m_max_precision; //!< Maximum precision for interval arithmetic techniques, it switches to complete methods after that unsigned m_inf_precision; //!< 2^m_inf_precision is used as the lower bound of oo and -2^m_inf_precision is used as the upper_bound of -oo @@ -406,12 +407,12 @@ namespace realclosure { typedef ref_buffer value_seq; value_seq m_seq_coeffs; sbuffer m_begins; // start position (in m_seq_coeffs) of each polynomial in the sequence - sbuffer m_szs; // size of each polynomial in the sequence + sbuffer m_szs; // size of each polynomial in the sequence public: scoped_polynomial_seq(imp & m):m_seq_coeffs(m) {} ~scoped_polynomial_seq() { } - + /** \brief Add a new polynomial to the sequence. The contents of p is erased. @@ -426,14 +427,14 @@ namespace realclosure { \brief Return the number of polynomials in the sequence. */ unsigned size() const { return m_szs.size(); } - + /** \brief Return the vector of coefficients for the i-th polynomial in the sequence. */ - value * const * coeffs(unsigned i) const { - return m_seq_coeffs.c_ptr() + m_begins[i]; + value * const * coeffs(unsigned i) const { + return m_seq_coeffs.c_ptr() + m_begins[i]; } - + /** \brief Return the size of the i-th polynomial in the sequence. */ @@ -464,7 +465,7 @@ namespace realclosure { ~scoped_sign_conditions() { m_imp.del_sign_conditions(m_scs.size(), m_scs.c_ptr()); } - + sign_condition * & operator[](unsigned idx) { return m_scs[idx]; } unsigned size() const { return m_scs.size(); } bool empty() const { return m_scs.empty(); } @@ -481,7 +482,7 @@ namespace realclosure { } sign_condition * const * c_ptr() { return m_scs.c_ptr(); } }; - + struct scoped_inc_depth { imp & m_imp; scoped_inc_depth(imp & m):m_imp(m) { m_imp.m_exec_depth++; } @@ -515,7 +516,7 @@ namespace realclosure { m_in_aux_values = false; - + updt_params(p); } @@ -548,7 +549,7 @@ namespace realclosure { void checkpoint() { if (!m_limit.inc()) - throw exception("canceled"); + throw exception(Z3_CANCELED_MSG); cooperate("rcf"); } @@ -569,7 +570,7 @@ namespace realclosure { SASSERT(bqm().is_pos(w)); return bqm().magnitude_ub(w); } - + /** \brief Return the magnitude of the given interval. The magnitude is an approximation of the size of the interval. @@ -599,7 +600,7 @@ namespace realclosure { SASSERT(!i->m_lower_inf && !i->m_upper_inf); return magnitude(i->m_lower, i->m_upper); } - + /** \brief Return true if the magnitude of the given interval is less than the parameter m_max_precision. */ @@ -729,8 +730,8 @@ namespace realclosure { cleanup(extension::ALGEBRAIC); return m_extensions[extension::ALGEBRAIC].size(); } - - + + void updt_params(params_ref const & _p) { rcf_params p(_p); m_use_prem = p.use_prem(); @@ -835,7 +836,7 @@ namespace realclosure { bqim().del(t->m_interval); allocator().deallocate(sizeof(transcendental), t); } - + void del_infinitesimal(infinitesimal * i) { bqim().del(i->m_interval); allocator().deallocate(sizeof(infinitesimal), i); @@ -915,9 +916,9 @@ namespace realclosure { /** \brief Return true if v is represented using a nonzero arbitrary precision rational value. */ - static bool is_nz_rational(value * v) { + static bool is_nz_rational(value * v) { SASSERT(v != 0); - return v->is_rational(); + return v->is_rational(); } /** @@ -942,7 +943,7 @@ namespace realclosure { } /** - \brief Return true if p is the constant polynomial where the coefficient is + \brief Return true if p is the constant polynomial where the coefficient is the rational value 1. \remark This is NOT checking whether p is actually equal to 1. @@ -954,7 +955,7 @@ namespace realclosure { bool is_rational_one(value_ref_buffer const & p) const { return p.size() == 1 && is_rational_one(p[0]); } - + bool is_denominator_one(rational_function_value * v) const { if (v->ext()->is_algebraic()) { SASSERT(v->den().size() == 0); // we do not use denominator for algebraic extensions @@ -977,15 +978,15 @@ namespace realclosure { SASSERT(v != 0); return !(v->is_rational()); } - - static rational_value * to_nz_rational(value * v) { - SASSERT(is_nz_rational(v)); - return static_cast(v); + + static rational_value * to_nz_rational(value * v) { + SASSERT(is_nz_rational(v)); + return static_cast(v); } - - static rational_function_value * to_rational_function(value * v) { - SASSERT(!is_nz_rational(v)); - return static_cast(v); + + static rational_function_value * to_rational_function(value * v) { + SASSERT(!is_nz_rational(v)); + return static_cast(v); } static bool is_zero(numeral const & a) { @@ -1052,7 +1053,7 @@ namespace realclosure { } else if (rank_eq(to_rational_function(a)->ext(), to_rational_function(b)->ext())) return 0; - else + else return rank_lt(to_rational_function(a)->ext(), to_rational_function(b)->ext()) ? -1 : 1; } @@ -1070,18 +1071,18 @@ namespace realclosure { SASSERT(ext->is_algebraic()); return static_cast(ext); } - + /** \brief Return True if the given extension depends on infinitesimal extensions. If it doesn't, then it is definitely a real value. - + If it does, then it may or may not be a real value. - Example: Assume eps is an infinitesimal, and pi is 3.14... . + Example: Assume eps is an infinitesimal, and pi is 3.14... . Assume also that ext is the unique root between (3, 4) of the following polynomial: - x^2 - (pi + eps)*x + pi*ext + x^2 - (pi + eps)*x + pi*ext Thus, x is pi, but the system will return true, since its defining polynomial has infinitesimal coefficients. In the future, we should be able to factor the polynomial - above as + above as (x - eps)*(x - pi) and then detect that x is actually the root of (x - pi). */ @@ -1102,7 +1103,7 @@ namespace realclosure { bool depends_on_infinitesimals(value * v) const { if (is_zero(v) || is_nz_rational(v)) return false; - else + else return to_rational_function(v)->depends_on_infinitesimals(); } @@ -1248,7 +1249,7 @@ namespace realclosure { // Avoiding wasteful allocation... // We do not use the denominator for algebraic extensions SASSERT(den_sz == 0 || (den_sz == 1 && is_rational_one(den[0]))); - + SASSERT(r->den().size() == 0); } else { @@ -1256,7 +1257,7 @@ namespace realclosure { } r->set_depends_on_infinitesimals(depends_on_infinitesimals(ext) || depends_on_infinitesimals(num_sz, num) || depends_on_infinitesimals(den_sz, den)); return r; - } + } rational_function_value * mk_rational_function_value_core(algebraic * ext, unsigned num_sz, value * const * num) { return mk_rational_function_value_core(ext, num_sz, num, 0, 0); @@ -1283,7 +1284,7 @@ namespace realclosure { set_lower(eps->interval(), mpbq(0)); set_upper(eps->interval(), mpbq(1, m_ini_precision)); - + set(r, mk_rational_function_value(eps)); SASSERT(sign(r) > 0); @@ -1303,8 +1304,8 @@ namespace realclosure { t->m_k++; t->m_proc(t->m_k, qim(), i); int m = magnitude(i); - TRACE("rcf_transcendental", - tout << "refine_transcendental_interval rational: " << m << "\nrational interval: "; + TRACE("rcf_transcendental", + tout << "refine_transcendental_interval rational: " << m << "\nrational interval: "; qim().display(tout, i); tout << std::endl;); unsigned k; if (m >= 0) @@ -1314,7 +1315,7 @@ namespace realclosure { scoped_mpbq l(bqm()); mpq_to_mpbqi(i->m_lower, t->interval(), k); // save lower - bqm().set(l, t->interval().lower()); + bqm().set(l, t->interval().lower()); mpq_to_mpbqi(i->m_upper, t->interval(), k); bqm().set(t->interval().lower(), l); } @@ -1332,7 +1333,7 @@ namespace realclosure { unsigned idx = next_transcendental_idx(); transcendental * t = new (allocator()) transcendental(idx, n, pp_n, proc); m_extensions[extension::TRANSCENDENTAL].push_back(t); - + while (contains_zero(t->interval())) { checkpoint(); refine_transcendental_interval(t); @@ -1341,7 +1342,7 @@ namespace realclosure { SASSERT(!depends_on_infinitesimals(r)); } - + void mk_transcendental(char const * p, char const * pp_n, mk_interval & proc, numeral & r) { mk_transcendental(symbol(p), symbol(pp_n), proc, r); } @@ -1377,7 +1378,7 @@ namespace realclosure { // Root isolation // // --------------------------------- - + /** \brief r <- magnitude of the lower bound of |i|. That is, 2^r <= |i|.lower() @@ -1385,7 +1386,7 @@ namespace realclosure { 2^r is smaller than the absolute value of any element in the interval i. Return true if succeeded, and false if i contains elements that are infinitely close to 0. - + \pre !contains_zero(i) */ bool abs_lower_magnitude(mpbqi const & i, int & r) { @@ -1415,7 +1416,7 @@ namespace realclosure { 2^r is bigger than the absolute value of any element in the interval i. Return true if succeeded, and false if i is unbounded. - + \pre !contains_zero(i) */ bool abs_upper_magnitude(mpbqi const & i, int & r) { @@ -1440,20 +1441,20 @@ namespace realclosure { /** \brief Find positive root upper bound using Knuth's approach. - + Given p(x) = a_n * x^n + a_{n-1} * x^{n-1} + ... + a_0 - + If a_n is positive, Let B = max({ (-a_{n-k}/a_n)^{1/k} | 1 <= k <= n, a_{n-k} < 0 }) Then, 2*B is a bound for the positive roots - + Similarly, if a_n is negative Let B = max({ (-a_{n-k}/a_n)^{1/k} | 1 <= k <= n, a_{n-k} > 0 }) Then, 2*B is a bound for the positive roots - + This procedure returns a N s.t. 2*B <= 2^N - - The computation is performed using the intervals associated with the coefficients of + + The computation is performed using the intervals associated with the coefficients of the polynomial. The procedure may fail if the interval for a_n is of the form (l, 0) or (0, u). @@ -1483,11 +1484,11 @@ namespace realclosure { return true; } - + /** \brief Auxiliary method for creating the intervals of the coefficients of the polynomials p(-x) without actually creating p(-x). - + 'a' is the interval of the i-th coefficient of a polynomial a_n * x^n + ... + a_0 */ @@ -1500,8 +1501,8 @@ namespace realclosure { /** \brief Find negative root lower bound using Knuth's approach. - - This is similar to pos_root_upper_bound. In principle, we can use + + This is similar to pos_root_upper_bound. In principle, we can use the same algorithm. We just have to adjust the coefficients by using the transformation p(-x). */ @@ -1581,13 +1582,13 @@ namespace realclosure { } /** - \brief Store in ds all (non-constant) derivatives of p. - + \brief Store in ds all (non-constant) derivatives of p. + \post d.size() == n-2 */ void mk_derivatives(unsigned n, value * const * p, scoped_polynomial_seq & ds) { SASSERT(n >= 3); // p is at least quadratic - SASSERT(!is_zero(p[0])); + SASSERT(!is_zero(p[0])); SASSERT(!is_zero(p[n-1])); value_ref_buffer p_prime(*this); derivative(n, p, p_prime); @@ -1606,15 +1607,15 @@ namespace realclosure { /** \brief Auxiliary function for count_signs_at_zeros. (See comments at count_signs_at_zeros). - + - taq_p_q contains TaQ(p, q; interval) */ void count_signs_at_zeros_core(// Input values - int taq_p_q, + int taq_p_q, unsigned p_sz, value * const * p, // polynomial p unsigned q_sz, value * const * q, // polynomial q mpbqi const & interval, - int num_roots, // number of roots of p in the given interval + int num_roots, // number of roots of p in the given interval // Output values int & q_eq_0, int & q_gt_0, int & q_lt_0, value_ref_buffer & q2) { @@ -1658,27 +1659,27 @@ namespace realclosure { SASSERT(q_eq_0 + q_gt_0 + q_lt_0 == num_roots); } - + /** - \brief Given polynomials p and q, and an interval, compute the number of + \brief Given polynomials p and q, and an interval, compute the number of roots of p in the interval such that: - q is zero - q is positive - q is negative \pre num_roots is the number of roots of p in the given interval. - + \remark num_roots == q_eq_0 + q_gt_0 + q_lt_0 */ void count_signs_at_zeros(// Input values unsigned p_sz, value * const * p, // polynomial p unsigned q_sz, value * const * q, // polynomial q mpbqi const & interval, - int num_roots, // number of roots of p in the given interval + int num_roots, // number of roots of p in the given interval // Output values int & q_eq_0, int & q_gt_0, int & q_lt_0, value_ref_buffer & q2) { - TRACE("rcf_count_signs", + TRACE("rcf_count_signs", tout << "p: "; display_poly(tout, p_sz, p); tout << "\n"; tout << "q: "; display_poly(tout, q_sz, q); tout << "\n";); SASSERT(num_roots > 0); @@ -1691,20 +1692,20 @@ namespace realclosure { taqrs contains the results of TaQ(p, prs[i]; interval) We have that taqrs.size() == prs.size() - + We produce a new_taqrs and new_prs For each pr in new_prs we have pr in new_prs, TaQ(p, pr; interval) in new_taqrs pr*q in new_prs, TaQ(p, pr*q; interval) in new_taqrs if q2_sz != 0, we also have pr*q^2 in new_prs, TaQ(p, pr*q^2; interval) in new_taqrs - + */ void expand_taqrs(// Input values - int_buffer const & taqrs, + int_buffer const & taqrs, scoped_polynomial_seq const & prs, unsigned p_sz, value * const * p, - unsigned q_sz, value * const * q, + unsigned q_sz, value * const * q, bool use_q2, unsigned q2_sz, value * const * q2, mpbqi const & interval, // Output values @@ -1739,15 +1740,15 @@ namespace realclosure { /** \brief In the sign determination algorithm main loop, we keep processing polynomials q, and checking whether they discriminate the roots of the target polynomial. - + The vectors sc_cardinalities contains the cardinalites of the new realizable sign conditions. - That is, we started we a sequence of sign conditions - sc_1, ..., sc_n, + That is, we started we a sequence of sign conditions + sc_1, ..., sc_n, If q2_used is true, then we expanded this sequence as sc1_1 and q == 0, sc_1 and q > 0, sc_1 and q < 0, ..., sc_n and q == 0, sc_n and q > 0, sc_n and q < 0 If q2_used is false, then we considered only two possible signs of q. - Thus, q is useful (i.e., it is a discriminator for the roots of p) IF + Thus, q is useful (i.e., it is a discriminator for the roots of p) IF If !q2_used, then There is an i s.t. sc_cardinalities[2*i] > 0 && sc_cardinalities[2*i] > 0 If q2_used, then There is an i s.t. AtLeatTwo(sc_cardinalities[3*i] > 0, sc_cardinalities[3*i+1] > 0, sc_cardinalities[3*i+2] > 0) */ @@ -1788,8 +1789,8 @@ namespace realclosure { /** \brief Create a "sign determination" data-structure for an algebraic extension. - - The new object will assume the ownership of the elements stored in M and scs. + + The new object will assume the ownership of the elements stored in M and scs. M and scs will be empty after this operation. */ sign_det * mk_sign_det(mpz_matrix & M_s, scoped_polynomial_seq const & prs, int_buffer const & taqrs, scoped_polynomial_seq const & qs, scoped_sign_conditions & scs) { @@ -1810,7 +1811,7 @@ namespace realclosure { unsigned idx = next_algebraic_idx(); algebraic * r = new (allocator()) algebraic(idx); m_extensions[extension::ALGEBRAIC].push_back(r); - + set_p(r->m_p, p_sz, p); set_interval(r->m_interval, interval); set_interval(r->m_iso_interval, iso_interval); @@ -1842,78 +1843,78 @@ namespace realclosure { /** \brief Create (the square) matrix for sign determination of q on the roots of p. - It builds matrix based on the number of root of p where - q is == 0, > 0 and < 0. + It builds matrix based on the number of root of p where + q is == 0, > 0 and < 0. The resultant matrix is stored in M. Return false if the sign of q is already determined, that is only one of the q_eq_0, q_gt_0, q_lt_0 is greater than zero. - + If the return value is true, then the resultant matrix M has size 2x2 or 3x3 - q_eq_0 > 0, q_gt_0 > 0, q_lt_0 == 0 - M <- {{1, 1}, + M <- {{1, 1}, {0, 1}} - Meaning: + Meaning: M . [ #(q == 0), #(q > 0) ]^t == [ TaQ(p, 1), TaQ(p, q) ]^t [ ... ]^t represents a column matrix. - + - q_eq_0 > 0, q_gt_0 == 0, q_lt_0 > 0 - M <- {{1, 1}, + M <- {{1, 1}, {0, -1}} - Meaning: + Meaning: M . [ #(q == 0), #(q < 0) ]^t == [ TaQ(p, 1), TaQ(p, q) ]^t - q_eq_0 == 0, q_gt_0 > 0, q_lt_0 > 0 - M <- {{1, 1}, + M <- {{1, 1}, {1, -1}} - Meaning: + Meaning: M . [ #(q > 0), #(q < 0) ]^t == [ TaQ(p, 1), TaQ(p, q) ]^t - q_eq_0 > 0, q_gt_0 > 0, q_lt_0 > 0 - M <- {{1, 1, 1}, + M <- {{1, 1, 1}, {0, 1, -1}, {0, 1, 1}} - Meaning: + Meaning: M . [ #(q == 0), #(q > 0), #(q < 0) ]^t == [ TaQ(p, 1), TaQ(p, q), TaQ(p, q^2) ]^t */ bool mk_sign_det_matrix(int q_eq_0, int q_gt_0, int q_lt_0, scoped_mpz_matrix & M) { if (q_eq_0 > 0 && q_gt_0 > 0 && q_lt_0 == 0) { - // M <- {{1, 1}, + // M <- {{1, 1}, // {0, 1}} mm().mk(2,2,M); - M.set(0,0, 1); M.set(0,1, 1); + M.set(0,0, 1); M.set(0,1, 1); M.set(1,0, 0); M.set(1,1, 1); return true; } else if (q_eq_0 > 0 && q_gt_0 == 0 && q_lt_0 > 0) { - // M <- {{1, 1}, + // M <- {{1, 1}, // {0, -1}} mm().mk(2,2,M); - M.set(0,0, 1); M.set(0,1, 1); + M.set(0,0, 1); M.set(0,1, 1); M.set(1,0, 0); M.set(1,1, -1); return true; } else if (q_eq_0 == 0 && q_gt_0 > 0 && q_lt_0 > 0) { - // M <- {{1, 1}, + // M <- {{1, 1}, // {1, -1}} mm().mk(2,2,M); - M.set(0,0, 1); M.set(0,1, 1); + M.set(0,0, 1); M.set(0,1, 1); M.set(1,0, 1); M.set(1,1, -1); return true; } else if (q_eq_0 > 0 && q_gt_0 > 0 && q_lt_0 > 0) { - // M <- {{1, 1, 1}, + // M <- {{1, 1, 1}, // {0, 1, -1}, // {0, 1, 1}} mm().mk(3,3,M); - M.set(0,0, 1); M.set(0,1, 1); M.set(0,2, 1); + M.set(0,0, 1); M.set(0,1, 1); M.set(0,2, 1); M.set(1,0, 0); M.set(1,1, 1); M.set(1,2, -1); M.set(2,0, 0); M.set(2,1, 1); M.set(2,2, 1); return true; @@ -1923,16 +1924,16 @@ namespace realclosure { return false; } } - + /** \brief Isolate roots of p in the given interval using sign conditions to distinguish between them. We need this method when the polynomial contains roots that are infinitesimally close to each other. - For example, given an infinitesimal eps, the polynomial (x - 1)(x - 1 - eps) == (1 + eps) + (- 2 - eps)*x + x^2 + For example, given an infinitesimal eps, the polynomial (x - 1)(x - 1 - eps) == (1 + eps) + (- 2 - eps)*x + x^2 has two roots 1 and 1+eps, we can't isolate these roots using intervals with binary rational end points. In this case, we use the signs of (some of the) derivatives in the roots. By Thom's lemma, we know we can always use the signs of the derivatives to distinguish between different roots. - + Remark: the polynomials do not need to be the derivatives of p. We use derivatives because a simple sequential search can be used to find the set of polynomials that can be used to distinguish between the different roots. @@ -1943,14 +1944,14 @@ namespace realclosure { SASSERT(num_roots >= 2); scoped_polynomial_seq der_seq(*this); mk_derivatives(p_sz, p, der_seq); - + CASSERT("rcf_isolate_roots", TaQ_1(p_sz, p, interval) == num_roots); scoped_mpz_matrix M_s(mm()); mm().mk(1, 1, M_s); M_s.set(0, 0, 1); - + // Sequence of polynomials associated with each row of M_s - scoped_polynomial_seq prs(*this); + scoped_polynomial_seq prs(*this); value * one_p[] = { one() }; prs.push(1, one_p); // start with the polynomial one @@ -1967,7 +1968,7 @@ namespace realclosure { scs.push_back(0); // Starting configuration - // + // // M_s = {{1}} Matrix of size 1x1 containing the value 1 // prs = [1] Sequence of size 1 containing the constant polynomial 1 (one is always the first element of this sequence) // taqrs = [num_roots] Sequence of size 1 containing the integer num_roots @@ -1979,7 +1980,7 @@ namespace realclosure { int_buffer new_taqrs; scoped_polynomial_seq new_prs(*this); scoped_sign_conditions new_scs(*this); - + int_buffer sc_cardinalities; unsigned_buffer cols_to_keep; unsigned_buffer new_row_idxs; @@ -1995,7 +1996,7 @@ namespace realclosure { TRACE("rcf_sign_det", tout << M_s; for (unsigned j = 0; j < scs.size(); j++) { - display_sign_conditions(tout, scs[j]); + display_sign_conditions(tout, scs[j]); tout << " = " << taqrs[j] << "\n"; } tout << "qs:\n"; @@ -2024,7 +2025,7 @@ namespace realclosure { // ---> new_taqrs, new_prs); SASSERT(new_M_s.n() == new_M_s.m()); // it is a square matrix - SASSERT(new_M_s.m() == new_taqrs.size()); + SASSERT(new_M_s.m() == new_taqrs.size()); SASSERT(new_M_s.m() == new_prs.size()); // The system must have a solution sc_cardinalities.resize(new_taqrs.size(), 0); @@ -2035,17 +2036,17 @@ namespace realclosure { // The solution must contain only positive values <= num_roots DEBUG_CODE(for (unsigned j = 0; j < sc_cardinalities.size(); j++) { SASSERT(0 <= sc_cardinalities[j] && sc_cardinalities[j] <= num_roots); }); // We should keep q only if it discriminated something. - // That is, + // That is, // If !use_q2, then There is an i s.t. sc_cardinalities[2*i] > 0 && sc_cardinalities[2*i] > 0 // If use_q2, then There is an i s.t. AtLeatTwo(sc_cardinalities[3*i] > 0, sc_cardinalities[3*i+1] > 0, sc_cardinalities[3*i+2] > 0) if (!keep_new_sc_assignment(sc_cardinalities.size(), sc_cardinalities.c_ptr(), use_q2)) { // skip q since it did not reduced the cardinality of the existing sign conditions. - continue; + continue; } // keep q unsigned q_idx = qs.size(); qs.push(q_sz, q); - // We remove the columns associated with sign conditions that have cardinality zero, + // We remove the columns associated with sign conditions that have cardinality zero, // and create new extended sign condition objects for the ones that have cardinality > 0. cols_to_keep.reset(); unsigned j = 0; unsigned k = 0; @@ -2057,16 +2058,16 @@ namespace realclosure { for (unsigned s = 0; s < step_sz; s++) { // Remark: the second row of M contains the sign for q if (sc_cardinalities[j] > 0) { - new_scs.push_back(mk_sign_condition(q_idx, M.get_int(1, s), sc)); + new_scs.push_back(mk_sign_condition(q_idx, M.get_int(1, s), sc)); cols_to_keep.push_back(j); } - if (sc_cardinalities[j] > 1) + if (sc_cardinalities[j] > 1) all_one = false; j++; } } // Update scs with new_scs - scs.copy_from(new_scs); + scs.copy_from(new_scs); SASSERT(new_scs.empty()); // Update M_s mm().filter_cols(new_M_s, cols_to_keep.size(), cols_to_keep.c_ptr(), M_s); @@ -2085,7 +2086,7 @@ namespace realclosure { if (all_one) { // Stop each remaining sign condition in scs has cardinality one // So, they are discriminating the roots of p. - break; + break; } } TRACE("rcf_sign_det", @@ -2093,7 +2094,7 @@ namespace realclosure { display_poly(tout, p_sz, p); tout << "\n"; tout << M_s; for (unsigned j = 0; j < scs.size(); j++) { - display_sign_conditions(tout, scs[j]); + display_sign_conditions(tout, scs[j]); tout << " = " << taqrs[j] << "\n"; } tout << "qs:\n"; @@ -2191,7 +2192,7 @@ namespace realclosure { bisect_ctx(unsigned p_sz, value * const * p, bool dinf, scoped_polynomial_seq & seq, numeral_vector & roots): m_p_sz(p_sz), m_p(p), m_depends_on_infinitesimals(dinf), m_sturm_seq(seq), m_result_roots(roots) {} }; - + void bisect_isolate_roots(mpbqi & interval, mpbqi & iso_interval, int lower_sv, int upper_sv, bisect_ctx & ctx) { SASSERT(lower_sv >= upper_sv); int num_roots = lower_sv - upper_sv; @@ -2206,8 +2207,8 @@ namespace realclosure { numeral r; set(r, mk_rational(interval.upper())); ctx.m_result_roots.push_back(r); - } - else { + } + else { // interval is an isolating interval add_root(ctx.m_p_sz, ctx.m_p, interval, iso_interval, ctx.m_result_roots); } @@ -2217,7 +2218,7 @@ namespace realclosure { // - The polynomial depends on infinitesimals // - The interval contains more than one root // - The size of the interval is less than 1/2^m_max_precision - // THEN + // THEN // - We switch to expensive sign determination procedure, since // the roots may be infinitely close to each other. // @@ -2280,14 +2281,14 @@ namespace realclosure { */ void nl_nz_sqf_isolate_roots(unsigned n, value * const * p, numeral_vector & roots) { SASSERT(n > 2); - SASSERT(!is_zero(p[0])); + SASSERT(!is_zero(p[0])); SASSERT(!is_zero(p[n-1])); int pos_lower_N, pos_upper_N, neg_lower_N, neg_upper_N; bool has_neg_lower = neg_root_lower_bound(n, p, neg_lower_N); bool has_neg_upper = neg_root_upper_bound(n, p, neg_upper_N); bool has_pos_lower = pos_root_lower_bound(n, p, pos_lower_N); bool has_pos_upper = pos_root_upper_bound(n, p, pos_upper_N); - TRACE("rcf_isolate", + TRACE("rcf_isolate", display_poly(tout, n, p); tout << "\n"; if (has_neg_lower) tout << "-2^" << neg_lower_N; else tout << "-oo"; tout << " < neg-roots < "; @@ -2305,7 +2306,7 @@ namespace realclosure { int num_sv_plus_inf = sign_variations_at_plus_inf(seq); int num_neg_roots = num_sv_minus_inf - num_sv_zero; int num_pos_roots = num_sv_zero - num_sv_plus_inf; - TRACE("rcf_isolate", + TRACE("rcf_isolate", tout << "num_neg_roots: " << num_neg_roots << "\n"; tout << "num_pos_roots: " << num_pos_roots << "\n";); scoped_mpbqi pos_interval(bqim()); @@ -2318,7 +2319,7 @@ namespace realclosure { scoped_mpbqi zero_inf(bqim()); set_lower_zero(zero_inf); set_upper_inf(zero_inf); - + if (num_neg_roots > 0) { if (num_neg_roots == 1) { add_root(n, p, neg_interval, minf_zero, 0, UINT_MAX, roots); @@ -2332,7 +2333,7 @@ namespace realclosure { } } } - + if (num_pos_roots > 0) { if (num_pos_roots == 1) { add_root(n, p, pos_interval, zero_inf, 0, UINT_MAX, roots); @@ -2356,7 +2357,7 @@ namespace realclosure { */ void nz_sqf_isolate_roots(unsigned n, value * const * p, numeral_vector & roots) { SASSERT(n > 1); - SASSERT(!is_zero(p[0])); + SASSERT(!is_zero(p[0])); SASSERT(!is_zero(p[n-1])); if (n == 2) { // we don't need a field extension for linear polynomials. @@ -2368,23 +2369,23 @@ namespace realclosure { roots.push_back(r); } else { - nl_nz_sqf_isolate_roots(n, p, roots); + nl_nz_sqf_isolate_roots(n, p, roots); } } - + /** \brief Root isolation for polynomials where 0 is not a root, and the denominators have been cleaned when m_clean_denominators == true - + */ void nz_cd_isolate_roots(unsigned n, value * const * p, numeral_vector & roots) { SASSERT(n > 0); - SASSERT(!is_zero(p[0])); + SASSERT(!is_zero(p[0])); SASSERT(!is_zero(p[n-1])); SASSERT(!m_clean_denominators || has_clean_denominators(n, p)); if (n == 1) { // constant polynomial - return; + return; } value_ref_buffer sqf(*this); square_free(n, p, sqf); @@ -2395,7 +2396,7 @@ namespace realclosure { \brief Root isolation for polynomials where 0 is not a root. */ void nz_isolate_roots(unsigned n, value * const * p, numeral_vector & roots) { - TRACE("rcf_isolate", + TRACE("rcf_isolate", tout << "nz_isolate_roots\n"; display_poly(tout, n, p); tout << "\n";); if (m_clean_denominators) { @@ -2418,7 +2419,7 @@ namespace realclosure { SASSERT(!is_zero(p[n-1])); if (n == 1) { // constant polynomial - return; + return; } unsigned i = 0; for (; i < n; i++) { @@ -2463,7 +2464,7 @@ namespace realclosure { int sign(numeral const & a) { return sign(a.m_value); } - + /** \brief Return true the given rational function value is actually an integer. @@ -2484,7 +2485,7 @@ namespace realclosure { bool is_int(numeral const & a) { if (is_zero(a)) return true; - else if (is_nz_rational(a)) + else if (is_nz_rational(a)) return qm().is_int(to_mpq(a)); else { rational_function_value * rf = to_rational_function(a); @@ -2612,7 +2613,7 @@ namespace realclosure { reset(a); return; } - + del(a); a.m_value = mk_rational(); inc_ref(a.m_value); @@ -2633,7 +2634,7 @@ namespace realclosure { inc_ref(a.m_value); update_mpq_value(a, n); } - + /** \brief a <- n */ @@ -2647,7 +2648,7 @@ namespace realclosure { inc_ref(a.m_value); update_mpq_value(a, n); } - + /** \brief a <- n */ @@ -2752,7 +2753,7 @@ namespace realclosure { void mul(value * a, unsigned sz, value * const * p, value_ref_buffer & r) { SASSERT(p != r.c_ptr()); r.reset(); - if (a == 0) + if (a == 0) return; value_ref a_i(*this); for (unsigned i = 0; i < sz; i++) { @@ -2807,7 +2808,7 @@ namespace realclosure { /** \brief q <- quotient(p1, p2); r <- rem(p1, p2) */ - void div_rem(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, + void div_rem(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, value_ref_buffer & q, value_ref_buffer & r) { SASSERT(sz2 > 0); if (sz2 == 1) { @@ -2836,7 +2837,7 @@ namespace realclosure { adjust_size(q); break; } - unsigned m_n = sz1 - sz2; // m-n + unsigned m_n = sz1 - sz2; // m-n div(r[sz1 - 1], b_n, ratio); // q[m_n] <- q[m_n] + r[sz1 - 1]/b_n add(q[m_n], ratio, aux); @@ -2853,7 +2854,7 @@ namespace realclosure { } } } - + /** \brief q <- quotient(p1, p2) */ @@ -2861,7 +2862,7 @@ namespace realclosure { value_ref_buffer r(*this); div_rem(sz1, p1, sz2, p2, q, r); } - + /** \brief r <- p/a */ @@ -2880,7 +2881,7 @@ namespace realclosure { void rem(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, value_ref_buffer & r) { SASSERT(p1 != r.c_ptr()); SASSERT(p2 != r.c_ptr()); - TRACE("rcf_rem", + TRACE("rcf_rem", tout << "rem\n"; display_poly(tout, sz1, p1); tout << "\n"; display_poly(tout, sz2, p2); tout << "\n";); @@ -2916,7 +2917,7 @@ namespace realclosure { /** \brief r <- prem(p1, p2) Pseudo-remainder - + We are working on a field, but it is useful to use the pseudo-remainder algorithm because it does not create rational function values. That is, if has_clean_denominators(p1) and has_clean_denominators(p2) then has_clean_denominators(r). @@ -2924,7 +2925,7 @@ namespace realclosure { void prem(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, unsigned & d, value_ref_buffer & r) { SASSERT(p1 != r.c_ptr()); SASSERT(p2 != r.c_ptr()); - TRACE("rcf_prem", + TRACE("rcf_prem", tout << "prem\n"; display_poly(tout, sz1, p1); tout << "\n"; display_poly(tout, sz2, p2); tout << "\n";); @@ -2988,7 +2989,7 @@ namespace realclosure { r.push_back(a_i); } } - + /** \brief r <- -r */ @@ -3016,7 +3017,7 @@ namespace realclosure { } /** - \brief r <- srem(p1, p2) + \brief r <- srem(p1, p2) Signed remainder */ void srem(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, value_ref_buffer & r) { @@ -3027,7 +3028,7 @@ namespace realclosure { } /** - \brief r <- sprem(p1, p2) + \brief r <- sprem(p1, p2) Signed pseudo remainder */ void sprem(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, value_ref_buffer & r) { @@ -3077,7 +3078,7 @@ namespace realclosure { } /** - Auxiliary method for + Auxiliary method for bool struct_eq(value * a, value * b) */ bool struct_eq(unsigned sz_a, value * const * p_a, unsigned sz_b, value * const * p_b) const { @@ -3091,7 +3092,7 @@ namespace realclosure { } /** - Auxiliary method for + Auxiliary method for bool struct_eq(value * a, value * b) */ bool struct_eq(polynomial const & p_a, polynomial const & p_b) const { @@ -3131,7 +3132,7 @@ namespace realclosure { } return true; } - + /** \brief See comment at has_clean_denominators(value * a) */ @@ -3142,7 +3143,7 @@ namespace realclosure { /** \brief "Clean" the denominators of 'a'. That is, return p and q s.t. a == p/q - and + and has_clean_denominators(p) and has_clean_denominators(q) */ void clean_denominators_core(value * a, value_ref & p, value_ref & q) { @@ -3150,7 +3151,7 @@ namespace realclosure { TRACE("rcf_clean", tout << "clean_denominators_core [" << m_exec_depth << "]\na: "; display(tout, a, false); tout << "\n";); p.reset(); q.reset(); if (a == 0) { - p = a; + p = a; q = one(); } else if (is_nz_rational(a)) { @@ -3216,7 +3217,7 @@ namespace realclosure { // Compute lcm of the integer elements in dens. // This is a little trick to control the coefficient growth. // We don't compute lcm of the other elements of dens because it is too expensive. - scoped_mpq lcm_z(qm()); + scoped_mpq lcm_z(qm()); bool found_z = false; SASSERT(nums.size() == p_sz); SASSERT(dens.size() == p_sz); @@ -3235,7 +3236,7 @@ namespace realclosure { } } } - + value_ref lcm(*this); if (found_z) { lcm = mk_rational(lcm_z); @@ -3243,10 +3244,10 @@ namespace realclosure { else { lcm = one(); } - + // Compute the multipliers for nums. - // Compute norm_p and d - // + // Compute norm_p and d + // // We do NOT use GCD to compute the LCM of the denominators of non-rational values. // However, we detect structurally equivalent denominators. // @@ -3280,7 +3281,7 @@ namespace realclosure { continue; if (i != j && !is_nz_rational(dens[j])) { if (struct_eq(dens[i], dens[j])) { - if (j < i) + if (j < i) found_lt_eq = true; } else { @@ -3312,7 +3313,7 @@ namespace realclosure { clean_denominators_core(a, p, q); } } - + void clean_denominators(unsigned sz, value * const * p, value_ref_buffer & norm_p, value_ref & d) { if (has_clean_denominators(sz, p)) { norm_p.append(sz, p); @@ -3339,16 +3340,16 @@ namespace realclosure { // GCD of integer coefficients // // --------------------------------- - + /** \brief If has_clean_denominators(a), then this method store the gcd of the integer coefficients in g. If !has_clean_denominators(a) it returns false. - + If g != 0, then it will compute the gcd of g and the coefficients in a. */ bool gcd_int_coeffs(value * a, mpz & g) { if (a == 0) { - return false; + return false; } else if (is_nz_rational(a)) { if (!qm().is_int(to_mpq(a))) @@ -3397,7 +3398,7 @@ namespace realclosure { bool gcd_int_coeffs(polynomial const & p, mpz & g) { return gcd_int_coeffs(p.size(), p.c_ptr(), g); } - + /** \brief Compute gcd_int_coeffs and divide p by it (if applicable). */ @@ -3421,7 +3422,7 @@ namespace realclosure { \brief a <- a/b where b > 0 Auxiliary function for normalize_int_coeffs. It assumes has_clean_denominators(a), and that b divides all integer coefficients. - + FUTURE: perform the operation using destructive updates when a is not shared. */ void exact_div_z(value_ref & a, mpz const & b) { @@ -3463,7 +3464,7 @@ namespace realclosure { // GCD // // --------------------------------- - + bool is_monic(value_ref_buffer const & p) { return p.size() > 0 && is_rational_one(p[p.size() - 1]); } @@ -3638,7 +3639,7 @@ namespace realclosure { flet set(m_in_aux_values, true); SASSERT(seq.size() >= 2); - TRACE("rcf_sturm_seq", + TRACE("rcf_sturm_seq", unsigned sz = seq.size(); tout << "sturm_seq_core [" << m_exec_depth << "]\n"; display_poly(tout, seq.size(sz-2), seq.coeffs(sz-2)); tout << "\n"; @@ -3661,7 +3662,7 @@ namespace realclosure { seq.push(r.size(), r.c_ptr()); } } - + /** \brief Store in seq the Sturm sequence for (p1; p2) */ @@ -3671,7 +3672,7 @@ namespace realclosure { seq.push(sz2, p2); sturm_seq_core(seq); } - + /** \brief Store in seq the Sturm sequence for (p; p') */ @@ -3704,7 +3705,7 @@ namespace realclosure { // That is, sign of p(x) at b // // --------------------------------- - + /** \brief Return the sign of p(0) */ @@ -3723,7 +3724,7 @@ namespace realclosure { SASSERT(!is_zero(p[n-1])); // p is well formed return sign(p[n-1]); } - + /** \brief Return the sign of p(-oo) */ @@ -3740,7 +3741,7 @@ namespace realclosure { /** \brief Store in r an approximation (as an interval) for the interval p(b). - + \pre n >= 2 */ void eval_sign_at_approx(unsigned n, value * const * p, mpbq const & b, mpbqi & r) { @@ -3753,7 +3754,7 @@ namespace realclosure { scoped_mpbqi bi(bqim()); set_interval(bi, b); // bi <- [b, b] // r <- a_n * bi - bqim().mul(interval(p[n - 1]), bi, r); + bqim().mul(interval(p[n - 1]), bi, r); unsigned i = n - 1; while (i > 0) { checkpoint(); @@ -3766,7 +3767,7 @@ namespace realclosure { } /** - \brief We say a polynomial has "refinable" approximated coefficients if the intervals + \brief We say a polynomial has "refinable" approximated coefficients if the intervals approximating the coefficients do not have -oo or oo as lower/upper bounds. */ bool has_refineable_approx_coeffs(unsigned n, value * const * p) { @@ -3817,7 +3818,7 @@ namespace realclosure { // Original Horner Sequence // ((a_n * b + a_{n-1})*b + a_{n-2})*b + a_{n-3} ... // Variation of the Horner Sequence for (2^k)^n*p(b) - // ((a_n * c + a_{n-1}*2_k)*c + a_{n-2}*(2_k)^2)*c + a_{n-3}*(2_k)^3 ... + a_0*(2_k)^n + // ((a_n * c + a_{n-1}*2_k)*c + a_{n-2}*(2_k)^2)*c + a_{n-3}*(2_k)^3 ... + a_0*(2_k)^n scoped_mpz mpz_twok(qm()); qm().mul2k(mpz(1), b.k(), mpz_twok); value_ref twok(*this), twok_i(*this); @@ -3865,7 +3866,7 @@ namespace realclosure { } return r; } - + /** \brief Return the sign of p(b) */ @@ -3889,7 +3890,7 @@ namespace realclosure { unsigned prec; if (m >= 0) prec = 1; - else + else prec = -m; SASSERT(prec >= 1); while (prec <= m_max_precision) { @@ -3923,11 +3924,11 @@ namespace realclosure { PLUS_INF, MPBQ }; - + /** \brief Compute the number of sign variations at position (loc, b) in the given polynomial sequence. The position (loc, b) should be interpreted in the following way: - + - (ZERO, *) -> number of sign variations at 0. - (MINUS_INF, *) -> number of sign variations at -oo. - (PLUS_INF, *) -> number of sign variations at oo. @@ -3974,7 +3975,7 @@ namespace realclosure { } return r; } - + unsigned sign_variations_at_minus_inf(scoped_polynomial_seq const & seq) { mpbq dummy(0); return sign_variations_at_core(seq, MINUS_INF, dummy); @@ -3984,12 +3985,12 @@ namespace realclosure { mpbq dummy(0); return sign_variations_at_core(seq, PLUS_INF, dummy); } - + unsigned sign_variations_at_zero(scoped_polynomial_seq const & seq) { mpbq dummy(0); return sign_variations_at_core(seq, ZERO, dummy); } - + unsigned sign_variations_at(scoped_polynomial_seq const & seq, mpbq const & b) { return sign_variations_at_core(seq, MPBQ, b); } @@ -4020,7 +4021,7 @@ namespace realclosure { /** \brief Given a polynomial Sturm sequence seq for (P; P' * Q) and an interval (a, b], it returns - TaQ(Q, P; a, b) = + TaQ(Q, P; a, b) = #{ x \in (a, b] | P(x) = 0 and Q(x) > 0 } - #{ x \in (a, b] | P(x) = 0 and Q(x) < 0 } @@ -4030,9 +4031,9 @@ namespace realclosure { int TaQ(scoped_polynomial_seq & seq, mpbqi const & interval) { return sign_variations_at_lower(seq, interval) - sign_variations_at_upper(seq, interval); } - + /** - \brief Return TaQ(Q, P; a, b) = + \brief Return TaQ(Q, P; a, b) = #{ x \in (a, b] | P(x) = 0 and Q(x) > 0 } - #{ x \in (a, b] | P(x) = 0 and Q(x) < 0 } @@ -4041,7 +4042,7 @@ namespace realclosure { */ int TaQ(unsigned p_sz, value * const * p, unsigned q_sz, value * const * q, mpbqi const & interval) { INC_DEPTH(); - TRACE("rcf_TaQ", tout << "TaQ [" << m_exec_depth << "]\n"; + TRACE("rcf_TaQ", tout << "TaQ [" << m_exec_depth << "]\n"; display_poly(tout, p_sz, p); tout << "\n"; display_poly(tout, q_sz, q); tout << "\n";); scoped_polynomial_seq seq(*this); @@ -4050,14 +4051,14 @@ namespace realclosure { } /** - \brief Return TaQ(1, P; a, b) = + \brief Return TaQ(1, P; a, b) = #{ x \in (a, b] | P(x) = 0 } - + \remark This method ignores whether the interval end-points are closed or open. */ int TaQ_1(unsigned p_sz, value * const * p, mpbqi const & interval) { INC_DEPTH(); - TRACE("rcf_TaQ", tout << "TaQ_1 [" << m_exec_depth << "]\n"; + TRACE("rcf_TaQ", tout << "TaQ_1 [" << m_exec_depth << "]\n"; display_poly(tout, p_sz, p); tout << "\n";); scoped_polynomial_seq seq(*this); sturm_seq(p_sz, p, seq); @@ -4069,7 +4070,7 @@ namespace realclosure { // Interval refinement // // --------------------------------- - + void refine_rational_interval(rational_value * v, unsigned prec) { mpbqi & i = interval(v); if (!i.lower_is_open() && !i.upper_is_open()) { @@ -4116,7 +4117,7 @@ namespace realclosure { SASSERT(sz > 0); SASSERT(p[sz - 1] != 0); // r <- a_n * v - bqim().mul(interval(p[sz-1]), v, r); + bqim().mul(interval(p[sz-1]), v, r); unsigned i = sz - 1; while (i > 0) { --i; @@ -4129,7 +4130,7 @@ namespace realclosure { } /** - \brief Update the interval of v by using the intervals of + \brief Update the interval of v by using the intervals of extension and coefficients of the rational function. */ void update_rf_interval(rational_function_value * v, unsigned prec) { @@ -4156,10 +4157,10 @@ namespace realclosure { VERIFY(refine_coeffs_interval(d, _prec)); // must return true because a transcendental never depends on an infinitesimal refine_transcendental_interval(to_transcendental(v->ext()), _prec); update_rf_interval(v, prec); - + TRACE("rcf_transcendental", tout << "after update_rf_interval: " << magnitude(v->interval()) << " "; bqim().display(tout, v->interval()); tout << std::endl;); - + if (check_precision(v->interval(), prec)) return; _prec++; @@ -4208,13 +4209,13 @@ namespace realclosure { _prec++; } } - else { + else { // The following condition must hold because gcd(numerator, denominator) == 1 - // If num_idx > 0 and den_idx > 0, eps^{min(num_idx, den_idx)} is a factor of gcd(numerator, denominator) + // If num_idx > 0 and den_idx > 0, eps^{min(num_idx, den_idx)} is a factor of gcd(numerator, denominator) SASSERT(num_idx == 0 || den_idx == 0); int s = sign(numerator[num_idx]) * sign(denominator[den_idx]); // The following must hold since numerator[num_idx] and denominator[den_idx] are not zero. - SASSERT(s != 0); + SASSERT(s != 0); if (num_idx == 0) { SASSERT(den_idx > 0); // |v| is bigger than any binary rational @@ -4296,7 +4297,7 @@ namespace realclosure { bool refine_algebraic_interval(rational_function_value * v, unsigned prec) { SASSERT(v->ext()->is_algebraic()); polynomial const & n = v->num(); - SASSERT(is_denominator_one(v)); + SASSERT(is_denominator_one(v)); unsigned _prec = prec; while (true) { if (!refine_coeffs_interval(n, _prec) || @@ -4326,7 +4327,7 @@ namespace realclosure { refine_rational_interval(to_nz_rational(v), prec); return true; } - else { + else { rational_function_value * rf = to_rational_function(v); if (rf->ext()->is_transcendental()) { refine_transcendental_interval(rf, prec); @@ -4371,13 +4372,13 @@ namespace realclosure { UNREACHABLE(); return 0; } - + /** - out <- in + infinitesimal (if plus_eps == true) + out <- in + infinitesimal (if plus_eps == true) out <- in - infinitesimal (if plus_eps == false) We use the following rules for performing the assignment - + If plus_eps == True If lower(in) == v (closed or open), then lower(out) == v and open If upper(in) == v and open, then upper(out) == v and open @@ -4385,7 +4386,7 @@ namespace realclosure { where new_v is v + tiny_value / 2^k, where k is the smallest natural such that sign(new_v) == sign(v) If plus_eps == False If lower(in) == v and open, then lower(out) == v and open - If lower(in) == v and closed, then lower(out) == new_v and open + If lower(in) == v and closed, then lower(out) == new_v and open If upper(in) == v (closed or open), then upper(out) == v and open where new_v is v - tiny_value / 2^k, where k is the smallest natural such that sign(new_v) == sign(v) */ @@ -4478,13 +4479,13 @@ namespace realclosure { div(new_num_i, new_den_i, m_ini_precision, v->interval()); } } - else { + else { // The following condition must hold because gcd(numerator, denominator) == 1 - // If num_idx > 0 and den_idx > 0, eps^{min(num_idx, den_idx)} is a factor of gcd(numerator, denominator) + // If num_idx > 0 and den_idx > 0, eps^{min(num_idx, den_idx)} is a factor of gcd(numerator, denominator) SASSERT(num_idx == 0 || den_idx == 0); int s = sign(numerator[num_idx]) * sign(denominator[den_idx]); // The following must hold since numerator[num_idx] and denominator[den_idx] are not zero. - SASSERT(s != 0); + SASSERT(s != 0); if (num_idx == 0) { SASSERT(den_idx > 0); // |v| is bigger than any binary rational @@ -4607,7 +4608,7 @@ namespace realclosure { count_signs_at_zeros_core(taq_p_q, p.size(), p.c_ptr(), q.size(), q.c_ptr(), x->iso_interval(), num_roots, q_eq_0, q_gt_0, q_lt_0, q2); if (q_eq_0 > 0 && q_gt_0 == 0 && q_lt_0 == 0) { // q(x) is zero - return false; + return false; } else if (q_eq_0 == 0 && q_gt_0 > 0 && q_lt_0 == 0) { // q(x) is positive @@ -4623,7 +4624,7 @@ namespace realclosure { sign_det & sdt = *(x->sdt()); // Remark: // By definition of algebraic and sign_det, we know that - // sdt.M_s * [1, ..., 1]^t = sdt.taqrs()^t + // sdt.M_s * [1, ..., 1]^t = sdt.taqrs()^t // That is, // [1, ..., 1]^t = sdt.M_s^-1 * sdt.taqrs()^t // Moreover the number of roots in x->iso_interval() is equal to the number of rows and columns in sdt.M_s. @@ -4746,8 +4747,8 @@ namespace realclosure { bool expensive_determine_algebraic_sign(rational_function_value * v) { SASSERT(contains_zero(v->interval())); SASSERT(v->ext()->is_algebraic()); - TRACE("rcf_algebraic_sign", - tout << "expensive_determine_algebraic_sign\n"; display(tout, v, false); + TRACE("rcf_algebraic_sign", + tout << "expensive_determine_algebraic_sign\n"; display(tout, v, false); tout << "\ninterval: "; bqim().display(tout, v->interval()); tout << "\n";); algebraic * x = to_algebraic(v->ext()); scoped_mpbqi num_interval(bqim()); @@ -4783,7 +4784,7 @@ namespace realclosure { return expensive_determine_algebraic_sign(v); } SASSERT(!contains_zero(v->interval())); - return true; + return true; } } @@ -4856,16 +4857,16 @@ namespace realclosure { normalize_num_monic_den(tmp1.size(), tmp1.c_ptr(), tmp2.size(), tmp2.c_ptr(), new_p1, new_p2); } } - TRACE("normalize_fraction_bug", + TRACE("normalize_fraction_bug", display_poly(tout, sz1, p1); tout << "\n"; display_poly(tout, sz2, p2); tout << "\n"; tout << "====>\n"; display_poly(tout, new_p1.size(), new_p1.c_ptr()); tout << "\n"; display_poly(tout, new_p2.size(), new_p2.c_ptr()); tout << "\n";); } - + /** - \brief Auxiliary function for normalize_fraction. + \brief Auxiliary function for normalize_fraction. It produces new_p1 and new_p2 s.t. new_p1/new_p2 == p1/p2 gcd(new_p1, new_p2) == 1 @@ -4874,16 +4875,16 @@ namespace realclosure { \pre p2 is monic \pre sz2 > 1 */ - void normalize_num_monic_den(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, + void normalize_num_monic_den(unsigned sz1, value * const * p1, unsigned sz2, value * const * p2, value_ref_buffer & new_p1, value_ref_buffer & new_p2) { SASSERT(sz2 > 1); SASSERT(is_rational_one(p2[sz2-1])); - + value_ref_buffer g(*this); gcd(sz1, p1, sz2, p2, g); SASSERT(is_monic(g)); - + if (is_rational_one(g)) { new_p1.append(sz1, p1); new_p2.append(sz2, p2); @@ -4897,12 +4898,12 @@ namespace realclosure { /** \brief Simplify p1(x) using x's defining polynomial. - + By definition of polynomial division, we have: - + new_p1(x) == quotient(p1,p)(x) * p(x) + rem(p1,p)(x) - - Since p(x) == 0, we have that + + Since p(x) == 0, we have that new_p1(x) = rem(p1,p)(x) */ @@ -4916,14 +4917,14 @@ namespace realclosure { new_p1.append(sz1, p1); } } - + /** \brief Create a new value using the a->ext(), and the given numerator and denominator. Use interval(a) + interval(b) as an initial approximation for the interval of the result, and invoke determine_sign() */ void mk_add_value(rational_function_value * a, value * b, unsigned num_sz, value * const * num, unsigned den_sz, value * const * den, value_ref & r) { SASSERT(num_sz > 0); - // den_sz may be zero for algebraic extensions. + // den_sz may be zero for algebraic extensions. // We do not use denominators for algebraic extensions. if (num_sz == 1 && den_sz <= 1) { // In this case, the normalization rules guarantee that den is one. @@ -4959,7 +4960,7 @@ namespace realclosure { SASSERT(new_num.size() == an.size()); mk_add_value(a, b, new_num.size(), new_num.c_ptr(), one.size(), one.c_ptr(), r); } - + /** \brief Add a value 'a' of the form n/d with b where rank(a) > rank(b) */ @@ -5006,13 +5007,13 @@ namespace realclosure { else { // We don't need to invoke normalize_algebraic even if x (== a->ext()) is algebraic. // Reason: by construction the polynomials a->num() and b->num() are "normalized". - // That is, their degrees are < degree of the polynomial defining x. + // That is, their degrees are < degree of the polynomial defining x. // Moreover, when we add polynomials, the degree can only decrease. // So, degree of new_num must be < degree of x's defining polynomial. mk_add_value(a, b, new_num.size(), new_num.c_ptr(), one.size(), one.c_ptr(), r); } } - + /** \brief Add values 'a' and 'b' of the form n/d and rank(a) == rank(b) */ @@ -5047,7 +5048,7 @@ namespace realclosure { } } } - + void add(value * a, value * b, value_ref & r) { if (a == 0) { r = b; @@ -5060,7 +5061,7 @@ namespace realclosure { qm().add(to_mpq(a), to_mpq(b), v); if (qm().is_zero(v)) r = 0; - else + else r = mk_rational_and_swap(v); } else { @@ -5069,14 +5070,14 @@ namespace realclosure { display(tout, a, false); tout << "\n"; display(tout, b, false); tout << "\n";); switch (compare_rank(a, b)) { - case -1: add_rf_v(to_rational_function(b), a, r); break; + case -1: add_rf_v(to_rational_function(b), a, r); break; case 0: add_rf_rf(to_rational_function(a), to_rational_function(b), r); break; case 1: add_rf_v(to_rational_function(a), b, r); break; default: UNREACHABLE(); } } } - + void sub(value * a, value * b, value_ref & r) { if (a == 0) { neg(b, r); @@ -5089,7 +5090,7 @@ namespace realclosure { qm().sub(to_mpq(a), to_mpq(b), v); if (qm().is_zero(v)) r = 0; - else + else r = mk_rational_and_swap(v); } else { @@ -5138,7 +5139,7 @@ namespace realclosure { void mk_mul_value(rational_function_value * a, value * b, unsigned num_sz, value * const * num, unsigned den_sz, value * const * den, value_ref & r) { SASSERT(num_sz > 0); if (num_sz == 1 && den_sz <= 1) { - // den_sz may be zero for algebraic extensions. + // den_sz may be zero for algebraic extensions. // We do not use denominators for algebraic extensions. // In this case, the normalization rules guarantee that den is one. SASSERT(den_sz == 0 || is_rational_one(den[0])); @@ -5277,7 +5278,7 @@ namespace realclosure { display(tout, a, false); tout << "\n"; display(tout, b, false); tout << "\n";); switch (compare_rank(a, b)) { - case -1: mul_rf_v(to_rational_function(b), a, r); break; + case -1: mul_rf_v(to_rational_function(b), a, r); break; case 0: mul_rf_rf(to_rational_function(a), to_rational_function(b), r); break; case 1: mul_rf_v(to_rational_function(a), b, r); break; default: UNREACHABLE(); @@ -5324,13 +5325,13 @@ namespace realclosure { q(alpha) * h(alpha) = 1 The procedure succeeds (and returns true) if the GCD(q, p) = 1. - + If the GCD(q, p) != 1, then it returns false, and store the GCD in g. - + The following procedure is essentially a special case of the extended polynomial GCD algorithm. */ bool inv_algebraic(unsigned q_sz, value * const * q, unsigned p_sz, value * const * p, value_ref_buffer & g, value_ref_buffer & h) { - TRACE("inv_algebraic", + TRACE("inv_algebraic", tout << "q: "; display_poly(tout, q_sz, q); tout << "\n"; tout << "p: "; display_poly(tout, p_sz, p); tout << "\n";); SASSERT(q_sz > 0); @@ -5342,15 +5343,15 @@ namespace realclosure { value_ref_buffer R(*this); R.push_back(one()); value_ref_buffer Quo(*this), Rem(*this), aux(*this); - + // We find h(alpha), by rewriting the equation // q(alpha) * h(alpha) = 1 - // until we have + // until we have // 1 * h(alpha) = R(alpha) while (true) { // In every iteration of the loop we have - // Q(alpha) * h(alpha) = R(alpha) - TRACE("inv_algebraic", + // Q(alpha) * h(alpha) = R(alpha) + TRACE("inv_algebraic", tout << "Q: "; display_poly(tout, Q.size(), Q.c_ptr()); tout << "\n"; tout << "R: "; display_poly(tout, R.size(), R.c_ptr()); tout << "\n";); if (Q.size() == 1) { @@ -5375,13 +5376,13 @@ namespace realclosure { else { // By the definition of polynomial division, we have // p == Quo * Q + Rem - // Since, we have p(alpha) = 0 + // Since, we have p(alpha) = 0 // Quo(alpha) * Q(alpha) = -Rem(alpha) (*) // Now, if we multiply the equation // Q(alpha) * h(alpha) = R(alpha) // by Quo(alpha) and apply (*), we get // -Rem(alpha) * h(alpha) = R(alpha) * Quo(alpha) - // Thus, we update Q, and R for the next iteration, as + // Thus, we update Q, and R for the next iteration, as // Q <- -REM // R <- R * Quo // Q <- -Rem @@ -5410,7 +5411,7 @@ namespace realclosure { polynomial const & q = a->num(); polynomial const & p = alpha->p(); value_ref_buffer norm_q(*this); - // since p(alpha) = 0, we have that q(alpha) = rem(q, p)(alpha) + // since p(alpha) = 0, we have that q(alpha) = rem(q, p)(alpha) rem(q.size(), q.c_ptr(), p.size(), p.c_ptr(), norm_q); SASSERT(norm_q.size() < p.size()); value_ref_buffer new_num(*this), g(*this); @@ -5430,7 +5431,7 @@ namespace realclosure { // This can happen because we don't use minimal // polynomials to represent algebraic extensions such // as alpha. - + // We recover from the failure by refining the defining polynomial of alpha // with p/gcd(p, q) // Remark: g contains the gcd of p, q @@ -5447,7 +5448,7 @@ namespace realclosure { SASSERT(new_p.size() >= 2); if (new_p.size() == 2) { - // Easy case: alpha is actually equal to + // Easy case: alpha is actually equal to // -new_p[0]/new_p[1] value_ref alpha_val(*this); alpha_val = new_p[0]; @@ -5474,7 +5475,7 @@ namespace realclosure { else { // Let sdt be alpha->sdt(); // In pricipal, the signs of the polynomials sdt->qs can be used - // to discriminate the roots of new_p. The signs of this polynomials + // to discriminate the roots of new_p. The signs of this polynomials // depend only on alpha, and not on the polynomial used to define alpha // So, in principle, we can reuse m_qs and m_sign_conditions. // However, we have to recompute the tarski queries with respect to new_p. @@ -5523,7 +5524,7 @@ namespace realclosure { set_interval(alpha->m_iso_interval, new_alpha->m_iso_interval); alpha->m_sc_idx = new_alpha->m_sc_idx; alpha->m_depends_on_infinitesimals = new_alpha->m_depends_on_infinitesimals; - + // The new call will succeed because q and new_p are co-prime inv_algebraic(a, r); } @@ -5615,7 +5616,7 @@ namespace realclosure { mul(a.m_value, b.m_value, r); set(c, r); } - + void div(numeral const & a, numeral const & b, numeral & c) { value_ref r(*this); div(a.m_value, b.m_value, r); @@ -5628,7 +5629,7 @@ namespace realclosure { void root(numeral const & a, unsigned k, numeral & b) { if (k == 0) throw exception("0-th root is indeterminate"); - + if (k == 1 || is_zero(a)) { set(b, a); return; @@ -5636,7 +5637,7 @@ namespace realclosure { if (sign(a) < 0 && k % 2 == 0) throw exception("even root of negative number"); - + // create the polynomial p of the form x^k - a value_ref_buffer p(*this); value_ref neg_a(*this); @@ -5645,7 +5646,7 @@ namespace realclosure { for (unsigned i = 0; i < k - 1; i++) p.push_back(0); p.push_back(one()); - + numeral_vector roots; nz_isolate_roots(p.size(), p.c_ptr(), roots); SASSERT(roots.size() == 1 || roots.size() == 2); @@ -5659,7 +5660,7 @@ namespace realclosure { } del(roots); } - + /** \brief a <- b^k */ @@ -5741,7 +5742,7 @@ namespace realclosure { mark(p[i]); } } - + void mark(value * v) { if (v == 0 || is_nz_rational(v)) return; @@ -5762,7 +5763,7 @@ namespace realclosure { } bool use_parenthesis(value * v) const { - if (is_zero(v) || is_nz_rational(v)) + if (is_zero(v) || is_nz_rational(v)) return false; rational_function_value * rf = to_rational_function(v); return num_nz_coeffs(rf->num()) > 1 || !is_denominator_one(rf); @@ -5829,7 +5830,7 @@ namespace realclosure { struct display_ext_proc { imp const & m; - extension * m_ref; + extension * m_ref; display_ext_proc(imp const & _m, extension * r):m(_m), m_ref(r) {} void operator()(std::ostream & out, bool compact, bool pp) const { m.display_ext(out, m_ref, compact, pp); @@ -5848,7 +5849,7 @@ namespace realclosure { else out << " > 0"; } - + void display_sign_conditions(std::ostream & out, sign_condition * sc) const { bool first = true; out << "{"; @@ -5892,7 +5893,7 @@ namespace realclosure { out << ", "; display_interval(out, a->iso_interval(), pp); out << ", "; - if (a->sdt() != 0) + if (a->sdt() != 0) display_sign_conditions(out, a->sdt()->sc(a->sc_idx()), a->sdt()->qs(), compact, pp); else out << "{}"; @@ -5916,9 +5917,9 @@ namespace realclosure { switch (r->knd()) { case extension::TRANSCENDENTAL: to_transcendental(r)->display(out, pp); break; case extension::INFINITESIMAL: to_infinitesimal(r)->display(out, pp); break; - case extension::ALGEBRAIC: + case extension::ALGEBRAIC: if (compact) { - if (pp) + if (pp) out << "α" << r->idx() << ""; else out << "r!" << r->idx(); @@ -5932,7 +5933,7 @@ namespace realclosure { void display(std::ostream & out, value * v, bool compact, bool pp=false) const { if (v == 0) out << "0"; - else if (is_nz_rational(v)) + else if (is_nz_rational(v)) qm().display(out, to_mpq(v)); else { rational_function_value * rf = to_rational_function(v); @@ -5989,7 +5990,7 @@ namespace realclosure { mpbqi const & i = interval(a.m_value); if (refine_interval(a.m_value, precision*4)) { // hack - if (bqm().is_int(i.lower())) + if (bqm().is_int(i.lower())) bqm().display_decimal(out, i.upper(), precision); else bqm().display_decimal(out, i.lower(), precision); @@ -6001,7 +6002,7 @@ namespace realclosure { out << "-?"; } } - + void display_decimal(std::ostream & out, numeral const & a, unsigned precision) const { if (is_zero(a)) { out << "0"; @@ -6033,7 +6034,7 @@ namespace realclosure { manager::manager(reslimit& lim, unsynch_mpq_manager & m, params_ref const & p, small_object_allocator * a) { m_imp = alloc(imp, lim, m, p, a); } - + manager::~manager() { dealloc(m_imp); } @@ -6061,7 +6062,7 @@ namespace realclosure { void manager::mk_infinitesimal(numeral & r) { m_imp->mk_infinitesimal(r); } - + void manager::mk_transcendental(char const * n, char const * pp_n, mk_interval & proc, numeral & r) { m_imp->mk_transcendental(n, pp_n, proc, r); } @@ -6091,7 +6092,7 @@ namespace realclosure { save_interval_ctx ctx(this); return m_imp->sign(a); } - + bool manager::is_zero(numeral const & a) { return sign(a) == 0; } @@ -6107,11 +6108,11 @@ namespace realclosure { bool manager::is_int(numeral const & a) { return m_imp->is_int(a); } - + bool manager::depends_on_infinitesimals(numeral const & a) { return m_imp->depends_on_infinitesimals(a); } - + void manager::set(numeral & a, int n) { m_imp->set(a, n); } @@ -6136,7 +6137,7 @@ namespace realclosure { save_interval_ctx ctx(this); m_imp->root(a, k, b); } - + void manager::power(numeral const & a, unsigned k, numeral & b) { save_interval_ctx ctx(this); m_imp->power(a, k, b); diff --git a/src/math/subpaving/subpaving_t_def.h b/src/math/subpaving/subpaving_t_def.h index 8cdd016aa..6ae7d97b1 100644 --- a/src/math/subpaving/subpaving_t_def.h +++ b/src/math/subpaving/subpaving_t_def.h @@ -31,8 +31,8 @@ namespace subpaving { template class breadth_first_node_selector : public context_t::node_selector { typedef typename context_t::node node; -public: - breadth_first_node_selector(context_t * ctx): +public: + breadth_first_node_selector(context_t * ctx): context_t::node_selector(ctx) { } @@ -47,8 +47,8 @@ public: template class depth_first_node_selector : public context_t::node_selector { typedef typename context_t::node node; -public: - depth_first_node_selector(context_t * ctx): +public: + depth_first_node_selector(context_t * ctx): context_t::node_selector(ctx) { } @@ -73,12 +73,12 @@ class round_robing_var_selector : public context_t::var_selector { x = 0; } -public: +public: round_robing_var_selector(context_t * ctx, bool only_non_def = true): context_t::var_selector(ctx), m_only_non_def(only_non_def) { } - + // Return the next variable to branch. virtual var operator()(typename context_t::node * n) { typename context_t::numeral_manager & nm = this->ctx()->nm(); @@ -86,7 +86,7 @@ public: var x = this->ctx()->splitting_var(n); if (x == null_var) x = 0; - else + else next(x); var start = x; do { @@ -112,13 +112,13 @@ public: - All variables x s.t. lower(x) == upper(x) are ignored. - If node contains an unbounded variable (-oo, oo), then return the smallest unbounded variable. - + - Otherwise, select the smallest variable x with the largest width, where width is defined as: If x has lower and upper bound, then width = upper(x) - lower(x). If x has only lower, width = penalty/max(|lower(x)|, 1) - If x has only upper, width = penalty/max(|upper(x)|, 1) - penaly is a parameter of this class. + If x has only upper, width = penalty/max(|upper(x)|, 1) + penaly is a parameter of this class. This strategy guarantees fairness. */ @@ -127,13 +127,13 @@ class largest_interval_var_selector : public context_t::var_selector { unsigned m_penalty; bool m_only_non_def; -public: +public: largest_interval_var_selector(context_t * ctx, unsigned unbounded_penalty = 10, bool only_non_def = true): context_t::var_selector(ctx), m_penalty(unbounded_penalty), m_only_non_def(only_non_def) { } - + // Return the next variable to branch. virtual var operator()(typename context_t::node * n) { var y = null_var; @@ -149,7 +149,7 @@ public: typename context_t::bound * u = n->upper(x); // variables without lower and upper bounds are selected immediately. if (l == 0 && u == 0) - return x; + return x; if (l != 0 && u != 0) { // ignore variables s.t. lower(x) == upper(x) if (nm.eq(l->value(), u->value())) @@ -165,7 +165,7 @@ public: nm.set(width, l->value()); else nm.set(width, u->value()); - C::round_to_plus_inf(nm); + C::round_to_plus_inf(nm); if (nm.is_neg(width)) nm.neg(width); if (nm.lt(width, one)) @@ -215,7 +215,7 @@ public: nm.set(delta, static_cast(m_delta)); nm.set(mid, upper->value()); C::round_to_minus_inf(nm); - nm.sub(mid, delta, mid); + nm.sub(mid, delta, mid); // mid == upper - delta } else if (upper == 0) { @@ -224,7 +224,7 @@ public: nm.set(delta, static_cast(m_delta)); nm.set(mid, lower->value()); C::round_to_plus_inf(nm); - nm.add(mid, delta, mid); + nm.add(mid, delta, mid); // mid == lower + delta } else { @@ -237,10 +237,10 @@ public: throw subpaving::exception(); // mid == (lower + upper)/2 } - + this->mk_decided_bound(x, mid, false, m_left_open, left); this->mk_decided_bound(x, mid, true, !m_left_open, right); - TRACE("subpaving_int_split", + TRACE("subpaving_int_split", tout << "LEFT:\n"; this->ctx()->display_bounds(tout, left); tout << "\nRIGHT:\n"; this->ctx()->display_bounds(tout, right);); } @@ -342,7 +342,7 @@ void context_t::node::push(bound * b) { } } -/** +/** \brief Return the most recent variable that was used for splitting on node n. */ template @@ -395,11 +395,11 @@ void context_t::polynomial::display(std::ostream & out, numeral_manager & nm, out << nm.to_rational_string(m_c); first = false; } - + for (unsigned i = 0; i < m_size; i++) { if (first) first = false; - else + else out << " + "; if (!nm.is_one(a(i))) { out << nm.to_rational_string(a(i)); @@ -460,7 +460,7 @@ context_t::~context_t() { template void context_t::checkpoint() { if (!m_limit.inc()) - throw default_exception("canceled"); + throw default_exception(Z3_CANCELED_MSG); if (memory::get_allocation_size() > m_max_memory) throw default_exception(Z3_MAX_MEMORY_MSG); cooperate("subpaving"); @@ -497,7 +497,7 @@ void context_t::updt_params(params_ref const & p) { m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); unsigned prec = p.get_uint("nth_root_precision", 8192); - if (prec == 0) + if (prec == 0) prec = 1; nm().set(m_nth_root_prec, static_cast(prec)); nm().inv(m_nth_root_prec); @@ -513,7 +513,7 @@ void context_t::collect_param_descrs(param_descrs & d) { } template -void context_t::display_params(std::ostream & out) const { +void context_t::display_params(std::ostream & out) const { out << "max_nodes " << m_max_nodes << "\n"; out << "max_depth " << m_max_depth << "\n"; out << "epsilon " << nm().to_rational_string(m_epsilon) << "\n"; @@ -626,7 +626,7 @@ void context_t::display_definition(std::ostream & out, definition const * d, template void context_t::display(std::ostream & out, constraint * c, bool use_star) const { - if (c->get_kind() == constraint::CLAUSE) + if (c->get_kind() == constraint::CLAUSE) static_cast(c)->display(out, nm(), *m_display_proc); else display_definition(out, static_cast(c), use_star); @@ -639,7 +639,7 @@ void context_t::display_bounds(std::ostream & out, node * n) const { bound * l = n->lower(x); bound * u = n->upper(x); if (l != 0) { - display(out, l); + display(out, l); out << " "; } if (u != 0) { @@ -782,18 +782,18 @@ typename context_t::ineq * context_t::mk_ineq(var x, numeral const & k, bo } template -void context_t::inc_ref(ineq * a) { +void context_t::inc_ref(ineq * a) { TRACE("subpaving_ref_count", tout << "inc-ref: " << a << " " << a->m_ref_count << "\n";); - if (a) - a->m_ref_count++; + if (a) + a->m_ref_count++; } template void context_t::dec_ref(ineq * a) { if (a) { - TRACE("subpaving_ref_count", - tout << "dec-ref: " << a << " " << a->m_ref_count << "\n"; - a->display(tout, nm()); + TRACE("subpaving_ref_count", + tout << "dec-ref: " << a << " " << a->m_ref_count << "\n"; + a->display(tout, nm()); tout << "\n";); SASSERT(a->m_ref_count > 0); a->m_ref_count--; @@ -804,7 +804,7 @@ void context_t::dec_ref(ineq * a) { } } } - + template void context_t::add_clause_core(unsigned sz, ineq * const * atoms, bool lemma, bool watch) { SASSERT(lemma || watch); @@ -846,7 +846,7 @@ void context_t::del_clause(clause * c) { SASSERT(c->m_num_jst == 0); // We cannot delete a clause that is being used to justify some bound bool watch = c->watched(); var prev_x = null_var; - unsigned sz = c->size(); + unsigned sz = c->size(); for (unsigned i = 0; i < sz; i++) { var x = c->m_atoms[i]->x(); if (watch) { @@ -883,10 +883,10 @@ typename context_t::node * context_t::mk_node(node * parent) { else r = new (mem) node(parent, m_node_id_gen.mk()); m_var_selector->new_node_eh(r); - + // Add node in the leaf dlist push_front(r); - + m_num_nodes++; return r; } @@ -903,9 +903,9 @@ void context_t::del_node(node * n) { // recycle id m_node_id_gen.recycle(n->id()); - // disconnect n from list of leaves. + // disconnect n from list of leaves. remove_from_leaf_dlist(n); - + // disconnect n from parent node * p = n->parent(); bound * b = n->trail_stack(); @@ -1118,7 +1118,7 @@ void context_t::del_definitions() { if (d == 0) continue; switch (d->get_kind()) { - case constraint::MONOMIAL: + case constraint::MONOMIAL: del_monomial(static_cast(d)); break; case constraint::POLYNOMIAL: @@ -1130,7 +1130,7 @@ void context_t::del_definitions() { } } } - + template void context_t::display_constraints(std::ostream & out, bool use_star) const { // display definitions @@ -1160,9 +1160,9 @@ void context_t::display_constraints(std::ostream & out, bool use_star) const // ----------------------------------- template -void context_t::set_conflict(var x, node * n) { +void context_t::set_conflict(var x, node * n) { m_num_conflicts++; - n->set_conflict(x); + n->set_conflict(x); remove_from_leaf_dlist(n); } @@ -1222,12 +1222,12 @@ bool context_t::relevant_new_bound(var x, numeral const & k, bool lower, bool if (m_zero_epsilon && curr_lower != 0 && (nm().lt(k, curr_lower->value()) || ((curr_lower->is_open() || !open) && nm().eq(k, curr_lower->value())))) { // new lower bound does not improve existing bound TRACE("subpaving_relevant_bound", tout << "irrelevant because does not improve existing bound.\n";); - return false; + return false; } if (curr_upper == 0 && nm().lt(m_max_bound, k)) { // new lower bound exceeds the :max-bound threshold TRACE("subpaving_relevant_bound", tout << "irrelevant because exceeds :max-bound threshold.\n";); - return false; + return false; } if (!m_zero_epsilon && curr_lower != 0) { // check if: @@ -1250,10 +1250,10 @@ bool context_t::relevant_new_bound(var x, numeral const & k, bool lower, bool nm().set(delta, min); nm().mul(delta, m_epsilon, delta); nm().add(curr_lower->value(), delta, delta); - TRACE("subpaving_relevant_bound_bug", - tout << "k: "; nm().display(tout, k); + TRACE("subpaving_relevant_bound_bug", + tout << "k: "; nm().display(tout, k); tout << ", delta: "; nm().display(tout, delta); tout << "\n"; - tout << "curr_lower: "; nm().display(tout, curr_lower->value()); + tout << "curr_lower: "; nm().display(tout, curr_lower->value()); tout << ", min: "; nm().display(tout, min); tout << "\n";); if (nm().le(k, delta)) { TRACE("subpaving_relevant_bound", tout << "irrelevant because does not improve existing bound to at least "; @@ -1272,7 +1272,7 @@ bool context_t::relevant_new_bound(var x, numeral const & k, bool lower, bool if (m_zero_epsilon && curr_upper != 0 && (nm().lt(curr_upper->value(), k) || ((curr_upper->is_open() || !open) && nm().eq(k, curr_upper->value())))) { // new upper bound does not improve existing bound TRACE("subpaving_relevant_bound", tout << "irrelevant because does not improve existing bound.\n";); - return false; + return false; } if (curr_lower == 0 && nm().lt(k, m_minus_max_bound)) { // new upper bound exceeds the -:max-bound threshold @@ -1343,7 +1343,7 @@ bool context_t::conflicting_bounds(var x, node * n) const { /** \brief Return the truth value of the inequality t in node n. - + The result may be l_true (True), l_false (False), or l_undef(Unknown). */ template @@ -1399,7 +1399,7 @@ void context_t::propagate_clause(clause * c, node * n) { ineq * a = (*c)[j]; TRACE("propagate_clause", tout << "propagating inequality: "; display(tout, a); tout << "\n";); propagate_bound(a->x(), a->value(), a->is_lower(), a->is_open(), n, justification(c)); - // A clause can propagate only once. + // A clause can propagate only once. // So, we can safely set its timestamp again to avoid another useless visit. c->set_visited(m_timestamp); } @@ -1411,7 +1411,7 @@ void context_t::propagate_polynomial(var x, node * n, var y) { polynomial * p = get_polynomial(x); unsigned sz = p->size(); interval & r = m_i_tmp1; r.set_mutable(); - interval & v = m_i_tmp2; + interval & v = m_i_tmp2; interval & av = m_i_tmp3; av.set_mutable(); if (x == y) { for (unsigned i = 0; i < sz; i++) { @@ -1482,7 +1482,7 @@ void context_t::propagate_polynomial(var x, node * n) { } } TRACE("propagate_polynomial", tout << "unbounded_var: "; display(tout, unbounded_var); tout << "\n";); - + if (unbounded_var != null_var) { propagate_polynomial(x, n, unbounded_var); } @@ -1528,10 +1528,10 @@ void context_t::propagate_monomial(var x, node * n) { // x must be zero numeral & zero = m_tmp1; nm().set(zero, 0); - propagate_bound(x, zero, true, false, n, justification(x)); + propagate_bound(x, zero, true, false, n, justification(x)); if (inconsistent(n)) return; - propagate_bound(x, zero, false, false, n, justification(x)); + propagate_bound(x, zero, false, false, n, justification(x)); } // no need to downward propagation return; @@ -1572,11 +1572,11 @@ void context_t::propagate_monomial_upward(var x, node * n) { monomial * m = get_monomial(x); unsigned sz = m->size(); interval & r = m_i_tmp1; r.set_mutable(); - interval & y = m_i_tmp2; + interval & y = m_i_tmp2; interval & yk = m_i_tmp3; yk.set_mutable(); for (unsigned i = 0; i < sz; i++) { y.set_constant(n, m->x(i)); - im().power(y, m->degree(i), yk); + im().power(y, m->degree(i), yk); if (i == 0) im().set(r, yk); else @@ -1606,37 +1606,37 @@ void context_t::propagate_monomial_downward(var x, node * n, unsigned j) { monomial * m = get_monomial(x); SASSERT(j < m->size()); unsigned sz = m->size(); - + interval & r = m_i_tmp3; if (sz > 1) { interval & d = m_i_tmp1; d.set_mutable(); - interval & y = m_i_tmp2; + interval & y = m_i_tmp2; interval & yk = m_i_tmp3; yk.set_mutable(); bool first = true; for (unsigned i = 0; i < sz; i++) { if (i == j) continue; y.set_constant(n, m->x(i)); - im().power(y, m->degree(i), yk); + im().power(y, m->degree(i), yk); if (first) im().set(d, yk); else im().mul(d, yk, r); } - interval & aux = m_i_tmp2; + interval & aux = m_i_tmp2; aux.set_constant(n, x); im().div(aux, d, r); } else { SASSERT(sz == 1); SASSERT(j == 0); - interval & aux = m_i_tmp2; + interval & aux = m_i_tmp2; aux.set_constant(n, x); im().set(r, aux); } unsigned d = m->degree(j); if (d > 1) { - if (d % 2 == 0 && im().lower_is_neg(r)) + if (d % 2 == 0 && im().lower_is_neg(r)) return; // If d is even, we can't take the nth-root when lower(r) is negative. im().xn_eq_y(r, d, m_nth_root_prec, r); } @@ -1814,7 +1814,7 @@ void context_t::operator()() { if (m_num_nodes > m_max_nodes) break; node * n = (*m_node_selector)(m_leaf_head, m_leaf_tail); - if (n == 0) + if (n == 0) break; TRACE("subpaving_main", tout << "selected node: #" << n->id() << ", depth: " << n->depth() << "\n";); remove_from_leaf_dlist(n); diff --git a/src/math/subpaving/tactic/expr2subpaving.cpp b/src/math/subpaving/tactic/expr2subpaving.cpp index 9968c2f62..267a04b9a 100644 --- a/src/math/subpaving/tactic/expr2subpaving.cpp +++ b/src/math/subpaving/tactic/expr2subpaving.cpp @@ -8,8 +8,8 @@ Module Name: Abstract: Translator from Z3 expressions into generic subpaving data-structure. - - + + Author: Leonardo (leonardo) 2012-08-08 @@ -24,6 +24,7 @@ Notes: #include"cooperate.h" #include"arith_decl_plugin.h" #include"scoped_numeral_buffer.h" +#include"common_msgs.h" struct expr2subpaving::imp { struct frame { @@ -43,9 +44,9 @@ struct expr2subpaving::imp { expr_ref_vector m_var2expr; typedef svector var_vector; - + obj_map m_cache; - var_vector m_cached_vars; + var_vector m_cached_vars; scoped_mpz_vector m_cached_numerators; scoped_mpz_vector m_cached_denominators; @@ -69,17 +70,17 @@ struct expr2subpaving::imp { m_expr2var = e2v; m_expr2var_owner = false; } - + } - + ~imp() { reset_cache(); if (m_expr2var_owner) dealloc(m_expr2var); } - + ast_manager & m() { return m_manager; } - + subpaving::context & s() { return m_subpaving; } unsynch_mpq_manager & qm() const { return m_qm; } @@ -94,7 +95,7 @@ struct expr2subpaving::imp { void checkpoint() { if (m().canceled()) - throw default_exception("canceled"); + throw default_exception(Z3_CANCELED_MSG); cooperate("expr2subpaving"); } @@ -111,7 +112,7 @@ struct expr2subpaving::imp { } return x; } - + void found_non_simplified() { throw default_exception("you must apply simplifier before internalizing expressions into the subpaving module."); } @@ -128,7 +129,7 @@ struct expr2subpaving::imp { SASSERT(!m_cache.contains(t)); SASSERT(m_cached_numerators.size() == m_cached_vars.size()); SASSERT(m_cached_denominators.size() == m_cached_vars.size()); - if (t->get_ref_count() <= 1) + if (t->get_ref_count() <= 1) return; unsigned idx = m_cached_vars.size(); m_cache.insert(t, idx); @@ -196,7 +197,7 @@ struct expr2subpaving::imp { sbuffer pws; for (unsigned i = 0; i < sz; i++) { expr * arg = margs[i]; - unsigned k; + unsigned k; as_power(arg, arg, k); subpaving::var x_arg = process(arg, depth+1, n_arg, d_arg); qm().power(n_arg, k, n_arg); @@ -216,7 +217,7 @@ struct expr2subpaving::imp { cache_result(t, x, n, d); return x; } - + typedef _scoped_numeral_buffer mpz_buffer; typedef sbuffer var_buffer; @@ -291,13 +292,13 @@ struct expr2subpaving::imp { switch (t->get_decl_kind()) { case OP_NUM: return process_num(t, depth, n, d); - case OP_ADD: + case OP_ADD: return process_add(t, depth, n, d); - case OP_MUL: + case OP_MUL: return process_mul(t, depth, n, d); case OP_POWER: return process_power(t, depth, n, d); - case OP_TO_REAL: + case OP_TO_REAL: return process(t->get_arg(0), depth+1, n, d); case OP_SUB: case OP_UMINUS: @@ -310,7 +311,7 @@ struct expr2subpaving::imp { case OP_REM: case OP_IRRATIONAL_ALGEBRAIC_NUM: throw default_exception("you must apply arithmetic purifier before internalizing expressions into the subpaving module."); - case OP_SIN: + case OP_SIN: case OP_COS: case OP_TAN: case OP_ASIN: @@ -350,12 +351,12 @@ struct expr2subpaving::imp { return process_arith_app(to_app(t), depth, n, d); } - - bool is_var(expr * t) const { - return m_expr2var->is_var(t); + + bool is_var(expr * t) const { + return m_expr2var->is_var(t); } - + subpaving::var internalize_term(expr * t, mpz & n, mpz & d) { return process(t, 0, n, d); } @@ -376,11 +377,11 @@ ast_manager & expr2subpaving::m() const { subpaving::context & expr2subpaving::s() const { return m_imp->s(); } - + bool expr2subpaving::is_var(expr * t) const { return m_imp->is_var(t); } - + subpaving::var expr2subpaving::internalize_term(expr * t, mpz & n, mpz & d) { return m_imp->internalize_term(t, n, d); diff --git a/src/muz/bmc/dl_bmc_engine.cpp b/src/muz/bmc/dl_bmc_engine.cpp index bad1f2b4f..a7df8db77 100644 --- a/src/muz/bmc/dl_bmc_engine.cpp +++ b/src/muz/bmc/dl_bmc_engine.cpp @@ -60,11 +60,11 @@ namespace datalog { expr_ref fml(m.mk_app(q, T), m); b.assert_expr(fml); res = b.m_solver.check(); - + if (res == l_true) { res = get_model(); } - b.m_solver.pop(1); + b.m_solver.pop(1); ++m_bit_width; } return res; @@ -74,11 +74,11 @@ namespace datalog { sort_ref mk_index_sort() { return sort_ref(m_bv.mk_sort(m_bit_width), m); } - + var_ref mk_index_var() { return var_ref(m.mk_var(0, mk_index_sort()), m); } - + void compile() { sort_ref index_sort = mk_index_sort(); var_ref var = mk_index_var(); @@ -92,17 +92,17 @@ namespace datalog { // Assert: forall level . p(T) => body of rule i + equalities for head of rule i func_decl_ref pr = mk_q_func_decl(p); expr_ref pred = expr_ref(m.mk_app(pr, var.get()), m); - expr_ref_vector rules(m), sub(m), conjs(m); + expr_ref_vector rules(m), sub(m), conjs(m); expr_ref trm(m), rule_body(m), rule_i(m); - for (unsigned i = 0; i < rls.size(); ++i) { - sub.reset(); + for (unsigned i = 0; i < rls.size(); ++i) { + sub.reset(); conjs.reset(); - rule& r = *rls[i]; + rule& r = *rls[i]; rule_i = m.mk_app(mk_q_rule(p, i), var.get()); rules.push_back(rule_i); - + mk_qrule_vars(r, i, sub); - + // apply substitution to body. var_subst vs(m, false); for (unsigned k = 0; k < p->get_arity(); ++k) { @@ -137,21 +137,21 @@ namespace datalog { b.assert_expr(trm); } } - + void setup() { b.m_fparams.m_relevancy_lvl = 2; b.m_fparams.m_model = true; b.m_fparams.m_model_compact = true; b.m_fparams.m_mbqi = true; } - + void mk_qrule_vars(datalog::rule const& r, unsigned rule_id, expr_ref_vector& sub) { ptr_vector sorts; r.get_vars(m, sorts); // populate substitution of bound variables. sub.reset(); sub.resize(sorts.size()); - + for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { expr* arg = r.get_head()->get_arg(k); if (is_var(arg)) { @@ -177,52 +177,52 @@ namespace datalog { if (sorts[j] && !sub[j].get()) { sub[j] = mk_q_var(r.get_decl(), sorts[j], rule_id, idx++); } - } + } } - + expr_ref mk_q_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx) { std::stringstream _name; _name << pred->get_name() << "#" << rule_id << "_" << idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); var_ref var = mk_index_var(); return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), s), var), m); - } - + } + expr_ref mk_q_arg(func_decl* pred, unsigned idx, bool is_current) { SASSERT(idx < pred->get_arity()); std::stringstream _name; _name << pred->get_name() << "#" << idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); expr_ref var(mk_index_var(), m); if (!is_current) { var = m_bv.mk_bv_sub(var, mk_q_one()); } return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), pred->get_domain(idx)), var), m); } - + expr_ref mk_q_one() { return mk_q_num(1); } - + expr_ref mk_q_num(unsigned i) { return expr_ref(m_bv.mk_numeral(i, m_bit_width), m); } - + func_decl_ref mk_q_func_decl(func_decl* f) { std::stringstream _name; _name << f->get_name() << "#"; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), f->get_range()), m); } - + func_decl_ref mk_q_rule(func_decl* f, unsigned rule_id) { std::stringstream _name; _name << f->get_name() << "#" << rule_id; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), m.mk_bool_sort()), m); } - - + + expr_ref eval_q(model_ref& model, func_decl* f, unsigned i) { func_decl_ref fn = mk_q_func_decl(f); expr_ref t(m), result(m); @@ -230,7 +230,7 @@ namespace datalog { model->eval(t, result); return result; } - + expr_ref eval_q(model_ref& model, expr* t, unsigned i) { expr_ref tmp(m), result(m), num(m); var_subst vs(m, false); @@ -239,8 +239,8 @@ namespace datalog { vs(t, 1, nums, tmp); model->eval(tmp, result); return result; - } - + } + lbool get_model() { rule_manager& rm = b.m_ctx.get_rule_manager(); func_decl_ref q = mk_q_func_decl(b.m_query_pred); @@ -250,7 +250,7 @@ namespace datalog { rule_unifier unifier(b.m_ctx); rational num; unsigned level, bv_size; - + b.m_solver.get_model(md); func_decl* pred = b.m_query_pred; dl_decl_util util(m); @@ -261,7 +261,7 @@ namespace datalog { level = num.get_unsigned(); SASSERT(m.is_true(eval_q(md, b.m_query_pred, level))); TRACE("bmc", model_smt2_pp(tout, m, *md, 0);); - + rule_ref r0(rm), r1(rm), r2(rm); while (true) { TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); @@ -269,8 +269,8 @@ namespace datalog { rule_vector const& rls = b.m_rules.get_predicate_rules(pred); rule* r = 0; unsigned i = 0; - for (; i < rls.size(); ++i) { - rule_i = m.mk_app(mk_q_rule(pred, i), mk_q_num(level).get()); + for (; i < rls.size(); ++i) { + rule_i = m.mk_app(mk_q_rule(pred, i), mk_q_num(level).get()); TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); if (m.is_true(eval_q(md, rule_i, level))) { r = rls[i]; @@ -280,13 +280,13 @@ namespace datalog { SASSERT(r); mk_qrule_vars(*r, i, sub); // we have rule, we have variable names of rule. - + // extract values for the variables in the rule. for (unsigned j = 0; j < sub.size(); ++j) { expr_ref vl = eval_q(md, sub[j].get(), i); if (vl) { // vl can be 0 if the interpretation does not assign a value to it. - sub[j] = vl; + sub[j] = vl; } else { sub[j] = m.mk_var(j, m.get_sort(sub[j].get())); @@ -295,7 +295,7 @@ namespace datalog { svector > positions; vector substs; expr_ref fml(m), concl(m); - + rm.to_formula(*r, fml); r2 = r; rm.substitute(r2, sub.size(), sub.c_ptr()); @@ -308,15 +308,15 @@ namespace datalog { unifier.apply(*r0.get(), 0, *r2.get(), r1); rm.to_formula(*r1.get(), concl); scoped_proof _sp(m); - + p = r->get_proof(); if (!p) { p = m.mk_asserted(fml); } proof* premises[2] = { pr, p }; - + positions.push_back(std::make_pair(0, 1)); - + substs.push_back(sub1); substs.push_back(sub); pr = m.mk_hyper_resolve(2, premises, concl, positions, substs); @@ -339,7 +339,7 @@ namespace datalog { } r0 = r2; } - + if (level == 0) { SASSERT(r->get_uninterpreted_tail_size() == 0); break; @@ -370,7 +370,7 @@ namespace datalog { lbool check() { setup(); for (unsigned i = 0; ; ++i) { - IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); + IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); b.checkpoint(); expr_ref_vector fmls(m); compile(b.m_rules, fmls, i); @@ -392,12 +392,12 @@ namespace datalog { for (unsigned i = 0; i < level_p->get_arity(); ++i) { std::stringstream _name; _name << query_pred->get_name() << "#" << level << "_" << i; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); vars.push_back(m.mk_const(nm, level_p->get_domain(i))); } return expr_ref(m.mk_app(level_p, vars.size(), vars.c_ptr()), m); } - + void compile(rule_set const& rules, expr_ref_vector& result, unsigned level) { bool_rewriter br(m); rule_set::decl2rules::iterator it = rules.begin_grouped_rules(); @@ -405,16 +405,16 @@ namespace datalog { for (; it != end; ++it) { func_decl* p = it->m_key; rule_vector const& rls = *it->m_value; - + // Assert: p_level(vars) => r1_level(vars) \/ r2_level(vars) \/ r3_level(vars) \/ ... - // Assert: r_i_level(vars) => exists aux_vars . body of rule i for level - + // Assert: r_i_level(vars) => exists aux_vars . body of rule i for level + func_decl_ref level_pred = mk_level_predicate(p, level); expr_ref_vector rules(m); expr_ref body(m), head(m); - for (unsigned i = 0; i < rls.size(); ++i) { - rule& r = *rls[i]; - func_decl_ref rule_i = mk_level_rule(p, i, level); + for (unsigned i = 0; i < rls.size(); ++i) { + rule& r = *rls[i]; + func_decl_ref rule_i = mk_level_rule(p, i, level); rules.push_back(apply_vars(rule_i)); ptr_vector rule_vars; @@ -440,10 +440,10 @@ namespace datalog { head = m.mk_app(rule_i, args.size(), args.c_ptr()); for (unsigned i = 0; i < r.get_tail_size(); ++i) { conjs.push_back(r.get_tail(i)); - } + } br.mk_and(conjs.size(), conjs.c_ptr(), body); - - replace_by_level_predicates(level, body); + + replace_by_level_predicates(level, body); body = skolemize_vars(r, args, rule_vars, body); body = m.mk_implies(head, body); body = bind_vars(body, head); @@ -496,7 +496,7 @@ namespace datalog { // find the rule that was triggered by evaluating the arguments to prop. rule_vector const& rls = b.m_rules.get_predicate_rules(pred); rule* r = 0; - for (unsigned i = 0; i < rls.size(); ++i) { + for (unsigned i = 0; i < rls.size(); ++i) { func_decl_ref rule_i = mk_level_rule(pred, i, level); TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); prop_r = m.mk_app(rule_i, prop->get_num_args(), prop->get_args()); @@ -537,7 +537,7 @@ namespace datalog { prs.push_back(get_proof(md, head_j, to_app(prop_body), level-1)); positions.push_back(std::make_pair(j+1,0)); substs.push_back(expr_ref_vector(m)); - } + } pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), prop, positions, substs); return pr; } @@ -557,16 +557,16 @@ namespace datalog { func_decl_ref mk_level_predicate(func_decl* p, unsigned level) { std::stringstream _name; _name << p->get_name() << "#" << level; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return func_decl_ref(m.mk_func_decl(nm, p->get_arity(), p->get_domain(), m.mk_bool_sort()), m); } func_decl_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) { std::stringstream _name; _name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return func_decl_ref(m.mk_func_decl(nm, p->get_arity(), p->get_domain(), m.mk_bool_sort()), m); - } + } expr_ref apply_vars(func_decl* p) { expr_ref_vector vars(m); @@ -617,7 +617,7 @@ namespace datalog { func_decl_ref mk_body_func(rule& r, ptr_vector const& args, unsigned index, sort* s) { std::stringstream _name; _name << r.get_decl()->get_name() << "@" << index; - symbol name(_name.str().c_str()); + symbol name(_name.str().c_str()); func_decl* f = m.mk_func_decl(name, args.size(), args.c_ptr(), s); return func_decl_ref(f, m); } @@ -689,16 +689,16 @@ namespace datalog { struct level_replacer_cfg : public default_rewriter_cfg { level_replacer m_r; - level_replacer_cfg(nonlinear& nl, unsigned level): + level_replacer_cfg(nonlinear& nl, unsigned level): m_r(nl, level) {} bool rewrite_patterns() const { return false; } br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { return m_r.mk_app_core(f, num, args, result); } - bool reduce_quantifier(quantifier * old_q, - expr * new_body, - expr * const * new_patterns, + bool reduce_quantifier(quantifier * old_q, + expr * new_body, + expr * const * new_patterns, expr * const * new_no_patterns, expr_ref & result, proof_ref & result_pr) { @@ -725,9 +725,9 @@ namespace datalog { fml = tmp; } - + }; - + // -------------------------------------------------------------------------- // Basic non-linear BMC based on compiling into data-types (it is inefficient) @@ -747,7 +747,7 @@ namespace datalog { setup(); declare_datatypes(); compile(); - return check_query(); + return check_query(); } private: @@ -765,7 +765,7 @@ namespace datalog { func_decl_ref mk_predicate(func_decl* pred) { std::stringstream _name; _name << pred->get_name() << "#"; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); sort* pred_trace_sort = m_pred2sort.find(pred); return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); } @@ -773,30 +773,30 @@ namespace datalog { func_decl_ref mk_rule(func_decl* p, unsigned rule_idx) { std::stringstream _name; _name << "rule:" << p->get_name() << "#" << rule_idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); sort* pred_trace_sort = m_pred2sort.find(p); - return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); + return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); } - + expr_ref mk_var(func_decl* pred, sort*s, unsigned idx, expr* path_arg, expr* trace_arg) { std::stringstream _name; _name << pred->get_name() << "#V_" << idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); func_decl_ref fn(m); fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, s); return expr_ref(m.mk_app(fn, trace_arg, path_arg), m); } - + expr_ref mk_arg(func_decl* pred, unsigned idx, expr* path_arg, expr* trace_arg) { SASSERT(idx < pred->get_arity()); std::stringstream _name; _name << pred->get_name() << "#X_" << idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); func_decl_ref fn(m); fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, pred->get_domain(idx)); return expr_ref(m.mk_app(fn, trace_arg, path_arg), m); } - + void mk_subst(datalog::rule& r, expr* path, app* trace, expr_ref_vector& sub) { datatype_util dtu(m); ptr_vector sorts; @@ -840,52 +840,52 @@ namespace datalog { } } } - + /** \brief compile Horn rule into co-Horn implication. forall args . R(path_var, rule_i(trace_vars)) => Body[X(path_var, rule_i(trace_vars)), Y(S_j(path_var), trace_vars_j)] - */ + */ void compile() { datatype_util dtu(m); - + rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); for (; it != end; ++it) { func_decl* p = it->m_key; rule_vector const& rls = *it->m_value; - + // Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ... // where: r_i_level = body of rule i for level + equalities for head of rule i - + expr_ref rule_body(m), tmp(m), pred(m), trace_arg(m), fml(m); var_ref path_var(m), trace_var(m); expr_ref_vector rules(m), sub(m), conjs(m), vars(m), patterns(m); sort* pred_sort = m_pred2sort.find(p); path_var = m.mk_var(0, m_path_sort); - trace_var = m.mk_var(1, pred_sort); + trace_var = m.mk_var(1, pred_sort); // sort* sorts[2] = { pred_sort, m_path_sort }; ptr_vector const& cnstrs = *dtu.get_datatype_constructors(pred_sort); ptr_vector const& succs = *dtu.get_datatype_constructors(m_path_sort); SASSERT(cnstrs.size() == rls.size()); pred = m.mk_app(mk_predicate(p), trace_var.get(), path_var.get()); - for (unsigned i = 0; i < rls.size(); ++i) { - sub.reset(); + for (unsigned i = 0; i < rls.size(); ++i) { + sub.reset(); conjs.reset(); vars.reset(); - rule& r = *rls[i]; + rule& r = *rls[i]; func_decl_ref rule_pred_i = mk_rule(p, i); - + // Create cnstr_rule_i(Vars) func_decl* cnstr = cnstrs[i]; rules.push_back(m.mk_app(rule_pred_i, trace_var.get(), path_var.get())); unsigned arity = cnstr->get_arity(); for (unsigned j = 0; j < arity; ++j) { - vars.push_back(m.mk_var(arity-j,cnstr->get_domain(j))); + vars.push_back(m.mk_var(arity-j,cnstr->get_domain(j))); } trace_arg = m.mk_app(cnstr, vars.size(), vars.c_ptr()); - + mk_subst(r, path_var, to_app(trace_arg), sub); - + // apply substitution to body. var_subst vs(m, false); for (unsigned k = 0; k < p->get_arity(); ++k) { @@ -926,28 +926,28 @@ namespace datalog { names.push_back(symbol("path")); SASSERT(names.size() == q_sorts.size()); SASSERT(vars.size() == names.size()); - symbol qid = r.name(), skid; + symbol qid = r.name(), skid; tmp = m.mk_app(mk_predicate(p), trace_arg.get(), path_var.get()); patterns.reset(); patterns.push_back(m.mk_pattern(to_app(tmp))); fml = m.mk_implies(tmp, rule_body); fml = m.mk_forall(vars.size(), q_sorts.c_ptr(), names.c_ptr(), fml, 1, qid, skid, 1, patterns.c_ptr()); - b.assert_expr(fml); + b.assert_expr(fml); } - } + } } - + void declare_datatypes() { rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); datatype_util dtu(m); ptr_vector dts; - + obj_map pred_idx; for (unsigned i = 0; it != end; ++it, ++i) { pred_idx.insert(it->m_key, i); } - + it = b.m_rules.begin_grouped_rules(); for (; it != end; ++it) { rule_vector const& rls = *it->m_value; @@ -971,27 +971,27 @@ namespace datalog { _name << "?"; symbol is_name(_name.str().c_str()); cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); - } + } dts.push_back(mk_datatype_decl(pred->get_name(), cnstrs.size(), cnstrs.c_ptr())); } - - + + sort_ref_vector new_sorts(m); family_id dfid = m.mk_family_id("datatype"); datatype_decl_plugin* dtp = static_cast(m.get_plugin(dfid)); VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); - + it = b.m_rules.begin_grouped_rules(); - for (unsigned i = 0; it != end; ++it, ++i) { + for (unsigned i = 0; it != end; ++it, ++i) { m_pred2sort.insert(it->m_key, new_sorts[i].get()); m_sort2pred.insert(new_sorts[i].get(), it->m_key); - m_pinned.push_back(new_sorts[i].get()); + m_pinned.push_back(new_sorts[i].get()); } if (new_sorts.size() > 0) { TRACE("bmc", dtu.display_datatype(new_sorts[0].get(), tout);); } del_datatype_decls(dts.size(), dts.c_ptr()); - + // declare path data-type. { new_sorts.reset(); @@ -1004,9 +1004,9 @@ namespace datalog { rule* r = *it; unsigned sz = r->get_uninterpreted_tail_size(); max_arity = std::max(sz, max_arity); - } + } cnstrs.push_back(mk_constructor_decl(symbol("Z#"), symbol("Z#?"), 0, 0)); - + for (unsigned i = 0; i + 1 < max_arity; ++i) { std::stringstream _name; _name << "succ#" << i; @@ -1019,13 +1019,13 @@ namespace datalog { type_ref tr(0); accs.push_back(mk_accessor_decl(name, tr)); cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); - } + } dts.push_back(mk_datatype_decl(symbol("Path"), cnstrs.size(), cnstrs.c_ptr())); VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); m_path_sort = new_sorts[0].get(); } } - + proof_ref get_proof(model_ref& md, app* trace, app* path) { datatype_util dtu(m); rule_manager& rm = b.m_ctx.get_rule_manager(); @@ -1044,7 +1044,7 @@ namespace datalog { proof_ref pr(m); expr_ref fml(m), head(m), tmp(m); app_ref path1(m); - + var_subst vs(m, false); mk_subst(*rules[i], path, trace, sub); rm.to_formula(*rules[i], fml); @@ -1061,30 +1061,30 @@ namespace datalog { rule_ref rl(b.m_ctx.get_rule_manager()); rl = rules[i]; b.m_ctx.get_rule_manager().substitute(rl, sub.size(), sub.c_ptr()); - + substs.push_back(sub); - + for (unsigned j = 0; j < sz; ++j) { if (j == 0) { - path1 = path; + path1 = path; } else { path1 = m.mk_app(succs[j], path); } - + prs.push_back(get_proof(md, to_app(trace->get_arg(j)), path1)); positions.push_back(std::make_pair(j+1,0)); - substs.push_back(expr_ref_vector(m)); + substs.push_back(expr_ref_vector(m)); } head = rl->get_head(); - pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), head, positions, substs); + pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), head, positions, substs); return pr; } } UNREACHABLE(); return proof_ref(0, m); } - + // instantiation of algebraic data-types takes care of the rest. lbool check_query() { sort* trace_sort = m_pred2sort.find(b.m_query_pred); @@ -1102,10 +1102,10 @@ namespace datalog { } b.m_solver.get_model(md); mk_answer(md, trace, path); - return l_true; + return l_true; } } - + bool check_model(model_ref& md, expr* trace) { expr_ref trace_val(m), eq(m); md->eval(trace, trace_val); @@ -1122,10 +1122,10 @@ namespace datalog { eq = m.mk_not(eq); b.assert_expr(eq); } - return is_sat != l_false; + return is_sat != l_false; } - - void mk_answer(model_ref& md, expr_ref& trace, expr_ref& path) { + + void mk_answer(model_ref& md, expr_ref& trace, expr_ref& path) { IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0);); md->eval(trace, trace); md->eval(path, path); @@ -1139,7 +1139,7 @@ namespace datalog { apply(m, b.m_ctx.get_proof_converter().get(), pr); b.m_answer = pr; } - + }; // -------------------------------------------------------------------------- @@ -1155,7 +1155,7 @@ namespace datalog { lbool check() { setup(); for (unsigned i = 0; ; ++i) { - IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); + IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); b.checkpoint(); compile(i); lbool res = check(i); @@ -1183,9 +1183,9 @@ namespace datalog { b.m_solver.get_model(md); func_decl* pred = b.m_query_pred; SASSERT(m.is_true(md->get_const_interp(to_app(level_query)->get_decl()))); - + TRACE("bmc", model_smt2_pp(tout, m, *md, 0);); - + rule_ref r0(rm), r1(rm), r2(rm); while (true) { TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); @@ -1193,7 +1193,7 @@ namespace datalog { rule_vector const& rls = b.m_rules.get_predicate_rules(pred); rule* r = 0; unsigned i = 0; - for (; i < rls.size(); ++i) { + for (; i < rls.size(); ++i) { expr_ref rule_i = mk_level_rule(pred, i, level); TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); if (m.is_true(md->get_const_interp(to_app(rule_i)->get_decl()))) { @@ -1204,13 +1204,13 @@ namespace datalog { SASSERT(r); mk_rule_vars(*r, level, i, sub); // we have rule, we have variable names of rule. - + // extract values for the variables in the rule. for (unsigned j = 0; j < sub.size(); ++j) { expr* vl = md->get_const_interp(to_app(sub[j].get())->get_decl()); if (vl) { // vl can be 0 if the interpretation does not assign a value to it. - sub[j] = vl; + sub[j] = vl; } else { sub[j] = m.mk_var(j, m.get_sort(sub[j].get())); @@ -1219,7 +1219,7 @@ namespace datalog { svector > positions; vector substs; expr_ref fml(m), concl(m); - + rm.to_formula(*r, fml); r2 = r; rm.substitute(r2, sub.size(), sub.c_ptr()); @@ -1239,12 +1239,12 @@ namespace datalog { apply_subst(sub, sub2); unifier.apply(*r0.get(), 0, *r2.get(), r1); rm.to_formula(*r1.get(), concl); - + scoped_proof _sp(m); proof* premises[2] = { pr, p }; - + positions.push_back(std::make_pair(0, 1)); - + substs.push_back(sub1); substs.push_back(sub); pr = m.mk_hyper_resolve(2, premises, concl, positions, substs); @@ -1263,7 +1263,7 @@ namespace datalog { } r0 = r2; } - + if (level == 0) { SASSERT(r->get_uninterpreted_tail_size() == 0); break; @@ -1276,8 +1276,8 @@ namespace datalog { apply(m, b.m_ctx.get_proof_converter().get(), pr); b.m_answer = pr; } - - + + void setup() { b.m_fparams.m_relevancy_lvl = 0; b.m_fparams.m_model = true; @@ -1285,54 +1285,54 @@ namespace datalog { b.m_fparams.m_mbqi = false; // m_fparams.m_auto_config = false; } - - + + lbool check(unsigned level) { expr_ref level_query = mk_level_predicate(b.m_query_pred, level); expr* q = level_query.get(); return b.m_solver.check(1, &q); } - + expr_ref mk_level_predicate(func_decl* p, unsigned level) { return mk_level_predicate(p->get_name(), level); } - + expr_ref mk_level_predicate(symbol const& name, unsigned level) { std::stringstream _name; _name << name << "#" << level; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m); } - + expr_ref mk_level_arg(func_decl* pred, unsigned idx, unsigned level) { SASSERT(idx < pred->get_arity()); std::stringstream _name; _name << pred->get_name() << "#" << level << "_" << idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return expr_ref(m.mk_const(nm, pred->get_domain(idx)), m); } - + expr_ref mk_level_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx, unsigned level) { std::stringstream _name; _name << pred->get_name() << "#" << level << "_" << rule_id << "_" << idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return expr_ref(m.mk_const(nm, s), m); } - + expr_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) { std::stringstream _name; _name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx; - symbol nm(_name.str().c_str()); + symbol nm(_name.str().c_str()); return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m); } - + void mk_rule_vars(rule& r, unsigned level, unsigned rule_id, expr_ref_vector& sub) { ptr_vector sorts; r.get_vars(m, sorts); // populate substitution of bound variables. sub.reset(); sub.resize(sorts.size()); - + for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { expr* arg = r.get_head()->get_arg(k); if (is_var(arg)) { @@ -1361,34 +1361,34 @@ namespace datalog { } } } - + void compile(unsigned level) { rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); for (; it != end; ++it) { func_decl* p = it->m_key; rule_vector const& rls = *it->m_value; - + // Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ... // Assert: r_i_level => body of rule i for level + equalities for head of rule i - + expr_ref level_pred = mk_level_predicate(p, level); expr_ref_vector rules(m), sub(m), conjs(m); expr_ref rule_body(m), tmp(m); - for (unsigned i = 0; i < rls.size(); ++i) { - sub.reset(); + for (unsigned i = 0; i < rls.size(); ++i) { + sub.reset(); conjs.reset(); - rule& r = *rls[i]; - expr_ref rule_i = mk_level_rule(p, i, level); + rule& r = *rls[i]; + expr_ref rule_i = mk_level_rule(p, i, level); rules.push_back(rule_i); if (level == 0 && r.get_uninterpreted_tail_size() > 0) { tmp = m.mk_not(rule_i); b.assert_expr(tmp); continue; } - + mk_rule_vars(r, level, i, sub); - + // apply substitution to body. var_subst vs(m, false); for (unsigned k = 0; k < p->get_arity(); ++k) { @@ -1418,11 +1418,11 @@ namespace datalog { } } }; - - bmc::bmc(context& ctx): + + bmc::bmc(context& ctx): engine_base(ctx.get_manager(), "bmc"), - m_ctx(ctx), - m(ctx.get_manager()), + m_ctx(ctx), + m(ctx.get_manager()), m_solver(m, m_fparams), m_rules(ctx), m_query_pred(m), @@ -1440,9 +1440,9 @@ namespace datalog { rule_set& rules0 = m_ctx.get_rules(); datalog::rule_set old_rules(rules0); rule_manager.mk_query(query, rules0); - expr_ref bg_assertion = m_ctx.get_background_assertion(); + expr_ref bg_assertion = m_ctx.get_background_assertion(); apply_default_transformation(m_ctx); - + if (m_ctx.xform_slice()) { datalog::rule_transformer transformer(m_ctx); datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx); @@ -1490,7 +1490,7 @@ namespace datalog { } } - void bmc::assert_expr(expr* e) { + void bmc::assert_expr(expr* e) { TRACE("bmc", tout << mk_pp(e, m) << "\n";); m_solver.assert_expr(e); } @@ -1510,7 +1510,7 @@ namespace datalog { void bmc::checkpoint() { if (m.canceled()) { - throw default_exception("bmc canceled"); + throw default_exception(Z3_CANCELED_MSG); } } @@ -1526,7 +1526,7 @@ namespace datalog { m_solver.reset_statistics(); } - expr_ref bmc::get_answer() { + expr_ref bmc::get_answer() { return m_answer; } diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 1f64236d9..978391ad2 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -62,7 +62,7 @@ namespace Duality { context ctx; RPFP::LogicSolver *ls; RPFP *rpfp; - + DualityStatus status; std::vector clauses; std::vector > clause_labels; @@ -104,14 +104,14 @@ namespace Duality { // - // Check if the new rules are weaker so that we can + // Check if the new rules are weaker so that we can // re-use existing context. - // + // #if 0 void dl_interface::check_reset() { // TODO datalog::rule_ref_vector const& new_rules = m_ctx.get_rules().get_rules(); - datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules(); + datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules(); bool is_subsumed = !old_rules.empty(); for (unsigned i = 0; is_subsumed && i < new_rules.size(); ++i) { is_subsumed = false; @@ -155,7 +155,7 @@ namespace Duality { expr_ref_vector rules(m_ctx.get_manager()); - svector< ::symbol> names; + svector< ::symbol> names; unsigned_vector bounds; // m_ctx.get_rules_as_formulas(rules, names); @@ -189,7 +189,7 @@ namespace Duality { rules.push_back(f); } } - else + else m_ctx.get_raw_rule_formulas(rules, names, bounds); // get all the rules as clauses @@ -199,7 +199,7 @@ namespace Duality { expr e(_d->ctx,rules[i].get()); clauses.push_back(e); } - + std::vector b_sorts; std::vector b_names; used_vars uv; @@ -216,7 +216,7 @@ namespace Duality { #if 0 // turn the query into a clause expr q(_d->ctx,m_ctx.bind_variables(query,false)); - + std::vector b_sorts; std::vector b_names; if (q.is_quantifier() && !q.is_quantifier_forall()) { @@ -235,14 +235,14 @@ namespace Duality { qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc); clauses.push_back(qc); bounds.push_back(UINT_MAX); - + // get the background axioms unsigned num_asserts = m_ctx.get_num_assertions(); for (unsigned i = 0; i < num_asserts; ++i) { expr e(_d->ctx,m_ctx.get_assertion(i)); _d->rpfp->AssertAxiom(e); } - + // make sure each predicate is the head of at least one clause func_decl_set heads; for(unsigned i = 0; i < clauses.size(); i++){ @@ -297,14 +297,14 @@ namespace Duality { // populate the edge-to-clause map for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i) _d->map[_d->rpfp->edges[i]] = i; - + // create a solver object Solver *rs = Solver::Create("duality", _d->rpfp); if(old_rs) rs->LearnFrom(old_rs); // new solver gets hints from old solver - + // set its options IF_VERBOSE(1, rs->SetOption("report","1");); rs->SetOption("full_expand",m_ctx.get_params().duality_full_expand() ? "1" : "0"); @@ -328,12 +328,12 @@ namespace Duality { ans = rs->Solve(); } catch (Duality::solver::cancel_exception &exn){ - throw default_exception("duality canceled"); + throw default_exception(Z3_CANCELED_MSG); } catch (Duality::Solver::Incompleteness &exn){ throw default_exception("incompleteness"); } - + // profile! if(m_ctx.get_params().duality_profile()) @@ -343,7 +343,7 @@ namespace Duality { _d->status = ans ? StatusModel : StatusRefutation; _d->cex.swap(rs->GetCounterexample()); // take ownership of cex _d->old_rs = rs; // save this for later hints - + if(old_data){ dealloc(old_data); // this deallocates the old solver if there is one } @@ -392,7 +392,7 @@ namespace Duality { context &ctx = d->dd()->ctx; RPFP::Node &node = *root; RPFP::Edge &edge = *node.Outgoing; - + // first, prove the children (that are actually used) for(unsigned i = 0; i < edge.Children.size(); i++){ @@ -434,19 +434,19 @@ namespace Duality { } } out << " )\n"; - + out << " (labels"; std::vector labels; tree->GetLabels(&edge,labels); for(unsigned j = 0; j < labels.size(); j++){ out << " " << labels[j]; } - + out << " )\n"; // reference the proofs of all the children, in syntactic order // "true" means the child is not needed - + out << " (ref "; for(unsigned i = 0; i < edge.Children.size(); i++){ if(!tree->Empty(edge.Children[i])) @@ -468,7 +468,7 @@ namespace Duality { ast_manager &m = m_ctx.get_manager(); model_ref md = get_model(); out << "(fixedpoint \n"; - model_smt2_pp(out, m, *md.get(), 0); + model_smt2_pp(out, m, *md.get(), 0); out << ")\n"; } else if(_d->status == StatusRefutation){ @@ -550,22 +550,22 @@ namespace Duality { } return md; } - + static proof_ref extract_proof(dl_interface *d, RPFP *tree, RPFP::Node *root) { context &ctx = d->dd()->ctx; ast_manager &mgr = ctx.m(); RPFP::Node &node = *root; RPFP::Edge &edge = *node.Outgoing; RPFP::Edge *orig_edge = edge.map; - + // first, prove the children (that are actually used) - + proof_ref_vector prems(mgr); ::vector substs; int orig_clause = d->dd()->map[orig_edge]; expr &t = d->dd()->clauses[orig_clause]; prems.push_back(mgr.mk_asserted(ctx.uncook(t))); - + substs.push_back(expr_ref_vector(mgr)); if (t.is_quantifier() && t.is_quantifier_forall()) { int bound = t.get_quantifier_num_bound(); @@ -599,12 +599,12 @@ namespace Duality { for(unsigned i = 0; i < edge.F.IndParams.size(); i++) args.push_back(tree->Eval(&edge,edge.F.IndParams[i])); expr conc = f(args); - + ::vector< ::proof *> pprems; for(unsigned i = 0; i < prems.size(); i++) pprems.push_back(prems[i].get()); - + proof_ref res(mgr.mk_hyper_resolve(pprems.size(),&pprems[0], ctx.uncook(conc), pos, substs),mgr); return res; diff --git a/src/muz/pdr/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp index 20bf183e0..0c79f0393 100644 --- a/src/muz/pdr/pdr_context.cpp +++ b/src/muz/pdr/pdr_context.cpp @@ -20,7 +20,7 @@ Revision History: Notes: - + --*/ @@ -63,7 +63,7 @@ namespace pdr { struct pp_level { unsigned m_level; - pp_level(unsigned l): m_level(l) {} + pp_level(unsigned l): m_level(l) {} }; static std::ostream& operator<<(std::ostream& out, pp_level const& p) { @@ -74,15 +74,15 @@ namespace pdr { return out << p.m_level; } } - + // ---------------- // pred_tansformer - pred_transformer::pred_transformer(context& ctx, manager& pm, func_decl* head): + pred_transformer::pred_transformer(context& ctx, manager& pm, func_decl* head): pm(pm), m(pm.get_manager()), - ctx(ctx), m_head(head, m), + ctx(ctx), m_head(head, m), m_sig(m), m_solver(pm, head->get_name()), - m_invariants(m), m_transition(m), m_initial_state(m), + m_invariants(m), m_transition(m), m_initial_state(m), m_reachable(pm, (datalog::PDR_CACHE_MODE)ctx.get_params().pdr_cache_mode()) {} pred_transformer::~pred_transformer() { @@ -101,7 +101,7 @@ namespace pdr { datalog::rule_manager& rm = ctx.get_context().get_rule_manager(); for (unsigned i = 0; i < rules().size(); ++i) { rm.display_smt2(*rules()[i], out) << "\n"; - } + } out << "transition\n" << mk_pp(transition(), m) << "\n"; return out; } @@ -113,8 +113,8 @@ namespace pdr { unsigned np = m_invariants.size(); for (unsigned i = 0; i < m_levels.size(); ++i) { np += m_levels[i].size(); - } - st.update("PDR num properties", np); + } + st.update("PDR num properties", np); } void pred_transformer::reset_statistics() { @@ -122,16 +122,16 @@ namespace pdr { m_reachable.reset_statistics(); m_stats.reset(); } - + void pred_transformer::init_sig() { - if (m_sig.empty()) { + if (m_sig.empty()) { for (unsigned i = 0; i < m_head->get_arity(); ++i) { sort * arg_sort = m_head->get_domain(i); std::stringstream name_stm; name_stm << m_head->get_name() << '_' << i; func_decl_ref stm(m); stm = m.mk_func_decl(symbol(name_stm.str().c_str()), 0, (sort*const*)0, arg_sort); - m_sig.push_back(pm.get_o_pred(stm, 0)); + m_sig.push_back(pm.get_o_pred(stm, 0)); } } } @@ -157,10 +157,10 @@ namespace pdr { for (; it != end; ++it) { expr* pred = it->m_key; tout << mk_pp(pred, m) << ":\n"; - if (it->m_value) rm.display_smt2(*it->m_value, tout) << "\n"; + if (it->m_value) rm.display_smt2(*it->m_value, tout) << "\n"; } ); - + it = m_tag2rule.begin(); if (m_tag2rule.size() == 1) { return *it->m_value; @@ -203,7 +203,7 @@ namespace pdr { void pred_transformer::simplify_formulas(tactic& tac, expr_ref_vector& v) { goal_ref g(alloc(goal, m, false, false, false)); - for (unsigned j = 0; j < v.size(); ++j) g->assert_expr(v[j].get()); + for (unsigned j = 0; j < v.size(); ++j) g->assert_expr(v[j].get()); model_converter_ref mc; proof_converter_ref pc; expr_dependency_ref core(m); @@ -212,7 +212,7 @@ namespace pdr { SASSERT(result.size() == 1); goal* r = result[0]; v.reset(); - for (unsigned j = 0; j < r->size(); ++j) v.push_back(r->form(j)); + for (unsigned j = 0; j < r->size(); ++j) v.push_back(r->form(j)); } void pred_transformer::simplify_formulas() { @@ -220,7 +220,7 @@ namespace pdr { simplify_formulas(*us, m_invariants); for (unsigned i = 0; i < m_levels.size(); ++i) { simplify_formulas(*us, m_levels[i]); - } + } } expr_ref pred_transformer::get_formulas(unsigned level, bool add_axioms) { @@ -232,7 +232,7 @@ namespace pdr { res.append(m_invariants); for (unsigned i = level; i < m_levels.size(); ++i) { res.append(m_levels[i]); - } + } return pm.mk_and(res); } @@ -245,7 +245,7 @@ namespace pdr { else { conj.push_back(transition()); } - conj.push_back(get_formulas(level, true)); + conj.push_back(get_formulas(level, true)); obj_map::iterator it = m_tag2rule.begin(), end = m_tag2rule.end(); for (; level > 0 && it != end; ++it) { expr* tag = it->m_key; @@ -260,7 +260,7 @@ namespace pdr { pm.formula_n2o(tmp1, tmp2, i, false); conj.push_back(m.mk_implies(tag, tmp2)); } - } + } return pm.mk_and(conj); } @@ -269,12 +269,12 @@ namespace pdr { ensure_level(next_level(tgt_level)); expr_ref_vector& src = m_levels[src_level]; - CTRACE("pdr", !src.empty(), + CTRACE("pdr", !src.empty(), tout << "propagating " << src_level << " to " << tgt_level; tout << " for relation " << head()->get_name() << "\n";); - + for (unsigned i = 0; i < src.size(); ) { - expr * curr = src[i].get(); + expr * curr = src[i].get(); unsigned stored_lvl; VERIFY(m_prop2level.find(curr, stored_lvl)); SASSERT(stored_lvl >= src_level); @@ -287,24 +287,24 @@ namespace pdr { else if (is_invariant(tgt_level, curr, false, assumes_level)) { add_property(curr, assumes_level?tgt_level:infty_level); - TRACE("pdr", tout << "is invariant: "<< pp_level(tgt_level) << " " << mk_pp(curr, m) << "\n";); + TRACE("pdr", tout << "is invariant: "<< pp_level(tgt_level) << " " << mk_pp(curr, m) << "\n";); src[i] = src.back(); src.pop_back(); ++m_stats.m_num_propagations; } else { - TRACE("pdr", tout << "not propagated: " << mk_pp(curr, m) << "\n";); + TRACE("pdr", tout << "not propagated: " << mk_pp(curr, m) << "\n";); ++i; } - } + } IF_VERBOSE(3, verbose_stream() << "propagate: " << pp_level(src_level) << "\n"; for (unsigned i = 0; i < src.size(); ++i) { - verbose_stream() << mk_pp(src[i].get(), m) << "\n"; + verbose_stream() << mk_pp(src[i].get(), m) << "\n"; }); return src.empty(); } - bool pred_transformer::add_property1(expr * lemma, unsigned lvl) { + bool pred_transformer::add_property1(expr * lemma, unsigned lvl) { if (is_infty_level(lvl)) { if (!m_invariants.contains(lemma)) { TRACE("pdr", tout << "property1: " << head()->get_name() << " " << mk_pp(lemma, m) << "\n";); @@ -318,7 +318,7 @@ namespace pdr { return false; } } - ensure_level(lvl); + ensure_level(lvl); unsigned old_level; if (!m_prop2level.find(lemma, old_level) || old_level < lvl) { TRACE("pdr", tout << "property1: " << pp_level(lvl) << " " << head()->get_name() << " " << mk_pp(lemma, m) << "\n";); @@ -365,13 +365,13 @@ namespace pdr { expr_ref pred_transformer::get_cover_delta(func_decl* p_orig, int level) { expr_ref result(m.mk_true(), m), v(m), c(m); if (level == -1) { - result = pm.mk_and(m_invariants); + result = pm.mk_and(m_invariants); } else if ((unsigned)level < m_levels.size()) { result = pm.mk_and(m_levels[level]); } // replace local constants by bound variables. - expr_substitution sub(m); + expr_substitution sub(m); for (unsigned i = 0; i < sig_size(); ++i) { c = m.mk_const(pm.o2n(sig(i), 0)); v = m.mk_var(i, sig(i)->get_range()); @@ -400,13 +400,13 @@ namespace pdr { else { result = md->get_func_interp(p_orig)->get_interp(); } - return result; + return result; } void pred_transformer::add_cover(unsigned level, expr* property) { // replace bound variables by local constants. expr_ref result(property, m), v(m), c(m); - expr_substitution sub(m); + expr_substitution sub(m); for (unsigned i = 0; i < sig_size(); ++i) { c = m.mk_const(pm.o2n(sig(i), 0)); v = m.mk_var(i, sig(i)->get_range()); @@ -417,7 +417,7 @@ namespace pdr { (*rep)(result); TRACE("pdr", tout << "cover:\n" << mk_pp(result, m) << "\n";); // add the property. - add_property(result, level); + add_property(result, level); } void pred_transformer::propagate_to_infinity(unsigned invariant_level) { @@ -430,18 +430,18 @@ namespace pdr { } lbool pred_transformer::is_reachable(model_node& n, expr_ref_vector* core, bool& uses_level) { - TRACE("pdr", + TRACE("pdr", tout << "is-reachable: " << head()->get_name() << " level: " << n.level() << "\n"; tout << mk_pp(n.state(), m) << "\n";); - ensure_level(n.level()); + ensure_level(n.level()); model_ref model; prop_solver::scoped_level _sl(m_solver, n.level()); m_solver.set_core(core); m_solver.set_model(&model); lbool is_sat = m_solver.check_conjunction_as_assumptions(n.state()); - if (is_sat == l_true && core) { + if (is_sat == l_true && core) { core->reset(); - TRACE("pdr", tout << "updating model\n"; + TRACE("pdr", tout << "updating model\n"; model_smt2_pp(tout, m, *model, 0); tout << mk_pp(n.state(), m) << "\n";); n.set_model(model); @@ -456,7 +456,7 @@ namespace pdr { bool pred_transformer::is_invariant(unsigned level, expr* states, bool inductive, bool& assumes_level, expr_ref_vector* core) { expr_ref_vector conj(m); expr_ref tmp(m); - + conj.push_back(m.mk_not(states)); if (inductive) { @@ -508,21 +508,21 @@ namespace pdr { pm.formula_n2o(tmp1, tmp2, i); result.push_back(tmp2); } - } + } } } void pred_transformer::initialize(decl2rel const& pts) { m_initial_state = m.mk_false(); - m_transition = m.mk_true(); + m_transition = m.mk_true(); init_rules(pts, m_initial_state, m_transition); th_rewriter rw(m); rw(m_transition); rw(m_initial_state); - + m_solver.add_formula(m_transition); m_solver.add_level_formula(m_initial_state, 0); - TRACE("pdr", + TRACE("pdr", tout << "Initial state: " << mk_pp(m_initial_state, m) << "\n"; tout << "Transition: " << mk_pp(m_transition, m) << "\n";); SASSERT(is_app(m_initial_state)); @@ -540,14 +540,14 @@ namespace pdr { } switch(transitions.size()) { case 0: - transition = m.mk_false(); + transition = m.mk_false(); break; case 1: // create a dummy tag. pred = m.mk_fresh_const(head()->get_name().str().c_str(), m.mk_bool_sort()); rule = tr_rules[0]; m_tag2rule.insert(pred, rule); - m_rule2tag.insert(rule, pred.get()); + m_rule2tag.insert(rule, pred.get()); transitions.push_back(pred); transition = pm.mk_and(transitions); break; @@ -555,32 +555,32 @@ namespace pdr { for (unsigned i = 0; i < transitions.size(); ++i) { pred = m.mk_fresh_const(head()->get_name().str().c_str(), m.mk_bool_sort()); rule = tr_rules[i]; - m_tag2rule.insert(pred, rule); - m_rule2tag.insert(rule, pred); + m_tag2rule.insert(pred, rule); + m_rule2tag.insert(rule, pred); disj.push_back(pred); transitions[i] = m.mk_implies(pred, transitions[i].get()); } transitions.push_back(m.mk_or(disj.size(), disj.c_ptr())); transition = pm.mk_and(transitions); - break; + break; } } void pred_transformer::init_rule( decl2rel const& pts, - datalog::rule const& rule, - expr_ref& init, + datalog::rule const& rule, + expr_ref& init, ptr_vector& rules, - expr_ref_vector& transitions) + expr_ref_vector& transitions) { - // Predicates that are variable representatives. Other predicates at + // Predicates that are variable representatives. Other predicates at // positions the variables occur are made equivalent with these. expr_ref_vector conj(m); app_ref_vector& var_reprs = *(alloc(app_ref_vector, m)); ptr_vector aux_vars; - + unsigned ut_size = rule.get_uninterpreted_tail_size(); - unsigned t_size = rule.get_tail_size(); + unsigned t_size = rule.get_tail_size(); SASSERT(ut_size <= t_size); init_atom(pts, rule.get_head(), var_reprs, conj, UINT_MAX); for (unsigned i = 0; i < ut_size; ++i) { @@ -588,7 +588,7 @@ namespace pdr { throw default_exception("PDR does not support negated predicates in rule tails"); } init_atom(pts, rule.get_tail(i), var_reprs, conj, i); - } + } for (unsigned i = ut_size; i < t_size; ++i) { ground_free_vars(rule.get_tail(i), var_reprs, aux_vars); } @@ -596,7 +596,7 @@ namespace pdr { expr_ref_vector tail(m); for (unsigned i = ut_size; i < t_size; ++i) { tail.push_back(rule.get_tail(i)); - } + } flatten_and(tail); for (unsigned i = 0; i < tail.size(); ++i) { expr_ref tmp(m); @@ -604,7 +604,7 @@ namespace pdr { conj.push_back(tmp); TRACE("pdr", tout << mk_pp(tail[i].get(), m) << "\n" << mk_pp(tmp, m) << "\n";); SASSERT(is_ground(tmp)); - } + } expr_ref fml = pm.mk_and(conj); th_rewriter rw(m); rw(fml); @@ -620,14 +620,14 @@ namespace pdr { if (ut_size == 0) { init = m.mk_or(init, fml); } - transitions.push_back(fml); + transitions.push_back(fml); m.inc_ref(fml); m_rule2transition.insert(&rule, fml.get()); rules.push_back(&rule); } m_rule2inst.insert(&rule, &var_reprs); m_rule2vars.insert(&rule, aux_vars); - TRACE("pdr", + TRACE("pdr", tout << rule.get_decl()->get_name() << "\n"; for (unsigned i = 0; i < var_reprs.size(); ++i) { tout << mk_pp(var_reprs[i].get(), m) << " "; @@ -659,10 +659,10 @@ namespace pdr { // create names for variables used in relations. void pred_transformer::init_atom( - decl2rel const& pts, - app * atom, - app_ref_vector& var_reprs, - expr_ref_vector& conj, + decl2rel const& pts, + app * atom, + app_ref_vector& var_reprs, + expr_ref_vector& conj, unsigned tail_idx ) { @@ -671,14 +671,14 @@ namespace pdr { pred_transformer& pt = *pts.find(head); for (unsigned i = 0; i < arity; i++) { app_ref rep(m); - + if (tail_idx == UINT_MAX) { rep = m.mk_const(pm.o2n(pt.sig(i), 0)); } else { rep = m.mk_const(pm.o2o(pt.sig(i), 0, tail_idx)); - } - + } + expr * arg = atom->get_arg(i); if (is_var(arg)) { var * v = to_var(arg); @@ -713,13 +713,13 @@ namespace pdr { m_reachable.add_reachable(e); } - void pred_transformer::add_premises(decl2rel const& pts, unsigned lvl, datalog::rule& rule, expr_ref_vector& r) { + void pred_transformer::add_premises(decl2rel const& pts, unsigned lvl, datalog::rule& rule, expr_ref_vector& r) { find_predecessors(rule, m_predicates); for (unsigned i = 0; i < m_predicates.size(); ++i) { expr_ref tmp(m); func_decl* head = m_predicates[i]; pred_transformer& pt = *pts.find(head); - expr_ref inv = pt.get_formulas(lvl, false); + expr_ref inv = pt.get_formulas(lvl, false); if (!m.is_true(inv)) { pm.formula_n2o(inv, tmp, i, true); r.push_back(tmp); @@ -730,7 +730,7 @@ namespace pdr { void pred_transformer::inherit_properties(pred_transformer& other) { SASSERT(m_head == other.m_head); obj_map::iterator it = other.m_prop2level.begin(); - obj_map::iterator end = other.m_prop2level.end(); + obj_map::iterator end = other.m_prop2level.end(); for (; it != end; ++it) { IF_VERBOSE(2, verbose_stream() << "(pdr-inherit: " << mk_pp(it->m_key, m) << ")\n";); add_property(it->m_key, it->m_value); @@ -743,7 +743,7 @@ namespace pdr { void model_node::set_closed() { TRACE("pdr", tout << state() << "\n";); pt().close(state()); - m_closed = true; + m_closed = true; } void model_node::set_open() { @@ -820,7 +820,7 @@ namespace pdr { SASSERT(is_ini(rl2)); set_rule(&rl2); pt().get_solver().set_model(0); - return const_cast(m_rule); + return const_cast(m_rule); } @@ -853,10 +853,10 @@ namespace pdr { expr* v; if (model.find(inst[i].get(), v)) { binding.push_back(v); - } + } else { binding.push_back(m.mk_var(i, m.get_sort(inst[i].get()))); - } + } } r1 = r0; if (!inst.empty()) { @@ -963,13 +963,13 @@ namespace pdr { void model_search::set_leaf(model_node& n) { erase_children(n, true); - SASSERT(n.is_open()); + SASSERT(n.is_open()); enqueue_leaf(&n); } void model_search::enqueue_leaf(model_node* n) { TRACE("pdr_verbose", tout << n << " " << n->state() << " goal: " << m_goal << "\n";); - SASSERT(n->is_open()); + SASSERT(n->is_open()); if (!m_goal) { m_goal = n; m_goal->enqueue(n); @@ -985,7 +985,7 @@ namespace pdr { void model_search::set_root(model_node* root) { reset(); m_root = root; - SASSERT(cache(*root).empty()); + SASSERT(cache(*root).empty()); cache(*root).insert(root->state(), 1); set_leaf(*root); } @@ -1022,7 +1022,7 @@ namespace pdr { if (!nodes.empty() && backtrack && nodes[0]->children().empty() && nodes[0]->is_closed()) { TRACE("pdr_verbose", for (unsigned i = 0; i < nodes.size(); ++i) n.display(tout << &n << "\n", 2);); model_node* n1 = nodes[0]; - n1->set_open(); + n1->set_open(); enqueue_leaf(n1); } @@ -1030,13 +1030,13 @@ namespace pdr { model_ref mr(n.get_model_ptr()); nodes[0]->set_model(mr); } - if (nodes.empty()) { + if (nodes.empty()) { cache(n).remove(n.state()); } } void model_search::remove_goal(model_node& n) { - n.dequeue(m_goal); + n.dequeue(m_goal); } void model_search::well_formed() { @@ -1055,24 +1055,24 @@ namespace pdr { } } if (m_goal) { - model_node* n = m_goal; + model_node* n = m_goal; do { if (!n->is_open() || !n->children().empty()) { - TRACE("pdr", n->display(tout << "invalid leaf\n", 0); + TRACE("pdr", n->display(tout << "invalid leaf\n", 0); display(tout);); UNREACHABLE(); return; - } + } n = n->next(); } while (m_goal != n); } - // each state appears in at most one goal per level. + // each state appears in at most one goal per level. bool found = true; for (unsigned l = 0; m_goal && found; ++l) { found = false; - obj_hashtable open_states; + obj_hashtable open_states; model_node* n = m_goal; do { if (n->level() == l) { @@ -1089,7 +1089,7 @@ namespace pdr { } while (m_goal != n); } - // a node is open if and only if it contains an + // a node is open if and only if it contains an // open child which is a goal. for (unsigned i = 0; i < nodes.size(); ++i) { model_node* n = nodes[i]; @@ -1177,15 +1177,15 @@ namespace pdr { } todo.pop_back(); todo.append(n->children().size(), n->children().c_ptr()); - } + } } /** - Extract trace comprising of constraints + Extract trace comprising of constraints and predicates that are satisfied from facts to the query. - The resulting trace + The resulting trace */ - expr_ref model_search::get_trace(context const& ctx) { + expr_ref model_search::get_trace(context const& ctx) { pred_transformer& pt = get_root().pt(); ast_manager& m = pt.get_manager(); manager& pm = pt.get_pdr_manager(); @@ -1213,13 +1213,13 @@ namespace pdr { children.pop_back(); TRACE("pdr", n->display(tout, 0);); n->mk_instantiate(r0, rule, binding); - + max_var = std::max(max_var, vc.get_max_rule_var(*rule)); subst.reset(); subst.reserve(2, max_var+1); deltas[0] = 0; deltas[1] = max_var+1; - + VERIFY(unif(predicates.back(), rule->get_head(), subst)); for (unsigned i = 0; i < constraints.size(); ++i) { subst.apply(2, deltas, expr_offset(constraints[i].get(), 0), tmp); @@ -1237,17 +1237,17 @@ namespace pdr { predicates.pop_back(); for (unsigned i = rule->get_uninterpreted_tail_size(); i < rule->get_tail_size(); ++i) { subst.apply(2, deltas, expr_offset(rule->get_tail(i), 1), tmp); - constraints.push_back(tmp); + constraints.push_back(tmp); } for (unsigned i = 0; i < constraints.size(); ++i) { max_var = std::max(vc.get_max_var(constraints[i].get()), max_var); } if (n->children().empty()) { - // nodes whose states are repeated + // nodes whose states are repeated // in the search tree do not have children. continue; } - + SASSERT(n->children().size() == rule->get_uninterpreted_tail_size()); for (unsigned i = 0; i < rule->get_uninterpreted_tail_size(); ++i) { @@ -1259,7 +1259,7 @@ namespace pdr { } children.append(n->children()); - } + } expr_safe_replace repl(m); for (unsigned i = 0; i < constraints.size(); ++i) { expr* e = constraints[i].get(), *e1, *e2; @@ -1279,7 +1279,7 @@ namespace pdr { if (!m.is_true(tmp)) { result.push_back(tmp); } - } + } return pm.mk_and(result); } @@ -1320,7 +1320,7 @@ namespace pdr { else { todo.push_back(chs[i]); } - } + } if (pfs.size() != 1 + chs.size()) { continue; } @@ -1342,7 +1342,7 @@ namespace pdr { tout << mk_pp(pfs[i], m) << "\n"; } ); - datalog::rule_ref reduced_rule(rm), r3(rm); + datalog::rule_ref reduced_rule(rm), r3(rm); reduced_rule = rls[0]; // check if binding is identity. bool binding_is_id = true; @@ -1389,7 +1389,7 @@ namespace pdr { } expr_ref fml_concl(m); - rm.to_formula(*reduced_rule.get(), fml_concl); + rm.to_formula(*reduced_rule.get(), fml_concl); p1 = m.mk_hyper_resolve(pfs.size(), pfs.c_ptr(), fml_concl, positions, substs); } @@ -1428,8 +1428,8 @@ namespace pdr { model_node* p = n.parent(); if (p) { set_leaf(*p); - } - } + } + } DEBUG_CODE(well_formed();); } @@ -1468,9 +1468,9 @@ namespace pdr { } m_rels.reset(); m_search.reset(); - m_query = 0; + m_query = 0; m_last_result = l_undef; - m_inductive_lvl = 0; + m_inductive_lvl = 0; } void context::init_rules(datalog::rule_set& rules, decl2rel& rels) { @@ -1478,12 +1478,12 @@ namespace pdr { // Allocate collection of predicate transformers datalog::rule_set::decl2rules::iterator dit = rules.begin_grouped_rules(), dend = rules.end_grouped_rules(); decl2rel::obj_map_entry* e; - for (; dit != dend; ++dit) { + for (; dit != dend; ++dit) { func_decl* pred = dit->m_key; TRACE("pdr", tout << mk_pp(pred, m) << "\n";); SASSERT(!rels.contains(pred)); - e = rels.insert_if_not_there2(pred, alloc(pred_transformer, *this, get_pdr_manager(), pred)); - datalog::rule_vector const& pred_rules = *dit->m_value; + e = rels.insert_if_not_there2(pred, alloc(pred_transformer, *this, get_pdr_manager(), pred)); + datalog::rule_vector const& pred_rules = *dit->m_value; for (unsigned i = 0; i < pred_rules.size(); ++i) { e->get_data().m_value->add_rule(pred_rules[i]); } @@ -1497,27 +1497,27 @@ namespace pdr { func_decl* pred = r->get_decl(i); if (!rels.find(pred, pt)) { pt = alloc(pred_transformer, *this, get_pdr_manager(), pred); - rels.insert(pred, pt); + rels.insert(pred, pt); } } } // Initialize use list dependencies - decl2rel::iterator it = rels.begin(), end = rels.end(); + decl2rel::iterator it = rels.begin(), end = rels.end(); for (; it != end; ++it) { - func_decl* pred = it->m_key; + func_decl* pred = it->m_key; pred_transformer* pt = it->m_value, *pt_user; obj_hashtable const& deps = rules.get_dependencies().get_deps(pred); obj_hashtable::iterator itf = deps.begin(), endf = deps.end(); for (; itf != endf; ++itf) { TRACE("pdr", tout << mk_pp(pred, m) << " " << mk_pp(*itf, m) << "\n";); pt_user = rels.find(*itf); - pt_user->add_use(pt); + pt_user->add_use(pt); } - } + } // Initialize the predicate transformers. - it = rels.begin(), end = rels.end(); - for (; it != end; ++it) { + it = rels.begin(), end = rels.end(); + for (; it != end; ++it) { pred_transformer& rel = *it->m_value; rel.initialize(rels); TRACE("pdr", rel.display(tout); ); @@ -1527,7 +1527,7 @@ namespace pdr { void context::update_rules(datalog::rule_set& rules) { decl2rel rels; init_core_generalizers(rules); - init_rules(rules, rels); + init_rules(rules, rels); decl2rel::iterator it = rels.begin(), end = rels.end(); for (; it != end; ++it) { pred_transformer* pt = 0; @@ -1589,7 +1589,7 @@ namespace pdr { classify(rules); } void operator()(expr* e) { - if (m_is_bool) { + if (m_is_bool) { if (!m.is_bool(e)) { m_is_bool = false; } @@ -1607,7 +1607,7 @@ namespace pdr { m_has_arith = m_has_arith || a.is_int_real(e); - if (m_is_bool_arith) { + if (m_is_bool_arith) { if (!m.is_bool(e) && !a.is_int_real(e)) { m_is_bool_arith = false; } @@ -1637,31 +1637,31 @@ namespace pdr { void classify(datalog::rule_set& rules) { expr_fast_mark1 mark; - datalog::rule_set::iterator it = rules.begin(), end = rules.end(); - for (; it != end; ++it) { + datalog::rule_set::iterator it = rules.begin(), end = rules.end(); + for (; it != end; ++it) { datalog::rule& r = *(*it); classify_pred(mark, r.get_head()); unsigned utsz = r.get_uninterpreted_tail_size(); for (unsigned i = 0; i < utsz; ++i) { - classify_pred(mark, r.get_tail(i)); + classify_pred(mark, r.get_tail(i)); } for (unsigned i = utsz; i < r.get_tail_size(); ++i) { - quick_for_each_expr(*this, mark, r.get_tail(i)); + quick_for_each_expr(*this, mark, r.get_tail(i)); } } mark.reset(); - + m_is_dl = false; m_is_utvpi = false; if (m_has_arith) { ptr_vector forms; - for (it = rules.begin(); it != end; ++it) { + for (it = rules.begin(); it != end; ++it) { datalog::rule& r = *(*it); unsigned utsz = r.get_uninterpreted_tail_size(); forms.push_back(r.get_head()); for (unsigned i = utsz; i < r.get_tail_size(); ++i) { forms.push_back(r.get_tail(i)); - } + } } m_is_dl = is_difference_logic(m, forms.size(), forms.c_ptr()); m_is_utvpi = m_is_dl || is_utvpi_logic(m, forms.size(), forms.c_ptr()); @@ -1674,7 +1674,7 @@ namespace pdr { } } }; - + void context::validate_proof() { std::stringstream msg; proof_ref pr = get_proof(); @@ -1689,7 +1689,7 @@ namespace pdr { for (unsigned i = 0; i < side_conditions.size(); ++i) { expr* cond = side_conditions[i].get(); expr_ref tmp(m); - + tmp = m.mk_not(cond); IF_VERBOSE(2, verbose_stream() << "checking side-condition:\n" << mk_pp(cond, m) << "\n";); smt::kernel solver(m, get_fparams()); @@ -1699,7 +1699,7 @@ namespace pdr { msg << "rule validation failed when checking: " << mk_pp(cond, m); IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); throw default_exception(msg.str()); - } + } } } @@ -1714,7 +1714,7 @@ namespace pdr { msg << "rule validation failed when checking: " << tr; IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); throw default_exception(msg.str()); - } + } } void context::validate_model() { @@ -1724,11 +1724,11 @@ namespace pdr { model_ref model; vector rs; model_converter_ref mc; - get_level_property(m_inductive_lvl, refs, rs); + get_level_property(m_inductive_lvl, refs, rs); inductive_property ex(m, mc, rs); ex.to_model(model); decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); - var_subst vs(m, false); + var_subst vs(m, false); expr_free_vars fv; for (; it != end; ++it) { ptr_vector const& rules = it->m_value->rules(); @@ -1746,7 +1746,7 @@ namespace pdr { for (unsigned j = utsz; j < tsz; ++j) { fmls.push_back(r.get_tail(j)); } - tmp = m.mk_and(fmls.size(), fmls.c_ptr()); + tmp = m.mk_and(fmls.size(), fmls.c_ptr()); svector names; fv(tmp); fv.set_default_sort(m.mk_bool_sort()); @@ -1774,14 +1774,14 @@ namespace pdr { return; } switch(m_last_result) { - case l_true: + case l_true: if (m_params.generate_proof_trace()) { validate_proof(); } validate_search(); - break; - case l_false: - validate_model(); + break; + case l_false: + validate_model(); break; default: break; @@ -1806,7 +1806,7 @@ namespace pdr { m_fparams.m_arith_auto_config_simplex = true; m_fparams.m_arith_propagate_eqs = false; m_fparams.m_arith_eager_eq_axioms = false; - if (m_params.pdr_utvpi() && + if (m_params.pdr_utvpi() && !m_params.pdr_use_convex_closure_generalizer() && !m_params.pdr_use_convex_interior_generalizer()) { if (classify.is_dl()) { @@ -1816,7 +1816,7 @@ namespace pdr { else if (classify.is_utvpi()) { IF_VERBOSE(1, verbose_stream() << "UTVPI\n";); m_fparams.m_arith_mode = AS_UTVPI; - m_fparams.m_arith_expand_eqs = true; + m_fparams.m_arith_expand_eqs = true; } } } @@ -1835,7 +1835,7 @@ namespace pdr { if (m_params.pdr_use_arith_inductive_generalizer()) { m_core_generalizers.push_back(alloc(core_arith_inductive_generalizer, *this)); } - + } void context::get_level_property(unsigned lvl, expr_ref_vector& res, vector& rs) const { @@ -1845,8 +1845,8 @@ namespace pdr { if (r->head() == m_query_pred) { continue; } - expr_ref conj = r->get_formulas(lvl, false); - m_pm.formula_n2o(0, false, conj); + expr_ref conj = r->get_formulas(lvl, false); + m_pm.formula_n2o(0, false, conj); res.push_back(conj); ptr_vector sig(r->head()->get_arity(), r->sig()); rs.push_back(relation_info(m, r->head(), sig, conj)); @@ -1858,7 +1858,7 @@ namespace pdr { for (; it != end; ++it) { pred_transformer* r = it->m_value; r->simplify_formulas(); - } + } } lbool context::solve() { @@ -1867,12 +1867,12 @@ namespace pdr { solve_impl(); UNREACHABLE(); } - catch (model_exception) { - IF_VERBOSE(1, verbose_stream() << "\n"; m_search.display(verbose_stream());); + catch (model_exception) { + IF_VERBOSE(1, verbose_stream() << "\n"; m_search.display(verbose_stream());); m_last_result = l_true; validate(); - IF_VERBOSE(1, + IF_VERBOSE(1, if (m_params.print_boogie_certificate()) { display_certificate(verbose_stream()); }); @@ -1882,21 +1882,21 @@ namespace pdr { catch (inductive_exception) { simplify_formulas(); m_last_result = l_false; - TRACE("pdr", display_certificate(tout);); + TRACE("pdr", display_certificate(tout);); IF_VERBOSE(1, { expr_ref_vector refs(m); vector rs; - get_level_property(m_inductive_lvl, refs, rs); + get_level_property(m_inductive_lvl, refs, rs); model_converter_ref mc; inductive_property ex(m, mc, rs); verbose_stream() << ex.to_string(); }); - + // upgrade invariants that are known to be inductive. decl2rel::iterator it = m_rels.begin (), end = m_rels.end (); for (; m_inductive_lvl > 0 && it != end; ++it) { if (it->m_value->head() != m_query_pred) { - it->m_value->propagate_to_infinity (m_inductive_lvl); + it->m_value->propagate_to_infinity (m_inductive_lvl); } } validate(); @@ -1911,7 +1911,7 @@ namespace pdr { void context::checkpoint() { if (m.canceled()) { - throw default_exception("pdr canceled"); + throw default_exception(Z3_CANCELED_MSG); } } @@ -1927,16 +1927,16 @@ namespace pdr { } model_ref context::get_model() { - SASSERT(m_last_result == l_false); + SASSERT(m_last_result == l_false); expr_ref_vector refs(m); vector rs; model_ref md; - get_level_property(m_inductive_lvl, refs, rs); + get_level_property(m_inductive_lvl, refs, rs); inductive_property ex(m, m_mc, rs); ex.to_model(md); return md; } - + proof_ref context::get_proof() const { scoped_proof _sc(m); proof_ref proof(m); @@ -1965,14 +1965,14 @@ namespace pdr { expr_ref context::mk_unsat_answer() const { expr_ref_vector refs(m); vector rs; - get_level_property(m_inductive_lvl, refs, rs); + get_level_property(m_inductive_lvl, refs, rs); inductive_property ex(m, const_cast(m_mc), rs); return ex.to_expr(); } void context::solve_impl() { if (!m_rels.find(m_query_pred, m_query)) { - throw inductive_exception(); + throw inductive_exception(); } unsigned lvl = 0; bool reachable; @@ -2003,12 +2003,12 @@ namespace pdr { bool context::check_reachability(unsigned level) { expr_ref state(m.mk_true(), m); model_node* root = alloc(model_node, 0, state, *m_query, level); - m_search.set_root(root); - + m_search.set_root(root); + while (model_node* node = m_search.next()) { IF_VERBOSE(2, verbose_stream() << "Expand node: " << node->level() << "\n";); checkpoint(); - expand_node(*node); + expand_node(*node); } return root->is_closed(); } @@ -2026,7 +2026,7 @@ namespace pdr { void context::expand_node(model_node& n) { SASSERT(n.is_open()); expr_ref_vector cube(m); - + if (n.level() < m_expanded_lvl) { m_expanded_lvl = n.level(); } @@ -2045,17 +2045,17 @@ namespace pdr { close_node(n); } else { - TRACE("pdr", n.display(tout, 0);); + TRACE("pdr", n.display(tout, 0);); create_children(n); } break; case l_false: { core_generalizer::cores cores; cores.push_back(std::make_pair(cube, uses_level)); - TRACE("pdr", tout << "cube:\n"; + TRACE("pdr", tout << "cube:\n"; for (unsigned j = 0; j < cube.size(); ++j) tout << mk_pp(cube[j].get(), m) << "\n";); for (unsigned i = 0; !cores.empty() && i < m_core_generalizers.size(); ++i) { - core_generalizer::cores new_cores; + core_generalizer::cores new_cores; for (unsigned j = 0; j < cores.size(); ++j) { (*m_core_generalizers[i])(n, cores[j].first, cores[j].second, new_cores); } @@ -2085,20 +2085,20 @@ namespace pdr { // // check if predicate transformer has a satisfiable predecessor state. - // returns either a satisfiable predecessor state or - // return a property that blocks state and is implied by the + // returns either a satisfiable predecessor state or + // return a property that blocks state and is implied by the // predicate transformer (or some unfolding of it). - // + // lbool context::expand_state(model_node& n, expr_ref_vector& result, bool& uses_level) { - TRACE("pdr", + TRACE("pdr", tout << "expand_state: " << n.pt().head()->get_name(); tout << " level: " << n.level() << "\n"; tout << mk_pp(n.state(), m) << "\n";); - + return n.pt().is_reachable(n, &result, uses_level); } - void context::propagate(unsigned max_prop_lvl) { + void context::propagate(unsigned max_prop_lvl) { if (m_params.pdr_simplify_formulas_pre()) { simplify_formulas(); } @@ -2107,7 +2107,7 @@ namespace pdr { bool all_propagated = true; decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); for (; it != end; ++it) { - checkpoint(); + checkpoint(); pred_transformer& r = *it->m_value; all_propagated = r.propagate_to_next_level(lvl) && all_propagated; } @@ -2118,7 +2118,7 @@ namespace pdr { throw inductive_exception(); } } - if (m_params.pdr_simplify_formulas_post()) { + if (m_params.pdr_simplify_formulas_post()) { simplify_formulas(); } } @@ -2136,22 +2136,22 @@ namespace pdr { Assumptions: M => phi & T - In other words, + In other words, 1. phi & T is implied by M - + Goal is to find phi0(x0), phi1(x1) such that: - phi(x) & phi0(x0) & phi1(x1) => T(x0, x1, x) + phi(x) & phi0(x0) & phi1(x1) => T(x0, x1, x) - Strategy: + Strategy: - Extract literals from T & phi using ternary simulation with M. - resulting formula is Phi. - - perform cheap existential quantifier elimination on + - perform cheap existential quantifier elimination on Phi <- exists x . Phi(x0,x1,x) - (e.g., destructive equality resolution) - + (e.g., destructive equality resolution) + - Sub-strategy 1: rename remaining x to fresh variables. - Sub-strategy 2: replace remaining x to M(x). @@ -2160,15 +2160,15 @@ namespace pdr { - if L is x0 pure, add L to L0 - if L is x1 pure, add L to L1 - if L mixes x0, x1, add x1 = M(x1) to L1, add L(x1 |-> M(x1)) to L0 - + - Create sub-goals for L0 and L1. */ - void context::create_children(model_node& n) { + void context::create_children(model_node& n) { SASSERT(n.level() > 0); bool use_model_generalizer = m_params.pdr_use_model_generalizer(); scoped_no_proof _sc(m); - + pred_transformer& pt = n.pt(); model_ref M = n.get_model_ptr(); SASSERT(M.get()); @@ -2177,20 +2177,20 @@ namespace pdr { expr* phi = n.state(); n.set_rule(&r); - - TRACE("pdr", + + TRACE("pdr", tout << "Model:\n"; model_smt2_pp(tout, m, *M, 0); tout << "\n"; tout << "Transition:\n" << mk_pp(T, m) << "\n"; tout << "Phi:\n" << mk_pp(phi, m) << "\n";); - + model_implicant mev(m); expr_ref_vector mdl(m), forms(m), Phi(m); forms.push_back(T); forms.push_back(phi); - flatten_and(forms); + flatten_and(forms); ptr_vector forms1(forms.size(), forms.c_ptr()); if (use_model_generalizer) { Phi.append(mev.minimize_model(forms1, M)); @@ -2221,7 +2221,7 @@ namespace pdr { } get_context().get_rewriter()(phi1); - TRACE("pdr", + TRACE("pdr", tout << "Vars:\n"; for (unsigned i = 0; i < vars.size(); ++i) { tout << mk_pp(vars[i].get(), m) << "\n"; @@ -2229,14 +2229,14 @@ namespace pdr { tout << "Literals\n"; tout << mk_pp(m_pm.mk_and(Phi), m) << "\n"; tout << "Reduced\n" << mk_pp(phi1, m) << "\n";); - + if (!vars.empty()) { // also fresh names for auxiliary variables in body? expr_substitution sub(m); expr_ref tmp(m); proof_ref pr(m); pr = m.mk_asserted(m.mk_true()); - for (unsigned i = 0; i < vars.size(); ++i) { + for (unsigned i = 0; i < vars.size(); ++i) { tmp = mev.eval(M, vars[i].get()); sub.insert(vars[i].get(), tmp, pr); } @@ -2250,8 +2250,8 @@ namespace pdr { unsigned_vector indices; vector child_states; child_states.resize(preds.size(), expr_ref_vector(m)); - for (unsigned i = 0; i < Phi.size(); ++i) { - m_pm.collect_indices(Phi[i].get(), indices); + for (unsigned i = 0; i < Phi.size(); ++i) { + m_pm.collect_indices(Phi[i].get(), indices); if (indices.size() == 0) { IF_VERBOSE(3, verbose_stream() << "Skipping " << mk_pp(Phi[i].get(), m) << "\n";); } @@ -2282,16 +2282,16 @@ namespace pdr { } } - + expr_ref n_cube(m); - for (unsigned i = 0; i < preds.size(); ++i) { + for (unsigned i = 0; i < preds.size(); ++i) { pred_transformer& pt = *m_rels.find(preds[i]); - SASSERT(pt.head() == preds[i]); - expr_ref o_cube = m_pm.mk_and(child_states[i]); + SASSERT(pt.head() == preds[i]); + expr_ref o_cube = m_pm.mk_and(child_states[i]); m_pm.formula_o2n(o_cube, n_cube, i); model_node* child = alloc(model_node, &n, n_cube, pt, n.level()-1); ++m_stats.m_num_nodes; - m_search.add_leaf(*child); + m_search.add_leaf(*child); IF_VERBOSE(2, verbose_stream() << "Predecessor: " << mk_pp(n_cube, m) << " " << (child->is_closed()?"closed":"open") << "\n";); m_stats.m_max_depth = std::max(m_stats.m_max_depth, child->depth()); } @@ -2333,13 +2333,13 @@ namespace pdr { decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); for (; it != end; ++it) { it->m_value->display(out); - } + } m_search.display(out); return out; } bool context::check_invariant(unsigned lvl) { - decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); + decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); for (; it != end; ++it) { checkpoint(); if (!check_invariant(lvl, it->m_key)) { @@ -2369,7 +2369,7 @@ namespace pdr { case l_false: { expr_ref_vector refs(m); vector rs; - get_level_property(m_inductive_lvl, refs, rs); + get_level_property(m_inductive_lvl, refs, rs); inductive_property ex(m, const_cast(m_mc), rs); strm << ex.to_string(); break; diff --git a/src/smt/tactic/smt_tactic.cpp b/src/smt/tactic/smt_tactic.cpp index 63ca3e4e3..f50f0afa5 100644 --- a/src/smt/tactic/smt_tactic.cpp +++ b/src/smt/tactic/smt_tactic.cpp @@ -59,7 +59,7 @@ void extract_clauses_and_dependencies(goal_ref const& g, expr_ref_vector& clause clause.push_back(m.mk_not(d)); } else { - // must normalize assumption + // must normalize assumption expr * b = 0; if (!dep2bool.find(d, b)) { b = m.mk_fresh_const(0, m.mk_bool_sort()); @@ -79,7 +79,7 @@ void extract_clauses_and_dependencies(goal_ref const& g, expr_ref_vector& clause cls = mk_or(m, clause.size(), clause.c_ptr()); clauses.push_back(cls); } - } + } } class smt_tactic : public tactic { @@ -96,7 +96,7 @@ class smt_tactic : public tactic { public: smt_tactic(params_ref const & p): m_params_ref(p), - m_ctx(0), + m_ctx(0), m_callback(0) { updt_params_core(p); TRACE("smt_tactic", tout << this << "\np: " << p << "\n";); @@ -118,20 +118,20 @@ public: m_candidate_models = p.get_bool("candidate_models", false); m_fail_if_inconclusive = p.get_bool("fail_if_inconclusive", true); } - + virtual void updt_params(params_ref const & p) { TRACE("smt_tactic", tout << this << "\nupdt_params: " << p << "\n";); updt_params_core(p); fparams().updt_params(p); SASSERT(p.get_bool("auto_config", fparams().m_auto_config) == fparams().m_auto_config); } - + virtual void collect_param_descrs(param_descrs & r) { r.insert("candidate_models", CPK_BOOL, "(default: false) create candidate models even when quantifier or theory reasoning is incomplete."); r.insert("fail_if_inconclusive", CPK_BOOL, "(default: true) fail if found unsat (sat) for under (over) approximated goal."); smt_params_helper::collect_param_descrs(r); } - + virtual void collect_statistics(statistics & st) const { if (m_ctx) @@ -146,7 +146,7 @@ public: virtual void reset_statistics() { m_stats.reset(); } - + virtual void set_logic(symbol const & l) { m_logic = l; } @@ -154,7 +154,7 @@ public: virtual void set_progress_callback(progress_callback * callback) { m_callback = callback; } - + struct scoped_init_ctx { smt_tactic & m_owner; smt_params m_params; // smt-setup overwrites parameters depending on the current assertions. @@ -168,41 +168,41 @@ public: new_ctx->set_progress_callback(o.m_callback); } o.m_ctx = new_ctx; - + } ~scoped_init_ctx() { smt::kernel * d = m_owner.m_ctx; m_owner.m_ctx = 0; - + if (d) dealloc(d); } }; - virtual void operator()(goal_ref const & in, - goal_ref_buffer & result, - model_converter_ref & mc, + virtual void operator()(goal_ref const & in, + goal_ref_buffer & result, + model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { try { SASSERT(in->is_well_sorted()); ast_manager & m = in->m(); - TRACE("smt_tactic", tout << this << "\nAUTO_CONFIG: " << fparams().m_auto_config << " HIDIV0: " << fparams().m_hi_div0 << " " + TRACE("smt_tactic", tout << this << "\nAUTO_CONFIG: " << fparams().m_auto_config << " HIDIV0: " << fparams().m_hi_div0 << " " << " PREPROCESS: " << fparams().m_preprocess << "\n"; tout << "RELEVANCY: " << fparams().m_relevancy_lvl << "\n"; tout << "fail-if-inconclusive: " << m_fail_if_inconclusive << "\n"; tout << "params_ref: " << m_params_ref << "\n"; tout << "nnf: " << fparams().m_nnf_cnf << "\n";); TRACE("smt_tactic_detail", in->display(tout);); - TRACE("smt_tactic_memory", tout << "wasted_size: " << m.get_allocator().get_wasted_size() << "\n";); + TRACE("smt_tactic_memory", tout << "wasted_size: " << m.get_allocator().get_wasted_size() << "\n";); scoped_init_ctx init(*this, m); SASSERT(m_ctx != 0); expr_ref_vector clauses(m); - expr2expr_map bool2dep; - ptr_vector assumptions; + expr2expr_map bool2dep; + ptr_vector assumptions; ref fmc; if (in->unsat_core_enabled()) { extract_clauses_and_dependencies(in, clauses, assumptions, bool2dep, fmc); @@ -225,9 +225,9 @@ public: } } if (m_ctx->canceled()) { - throw tactic_exception("smt_tactic canceled"); + throw tactic_exception(Z3_CANCELED_MSG); } - + lbool r; if (assumptions.empty()) r = m_ctx->setup_and_check(); @@ -315,7 +315,7 @@ tactic * mk_smt_tactic(params_ref const & p) { } tactic * mk_smt_tactic_using(bool auto_config, params_ref const & _p) { - params_ref p = _p; + params_ref p = _p; p.set_bool("auto_config", auto_config); tactic * r = mk_smt_tactic(p); TRACE("smt_tactic", tout << "auto_config: " << auto_config << "\nr: " << r << "\np: " << p << "\n";); diff --git a/src/tactic/nlsat_smt/nl_purify_tactic.cpp b/src/tactic/nlsat_smt/nl_purify_tactic.cpp index 575aa4422..030d0bd8c 100644 --- a/src/tactic/nlsat_smt/nl_purify_tactic.cpp +++ b/src/tactic/nlsat_smt/nl_purify_tactic.cpp @@ -289,7 +289,7 @@ private: void check_point() { if (m.canceled()) { - throw tactic_exception("canceled"); + throw tactic_exception(Z3_CANCELED_MSG); } }