3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-23 06:13:40 +00:00
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-12-10 14:07:59 -08:00
commit 265bdbe757
76 changed files with 3991 additions and 1422 deletions

422
src/api/api_algebraic.cpp Normal file
View file

@ -0,0 +1,422 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_algebraic.cpp
Abstract:
Additional APIs for handling Z3 algebraic numbers encoded as
Z3_ASTs
Author:
Leonardo de Moura (leonardo) 2012-12-07
Notes:
--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
#include"api_ast_vector.h"
#include"algebraic_numbers.h"
#include"expr2polynomial.h"
#include"cancel_eh.h"
#include"scoped_timer.h"
#define CHECK_IS_ALGEBRAIC(ARG, RET) { \
if (!Z3_algebraic_is_value_core(c, ARG)) { \
SET_ERROR_CODE(Z3_INVALID_ARG); \
return RET; \
} \
}
#define CHECK_IS_ALGEBRAIC_X(ARG, RET) { \
if (!Z3_algebraic_is_value_core(c, ARG)) { \
SET_ERROR_CODE(Z3_INVALID_ARG); \
RETURN_Z3(RET); \
} \
}
static arith_util & au(Z3_context c) {
return mk_c(c)->autil();
}
static algebraic_numbers::manager & am(Z3_context c) {
return au(c).am();
}
static bool is_rational(Z3_context c, Z3_ast a) {
return au(c).is_numeral(to_expr(a));
}
static bool is_irrational(Z3_context c, Z3_ast a) {
return au(c).is_irrational_algebraic_numeral(to_expr(a));
}
static rational get_rational(Z3_context c, Z3_ast a) {
SASSERT(is_rational(c, a));
rational r;
VERIFY(au(c).is_numeral(to_expr(a), r));
return r;
}
static algebraic_numbers::anum const & get_irrational(Z3_context c, Z3_ast a) {
SASSERT(is_irrational(c, a));
return au(c).to_irrational_algebraic_numeral(to_expr(a));
}
extern "C" {
bool Z3_algebraic_is_value_core(Z3_context c, Z3_ast a) {
api::context * _c = mk_c(c);
return
is_expr(a) &&
(_c->autil().is_numeral(to_expr(a)) ||
_c->autil().is_irrational_algebraic_numeral(to_expr(a)));
}
Z3_bool Z3_API Z3_algebraic_is_value(Z3_context c, Z3_ast a) {
Z3_TRY;
LOG_Z3_algebraic_is_value(c, a);
RESET_ERROR_CODE();
return Z3_algebraic_is_value_core(c, a) ? Z3_TRUE : Z3_FALSE;
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_algebraic_is_pos(Z3_context c, Z3_ast a) {
return Z3_algebraic_sign(c, a) > 0;
}
Z3_bool Z3_API Z3_algebraic_is_neg(Z3_context c, Z3_ast a) {
return Z3_algebraic_sign(c, a) < 0;
}
Z3_bool Z3_API Z3_algebraic_is_zero(Z3_context c, Z3_ast a) {
return Z3_algebraic_sign(c, a) == 0;
}
int Z3_API Z3_algebraic_sign(Z3_context c, Z3_ast a) {
Z3_TRY;
LOG_Z3_algebraic_sign(c, a);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC(a, 0);
if (is_rational(c, a)) {
rational v = get_rational(c, a);
if (v.is_pos()) return 1;
else if (v.is_neg()) return -1;
else return 0;
}
else {
algebraic_numbers::anum const & v = get_irrational(c, a);
if (am(c).is_pos(v)) return 1;
else if (am(c).is_neg(v)) return -1;
else return 0;
}
Z3_CATCH_RETURN(0);
}
#define BIN_OP(RAT_OP, IRAT_OP) \
algebraic_numbers::manager & _am = am(c); \
ast * r = 0; \
if (is_rational(c, a)) { \
rational av = get_rational(c, a); \
if (is_rational(c, b)) { \
rational bv = get_rational(c, b); \
r = au(c).mk_numeral(av RAT_OP bv, false); \
} \
else { \
algebraic_numbers::anum const & bv = get_irrational(c, b); \
scoped_anum _av(_am); \
_am.set(_av, av.to_mpq()); \
scoped_anum _r(_am); \
_am.IRAT_OP(_av, bv, _r); \
r = au(c).mk_numeral(_r, false); \
} \
} \
else { \
algebraic_numbers::anum const & av = get_irrational(c, a); \
if (is_rational(c, b)) { \
rational bv = get_rational(c, b); \
scoped_anum _bv(_am); \
_am.set(_bv, bv.to_mpq()); \
scoped_anum _r(_am); \
_am.IRAT_OP(av, _bv, _r); \
r = au(c).mk_numeral(_r, false); \
} \
else { \
algebraic_numbers::anum const & bv = get_irrational(c, b); \
scoped_anum _r(_am); \
_am.IRAT_OP(av, bv, _r); \
r = au(c).mk_numeral(_r, false); \
} \
} \
mk_c(c)->save_ast_trail(r); \
RETURN_Z3(of_ast(r));
Z3_ast Z3_API Z3_algebraic_add(Z3_context c, Z3_ast a, Z3_ast b) {
Z3_TRY;
LOG_Z3_algebraic_add(c, a, b);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC_X(a, 0);
CHECK_IS_ALGEBRAIC_X(b, 0);
BIN_OP(+,add);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_algebraic_sub(Z3_context c, Z3_ast a, Z3_ast b) {
Z3_TRY;
LOG_Z3_algebraic_sub(c, a, b);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC_X(a, 0);
CHECK_IS_ALGEBRAIC_X(b, 0);
BIN_OP(-,sub);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_algebraic_mul(Z3_context c, Z3_ast a, Z3_ast b) {
Z3_TRY;
LOG_Z3_algebraic_mul(c, a, b);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC_X(a, 0);
CHECK_IS_ALGEBRAIC_X(b, 0);
BIN_OP(*,mul);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_algebraic_div(Z3_context c, Z3_ast a, Z3_ast b) {
Z3_TRY;
LOG_Z3_algebraic_div(c, a, b);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC_X(a, 0);
CHECK_IS_ALGEBRAIC_X(b, 0);
if ((is_rational(c, b) && get_rational(c, b).is_zero()) ||
(!is_rational(c, b) && am(c).is_zero(get_irrational(c, b)))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
BIN_OP(/,div);
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_algebraic_root(Z3_context c, Z3_ast a, unsigned k) {
Z3_TRY;
LOG_Z3_algebraic_root(c, a, k);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC_X(a, 0);
if (k % 2 == 0) {
if ((is_rational(c, a) && get_rational(c, a).is_neg()) ||
(!is_rational(c, a) && am(c).is_neg(get_irrational(c, a)))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
RETURN_Z3(0);
}
}
algebraic_numbers::manager & _am = am(c);
scoped_anum _r(_am);
if (is_rational(c, a)) {
scoped_anum av(_am);
_am.set(av, get_rational(c, a).to_mpq());
_am.root(av, k, _r);
}
else {
algebraic_numbers::anum const & av = get_irrational(c, a);
_am.root(av, k, _r);
}
expr * r = au(c).mk_numeral(_r, false);
mk_c(c)->save_ast_trail(r);
RETURN_Z3(of_ast(r));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_algebraic_power(Z3_context c, Z3_ast a, unsigned k) {
Z3_TRY;
LOG_Z3_algebraic_power(c, a, k);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC_X(a, 0);
algebraic_numbers::manager & _am = am(c);
scoped_anum _r(_am);
if (is_rational(c, a)) {
scoped_anum av(_am);
_am.set(av, get_rational(c, a).to_mpq());
_am.power(av, k, _r);
}
else {
algebraic_numbers::anum const & av = get_irrational(c, a);
_am.power(av, k, _r);
}
expr * r = au(c).mk_numeral(_r, false);
mk_c(c)->save_ast_trail(r);
RETURN_Z3(of_ast(r));
Z3_CATCH_RETURN(0);
}
#define BIN_PRED(RAT_PRED, IRAT_PRED) \
algebraic_numbers::manager & _am = am(c); \
bool r; \
if (is_rational(c, a)) { \
rational av = get_rational(c, a); \
if (is_rational(c, b)) { \
rational bv = get_rational(c, b); \
r = av RAT_PRED bv; \
} \
else { \
algebraic_numbers::anum const & bv = get_irrational(c, b); \
scoped_anum _av(_am); \
_am.set(_av, av.to_mpq()); \
r = _am.IRAT_PRED(_av, bv); \
} \
} \
else { \
algebraic_numbers::anum const & av = get_irrational(c, a); \
if (is_rational(c, b)) { \
rational bv = get_rational(c, b); \
scoped_anum _bv(_am); \
_am.set(_bv, bv.to_mpq()); \
r = _am.IRAT_PRED(av, _bv); \
} \
else { \
algebraic_numbers::anum const & bv = get_irrational(c, b); \
r = _am.IRAT_PRED(av, bv); \
} \
} \
return r ? Z3_TRUE : Z3_FALSE;
Z3_bool Z3_API Z3_algebraic_lt(Z3_context c, Z3_ast a, Z3_ast b) {
Z3_TRY;
LOG_Z3_algebraic_lt(c, a, b);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC(a, 0);
CHECK_IS_ALGEBRAIC(b, 0);
BIN_PRED(<,lt);
Z3_CATCH_RETURN(Z3_FALSE);
}
Z3_bool Z3_API Z3_algebraic_gt(Z3_context c, Z3_ast a, Z3_ast b) {
return Z3_algebraic_lt(c, b, a);
}
Z3_bool Z3_API Z3_algebraic_le(Z3_context c, Z3_ast a, Z3_ast b) {
return !Z3_algebraic_lt(c, b, a);
}
Z3_bool Z3_API Z3_algebraic_ge(Z3_context c, Z3_ast a, Z3_ast b) {
return !Z3_algebraic_lt(c, a, b);
}
Z3_bool Z3_API Z3_algebraic_eq(Z3_context c, Z3_ast a, Z3_ast b) {
Z3_TRY;
LOG_Z3_algebraic_eq(c, a, b);
RESET_ERROR_CODE();
CHECK_IS_ALGEBRAIC(a, 0);
CHECK_IS_ALGEBRAIC(b, 0);
BIN_PRED(==,eq);
Z3_CATCH_RETURN(0);
}
Z3_bool Z3_API Z3_algebraic_neq(Z3_context c, Z3_ast a, Z3_ast b) {
return !Z3_algebraic_eq(c, a, b);
}
static bool to_anum_vector(Z3_context c, unsigned n, Z3_ast a[], scoped_anum_vector & as) {
algebraic_numbers::manager & _am = am(c);
scoped_anum tmp(_am);
for (unsigned i = 0; i < n; i++) {
if (is_rational(c, a[i])) {
_am.set(tmp, get_rational(c, a[i]).to_mpq());
as.push_back(tmp);
}
else if (is_irrational(c, a[i])) {
as.push_back(get_irrational(c, a[i]));
}
else {
return false;
}
}
return true;
}
class vector_var2anum : public polynomial::var2anum {
scoped_anum_vector const & m_as;
public:
vector_var2anum(scoped_anum_vector & as):m_as(as) {}
virtual ~vector_var2anum() {}
virtual algebraic_numbers::manager & m() const { return m_as.m(); }
virtual bool contains(polynomial::var x) const { return static_cast<unsigned>(x) < m_as.size(); }
virtual algebraic_numbers::anum const & operator()(polynomial::var x) const { return m_as.get(x); }
};
Z3_ast_vector Z3_API Z3_algebraic_roots(Z3_context c, Z3_ast p, unsigned n, Z3_ast a[]) {
Z3_TRY;
LOG_Z3_algebraic_roots(c, p, n, a);
RESET_ERROR_CODE();
polynomial::manager & pm = mk_c(c)->pm();
polynomial_ref _p(pm);
polynomial::scoped_numeral d(pm.m());
expr2polynomial converter(mk_c(c)->m(), pm, 0, true);
if (!converter.to_polynomial(to_expr(p), _p, d) ||
static_cast<unsigned>(max_var(_p)) >= n + 1) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
algebraic_numbers::manager & _am = am(c);
scoped_anum_vector as(_am);
if (!to_anum_vector(c, n, a, as)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
scoped_anum_vector roots(_am);
{
cancel_eh<algebraic_numbers::manager> eh(_am);
api::context::set_interruptable(*(mk_c(c)), eh);
scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
vector_var2anum v2a(as);
_am.isolate_roots(_p, v2a, roots);
}
Z3_ast_vector_ref* result = alloc(Z3_ast_vector_ref, mk_c(c)->m());
mk_c(c)->save_object(result);
for (unsigned i = 0; i < roots.size(); i++) {
result->m_ast_vector.push_back(au(c).mk_numeral(roots.get(i), false));
}
RETURN_Z3(of_ast_vector(result));
Z3_CATCH_RETURN(0);
}
int Z3_API Z3_algebraic_eval(Z3_context c, Z3_ast p, unsigned n, Z3_ast a[]) {
Z3_TRY;
LOG_Z3_algebraic_eval(c, p, n, a);
RESET_ERROR_CODE();
polynomial::manager & pm = mk_c(c)->pm();
polynomial_ref _p(pm);
polynomial::scoped_numeral d(pm.m());
expr2polynomial converter(mk_c(c)->m(), pm, 0, true);
if (!converter.to_polynomial(to_expr(p), _p, d) ||
static_cast<unsigned>(max_var(_p)) >= n) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
algebraic_numbers::manager & _am = am(c);
scoped_anum_vector as(_am);
if (!to_anum_vector(c, n, a, as)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
{
cancel_eh<algebraic_numbers::manager> eh(_am);
api::context::set_interruptable(*(mk_c(c)), eh);
scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
vector_var2anum v2a(as);
int r = _am.eval_sign_at(_p, v2a);
if (r > 0) return 1;
else if (r < 0) return -1;
else return 0;
}
Z3_CATCH_RETURN(0);
}
};

View file

@ -324,7 +324,8 @@ extern "C" {
switch (_a->get_kind()) {
case AST_APP: {
expr * e = to_expr(_a);
if (is_numeral_sort(c, of_sort(mk_c(c)->m().get_sort(e))) && mk_c(c)->m().is_value(e))
// Real algebraic numbers are not considered Z3_NUMERAL_AST
if (is_numeral_sort(c, of_sort(mk_c(c)->m().get_sort(e))) && mk_c(c)->m().is_unique_value(e))
return Z3_NUMERAL_AST;
return Z3_APP_AST;
}

View file

@ -82,13 +82,13 @@ namespace api {
context::context(context_params * p, bool user_ref_count):
m_params(p != 0 ? *p : context_params()),
m_user_ref_count(user_ref_count),
m_manager(m_params.m_proof ? PGM_FINE : PGM_DISABLED, m_params.m_trace ? m_params.m_trace_file_name.c_str() : 0),
m_plugins(m_manager),
m_arith_util(m_manager),
m_bv_util(m_manager),
m_datalog_util(m_manager),
m_last_result(m_manager),
m_ast_trail(m_manager),
m_manager(m_params.mk_ast_manager()),
m_plugins(m()),
m_arith_util(m()),
m_bv_util(m()),
m_datalog_util(m()),
m_last_result(m()),
m_ast_trail(m()),
m_replay_stack() {
m_solver = 0;
@ -102,22 +102,16 @@ namespace api {
m_smtlib_parser_has_decls = false;
z3_bound_num_procs();
//
// Configuration parameter settings.
//
if (m_params.m_debug_ref_count) {
m_manager.debug_ref_count();
}
m_error_handler = &default_error_handler;
m_basic_fid = m_manager.get_basic_family_id();
m_arith_fid = m_manager.get_family_id("arith");
m_bv_fid = m_manager.get_family_id("bv");
m_array_fid = m_manager.get_family_id("array");
m_dt_fid = m_manager.get_family_id("datatype");
m_datalog_fid = m_manager.get_family_id("datalog_relation");
m_dt_plugin = static_cast<datatype_decl_plugin*>(m_manager.get_plugin(m_dt_fid));
m_basic_fid = m().get_basic_family_id();
m_arith_fid = m().get_family_id("arith");
m_bv_fid = m().get_family_id("bv");
m_array_fid = m().get_family_id("array");
m_dt_fid = m().get_family_id("datatype");
m_datalog_fid = m().get_family_id("datalog_relation");
m_dt_plugin = static_cast<datatype_decl_plugin*>(m().get_plugin(m_dt_fid));
if (!m_user_ref_count) {
m_replay_stack.push_back(0);
@ -143,6 +137,7 @@ namespace api {
{
if (m_interruptable)
(*m_interruptable)();
m().set_cancel(true);
}
}
@ -195,12 +190,12 @@ namespace api {
expr * context::mk_and(unsigned num_exprs, expr * const * exprs) {
switch(num_exprs) {
case 0:
return m_manager.mk_true();
return m().mk_true();
case 1:
save_ast_trail(exprs[0]);
return exprs[0];
default: {
expr * a = m_manager.mk_and(num_exprs, exprs);
expr * a = m().mk_and(num_exprs, exprs);
save_ast_trail(a);
return a;
} }
@ -216,7 +211,7 @@ namespace api {
SASSERT(m_replay_stack.size() > num_scopes);
unsigned j = m_replay_stack.size() - num_scopes - 1;
if (!m_replay_stack[j]) {
m_replay_stack[j] = alloc(ast_ref_vector, m_manager);
m_replay_stack[j] = alloc(ast_ref_vector, m());
}
m_replay_stack[j]->push_back(n);
}
@ -324,7 +319,7 @@ namespace api {
smt::kernel & context::get_smt_kernel() {
if (!m_solver) {
m_fparams.updt_params(m_params);
m_solver = alloc(smt::kernel, m_manager, m_fparams);
m_solver = alloc(smt::kernel, m(), m_fparams);
}
return *m_solver;
}

View file

@ -32,6 +32,7 @@ Revision History:
#include"event_handler.h"
#include"tactic_manager.h"
#include"context_params.h"
#include"api_polynomial.h"
namespace smtlib {
class parser;
@ -45,7 +46,7 @@ namespace api {
struct add_plugins { add_plugins(ast_manager & m); };
context_params m_params;
bool m_user_ref_count; //!< if true, the user is responsible for managing referenc counters.
ast_manager m_manager;
scoped_ptr<ast_manager> m_manager;
add_plugins m_plugins;
arith_util m_arith_util;
@ -81,6 +82,8 @@ namespace api {
Z3_ast_print_mode m_print_mode;
event_handler * m_interruptable; // Reference to an object that can be interrupted by Z3_interrupt
pmanager m_pmanager;
public:
// Scoped obj for setting m_interruptable
class set_interruptable {
@ -98,10 +101,10 @@ namespace api {
context(context_params * p, bool user_ref_count = false);
~context();
ast_manager & m() { return m_manager; }
ast_manager & m() const { return *(m_manager.get()); }
context_params & params() { return m_params; }
bool produce_proofs() const { return m_manager.proofs_enabled(); }
bool produce_proofs() const { return m().proofs_enabled(); }
bool produce_models() const { return m_params.m_model; }
bool produce_unsat_cores() const { return m_params.m_unsat_core; }
bool use_auto_config() const { return m_params.m_auto_config; }
@ -167,6 +170,13 @@ namespace api {
void check_sorts(ast * n);
// ------------------------
//
// Polynomial manager & caches
//
// -----------------------
polynomial::manager & pm() { return m_pmanager.pm(); }
// ------------------------
//
// Solver interface for backward compatibility

View file

@ -0,0 +1,84 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_polynomial.cpp
Abstract:
Polynomial manager and caches for the external API.
Author:
Leonardo de Moura (leonardo) 2012-12-08
Notes:
--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
#include"api_polynomial.h"
#include"api_ast_vector.h"
#include"expr2polynomial.h"
#include"cancel_eh.h"
#include"scoped_timer.h"
#include"expr2var.h"
namespace api {
pmanager::pmanager():
m_pm(m_nm) {
}
pmanager::~pmanager() {
}
void pmanager::set_cancel(bool f) {
m_pm.set_cancel(f);
}
};
extern "C" {
Z3_ast_vector Z3_API Z3_polynomial_subresultants(Z3_context c, Z3_ast p, Z3_ast q, Z3_ast x) {
Z3_TRY;
LOG_Z3_polynomial_subresultants(c, p, q, x);
RESET_ERROR_CODE();
polynomial::manager & pm = mk_c(c)->pm();
polynomial_ref _p(pm), _q(pm);
polynomial::scoped_numeral d(pm.m());
default_expr2polynomial converter(mk_c(c)->m(), pm);
if (!converter.to_polynomial(to_expr(p), _p, d) ||
!converter.to_polynomial(to_expr(q), _q, d)) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return 0;
}
Z3_ast_vector_ref* result = alloc(Z3_ast_vector_ref, mk_c(c)->m());
mk_c(c)->save_object(result);
if (converter.is_var(to_expr(x))) {
expr2var const & mapping = converter.get_mapping();
unsigned v_x = mapping.to_var(to_expr(x));
polynomial_ref_vector rs(pm);
polynomial_ref r(pm);
expr_ref _r(mk_c(c)->m());
{
cancel_eh<polynomial::manager> eh(pm);
api::context::set_interruptable(*(mk_c(c)), eh);
scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
pm.psc_chain(_p, _q, v_x, rs);
}
for (unsigned i = 0; i < rs.size(); i++) {
r = rs.get(i);
converter.to_expr(r, true, _r);
result->m_ast_vector.push_back(_r);
}
}
RETURN_Z3(of_ast_vector(result));
Z3_CATCH_RETURN(0);
}
};

39
src/api/api_polynomial.h Normal file
View file

@ -0,0 +1,39 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_polynomial.h
Abstract:
Polynomial manager and caches for the external API.
Author:
Leonardo de Moura (leonardo) 2012-12-08
Notes:
--*/
#ifndef _API_POLYNOMIAL_H_
#define _API_POLYNOMIAL_H_
#include"polynomial.h"
namespace api {
class pmanager {
unsynch_mpz_manager m_nm;
polynomial::manager m_pm;
// TODO: add support for caching expressions -> polynomial and back
public:
pmanager();
virtual ~pmanager();
polynomial::manager & pm() { return m_pm; }
void set_cancel(bool f);
};
};
#endif

View file

@ -36,17 +36,7 @@ extern "C" {
static void init_solver_core(Z3_context c, Z3_solver _s) {
ast_manager & m = mk_c(c)->m();
Z3_solver_ref * s = to_solver(_s);
s->m_solver->set_produce_proofs(mk_c(c)->produce_proofs());
s->m_solver->set_produce_unsat_cores(s->m_params.get_bool("unsat_core", mk_c(c)->produce_unsat_cores()));
s->m_solver->set_produce_models(s->m_params.get_bool("model", mk_c(c)->produce_models()));
if (!mk_c(c)->use_auto_config()) {
params_ref p = s->m_params;
p.set_bool("auto_config", false);
s->m_solver->updt_params(p);
}
else {
s->m_solver->updt_params(s->m_params);
}
mk_c(c)->params().init_solver_params(mk_c(c)->m(), *(s->m_solver), s->m_params);
s->m_solver->init(m, s->m_logic);
s->m_initialized = true;
}

View file

@ -1,4 +1,3 @@
Java bindings
-------------
This is currently "working in progress".

View file

@ -1126,6 +1126,27 @@ def Var(idx, s):
_z3_assert(is_sort(s), "Z3 sort expected")
return _to_expr_ref(Z3_mk_bound(s.ctx_ref(), idx, s.ast), s.ctx)
def RealVar(idx, ctx=None):
"""
Create a real free variable. Free variables are used to create quantified formulas.
They are also used to create polynomials.
>>> RealVar(0)
Var(0)
"""
return Var(idx, RealSort(ctx))
def RealVarVector(n, ctx=None):
"""
Create a list of Real free variables.
The variables have ids: 0, 1, ..., n-1
>>> x0, x1, x2, x3 = RealVarVector(4)
>>> x2
Var(2)
"""
return [ RealVar(i, ctx) for i in range(n) ]
#########################################
#
# Booleans

564
src/api/python/z3num.py Normal file
View file

@ -0,0 +1,564 @@
############################################
# Copyright (c) 2012 Microsoft Corporation
#
# Z3 Python interface for Z3 numerals
#
# Author: Leonardo de Moura (leonardo)
############################################
from z3 import *
from z3core import *
from z3printer import *
def _to_numeral(num, ctx=None):
if isinstance(num, Numeral):
return num
else:
return Numeral(num, ctx)
class Numeral:
"""
A Z3 numeral can be used to perform computations over arbitrary
precision integers, rationals and real algebraic numbers.
It also automatically converts python numeric values.
>>> Numeral(2)
2
>>> Numeral("3/2") + 1
5/2
>>> Numeral(Sqrt(2))
1.4142135623?
>>> Numeral(Sqrt(2)) + 2
3.4142135623?
>>> Numeral(Sqrt(2)) + Numeral(Sqrt(3))
3.1462643699?
Z3 numerals can be used to perform computations with
values in a Z3 model.
>>> s = Solver()
>>> x = Real('x')
>>> s.add(x*x == 2)
>>> s.add(x > 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[x]
1.4142135623?
>>> m[x] + 1
1.4142135623? + 1
The previous result is a Z3 expression.
>>> (m[x] + 1).sexpr()
'(+ (root-obj (+ (^ x 2) (- 2)) 2) 1.0)'
>>> Numeral(m[x]) + 1
2.4142135623?
>>> Numeral(m[x]).is_pos()
True
>>> Numeral(m[x])**2
2
We can also isolate the roots of polynomials.
>>> x0, x1, x2 = RealVarVector(3)
>>> r0 = isolate_roots(x0**5 - x0 - 1)
>>> r0
[1.1673039782?]
In the following example, we are isolating the roots
of a univariate polynomial (on x1) obtained after substituting
x0 -> r0[0]
>>> r1 = isolate_roots(x1**2 - x0 + 1, [ r0[0] ])
>>> r1
[-0.4090280898?, 0.4090280898?]
Similarly, in the next example we isolate the roots of
a univariate polynomial (on x2) obtained after substituting
x0 -> r0[0] and x1 -> r1[0]
>>> isolate_roots(x1*x2 + x0, [ r0[0], r1[0] ])
[2.8538479564?]
"""
def __init__(self, num, ctx=None):
if isinstance(num, Ast):
self.ast = num
self.ctx = z3._get_ctx(ctx)
elif isinstance(num, RatNumRef) or isinstance(num, AlgebraicNumRef):
self.ast = num.ast
self.ctx = num.ctx
elif isinstance(num, ArithRef):
r = simplify(num)
self.ast = r.ast
self.ctx = r.ctx
else:
v = RealVal(num, ctx)
self.ast = v.ast
self.ctx = v.ctx
Z3_inc_ref(self.ctx_ref(), self.as_ast())
assert Z3_algebraic_is_value(self.ctx_ref(), self.ast)
def __del__(self):
Z3_dec_ref(self.ctx_ref(), self.as_ast())
def is_integer(self):
""" Return True if the numeral is integer.
>>> Numeral(2).is_integer()
True
>>> (Numeral(Sqrt(2)) * Numeral(Sqrt(2))).is_integer()
True
>>> Numeral(Sqrt(2)).is_integer()
False
>>> Numeral("2/3").is_integer()
False
"""
return self.is_rational() and self.denominator() == 1
def is_rational(self):
""" Return True if the numeral is rational.
>>> Numeral(2).is_rational()
True
>>> Numeral("2/3").is_rational()
True
>>> Numeral(Sqrt(2)).is_rational()
False
"""
return Z3_get_ast_kind(self.ctx_ref(), self.as_ast()) == Z3_NUMERAL_AST
def denominator(self):
""" Return the denominator if `self` is rational.
>>> Numeral("2/3").denominator()
3
"""
assert(self.is_rational())
return Numeral(Z3_get_denominator(self.ctx_ref(), self.as_ast()), self.ctx)
def numerator(self):
""" Return the numerator if `self` is rational.
>>> Numeral("2/3").numerator()
2
"""
assert(self.is_rational())
return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx)
def is_irrational(self):
""" Return True if the numeral is irrational.
>>> Numeral(2).is_irrational()
False
>>> Numeral("2/3").is_irrational()
False
>>> Numeral(Sqrt(2)).is_irrational()
True
"""
return not self.is_rational()
def as_long(self):
""" Return a numeral (that is an integer) as a Python long.
>>> (Numeral(10)**20).as_long()
100000000000000000000L
"""
assert(self.is_integer())
return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
def approx(self, precision=10):
"""Return a numeral that approximates the numeral `self`.
The result `r` is such that |r - self| <= 1/10^precision
If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2)
>>> x.approx(20)
6838717160008073720548335/4835703278458516698824704
>>> x.approx(5)
2965821/2097152
>>> Numeral(2).approx(10)
2
"""
return self.upper(precision)
def upper(self, precision=10):
"""Return a upper bound that approximates the numeral `self`.
The result `r` is such that r - self <= 1/10^precision
If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2)
>>> x.upper(20)
6838717160008073720548335/4835703278458516698824704
>>> x.upper(5)
2965821/2097152
>>> Numeral(2).upper(10)
2
"""
if self.is_rational():
return self
else:
return Numeral(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx)
def lower(self, precision=10):
"""Return a lower bound that approximates the numeral `self`.
The result `r` is such that self - r <= 1/10^precision
If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2)
>>> x.lower(20)
1709679290002018430137083/1208925819614629174706176
>>> Numeral("2/3").lower(10)
2/3
"""
if self.is_rational():
return self
else:
return Numeral(Z3_get_algebraic_number_lower(self.ctx_ref(), self.as_ast(), precision), self.ctx)
def sign(self):
""" Return the sign of the numeral.
>>> Numeral(2).sign()
1
>>> Numeral(-3).sign()
-1
>>> Numeral(0).sign()
0
"""
return Z3_algebraic_sign(self.ctx_ref(), self.ast)
def is_pos(self):
""" Return True if the numeral is positive.
>>> Numeral(2).is_pos()
True
>>> Numeral(-3).is_pos()
False
>>> Numeral(0).is_pos()
False
"""
return Z3_algebraic_is_pos(self.ctx_ref(), self.ast)
def is_neg(self):
""" Return True if the numeral is negative.
>>> Numeral(2).is_neg()
False
>>> Numeral(-3).is_neg()
True
>>> Numeral(0).is_neg()
False
"""
return Z3_algebraic_is_neg(self.ctx_ref(), self.ast)
def is_zero(self):
""" Return True if the numeral is zero.
>>> Numeral(2).is_zero()
False
>>> Numeral(-3).is_zero()
False
>>> Numeral(0).is_zero()
True
>>> sqrt2 = Numeral(2).root(2)
>>> sqrt2.is_zero()
False
>>> (sqrt2 - sqrt2).is_zero()
True
"""
return Z3_algebraic_is_zero(self.ctx_ref(), self.ast)
def __add__(self, other):
""" Return the numeral `self + other`.
>>> Numeral(2) + 3
5
>>> Numeral(2) + Numeral(4)
6
>>> Numeral("2/3") + 1
5/3
"""
return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx)
def __radd__(self, other):
""" Return the numeral `other + self`.
>>> 3 + Numeral(2)
5
"""
return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx)
def __sub__(self, other):
""" Return the numeral `self - other`.
>>> Numeral(2) - 3
-1
"""
return Numeral(Z3_algebraic_sub(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx)
def __rsub__(self, other):
""" Return the numeral `other - self`.
>>> 3 - Numeral(2)
1
"""
return Numeral(Z3_algebraic_sub(self.ctx_ref(), _to_numeral(other, self.ctx).ast, self.ast), self.ctx)
def __mul__(self, other):
""" Return the numeral `self * other`.
>>> Numeral(2) * 3
6
"""
return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx)
def __rmul__(self, other):
""" Return the numeral `other * mul`.
>>> 3 * Numeral(2)
6
"""
return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx)
def __div__(self, other):
""" Return the numeral `self / other`.
>>> Numeral(2) / 3
2/3
>>> Numeral(2).root(2) / 3
0.4714045207?
>>> Numeral(Sqrt(2)) / Numeral(Sqrt(3))
0.8164965809?
"""
return Numeral(Z3_algebraic_div(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx)
def __rdiv__(self, other):
""" Return the numeral `other / self`.
>>> 3 / Numeral(2)
3/2
>>> 3 / Numeral(2).root(2)
2.1213203435?
"""
return Numeral(Z3_algebraic_div(self.ctx_ref(), _to_numeral(other, self.ctx).ast, self.ast), self.ctx)
def root(self, k):
""" Return the numeral `self^(1/k)`.
>>> sqrt2 = Numeral(2).root(2)
>>> sqrt2
1.4142135623?
>>> sqrt2 * sqrt2
2
>>> sqrt2 * 2 + 1
3.8284271247?
>>> (sqrt2 * 2 + 1).sexpr()
'(root-obj (+ (^ x 2) (* (- 2) x) (- 7)) 2)'
"""
return Numeral(Z3_algebraic_root(self.ctx_ref(), self.ast, k), self.ctx)
def power(self, k):
""" Return the numeral `self^k`.
>>> sqrt3 = Numeral(3).root(2)
>>> sqrt3
1.7320508075?
>>> sqrt3.power(2)
3
"""
return Numeral(Z3_algebraic_power(self.ctx_ref(), self.ast, k), self.ctx)
def __pow__(self, k):
""" Return the numeral `self^k`.
>>> sqrt3 = Numeral(3).root(2)
>>> sqrt3
1.7320508075?
>>> sqrt3**2
3
"""
return self.power(k)
def __lt__(self, other):
""" Return True if `self < other`.
>>> Numeral(Sqrt(2)) < 2
True
>>> Numeral(Sqrt(3)) < Numeral(Sqrt(2))
False
>>> Numeral(Sqrt(2)) < Numeral(Sqrt(2))
False
"""
return Z3_algebraic_lt(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast)
def __rlt__(self, other):
""" Return True if `other < self`.
>>> 2 < Numeral(Sqrt(2))
False
"""
return self > other
def __gt__(self, other):
""" Return True if `self > other`.
>>> Numeral(Sqrt(2)) > 2
False
>>> Numeral(Sqrt(3)) > Numeral(Sqrt(2))
True
>>> Numeral(Sqrt(2)) > Numeral(Sqrt(2))
False
"""
return Z3_algebraic_gt(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast)
def __rgt__(self, other):
""" Return True if `other > self`.
>>> 2 > Numeral(Sqrt(2))
True
"""
return self < other
def __le__(self, other):
""" Return True if `self <= other`.
>>> Numeral(Sqrt(2)) <= 2
True
>>> Numeral(Sqrt(3)) <= Numeral(Sqrt(2))
False
>>> Numeral(Sqrt(2)) <= Numeral(Sqrt(2))
True
"""
return Z3_algebraic_le(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast)
def __rle__(self, other):
""" Return True if `other <= self`.
>>> 2 <= Numeral(Sqrt(2))
False
"""
return self >= other
def __ge__(self, other):
""" Return True if `self >= other`.
>>> Numeral(Sqrt(2)) >= 2
False
>>> Numeral(Sqrt(3)) >= Numeral(Sqrt(2))
True
>>> Numeral(Sqrt(2)) >= Numeral(Sqrt(2))
True
"""
return Z3_algebraic_ge(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast)
def __rge__(self, other):
""" Return True if `other >= self`.
>>> 2 >= Numeral(Sqrt(2))
True
"""
return self <= other
def __eq__(self, other):
""" Return True if `self == other`.
>>> Numeral(Sqrt(2)) == 2
False
>>> Numeral(Sqrt(3)) == Numeral(Sqrt(2))
False
>>> Numeral(Sqrt(2)) == Numeral(Sqrt(2))
True
"""
return Z3_algebraic_eq(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast)
def __ne__(self, other):
""" Return True if `self != other`.
>>> Numeral(Sqrt(2)) != 2
True
>>> Numeral(Sqrt(3)) != Numeral(Sqrt(2))
True
>>> Numeral(Sqrt(2)) != Numeral(Sqrt(2))
False
"""
return Z3_algebraic_neq(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast)
def __str__(self):
if Z3_is_numeral_ast(self.ctx_ref(), self.ast):
return str(RatNumRef(self.ast, self.ctx))
else:
return str(AlgebraicNumRef(self.ast, self.ctx))
def __repr__(self):
return self.__str__()
def sexpr(self):
return Z3_ast_to_string(self.ctx_ref(), self.as_ast())
def as_ast(self):
return self.ast
def ctx_ref(self):
return self.ctx.ref()
def eval_sign_at(p, vs):
"""
Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3
Expression containing arithmetic operators: +, -, *, ^k where k is
an integer; and free variables x that is_var(x) is True. Moreover,
all variables must be real.
The result is 1 if the polynomial is positive at the given point,
-1 if negative, and 0 if zero.
>>> x0, x1, x2 = RealVarVector(3)
>>> eval_sign_at(x0**2 + x1*x2 + 1, (Numeral(0), Numeral(1), Numeral(2)))
1
>>> eval_sign_at(x0**2 - 2, [ Numeral(Sqrt(2)) ])
0
>>> eval_sign_at((x0 + x1)*(x0 + x2), (Numeral(0), Numeral(Sqrt(2)), Numeral(Sqrt(3))))
1
"""
num = len(vs)
_vs = (Ast * num)()
for i in range(num):
_vs[i] = vs[i].ast
return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs)
def isolate_roots(p, vs=[]):
"""
Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the
roots of the univariate polynomial p(vs[0], ..., vs[len(vs)-1], x_n).
Remarks:
* p is a Z3 expression that contains only arithmetic terms and free variables.
* forall i in [0, n) vs is a numeral.
The result is a list of numerals
>>> x0 = RealVar(0)
>>> isolate_roots(x0**5 - x0 - 1)
[1.1673039782?]
>>> x1 = RealVar(1)
>>> isolate_roots(x0**2 - x1**4 - 1, [ Numeral(Sqrt(3)) ])
[-1.1892071150?, 1.1892071150?]
>>> x2 = RealVar(2)
>>> isolate_roots(x2**2 + x0 - x1, [ Numeral(Sqrt(3)), Numeral(Sqrt(2)) ])
[]
"""
num = len(vs)
_vs = (Ast * num)()
for i in range(num):
_vs[i] = vs[i].ast
_roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx)
return [ Numeral(r) for r in _roots ]
if __name__ == "__main__":
import doctest
if doctest.testmod().failed:
exit(1)

37
src/api/python/z3poly.py Normal file
View file

@ -0,0 +1,37 @@
############################################
# Copyright (c) 2012 Microsoft Corporation
#
# Z3 Python interface for Z3 polynomials
#
# Author: Leonardo de Moura (leonardo)
############################################
from z3 import *
def subresultants(p, q, x):
"""
Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'.
'p', 'q' and 'x' are Z3 expressions where 'p' and 'q' are arithmetic terms.
Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable.
Example: f(a) is a considered to be a variable b in the polynomial
f(a)*f(a) + 2*f(a) + 1
>>> x, y = Reals('x y')
>>> subresultants(2*x + y, 3*x - 2*y + 2, x)
[-7*y + 4]
>>> r = subresultants(3*y*x**2 + y**3 + 1, 2*x**3 + y + 3, x)
>>> r[0]
4*y**9 + 12*y**6 + 27*y**5 + 162*y**4 + 255*y**3 + 4
>>> r[1]
-6*y**4 + -6*y
"""
return AstVector(Z3_polynomial_subresultants(p.ctx_ref(), p.as_ast(), q.as_ast(), x.as_ast()), p.ctx)
if __name__ == "__main__":
import doctest
if doctest.testmod().failed:
exit(1)

View file

@ -24,6 +24,8 @@ Notes:
#include<stdio.h>
#include"z3_macros.h"
#include"z3_api.h"
#include"z3_algebraic.h"
#include"z3_polynomial.h"
#undef __in
#undef __out

226
src/api/z3_algebraic.h Normal file
View file

@ -0,0 +1,226 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_algebraic.h
Abstract:
Additional APIs for handling Z3 algebraic numbers encoded as
Z3_ASTs
Author:
Leonardo de Moura (leonardo) 2012-12-07
Notes:
--*/
#ifndef _Z3_ALGEBRAIC_H_
#define _Z3_ALGEBRAIC_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
\brief Return Z3_TRUE if \c can be used as value in the Z3 real algebraic
number package.
def_API('Z3_algebraic_is_value', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_is_value(__in Z3_context c, __in Z3_ast a);
/**
\brief Return the Z3_TRUE if \c a is positive, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
def_API('Z3_algebraic_is_pos', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_is_pos(__in Z3_context c, __in Z3_ast a);
/**
\brief Return the Z3_TRUE if \c a is negative, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
def_API('Z3_algebraic_is_neg', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_is_neg(__in Z3_context c, __in Z3_ast a);
/**
\brief Return the Z3_TRUE if \c a is zero, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
def_API('Z3_algebraic_is_zero', BOOL, (_in(CONTEXT), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_is_zero(__in Z3_context c, __in Z3_ast a);
/**
\brief Return 1 if \c a is positive, 0 if \c a is zero, and -1 if \c a is negative.
\pre Z3_algebraic_is_value(c, a)
def_API('Z3_algebraic_sign', INT, (_in(CONTEXT), _in(AST)))
*/
int Z3_API Z3_algebraic_sign(__in Z3_context c, __in Z3_ast a);
/**
\brief Return the value a + b.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
\post Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_add', AST, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_algebraic_add(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return the value a - b.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
\post Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_sub', AST, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_algebraic_sub(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return the value a * b.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
\post Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_mul', AST, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_algebraic_mul(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return the value a / b.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
\pre !Z3_algebraic_is_zero(c, b)
\post Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_div', AST, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_algebraic_div(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return the a^(1/k)
\pre Z3_algebraic_is_value(c, a)
\pre k is even => !Z3_algebraic_is_neg(c, a)
\post Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_root', AST, (_in(CONTEXT), _in(AST), _in(UINT)))
*/
Z3_ast Z3_API Z3_algebraic_root(__in Z3_context c, __in Z3_ast a, __in unsigned k);
/**
\brief Return the a^k
\pre Z3_algebraic_is_value(c, a)
\post Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_power', AST, (_in(CONTEXT), _in(AST), _in(UINT)))
*/
Z3_ast Z3_API Z3_algebraic_power(__in Z3_context c, __in Z3_ast a, __in unsigned k);
/**
\brief Return Z3_TRUE if a < b, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
def_API('Z3_algebraic_lt', BOOL, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_lt(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return Z3_TRUE if a > b, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
def_API('Z3_algebraic_gt', BOOL, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_gt(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return Z3_TRUE if a <= b, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
def_API('Z3_algebraic_le', BOOL, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_le(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return Z3_TRUE if a >= b, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
def_API('Z3_algebraic_ge', BOOL, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_ge(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return Z3_TRUE if a == b, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
def_API('Z3_algebraic_eq', BOOL, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_eq(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Return Z3_TRUE if a != b, and Z3_FALSE otherwise.
\pre Z3_algebraic_is_value(c, a)
\pre Z3_algebraic_is_value(c, b)
def_API('Z3_algebraic_neq', BOOL, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_bool Z3_API Z3_algebraic_neq(__in Z3_context c, __in Z3_ast a, __in Z3_ast b);
/**
\brief Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the
roots of the univariate polynomial p(a[0], ..., a[n-1], x_n).
\pre p is a Z3 expression that contains only arithmetic terms and free variables.
\pre forall i in [0, n) Z3_algebraic_is_value(c, a[i])
\post forall r in result Z3_algebraic_is_value(c, result)
def_API('Z3_algebraic_roots', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST)))
*/
Z3_ast_vector Z3_API Z3_algebraic_roots(__in Z3_context c, __in Z3_ast p, __in unsigned n, __in Z3_ast a[]);
/**
\brief Given a multivariate polynomial p(x_0, ..., x_{n-1}), return the
sign of p(a[0], ..., a[n-1]).
\pre p is a Z3 expression that contains only arithmetic terms and free variables.
\pre forall i in [0, n) Z3_algebraic_is_value(c, a[i])
def_API('Z3_algebraic_eval', INT, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST)))
*/
int Z3_API Z3_algebraic_eval(__in Z3_context c, __in Z3_ast p, __in unsigned n, __in Z3_ast a[]);
#ifdef __cplusplus
};
#endif // __cplusplus
#endif

45
src/api/z3_polynomial.h Normal file
View file

@ -0,0 +1,45 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_polynomial.h
Abstract:
Additional APIs for polynomials.
Author:
Leonardo de Moura (leonardo) 2012-12-09
Notes:
--*/
#ifndef _Z3_POLYNOMIAL_H_
#define _Z3_POLYNOMIAL_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
\brief Return the nonzero subresultants of \c p and \c q with respect to the "variable" \c x.
\pre \c p, \c q and \c x are Z3 expressions where \c p and \c q are arithmetic terms.
Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable.
Example: f(a) is a considered to be a variable in the polynomial
f(a)*f(a) + 2*f(a) + 1
def_API('Z3_polynomial_subresultants', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(AST)))
*/
Z3_ast_vector Z3_API Z3_polynomial_subresultants(__in Z3_context c, __in Z3_ast p, __in Z3_ast q, __in Z3_ast x);
#ifdef __cplusplus
};
#endif // __cplusplus
#endif