3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

Merge branch 'master' into polysat

This commit is contained in:
Jakob Rath 2023-05-26 15:58:09 +02:00
commit f54f33551e
308 changed files with 6606 additions and 18485 deletions

View file

@ -120,10 +120,8 @@ extern "C" {
RESET_ERROR_CODE();
//
recfun::promise_def def =
mk_c(c)->recfun().get_plugin().mk_def(to_symbol(s),
domain_size,
to_sorts(domain),
to_sort(range));
mk_c(c)->recfun().get_plugin().mk_def(
to_symbol(s), domain_size, to_sorts(domain), to_sort(range), false);
func_decl* d = def.get_def()->get_decl();
mk_c(c)->save_ast_trail(d);
RETURN_Z3(of_func_decl(d));

View file

@ -198,7 +198,7 @@ extern "C" {
RESET_ERROR_CODE();
std::ostringstream buffer;
if (!to_goal_ref(g)->is_cnf()) {
SET_ERROR_CODE(Z3_INVALID_ARG, "If this is not what you want, then preprocess by optional bit-blasting and applying tseitin-cnf");
SET_ERROR_CODE(Z3_INVALID_ARG, "Goal is not converted into CNF. Preprocess by optional bit-blasting and applying tseitin-cnf");
RETURN_Z3(nullptr);
}
to_goal_ref(g)->display_dimacs(buffer, include_names);

View file

@ -128,7 +128,8 @@ extern "C" {
static Z3_ast_vector Z3_parser_context_parse_stream(Z3_context c, scoped_ptr<cmd_context>& ctx, bool owned, std::istream& is) {
Z3_TRY;
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
ast_manager& m = mk_c(c)->m();
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
mk_c(c)->save_object(v);
std::stringstream errstrm;
ctx->set_regular_stream(errstrm);
@ -147,8 +148,11 @@ extern "C" {
SET_ERROR_CODE(Z3_PARSER_ERROR, errstrm.str());
return of_ast_vector(v);
}
for (expr* e : ctx->tracked_assertions())
v->m_ast_vector.push_back(e);
for (auto const& [asr, an] : ctx->tracked_assertions())
if (an)
v->m_ast_vector.push_back(m.mk_implies(an, asr));
else
v->m_ast_vector.push_back(asr);
ctx->reset_tracked_assertions();
return of_ast_vector(v);
Z3_CATCH_RETURN(nullptr);

View file

@ -314,8 +314,11 @@ extern "C" {
bool initialized = to_solver(s)->m_solver.get() != nullptr;
if (!initialized)
init_solver(c, s);
for (expr* e : ctx->tracked_assertions())
to_solver(s)->assert_expr(e);
for (auto const& [asr, an] : ctx->tracked_assertions())
if (an)
to_solver(s)->assert_expr(asr, an);
else
to_solver(s)->assert_expr(asr);
ctx->reset_tracked_assertions();
to_solver_ref(s)->set_model_converter(ctx->get_model_converter());
auto* ctx_s = ctx->get_solver();

View file

@ -24,7 +24,7 @@ Revision History:
#include "util/scoped_ctrl_c.h"
#include "util/cancel_eh.h"
#include "util/scoped_timer.h"
#include "ast/simplifiers/seq_simplifier.h"
#include "ast/simplifiers/then_simplifier.h"
Z3_apply_result_ref::Z3_apply_result_ref(api::context& c, ast_manager & m): api::object(c) {
}
@ -589,7 +589,7 @@ extern "C" {
auto fac1 = *to_simplifier_ref(t1);
auto fac2 = *to_simplifier_ref(t2);
auto new_s = [fac1, fac2](auto& m, auto& p, auto& st) {
auto* r = alloc(seq_simplifier, m, p, st);
auto* r = alloc(then_simplifier, m, p, st);
r->add_simplifier(fac1(m, p, st));
r->add_simplifier(fac2(m, p, st));
return r;

View file

@ -151,6 +151,7 @@ namespace z3 {
}
/**
\brief A Context manages all other Z3 objects, global configuration options, etc.
*/
@ -360,11 +361,19 @@ namespace z3 {
func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range);
func_decl recfun(symbol const & name, unsigned arity, sort const * domain, sort const & range);
func_decl recfun(symbol const & name, const sort_vector& domain, sort const & range);
func_decl recfun(char const * name, sort_vector const& domain, sort const & range);
func_decl recfun(char const * name, unsigned arity, sort const * domain, sort const & range);
func_decl recfun(char const * name, sort const & domain, sort const & range);
func_decl recfun(char const * name, sort const & d1, sort const & d2, sort const & range);
void recdef(func_decl, expr_vector const& args, expr const& body);
/**
* \brief add function definition body to declaration decl. decl needs to be declared using context::<recfun>.
* @param decl
* @param args
* @param body
*/
void recdef(func_decl decl, expr_vector const& args, expr const& body);
func_decl user_propagate_function(symbol const& name, sort_vector const& domain, sort const& range);
/**
@ -742,6 +751,7 @@ namespace z3 {
func_decl_vector recognizers();
};
/**
\brief Function declaration (aka function definition). It is the signature of interpreted and uninterpreted functions in Z3.
The basic building block in Z3 is the function application.
@ -762,6 +772,8 @@ namespace z3 {
sort range() const { Z3_sort r = Z3_get_range(ctx(), *this); check_error(); return sort(ctx(), r); }
symbol name() const { Z3_symbol s = Z3_get_decl_name(ctx(), *this); check_error(); return symbol(ctx(), s); }
Z3_decl_kind decl_kind() const { return Z3_get_decl_kind(ctx(), *this); }
unsigned num_parameters() const { return Z3_get_decl_num_parameters(ctx(), *this); }
func_decl transitive_closure(func_decl const&) {
Z3_func_decl tc = Z3_mk_transitive_closure(ctx(), *this); check_error(); return func_decl(ctx(), tc);
@ -2679,6 +2691,43 @@ namespace z3 {
return out;
}
/**
\brief class for auxiliary parameters associated with func_decl
The class is initialized with a func_decl or application expression and an index
The accessor get_expr, get_sort, ... is available depending on the value of kind().
The caller is responsible to check that the kind of the parameter aligns with the call (get_expr etc).
Parameters are available on some declarations to contain additional information that is not passed as
arguments when a function is applied to arguments. For example, bit-vector extraction has two
integer parameters. Array map has a function parameter.
*/
class parameter {
Z3_parameter_kind m_kind;
func_decl m_decl;
unsigned m_index;
context& ctx() const { return m_decl.ctx(); }
void check_error() const { ctx().check_error(); }
public:
parameter(func_decl const& d, unsigned idx) : m_decl(d), m_index(idx) {
if (ctx().enable_exceptions() && idx >= d.num_parameters())
Z3_THROW(exception("parameter index is out of bounds"));
m_kind = Z3_get_decl_parameter_kind(ctx(), d, idx);
}
parameter(expr const& e, unsigned idx) : m_decl(e.decl()), m_index(idx) {
if (ctx().enable_exceptions() && idx >= m_decl.num_parameters())
Z3_THROW(exception("parameter index is out of bounds"));
m_kind = Z3_get_decl_parameter_kind(ctx(), m_decl, idx);
}
Z3_parameter_kind kind() const { return m_kind; }
expr get_expr() const { Z3_ast a = Z3_get_decl_ast_parameter(ctx(), m_decl, m_index); check_error(); return expr(ctx(), a); }
sort get_sort() const { Z3_sort s = Z3_get_decl_sort_parameter(ctx(), m_decl, m_index); check_error(); return sort(ctx(), s); }
func_decl get_decl() const { Z3_func_decl f = Z3_get_decl_func_decl_parameter(ctx(), m_decl, m_index); check_error(); return func_decl(ctx(), f); }
symbol get_symbol() const { Z3_symbol s = Z3_get_decl_symbol_parameter(ctx(), m_decl, m_index); check_error(); return symbol(ctx(), s); }
std::string get_rational() const { Z3_string s = Z3_get_decl_rational_parameter(ctx(), m_decl, m_index); check_error(); return s; }
double get_double() const { double d = Z3_get_decl_double_parameter(ctx(), m_decl, m_index); check_error(); return d; }
int get_int() const { int i = Z3_get_decl_int_parameter(ctx(), m_decl, m_index); check_error(); return i; }
};
class solver : public object {
Z3_solver m_solver;
@ -2712,6 +2761,16 @@ namespace z3 {
void set(char const * k, double v) { params p(ctx()); p.set(k, v); set(p); }
void set(char const * k, symbol const & v) { params p(ctx()); p.set(k, v); set(p); }
void set(char const * k, char const* v) { params p(ctx()); p.set(k, v); set(p); }
/**
\brief Create a backtracking point.
The solver contains a stack of assertions.
\sa Z3_solver_get_num_scopes
\sa Z3_solver_pop
def_API('Z3_solver_push', VOID, (_in(CONTEXT), _in(SOLVER)))
*/
void push() { Z3_solver_push(ctx(), m_solver); check_error(); }
void pop(unsigned n = 1) { Z3_solver_pop(ctx(), m_solver, n); check_error(); }
void reset() { Z3_solver_reset(ctx(), m_solver); check_error(); }
@ -3604,6 +3663,19 @@ namespace z3 {
}
inline func_decl context::recfun(symbol const & name, sort_vector const& domain, sort const & range) {
check_context(domain, range);
array<Z3_sort> domain1(domain);
Z3_func_decl f = Z3_mk_rec_func_decl(m_ctx, name, domain1.size(), domain1.ptr(), range);
check_error();
return func_decl(*this, f);
}
inline func_decl context::recfun(char const * name, sort_vector const& domain, sort const & range) {
return recfun(str_symbol(name), domain, range);
}
inline func_decl context::recfun(char const * name, unsigned arity, sort const * domain, sort const & range) {
return recfun(str_symbol(name), arity, domain, range);
}

View file

@ -179,6 +179,7 @@ set(Z3_JAVA_JAR_SOURCE_FILES
Tactic.java
TupleSort.java
UninterpretedSort.java
UserPropagatorBase.java
Version.java
Z3Exception.java
Z3Object.java

View file

@ -227,7 +227,7 @@ public class Context implements AutoCloseable {
/**
* Create a new array sort.
**/
public <D extends Sort, R extends Sort> ArraySort<D, R> mkArraySort(D domain, R range)
public final <D extends Sort, R extends Sort> ArraySort<D, R> mkArraySort(D domain, R range)
{
checkContextMatch(domain);
checkContextMatch(range);
@ -238,7 +238,7 @@ public class Context implements AutoCloseable {
/**
* Create a new array sort.
**/
public <R extends Sort> ArraySort<Sort, R> mkArraySort(Sort[] domains, R range)
public final <R extends Sort> ArraySort<Sort, R> mkArraySort(Sort[] domains, R range)
{
checkContextMatch(domains);
checkContextMatch(range);
@ -256,7 +256,7 @@ public class Context implements AutoCloseable {
/**
* Create a new sequence sort
**/
public <R extends Sort> SeqSort<R> mkSeqSort(R s)
public final <R extends Sort> SeqSort<R> mkSeqSort(R s)
{
return new SeqSort<>(this, Native.mkSeqSort(nCtx(), s.getNativeObject()));
}
@ -264,7 +264,7 @@ public class Context implements AutoCloseable {
/**
* Create a new regular expression sort
**/
public <R extends Sort> ReSort<R> mkReSort(R s)
public final <R extends Sort> ReSort<R> mkReSort(R s)
{
return new ReSort<>(this, Native.mkReSort(nCtx(), s.getNativeObject()));
}
@ -286,7 +286,7 @@ public class Context implements AutoCloseable {
/**
* Create a new enumeration sort.
**/
public <R> EnumSort<R> mkEnumSort(Symbol name, Symbol... enumNames)
public final <R> EnumSort<R> mkEnumSort(Symbol name, Symbol... enumNames)
{
checkContextMatch(name);
@ -297,7 +297,7 @@ public class Context implements AutoCloseable {
/**
* Create a new enumeration sort.
**/
public <R> EnumSort<R> mkEnumSort(String name, String... enumNames)
public final <R> EnumSort<R> mkEnumSort(String name, String... enumNames)
{
return new EnumSort<>(this, mkSymbol(name), mkSymbols(enumNames));
@ -306,7 +306,7 @@ public class Context implements AutoCloseable {
/**
* Create a new list sort.
**/
public <R extends Sort> ListSort<R> mkListSort(Symbol name, R elemSort)
public final <R extends Sort> ListSort<R> mkListSort(Symbol name, R elemSort)
{
checkContextMatch(name);
checkContextMatch(elemSort);
@ -316,7 +316,7 @@ public class Context implements AutoCloseable {
/**
* Create a new list sort.
**/
public <R extends Sort> ListSort<R> mkListSort(String name, R elemSort)
public final <R extends Sort> ListSort<R> mkListSort(String name, R elemSort)
{
checkContextMatch(elemSort);
return new ListSort<>(this, mkSymbol(name), elemSort);
@ -325,7 +325,7 @@ public class Context implements AutoCloseable {
/**
* Create a new finite domain sort.
**/
public <R> FiniteDomainSort<R> mkFiniteDomainSort(Symbol name, long size)
public final <R> FiniteDomainSort<R> mkFiniteDomainSort(Symbol name, long size)
{
checkContextMatch(name);
@ -335,7 +335,7 @@ public class Context implements AutoCloseable {
/**
* Create a new finite domain sort.
**/
public <R> FiniteDomainSort<R> mkFiniteDomainSort(String name, long size)
public final <R> FiniteDomainSort<R> mkFiniteDomainSort(String name, long size)
{
return new FiniteDomainSort<>(this, mkSymbol(name), size);
@ -352,7 +352,7 @@ public class Context implements AutoCloseable {
* an index referring to one of the recursive datatypes that is
* declared.
**/
public <R> Constructor<R> mkConstructor(Symbol name, Symbol recognizer,
public final <R> Constructor<R> mkConstructor(Symbol name, Symbol recognizer,
Symbol[] fieldNames, Sort[] sorts, int[] sortRefs)
{
@ -362,7 +362,7 @@ public class Context implements AutoCloseable {
/**
* Create a datatype constructor.
**/
public <R> Constructor<R> mkConstructor(String name, String recognizer,
public final <R> Constructor<R> mkConstructor(String name, String recognizer,
String[] fieldNames, Sort[] sorts, int[] sortRefs)
{
return of(this, mkSymbol(name), mkSymbol(recognizer), mkSymbols(fieldNames), sorts, sortRefs);
@ -371,7 +371,7 @@ public class Context implements AutoCloseable {
/**
* Create a new datatype sort.
**/
public <R> DatatypeSort<R> mkDatatypeSort(Symbol name, Constructor<R>[] constructors)
public final <R> DatatypeSort<R> mkDatatypeSort(Symbol name, Constructor<R>[] constructors)
{
checkContextMatch(name);
checkContextMatch(constructors);
@ -381,7 +381,7 @@ public class Context implements AutoCloseable {
/**
* Create a new datatype sort.
**/
public <R> DatatypeSort<R> mkDatatypeSort(String name, Constructor<R>[] constructors)
public final <R> DatatypeSort<R> mkDatatypeSort(String name, Constructor<R>[] constructors)
{
checkContextMatch(constructors);
@ -431,7 +431,7 @@ public class Context implements AutoCloseable {
* that is passed in as argument is updated with value v,
* the remaining fields of t are unchanged.
**/
public <F extends Sort, R extends Sort> Expr<R> mkUpdateField(FuncDecl<F> field, Expr<R> t, Expr<F> v)
public final <F extends Sort, R extends Sort> Expr<R> mkUpdateField(FuncDecl<F> field, Expr<R> t, Expr<F> v)
throws Z3Exception
{
return (Expr<R>) Expr.create(this,
@ -444,7 +444,7 @@ public class Context implements AutoCloseable {
/**
* Creates a new function declaration.
**/
public <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort[] domain, R range)
public final <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort[] domain, R range)
{
checkContextMatch(name);
checkContextMatch(domain);
@ -452,10 +452,25 @@ public class Context implements AutoCloseable {
return new FuncDecl<>(this, name, domain, range);
}
public final <R extends Sort> FuncDecl<R> mkPropagateFunction(Symbol name, Sort[] domain, R range)
{
checkContextMatch(name);
checkContextMatch(domain);
checkContextMatch(range);
long f = Native.solverPropagateDeclare(
this.nCtx(),
name.getNativeObject(),
AST.arrayLength(domain),
AST.arrayToNative(domain),
range.getNativeObject());
return new FuncDecl<>(this, f);
}
/**
* Creates a new function declaration.
**/
public <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort domain, R range)
public final <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort domain, R range)
{
checkContextMatch(name);
@ -468,7 +483,7 @@ public class Context implements AutoCloseable {
/**
* Creates a new function declaration.
**/
public <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort[] domain, R range)
public final <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort[] domain, R range)
{
checkContextMatch(domain);
@ -479,7 +494,7 @@ public class Context implements AutoCloseable {
/**
* Creates a new function declaration.
**/
public <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort domain, R range)
public final <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort domain, R range)
{
checkContextMatch(domain);
@ -491,7 +506,7 @@ public class Context implements AutoCloseable {
/**
* Creates a new recursive function declaration.
**/
public <R extends Sort> FuncDecl<R> mkRecFuncDecl(Symbol name, Sort[] domain, R range)
public final <R extends Sort> FuncDecl<R> mkRecFuncDecl(Symbol name, Sort[] domain, R range)
{
checkContextMatch(name);
checkContextMatch(domain);
@ -506,7 +521,7 @@ public class Context implements AutoCloseable {
* MkRecFuncDecl. The body may contain recursive uses of the function or
* other mutually recursive functions.
*/
public <R extends Sort> void AddRecDef(FuncDecl<R> f, Expr<?>[] args, Expr<R> body)
public final <R extends Sort> void AddRecDef(FuncDecl<R> f, Expr<?>[] args, Expr<R> body)
{
checkContextMatch(f);
checkContextMatch(args);
@ -521,7 +536,7 @@ public class Context implements AutoCloseable {
* @see #mkFuncDecl(String,Sort,Sort)
* @see #mkFuncDecl(String,Sort[],Sort)
**/
public <R extends Sort> FuncDecl<R> mkFreshFuncDecl(String prefix, Sort[] domain, R range)
public final <R extends Sort> FuncDecl<R> mkFreshFuncDecl(String prefix, Sort[] domain, R range)
{
checkContextMatch(domain);
@ -532,7 +547,7 @@ public class Context implements AutoCloseable {
/**
* Creates a new constant function declaration.
**/
public <R extends Sort> FuncDecl<R> mkConstDecl(Symbol name, R range)
public final <R extends Sort> FuncDecl<R> mkConstDecl(Symbol name, R range)
{
checkContextMatch(name);
checkContextMatch(range);
@ -542,7 +557,7 @@ public class Context implements AutoCloseable {
/**
* Creates a new constant function declaration.
**/
public <R extends Sort> FuncDecl<R> mkConstDecl(String name, R range)
public final <R extends Sort> FuncDecl<R> mkConstDecl(String name, R range)
{
checkContextMatch(range);
return new FuncDecl<>(this, mkSymbol(name), null, range);
@ -554,7 +569,7 @@ public class Context implements AutoCloseable {
* @see #mkFuncDecl(String,Sort,Sort)
* @see #mkFuncDecl(String,Sort[],Sort)
**/
public <R extends Sort> FuncDecl<R> mkFreshConstDecl(String prefix, R range)
public final <R extends Sort> FuncDecl<R> mkFreshConstDecl(String prefix, R range)
{
checkContextMatch(range);
@ -566,7 +581,7 @@ public class Context implements AutoCloseable {
* @param index The de-Bruijn index of the variable
* @param ty The sort of the variable
**/
public <R extends Sort> Expr<R> mkBound(int index, R ty)
public final <R extends Sort> Expr<R> mkBound(int index, R ty)
{
return (Expr<R>) Expr.create(this,
Native.mkBound(nCtx(), index, ty.getNativeObject()));
@ -590,7 +605,7 @@ public class Context implements AutoCloseable {
* Creates a new Constant of sort {@code range} and named
* {@code name}.
**/
public <R extends Sort> Expr<R> mkConst(Symbol name, R range)
public final <R extends Sort> Expr<R> mkConst(Symbol name, R range)
{
checkContextMatch(name);
checkContextMatch(range);
@ -605,7 +620,7 @@ public class Context implements AutoCloseable {
* Creates a new Constant of sort {@code range} and named
* {@code name}.
**/
public <R extends Sort> Expr<R> mkConst(String name, R range)
public final <R extends Sort> Expr<R> mkConst(String name, R range)
{
return mkConst(mkSymbol(name), range);
}
@ -614,7 +629,7 @@ public class Context implements AutoCloseable {
* Creates a fresh Constant of sort {@code range} and a name
* prefixed with {@code prefix}.
**/
public <R extends Sort> Expr<R> mkFreshConst(String prefix, R range)
public final <R extends Sort> Expr<R> mkFreshConst(String prefix, R range)
{
checkContextMatch(range);
return (Expr<R>) Expr.create(this,
@ -625,7 +640,7 @@ public class Context implements AutoCloseable {
* Creates a fresh constant from the FuncDecl {@code f}.
* @param f A decl of a 0-arity function
**/
public <R extends Sort> Expr<R> mkConst(FuncDecl<R> f)
public final <R extends Sort> Expr<R> mkConst(FuncDecl<R> f)
{
return mkApp(f, (Expr<?>[]) null);
}
@ -754,7 +769,7 @@ public class Context implements AutoCloseable {
/**
* Create an expression representing {@code not(a)}.
**/
public BoolExpr mkNot(Expr<BoolSort> a)
public final BoolExpr mkNot(Expr<BoolSort> a)
{
checkContextMatch(a);
return new BoolExpr(this, Native.mkNot(nCtx(), a.getNativeObject()));
@ -767,7 +782,7 @@ public class Context implements AutoCloseable {
* @param t2 An expression
* @param t3 An expression with the same sort as {@code t2}
**/
public <R extends Sort> Expr<R> mkITE(Expr<BoolSort> t1, Expr<? extends R> t2, Expr<? extends R> t3)
public final <R extends Sort> Expr<R> mkITE(Expr<BoolSort> t1, Expr<? extends R> t2, Expr<? extends R> t3)
{
checkContextMatch(t1);
checkContextMatch(t2);
@ -867,7 +882,7 @@ public class Context implements AutoCloseable {
/**
* Create an expression representing {@code -t}.
**/
public <R extends ArithSort> ArithExpr<R> mkUnaryMinus(Expr<R> t)
public final <R extends ArithSort> ArithExpr<R> mkUnaryMinus(Expr<R> t)
{
checkContextMatch(t);
return (ArithExpr<R>) Expr.create(this,
@ -877,7 +892,7 @@ public class Context implements AutoCloseable {
/**
* Create an expression representing {@code t1 / t2}.
**/
public <R extends ArithSort> ArithExpr<R> mkDiv(Expr<? extends R> t1, Expr<? extends R> t2)
public final <R extends ArithSort> ArithExpr<R> mkDiv(Expr<? extends R> t1, Expr<? extends R> t2)
{
checkContextMatch(t1);
checkContextMatch(t2);
@ -914,7 +929,7 @@ public class Context implements AutoCloseable {
/**
* Create an expression representing {@code t1 ^ t2}.
**/
public <R extends ArithSort> ArithExpr<R> mkPower(Expr<? extends R> t1,
public final <R extends ArithSort> ArithExpr<R> mkPower(Expr<? extends R> t1,
Expr<? extends R> t2)
{
checkContextMatch(t1);
@ -1693,7 +1708,7 @@ public class Context implements AutoCloseable {
/**
* Create an array constant.
**/
public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(Symbol name, D domain, R range)
public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(Symbol name, D domain, R range)
{
return (ArrayExpr<D, R>) mkConst(name, mkArraySort(domain, range));
@ -1702,7 +1717,7 @@ public class Context implements AutoCloseable {
/**
* Create an array constant.
**/
public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(String name, D domain, R range)
public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(String name, D domain, R range)
{
return (ArrayExpr<D, R>) mkConst(mkSymbol(name), mkArraySort(domain, range));
@ -1720,7 +1735,7 @@ public class Context implements AutoCloseable {
* @see #mkArraySort(Sort[], R)
* @see #mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
**/
public <D extends Sort, R extends Sort> Expr<R> mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
public final <D extends Sort, R extends Sort> Expr<R> mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
{
checkContextMatch(a);
checkContextMatch(i);
@ -1742,7 +1757,7 @@ public class Context implements AutoCloseable {
* @see #mkArraySort(Sort[], R)
* @see #mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
**/
public <R extends Sort> Expr<R> mkSelect(Expr<ArraySort<Sort, R>> a, Expr<?>[] args)
public final <R extends Sort> Expr<R> mkSelect(Expr<ArraySort<Sort, R>> a, Expr<?>[] args)
{
checkContextMatch(a);
checkContextMatch(args);
@ -1767,7 +1782,7 @@ public class Context implements AutoCloseable {
* @see #mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
**/
public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
{
checkContextMatch(a);
checkContextMatch(i);
@ -1792,7 +1807,7 @@ public class Context implements AutoCloseable {
* @see #mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
**/
public <R extends Sort> ArrayExpr<Sort, R> mkStore(Expr<ArraySort<Sort, R>> a, Expr<?>[] args, Expr<R> v)
public final <R extends Sort> ArrayExpr<Sort, R> mkStore(Expr<ArraySort<Sort, R>> a, Expr<?>[] args, Expr<R> v)
{
checkContextMatch(a);
checkContextMatch(args);
@ -1810,7 +1825,7 @@ public class Context implements AutoCloseable {
* @see #mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
*
**/
public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkConstArray(D domain, Expr<R> v)
public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkConstArray(D domain, Expr<R> v)
{
checkContextMatch(domain);
checkContextMatch(v);
@ -1847,7 +1862,7 @@ public class Context implements AutoCloseable {
* value, for arrays that can be represented as finite maps with a default
* range value.
**/
public <D extends Sort, R extends Sort> Expr<R> mkTermArray(Expr<ArraySort<D, R>> array)
public final <D extends Sort, R extends Sort> Expr<R> mkTermArray(Expr<ArraySort<D, R>> array)
{
checkContextMatch(array);
return (Expr<R>) Expr.create(this,
@ -1857,7 +1872,7 @@ public class Context implements AutoCloseable {
/**
* Create Extentionality index. Two arrays are equal if and only if they are equal on the index returned by MkArrayExt.
**/
public <D extends Sort, R extends Sort> Expr<D> mkArrayExt(Expr<ArraySort<D, R>> arg1, Expr<ArraySort<D, R>> arg2)
public final <D extends Sort, R extends Sort> Expr<D> mkArrayExt(Expr<ArraySort<D, R>> arg1, Expr<ArraySort<D, R>> arg2)
{
checkContextMatch(arg1);
checkContextMatch(arg2);
@ -1868,7 +1883,7 @@ public class Context implements AutoCloseable {
/**
* Create a set type.
**/
public <D extends Sort> SetSort<D> mkSetSort(D ty)
public final <D extends Sort> SetSort<D> mkSetSort(D ty)
{
checkContextMatch(ty);
return new SetSort<>(this, ty);
@ -1877,7 +1892,7 @@ public class Context implements AutoCloseable {
/**
* Create an empty set.
**/
public <D extends Sort> ArrayExpr<D, BoolSort> mkEmptySet(D domain)
public final <D extends Sort> ArrayExpr<D, BoolSort> mkEmptySet(D domain)
{
checkContextMatch(domain);
return (ArrayExpr<D, BoolSort>) Expr.create(this,
@ -1887,7 +1902,7 @@ public class Context implements AutoCloseable {
/**
* Create the full set.
**/
public <D extends Sort> ArrayExpr<D, BoolSort> mkFullSet(D domain)
public final <D extends Sort> ArrayExpr<D, BoolSort> mkFullSet(D domain)
{
checkContextMatch(domain);
return (ArrayExpr<D, BoolSort>) Expr.create(this,
@ -1897,7 +1912,7 @@ public class Context implements AutoCloseable {
/**
* Add an element to the set.
**/
public <D extends Sort> ArrayExpr<D, BoolSort> mkSetAdd(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetAdd(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
{
checkContextMatch(set);
checkContextMatch(element);
@ -1909,7 +1924,7 @@ public class Context implements AutoCloseable {
/**
* Remove an element from a set.
**/
public <D extends Sort> ArrayExpr<D, BoolSort> mkSetDel(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetDel(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
{
checkContextMatch(set);
checkContextMatch(element);
@ -1945,7 +1960,7 @@ public class Context implements AutoCloseable {
/**
* Take the difference between two sets.
**/
public <D extends Sort> ArrayExpr<D, BoolSort> mkSetDifference(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetDifference(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
{
checkContextMatch(arg1);
checkContextMatch(arg2);
@ -1957,7 +1972,7 @@ public class Context implements AutoCloseable {
/**
* Take the complement of a set.
**/
public <D extends Sort> ArrayExpr<D, BoolSort> mkSetComplement(Expr<ArraySort<D, BoolSort>> arg)
public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetComplement(Expr<ArraySort<D, BoolSort>> arg)
{
checkContextMatch(arg);
return (ArrayExpr<D, BoolSort>)Expr.create(this,
@ -1967,7 +1982,7 @@ public class Context implements AutoCloseable {
/**
* Check for set membership.
**/
public <D extends Sort> BoolExpr mkSetMembership(Expr<D> elem, Expr<ArraySort<D, BoolSort>> set)
public final <D extends Sort> BoolExpr mkSetMembership(Expr<D> elem, Expr<ArraySort<D, BoolSort>> set)
{
checkContextMatch(elem);
checkContextMatch(set);
@ -1979,7 +1994,7 @@ public class Context implements AutoCloseable {
/**
* Check for subsetness of sets.
**/
public <D extends Sort> BoolExpr mkSetSubset(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
public final <D extends Sort> BoolExpr mkSetSubset(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
{
checkContextMatch(arg1);
checkContextMatch(arg2);
@ -1996,7 +2011,7 @@ public class Context implements AutoCloseable {
/**
* Create the empty sequence.
*/
public <R extends Sort> SeqExpr<R> mkEmptySeq(R s)
public final <R extends Sort> SeqExpr<R> mkEmptySeq(R s)
{
checkContextMatch(s);
return (SeqExpr<R>) Expr.create(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
@ -2005,7 +2020,7 @@ public class Context implements AutoCloseable {
/**
* Create the singleton sequence.
*/
public <R extends Sort> SeqExpr<R> mkUnit(Expr<R> elem)
public final <R extends Sort> SeqExpr<R> mkUnit(Expr<R> elem)
{
checkContextMatch(elem);
return (SeqExpr<R>) Expr.create(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
@ -2018,11 +2033,11 @@ public class Context implements AutoCloseable {
{
StringBuilder buf = new StringBuilder();
for (int i = 0; i < s.length(); ++i) {
int code = s.codePointAt(i);
if (code <= 32 || 127 < code)
buf.append(String.format("\\u{%x}", code));
else
buf.append(s.charAt(i));
int code = s.codePointAt(i);
if (code <= 32 || 127 < code)
buf.append(String.format("\\u{%x}", code));
else
buf.append(s.charAt(i));
}
return (SeqExpr<CharSort>) Expr.create(this, Native.mkString(nCtx(), buf.toString()));
}
@ -2073,7 +2088,7 @@ public class Context implements AutoCloseable {
/**
* Retrieve the length of a given sequence.
*/
public <R extends Sort> IntExpr mkLength(Expr<SeqSort<R>> s)
public final <R extends Sort> IntExpr mkLength(Expr<SeqSort<R>> s)
{
checkContextMatch(s);
return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
@ -2082,7 +2097,7 @@ public class Context implements AutoCloseable {
/**
* Check for sequence prefix.
*/
public <R extends Sort> BoolExpr mkPrefixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
public final <R extends Sort> BoolExpr mkPrefixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
{
checkContextMatch(s1, s2);
return (BoolExpr) Expr.create(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
@ -2091,7 +2106,7 @@ public class Context implements AutoCloseable {
/**
* Check for sequence suffix.
*/
public <R extends Sort> BoolExpr mkSuffixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
public final <R extends Sort> BoolExpr mkSuffixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
{
checkContextMatch(s1, s2);
return (BoolExpr)Expr.create(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
@ -2100,7 +2115,7 @@ public class Context implements AutoCloseable {
/**
* Check for sequence containment of s2 in s1.
*/
public <R extends Sort> BoolExpr mkContains(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
public final <R extends Sort> BoolExpr mkContains(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
{
checkContextMatch(s1, s2);
return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
@ -2129,7 +2144,7 @@ public class Context implements AutoCloseable {
/**
* Retrieve sequence of length one at index.
*/
public <R extends Sort> SeqExpr<R> mkAt(Expr<SeqSort<R>> s, Expr<IntSort> index)
public final <R extends Sort> SeqExpr<R> mkAt(Expr<SeqSort<R>> s, Expr<IntSort> index)
{
checkContextMatch(s, index);
return (SeqExpr<R>) Expr.create(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
@ -2138,7 +2153,7 @@ public class Context implements AutoCloseable {
/**
* Retrieve element at index.
*/
public <R extends Sort> Expr<R> mkNth(Expr<SeqSort<R>> s, Expr<IntSort> index)
public final <R extends Sort> Expr<R> mkNth(Expr<SeqSort<R>> s, Expr<IntSort> index)
{
checkContextMatch(s, index);
return (Expr<R>) Expr.create(this, Native.mkSeqNth(nCtx(), s.getNativeObject(), index.getNativeObject()));
@ -2148,7 +2163,7 @@ public class Context implements AutoCloseable {
/**
* Extract subsequence.
*/
public <R extends Sort> SeqExpr<R> mkExtract(Expr<SeqSort<R>> s, Expr<IntSort> offset, Expr<IntSort> length)
public final <R extends Sort> SeqExpr<R> mkExtract(Expr<SeqSort<R>> s, Expr<IntSort> offset, Expr<IntSort> length)
{
checkContextMatch(s, offset, length);
return (SeqExpr<R>) Expr.create(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
@ -2157,7 +2172,7 @@ public class Context implements AutoCloseable {
/**
* Extract index of sub-string starting at offset.
*/
public <R extends Sort> IntExpr mkIndexOf(Expr<SeqSort<R>> s, Expr<SeqSort<R>> substr, Expr<IntSort> offset)
public final <R extends Sort> IntExpr mkIndexOf(Expr<SeqSort<R>> s, Expr<SeqSort<R>> substr, Expr<IntSort> offset)
{
checkContextMatch(s, substr, offset);
return (IntExpr)Expr.create(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
@ -2166,7 +2181,7 @@ public class Context implements AutoCloseable {
/**
* Replace the first occurrence of src by dst in s.
*/
public <R extends Sort> SeqExpr<R> mkReplace(Expr<SeqSort<R>> s, Expr<SeqSort<R>> src, Expr<SeqSort<R>> dst)
public final <R extends Sort> SeqExpr<R> mkReplace(Expr<SeqSort<R>> s, Expr<SeqSort<R>> src, Expr<SeqSort<R>> dst)
{
checkContextMatch(s, src, dst);
return (SeqExpr<R>) Expr.create(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
@ -2175,17 +2190,17 @@ public class Context implements AutoCloseable {
/**
* Convert a regular expression that accepts sequence s.
*/
public <R extends Sort> ReExpr<R> mkToRe(Expr<SeqSort<R>> s)
public final <R extends Sort> ReExpr<SeqSort<R>> mkToRe(Expr<SeqSort<R>> s)
{
checkContextMatch(s);
return (ReExpr<R>) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
return (ReExpr<SeqSort<R>>) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
}
/**
* Check for regular expression membership.
*/
public <R extends Sort> BoolExpr mkInRe(Expr<SeqSort<R>> s, Expr<ReSort<R>> re)
public final <R extends Sort> BoolExpr mkInRe(Expr<SeqSort<R>> s, ReExpr<SeqSort<R>> re)
{
checkContextMatch(s, re);
return (BoolExpr) Expr.create(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
@ -2194,7 +2209,7 @@ public class Context implements AutoCloseable {
/**
* Take the Kleene star of a regular expression.
*/
public <R extends Sort> ReExpr<R> mkStar(Expr<ReSort<R>> re)
public final <R extends Sort> ReExpr<R> mkStar(Expr<ReSort<R>> re)
{
checkContextMatch(re);
return (ReExpr<R>) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
@ -2203,7 +2218,7 @@ public class Context implements AutoCloseable {
/**
* Create power regular expression.
*/
public <R extends Sort> ReExpr<R> mkPower(Expr<ReSort<R>> re, int n)
public final <R extends Sort> ReExpr<R> mkPower(Expr<ReSort<R>> re, int n)
{
return (ReExpr<R>) Expr.create(this, Native.mkRePower(nCtx(), re.getNativeObject(), n));
}
@ -2211,7 +2226,7 @@ public class Context implements AutoCloseable {
/**
* Take the lower and upper-bounded Kleene star of a regular expression.
*/
public <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo, int hi)
public final <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo, int hi)
{
return (ReExpr<R>) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, hi));
}
@ -2219,7 +2234,7 @@ public class Context implements AutoCloseable {
/**
* Take the lower-bounded Kleene star of a regular expression.
*/
public <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo)
public final <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo)
{
return (ReExpr<R>) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, 0));
}
@ -2228,7 +2243,7 @@ public class Context implements AutoCloseable {
/**
* Take the Kleene plus of a regular expression.
*/
public <R extends Sort> ReExpr<R> mkPlus(Expr<ReSort<R>> re)
public final <R extends Sort> ReExpr<R> mkPlus(Expr<ReSort<R>> re)
{
checkContextMatch(re);
return (ReExpr<R>) Expr.create(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
@ -2237,7 +2252,7 @@ public class Context implements AutoCloseable {
/**
* Create the optional regular expression.
*/
public <R extends Sort> ReExpr<R> mkOption(Expr<ReSort<R>> re)
public final <R extends Sort> ReExpr<R> mkOption(Expr<ReSort<R>> re)
{
checkContextMatch(re);
return (ReExpr<R>) Expr.create(this, Native.mkReOption(nCtx(), re.getNativeObject()));
@ -2246,7 +2261,7 @@ public class Context implements AutoCloseable {
/**
* Create the complement regular expression.
*/
public <R extends Sort> ReExpr<R> mkComplement(Expr<ReSort<R>> re)
public final <R extends Sort> ReExpr<R> mkComplement(Expr<ReSort<R>> re)
{
checkContextMatch(re);
return (ReExpr<R>) Expr.create(this, Native.mkReComplement(nCtx(), re.getNativeObject()));
@ -2285,10 +2300,10 @@ public class Context implements AutoCloseable {
/**
* Create a difference regular expression.
*/
public <R extends Sort> ReExpr<R> mkDiff(Expr<ReSort<R>> a, Expr<ReSort<R>> b)
public final <R extends Sort> ReExpr<R> mkDiff(Expr<ReSort<R>> a, Expr<ReSort<R>> b)
{
checkContextMatch(a, b);
return (ReExpr<R>) Expr.create(this, Native.mkReDiff(nCtx(), a.getNativeObject(), b.getNativeObject()));
return (ReExpr<R>) Expr.create(this, Native.mkReDiff(nCtx(), a.getNativeObject(), b.getNativeObject()));
}
@ -2296,7 +2311,7 @@ public class Context implements AutoCloseable {
* Create the empty regular expression.
* Coresponds to re.none
*/
public <R extends Sort> ReExpr<R> mkEmptyRe(R s)
public final <R extends Sort> ReExpr<R> mkEmptyRe(ReSort<R> s)
{
return (ReExpr<R>) Expr.create(this, Native.mkReEmpty(nCtx(), s.getNativeObject()));
}
@ -2305,16 +2320,17 @@ public class Context implements AutoCloseable {
* Create the full regular expression.
* Corresponds to re.all
*/
public <R extends Sort> ReExpr<R> mkFullRe(R s)
public final <R extends Sort> ReExpr<R> mkFullRe(ReSort<R> s)
{
return (ReExpr<R>) Expr.create(this, Native.mkReFull(nCtx(), s.getNativeObject()));
}
/**
* Create regular expression that accepts all characters
* R has to be a sequence sort.
* Corresponds to re.allchar
*/
public <R extends Sort> ReExpr<R> mkAllcharRe(R s)
public final <R extends Sort> ReExpr<R> mkAllcharRe(ReSort<R> s)
{
return (ReExpr<R>) Expr.create(this, Native.mkReAllchar(nCtx(), s.getNativeObject()));
}
@ -2322,10 +2338,10 @@ public class Context implements AutoCloseable {
/**
* Create a range expression.
*/
public <R extends Sort> ReExpr<R> mkRange(Expr<SeqSort<CharSort>> lo, Expr<SeqSort<CharSort>> hi)
public final ReExpr<SeqSort<CharSort>> mkRange(Expr<SeqSort<CharSort>> lo, Expr<SeqSort<CharSort>> hi)
{
checkContextMatch(lo, hi);
return (ReExpr<R>) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
return (ReExpr<SeqSort<CharSort>>) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
}
/**
@ -2429,7 +2445,7 @@ public class Context implements AutoCloseable {
*
* @return A Term with value {@code v} and sort {@code ty}
**/
public <R extends Sort> Expr<R> mkNumeral(String v, R ty)
public final <R extends Sort> Expr<R> mkNumeral(String v, R ty)
{
checkContextMatch(ty);
return (Expr<R>) Expr.create(this,
@ -2446,7 +2462,7 @@ public class Context implements AutoCloseable {
*
* @return A Term with value {@code v} and type {@code ty}
**/
public <R extends Sort> Expr<R> mkNumeral(int v, R ty)
public final <R extends Sort> Expr<R> mkNumeral(int v, R ty)
{
checkContextMatch(ty);
return (Expr<R>) Expr.create(this, Native.mkInt(nCtx(), v, ty.getNativeObject()));
@ -2462,7 +2478,7 @@ public class Context implements AutoCloseable {
*
* @return A Term with value {@code v} and type {@code ty}
**/
public <R extends Sort> Expr<R> mkNumeral(long v, R ty)
public final <R extends Sort> Expr<R> mkNumeral(long v, R ty)
{
checkContextMatch(ty);
return (Expr<R>) Expr.create(this,
@ -2717,7 +2733,7 @@ public class Context implements AutoCloseable {
* @param names names of the bound variables.
* @param body the body of the quantifier.
**/
public <R extends Sort> Lambda<R> mkLambda(Sort[] sorts, Symbol[] names, Expr<R> body)
public final <R extends Sort> Lambda<R> mkLambda(Sort[] sorts, Symbol[] names, Expr<R> body)
{
return Lambda.of(this, sorts, names, body);
}
@ -2728,7 +2744,7 @@ public class Context implements AutoCloseable {
* Creates a lambda expression using a list of constants that will
* form the set of bound variables.
**/
public <R extends Sort> Lambda<R> mkLambda(Expr<?>[] boundConstants, Expr<R> body)
public final <R extends Sort> Lambda<R> mkLambda(Expr<?>[] boundConstants, Expr<R> body)
{
return Lambda.of(this, boundConstants, body);
}
@ -4179,7 +4195,7 @@ public class Context implements AutoCloseable {
* @param index The index of the order.
* @param sort The sort of the order.
*/
public <R extends Sort> FuncDecl<BoolSort> mkLinearOrder(R sort, int index) {
public final <R extends Sort> FuncDecl<BoolSort> mkLinearOrder(R sort, int index) {
return (FuncDecl<BoolSort>) FuncDecl.create(
this,
Native.mkLinearOrder(
@ -4195,7 +4211,7 @@ public class Context implements AutoCloseable {
* @param index The index of the order.
* @param sort The sort of the order.
*/
public <R extends Sort> FuncDecl<BoolSort> mkPartialOrder(R sort, int index) {
public final <R extends Sort> FuncDecl<BoolSort> mkPartialOrder(R sort, int index) {
return (FuncDecl<BoolSort>) FuncDecl.create(
this,
Native.mkPartialOrder(

View file

@ -77,3 +77,156 @@ DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_setInternalErrorHand
Z3_set_error_handler((Z3_context)a0, Z3JavaErrorHandler);
}
#include <assert.h>
struct JavaInfo {
JNIEnv *jenv = nullptr;
jobject jobj = nullptr;
jmethodID push = nullptr;
jmethodID pop = nullptr;
jmethodID fresh = nullptr;
jmethodID created = nullptr;
jmethodID fixed = nullptr;
jmethodID eq = nullptr;
jmethodID final = nullptr;
Z3_solver_callback cb = nullptr;
};
struct ScopedCB {
JavaInfo *info;
ScopedCB(JavaInfo *_info, Z3_solver_callback cb): info(_info) {
info->cb = cb;
}
~ScopedCB() {
info->cb = nullptr;
}
};
static void push_eh(void* _p, Z3_solver_callback cb) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
info->jenv->CallVoidMethod(info->jobj, info->push);
}
static void pop_eh(void* _p, Z3_solver_callback cb, unsigned int number) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
info->jenv->CallVoidMethod(info->jobj, info->pop, number);
}
static void* fresh_eh(void* _p, Z3_context new_context) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
return info->jenv->CallObjectMethod(info->jobj, info->fresh, (jlong)new_context);
}
static void created_eh(void* _p, Z3_solver_callback cb, Z3_ast _e) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
info->jenv->CallVoidMethod(info->jobj, info->created, (jlong)_e);
}
static void fixed_eh(void* _p, Z3_solver_callback cb, Z3_ast _var, Z3_ast _value) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
info->jenv->CallVoidMethod(info->jobj, info->fixed, (jlong)_var, (jlong)_value);
}
static void eq_eh(void* _p, Z3_solver_callback cb, Z3_ast _x, Z3_ast _y) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
info->jenv->CallVoidMethod(info->jobj, info->eq, (jlong)_x, (jlong)_y);
}
static void final_eh(void* _p, Z3_solver_callback cb) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
info->jenv->CallVoidMethod(info->jobj, info->final);
}
// TODO: implement decide
static void decide_eh(void* _p, Z3_solver_callback cb, Z3_ast* _val, unsigned* bit, Z3_lbool* is_pos) {
JavaInfo *info = static_cast<JavaInfo*>(_p);
ScopedCB scoped(info, cb);
}
DLL_VIS JNIEXPORT jlong JNICALL Java_com_microsoft_z3_Native_propagateInit(JNIEnv *jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
JavaInfo *info = new JavaInfo;
info->jenv = jenv;
info->jobj = jenv->NewGlobalRef(jobj);
jclass jcls = jenv->GetObjectClass(info->jobj);
info->push = jenv->GetMethodID(jcls, "pushWrapper", "()V");
info->pop = jenv->GetMethodID(jcls, "popWrapper", "(I)V");
info->fresh = jenv->GetMethodID(jcls, "freshWrapper", "(J)Lcom/microsoft/z3/Native$UserPropagatorBase;");
info->created = jenv->GetMethodID(jcls, "createdWrapper", "(J)V");
info->fixed = jenv->GetMethodID(jcls, "fixedWrapper", "(JJ)V");
info->eq = jenv->GetMethodID(jcls, "eqWrapper", "(JJ)V");
info->final = jenv->GetMethodID(jcls, "finWrapper", "()V");
if (!info->push || !info->pop || !info->fresh || !info->created || !info->fixed || !info->eq || !info->final) {
assert(false);
}
Z3_solver_propagate_init((Z3_context)ctx, (Z3_solver)solver, info, push_eh, pop_eh, fresh_eh);
return (jlong)info;
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateDestroy(JNIEnv *jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo) {
JavaInfo *info = (JavaInfo*)javainfo;
info->jenv->DeleteGlobalRef(info->jobj);
delete info;
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterCreated(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
Z3_solver_propagate_created((Z3_context)ctx, (Z3_solver)solver, created_eh);
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterFinal(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
Z3_solver_propagate_final((Z3_context)ctx, (Z3_solver)solver, final_eh);
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterFixed(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
Z3_solver_propagate_fixed((Z3_context)ctx, (Z3_solver)solver, fixed_eh);
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterEq(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
Z3_solver_propagate_eq((Z3_context)ctx, (Z3_solver)solver, eq_eh);
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterDecide(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
Z3_solver_propagate_decide((Z3_context)ctx, (Z3_solver)solver, decide_eh);
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateConflict(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, jlong num_fixed, jlongArray fixed, jlong num_eqs, jlongArray eq_lhs, jlongArray eq_rhs, jlong conseq) {
JavaInfo *info = (JavaInfo*)javainfo;
GETLONGAELEMS(Z3_ast, fixed, _fixed);
GETLONGAELEMS(Z3_ast, eq_lhs, _eq_lhs);
GETLONGAELEMS(Z3_ast, eq_rhs, _eq_rhs);
Z3_solver_propagate_consequence((Z3_context)ctx, info->cb, num_fixed, _fixed, num_eqs, _eq_lhs, _eq_rhs, (Z3_ast)conseq);
RELEASELONGAELEMS(fixed, _fixed);
RELEASELONGAELEMS(eq_lhs, _eq_lhs);
RELEASELONGAELEMS(eq_rhs, _eq_rhs);
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateAdd(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, jlong e) {
JavaInfo *info = (JavaInfo*)javainfo;
Z3_solver_callback cb = info->cb;
if (cb)
Z3_solver_propagate_register_cb((Z3_context)ctx, cb, (Z3_ast)e);
else if (solver)
Z3_solver_propagate_register((Z3_context)ctx, (Z3_solver)solver, (Z3_ast)e);
else {
assert(false);
}
}
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateNextSplit(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, long e, long idx, long phase) {
JavaInfo *info = (JavaInfo*)javainfo;
Z3_solver_callback cb = info->cb;
Z3_solver_next_split((Z3_context)ctx, cb, (Z3_ast)e, idx, Z3_lbool(phase));
}

View file

@ -0,0 +1,97 @@
package com.microsoft.z3;
import com.microsoft.z3.Context;
import com.microsoft.z3.enumerations.Z3_lbool;
public abstract class UserPropagatorBase extends Native.UserPropagatorBase {
private Context ctx;
private Solver solver;
public UserPropagatorBase(Context _ctx, Solver _solver) {
super(_ctx.nCtx(), _solver.getNativeObject());
ctx = _ctx;
solver = _solver;
}
public final Context getCtx() {
return ctx;
}
public final Solver getSolver() {
return solver;
}
@Override
protected final void pushWrapper() {
push();
}
@Override
protected final void popWrapper(int number) {
pop(number);
}
@Override
protected final void finWrapper() {
fin();
}
@Override
protected final void eqWrapper(long lx, long ly) {
Expr x = new Expr(ctx, lx);
Expr y = new Expr(ctx, ly);
eq(x, y);
}
@Override
protected final UserPropagatorBase freshWrapper(long lctx) {
return fresh(new Context(lctx));
}
@Override
protected final void createdWrapper(long last) {
created(new Expr(ctx, last));
}
@Override
protected final void fixedWrapper(long lvar, long lvalue) {
Expr var = new Expr(ctx, lvar);
Expr value = new Expr(ctx, lvalue);
fixed(var, value);
}
public abstract void push();
public abstract void pop(int number);
public abstract UserPropagatorBase fresh(Context ctx);
public <R extends Sort> void created(Expr<R> ast) {}
public <R extends Sort> void fixed(Expr<R> var, Expr<R> value) {}
public <R extends Sort> void eq(Expr<R> x, Expr<R> y) {}
public void fin() {}
public final <R extends Sort> void add(Expr<R> expr) {
Native.propagateAdd(this, ctx.nCtx(), solver.getNativeObject(), javainfo, expr.getNativeObject());
}
public final <R extends Sort> void conflict(Expr<R>[] fixed) {
conflict(fixed, new Expr[0], new Expr[0]);
}
public final <R extends Sort> void conflict(Expr<R>[] fixed, Expr<R>[] lhs, Expr<R>[] rhs) {
AST conseq = ctx.mkBool(false);
Native.propagateConflict(
this, ctx.nCtx(), solver.getNativeObject(), javainfo,
fixed.length, AST.arrayToNative(fixed), lhs.length, AST.arrayToNative(lhs), AST.arrayToNative(rhs), conseq.getNativeObject());
}
public final <R extends Sort> void nextSplit(Expr<R> e, long idx, Z3_lbool phase) {
Native.propagateNextSplit(
this, ctx.nCtx(), solver.getNativeObject(), javainfo,
e.getNativeObject(), idx, phase.toInt());
}
}

View file

@ -0,0 +1,36 @@
// @ts-ignore we're not going to bother with types for this
import process from 'process';
import { init } from '../../build/node';
import assert from 'assert';
(async () => {
let { Context, em } = await init();
let z3 = Context('main');
const x = z3.BitVec.const('x', 256);
const y = z3.BitVec.const('y', 256);
const z = z3.BitVec.const('z', 256);
const xPlusY = x.add(y);
const xPlusZ = x.add(z);
const expr = xPlusY.mul(xPlusZ);
const to_check = expr.eq(z3.Const('test', expr.sort));
const solver = new z3.Solver();
solver.add(to_check);
const cr = await solver.check();
console.log(cr);
assert(cr === 'sat');
const model = solver.model();
let modelStr = model.sexpr();
modelStr = modelStr.replace(/\n/g, ' ');
console.log("Model: ", modelStr);
const exprs = z3.ast_from_string(modelStr);
console.log(exprs);
})().catch(e => {
console.error('error', e);
process.exit(1);
});

View file

@ -1,3 +1,4 @@
// @ts-ignore we're not going to bother with types for this
import process from 'process';
import { init, Z3_error_code } from '../../build/node';

View file

@ -4461,14 +4461,14 @@
"dev": true
},
"shiki": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz",
"integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==",
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz",
"integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==",
"dev": true,
"requires": {
"jsonc-parser": "^3.0.0",
"vscode-oniguruma": "^1.6.1",
"vscode-textmate": "5.2.0"
"vscode-textmate": "^6.0.0"
}
},
"side-channel": {
@ -4826,16 +4826,15 @@
"dev": true
},
"typedoc": {
"version": "0.22.18",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz",
"integrity": "sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA==",
"version": "0.23.16",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.16.tgz",
"integrity": "sha512-rumYsCeNRXlyuZVzefD7050n7ptL2uudsCJg50dY0v/stKniqIlRpvx/F/6expC0/Q6Dbab+g/JpZuB7Sw90FA==",
"dev": true,
"requires": {
"glob": "^8.0.3",
"lunr": "^2.3.9",
"marked": "^4.0.16",
"marked": "^4.0.19",
"minimatch": "^5.1.0",
"shiki": "^0.10.1"
"shiki": "^0.11.1"
},
"dependencies": {
"brace-expansion": {
@ -4847,19 +4846,6 @@
"balanced-match": "^1.0.0"
}
},
"glob": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
"integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
}
},
"minimatch": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
@ -4872,9 +4858,9 @@
}
},
"typescript": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
"integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true
},
"typical": {
@ -4945,9 +4931,9 @@
"dev": true
},
"vscode-textmate": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz",
"integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==",
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz",
"integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==",
"dev": true
},
"walker": {

View file

@ -1,5 +1,6 @@
{
"name": "z3-solver",
"version": "0.1.0",
"keywords": [
"Z3",
"theorem",
@ -26,8 +27,8 @@
"build:ts:generate": "ts-node --transpileOnly scripts/make-ts-wrapper.ts src/low-level/wrapper.__GENERATED__.ts src/low-level/types.__GENERATED__.ts",
"build:wasm": "ts-node --transpileOnly ./scripts/build-wasm.ts",
"clean": "rimraf build 'src/**/*.__GENERATED__.*'",
"lint": "prettier -c '{,src/,scripts/,examples}*.{js,ts}'",
"format": "prettier --write '{,src/,scripts/}*.{js,ts}'",
"lint": "prettier -c '{./,src/,scripts/,examples/}**/*.{js,ts}'",
"format": "prettier --write '{./,src/,scripts/}**/*.{js,ts}'",
"test": "jest",
"docs": "typedoc",
"check-engine": "check-engine"
@ -53,8 +54,8 @@
"ts-expect": "^1.3.0",
"ts-jest": "^28.0.3",
"ts-node": "^10.8.0",
"typedoc": "^0.22.17",
"typescript": "^4.5.4"
"typedoc": "^0.23.16",
"typescript": "^4.8.4"
},
"license": "MIT",
"dependencies": {

View file

@ -40,7 +40,7 @@ function spawnSync(command: string, opts: SpawnOptions = {}) {
}
function exportedFuncs(): string[] {
const extras = ['_set_throwy_error_handler', '_set_noop_error_handler', ...asyncFuncs.map(f => '_async_' + f)];
const extras = ['_malloc', '_set_throwy_error_handler', '_set_noop_error_handler', ...asyncFuncs.map(f => '_async_' + f)];
// TODO(ritave): This variable is unused in original script, find out if it's important
const fns: any[] = (functions as any[]).filter(f => !asyncFuncs.includes(f.name));

View file

@ -76,6 +76,7 @@ function makeTsWrapper() {
}
const isInParam = (p: FuncParam) => p.kind !== undefined && ['in', 'in_array'].includes(p.kind);
function wrapFunction(fn: Func) {
if (CUSTOM_IMPLEMENTATIONS.includes(fn.name)) {
return null;
@ -104,7 +105,7 @@ function makeTsWrapper() {
let isAsync = asyncFuncs.includes(fn.name);
let trivial =
!['string', 'boolean'].includes(fn.ret) &&
!['string', 'boolean', 'unsigned'].includes(fn.ret) &&
!fn.nullableRet &&
outParams.length === 0 &&
!inParams.some(p => p.type === 'string' || p.isArray || p.nullable);
@ -234,6 +235,7 @@ function makeTsWrapper() {
function setArg() {
args[outParam.idx] = memIdx === 0 ? 'outAddress' : `outAddress + ${memIdx * 4}`;
}
let read, type;
if (outParam.type === 'string') {
read = `Mod.UTF8ToString(getOutUint(${memIdx}))`;
@ -330,11 +332,15 @@ function makeTsWrapper() {
if (ret === 0) {
return null;
}
`.trim();
`.trim();
} else if (fn.ret === 'unsigned') {
infix += `
ret = (new Uint32Array([ret]))[0];
`.trim();
}
// prettier-ignore
let invocation = `Mod.ccall('${isAsync ? 'async_' : ''}${fn.name}', '${cReturnType}', ${JSON.stringify(ctypes)}, [${args.map(toEm).join(', ')}])`;
let invocation = `Mod.ccall('${isAsync ? "async_" : ""}${fn.name}', '${cReturnType}', ${JSON.stringify(ctypes)}, [${args.map(toEm).join(", ")}])`;
if (isAsync) {
invocation = `await Mod.async_call(() => ${invocation})`;

View file

@ -45,7 +45,7 @@ const types = {
__proto__: null,
// these are function types I can't be bothered to parse
// NSB: They can be extracted automatically from z3_api.h thanks to the use
// NSB: They can be extracted automatically from z3_api.h thanks to the use
// of a macro.
Z3_error_handler: 'Z3_error_handler',
Z3_push_eh: 'Z3_push_eh',

View file

@ -1,8 +1,8 @@
import assert from 'assert';
import asyncToArray from 'iter-tools/methods/async-to-array';
import { init, killThreads } from '../jest';
import { Arith, Bool, Model, Z3AssertionError, Z3HighLevel } from './types';
import { expectType } from "ts-expect";
import { Arith, Bool, Model, Quantifier, Z3AssertionError, Z3HighLevel, AstVector } from './types';
import { expectType } from 'ts-expect';
/**
* Generate all possible solutions from given assumptions.
@ -58,6 +58,7 @@ async function* allSolutions<Name extends string>(...assertions: Bool<Name>[]):
async function prove(conjecture: Bool): Promise<void> {
const solver = new conjecture.ctx.Solver();
solver.set('timeout', 1000);
const { Not } = solver.ctx;
solver.add(Not(conjecture));
expect(await solver.check()).toStrictEqual('unsat');
@ -113,11 +114,11 @@ describe('high-level', () => {
it('test loading a solver state from a string', async () => {
const { Solver, Not, Int } = api.Context('main');
const solver = new Solver();
solver.fromString("(declare-const x Int) (assert (and (< x 2) (> x 0)))")
expect(await solver.check()).toStrictEqual('sat')
const x = Int.const('x')
solver.add(Not(x.eq(1)))
expect(await solver.check()).toStrictEqual('unsat')
solver.fromString('(declare-const x Int) (assert (and (< x 2) (> x 0)))');
expect(await solver.check()).toStrictEqual('sat');
const x = Int.const('x');
solver.add(Not(x.eq(1)));
expect(await solver.check()).toStrictEqual('unsat');
});
it('disproves x = y implies g(g(x)) = g(y)', async () => {
@ -393,14 +394,13 @@ describe('high-level', () => {
});
describe('arrays', () => {
it('Example 1', async () => {
const Z3 = api.Context('main');
const arr = Z3.Array.const('arr', Z3.Int.sort(), Z3.Int.sort());
const [idx, val] = Z3.Int.consts('idx val');
const conjecture = (arr.store(idx, val).select(idx).eq(val));
const conjecture = arr.store(idx, val).select(idx).eq(val);
await prove(conjecture);
});
@ -428,7 +428,7 @@ describe('high-level', () => {
// and is detected at compile time
// @ts-expect-error
const arr3 = Array.const('arr3', BitVec.sort(1));
})
});
it('can do simple proofs', async () => {
const { BitVec, Array, isArray, isArraySort, isConstArray, Eq, Not } = api.Context('main');
@ -447,13 +447,6 @@ describe('high-level', () => {
await prove(Eq(arr2.select(0), FIVE_VAL));
await prove(Not(Eq(arr2.select(0), BitVec.val(6, 256))));
await prove(Eq(arr2.store(idx, val).select(idx), constArr.store(idx, val).select(idx)));
// TODO: add in Quantifiers and better typing of arrays
// await prove(
// ForAll([idx], idx.add(1).ugt(idx).and(arr.select(idx.add(1)).ugt(arr.select(idx)))).implies(
// arr.select(0).ult(arr.select(1000))
// )
// );
});
it('Finds arrays that differ but that sum to the same', async () => {
@ -465,18 +458,16 @@ describe('high-level', () => {
const arr1 = Array.const('arr', BitVec.sort(2), BitVec.sort(32));
const arr2 = Array.const('arr2', BitVec.sort(2), BitVec.sort(32));
const same_sum = arr1.select(0)
const same_sum = arr1
.select(0)
.add(arr1.select(1))
.add(arr1.select(2))
.add(arr1.select(3))
.eq(
arr2.select(0)
.add(arr2.select(1))
.add(arr2.select(2))
.add(arr2.select(3))
);
.eq(arr2.select(0).add(arr2.select(1)).add(arr2.select(2)).add(arr2.select(3)));
const different = arr1.select(0).neq(arr2.select(0))
const different = arr1
.select(0)
.neq(arr2.select(0))
.or(arr1.select(1).neq(arr2.select(1)))
.or(arr1.select(2).neq(arr2.select(2)))
.or(arr1.select(3).neq(arr2.select(3)));
@ -485,11 +476,105 @@ describe('high-level', () => {
const arr1Vals = [0, 1, 2, 3].map(i => model.eval(arr1.select(i)).value());
const arr2Vals = [0, 1, 2, 3].map(i => model.eval(arr2.select(i)).value());
expect((arr1Vals.reduce((a, b) => a + b, 0n) % mod) === arr2Vals.reduce((a, b) => a + b, 0n) % mod);
expect(arr1Vals.reduce((a, b) => a + b, 0n) % mod === arr2Vals.reduce((a, b) => a + b, 0n) % mod);
for (let i = 0; i < 4; i++) {
expect(arr1Vals[i] !== arr2Vals[i]);
}
});
it('Array type inference', async () => {
const z3 = api.Context('main');
const Z3_ADDR = z3.BitVec.const('Vault_addr', 160);
const Z3_GLOBAL_STORAGE = z3.Array.const(
'global_storage',
z3.BitVec.sort(160),
z3.Array.sort(z3.BitVec.sort(160), z3.BitVec.sort(256)),
);
const Z3_STORAGE = Z3_GLOBAL_STORAGE.select(Z3_ADDR);
// We are so far unable to properly infer the type of Z3_STORAGE
// expectType<
// SMTArray<'main', [BitVecSort<160>], BitVecSort<256>>
// >(Z3_STORAGE);
});
});
describe('quantifiers', () => {
it('Basic Universal', async () => {
const Z3 = api.Context('main');
const [x, y] = Z3.Int.consts('x y');
const conjecture = Z3.ForAll([x, y], x.neq(y).implies(x.lt(y).or(x.gt(y))));
expect(Z3.isBool(conjecture)).toBeTruthy();
expect(conjecture.var_name(0)).toBe('x');
expect(conjecture.var_sort(0).eqIdentity(Z3.Int.sort())).toBeTruthy();
expect(conjecture.var_name(1)).toBe('y');
expect(conjecture.var_sort(1).eqIdentity(Z3.Int.sort())).toBeTruthy();
await prove(conjecture);
});
it('Basic Existential', async () => {
const Z3 = api.Context('main');
const [x, y, z] = Z3.Int.consts('x y z');
const quantifier = Z3.Exists([z], Z3.Not(z.lt(x)).and(Z3.Not(z.gt(y))));
expect(Z3.isBool(quantifier)).toBeTruthy();
expect(quantifier.var_name(0)).toBe('z');
expect(quantifier.var_sort(0).eqIdentity(Z3.Int.sort())).toBeTruthy();
const conjecture = Z3.Not(x.gt(y)).implies(quantifier); // Can be trivially discovered with z = x or x = y
await prove(conjecture);
});
it('Basic Lambda', async () => {
const Z3 = api.Context('main');
const [x, y] = Z3.Int.consts('x y z');
const L = Z3.Lambda([x, y], x.add(y));
expect(Z3.isArraySort(L.sort)).toBeTruthy();
expect(Z3.isArray(L)).toBeFalsy();
expect(L.var_name(0)).toBe('x');
expect(L.var_sort(0).eqIdentity(Z3.Int.sort())).toBeTruthy();
expect(L.var_name(1)).toBe('y');
expect(L.var_sort(1).eqIdentity(Z3.Int.sort())).toBeTruthy();
const conjecture = L.select(Z3.Int.val(2), Z3.Int.val(5)).eq(Z3.Int.val(7));
await prove(conjecture);
});
it('Loading Quantifier Preserves Type', async () => {
const Z3 = api.Context('main');
const [x, y, z] = Z3.Int.consts('x y z');
const quantifier = Z3.Exists([z], Z3.Not(z.lt(x)).and(Z3.Not(z.gt(y))));
expect(Z3.isBool(quantifier)).toBeTruthy();
const solver = new Z3.Solver();
solver.add(quantifier);
const dumped_str = solver.toString();
const solver2 = new Z3.Solver();
solver2.fromString(dumped_str);
const quantifier2 = solver2.assertions().get(0) as unknown as Quantifier;
expect(Z3.isBool(quantifier2)).toBeTruthy();
expect(quantifier2.var_name(0)).toBe('z');
});
});
describe('uninterpreted functions', () => {
it('Type Inference', async () => {
const Z3 = api.Context('main');
const f = Z3.Function.declare('f', Z3.Int.sort(), Z3.Bool.sort());
const input = Z3.Int.val(6);
const output = f.call(input);
expectType<Bool>(output);
expect(output.sort.eqIdentity(Z3.Bool.sort())).toBeTruthy();
});
});
describe('Solver', () => {
@ -543,10 +628,11 @@ describe('high-level', () => {
describe('AstVector', () => {
it('can use basic methods', async () => {
const { Solver, AstVector, Int } = api.Context('main');
const Z3 = api.Context('main');
const { Solver, Int } = Z3;
const solver = new Solver();
const vector = new AstVector<Arith>();
const vector = new Z3.AstVector<Arith>();
for (let i = 0; i < 5; i++) {
vector.push(Int.const(`int__${i}`));
}
@ -559,4 +645,104 @@ describe('high-level', () => {
expect(await solver.check()).toStrictEqual('sat');
});
});
describe('Substitution', () => {
it('basic variable substitution', async () => {
const { Int, substitute } = api.Context('main');
const x = Int.const('x');
const y = Int.const('y');
const z = Int.const('z');
const expr = x.add(y);
const subst = substitute(expr, [x, z]);
expect(subst.eqIdentity(z.add(y))).toBeTruthy();
});
it('term substitution', async () => {
const { Int, substitute } = api.Context('main');
const x = Int.const('x');
const y = Int.const('y');
const z = Int.const('z');
const expr = x.add(y).mul(Int.val(1).sub(x.add(y)));
const subst = substitute(expr, [x.add(y), z]);
expect(subst.eqIdentity(z.mul(Int.val(1).sub(z)))).toBeTruthy();
});
});
describe('Model', () => {
it('Assigning constants', async () => {
const { Int, Model } = api.Context('main');
const m = new Model();
const [x, y] = Int.consts('x y');
m.updateValue(x, Int.val(6));
m.updateValue(y, Int.val(12));
expect(m.eval(x.add(y)).eqIdentity(Int.val(18))).toBeTruthy();
});
it('Creating Func Interpretations', async () => {
const { Int, Function, Model } = api.Context('main');
const m = new Model();
const f = Function.declare('f', Int.sort(), Int.sort(), Int.sort());
const f_interp = m.addFuncInterp(f, 0);
f_interp.addEntry([Int.val(1), Int.val(2)], Int.val(3));
f_interp.addEntry([Int.val(4), Int.val(5)], Int.val(6));
expect(m.eval(f.call(1, 2)).eqIdentity(Int.val(3))).toBeTruthy();
expect(m.eval(f.call(4, 5)).eqIdentity(Int.val(6))).toBeTruthy();
expect(m.eval(f.call(0, 0)).eqIdentity(Int.val(0))).toBeTruthy();
});
});
describe('optimize', () => {
it("maximization problem over reals", async () => {
const { Real, Optimize } = api.Context('main');
const opt = new Optimize();
const x = Real.const('x');
const y = Real.const('y');
const z = Real.const('z');
opt.add(x.ge(0), y.ge(0), z.ge(0));
opt.add(x.le(1), y.le(1), z.le(1));
opt.maximize(x.mul(7).add(y.mul(9)).sub(z.mul(3)))
const result = await opt.check()
expect(result).toStrictEqual('sat');
const model = opt.model();
expect(model.eval(x).eqIdentity(Real.val(1))).toBeTruthy();
expect(model.eval(y).eqIdentity(Real.val(1))).toBeTruthy();
expect(model.eval(z).eqIdentity(Real.val(0))).toBeTruthy();
});
it("minimization problem over integers using addSoft", async () => {
const { Int, Optimize } = api.Context('main');
const opt = new Optimize();
const x = Int.const('x');
const y = Int.const('y');
const z = Int.const('z');
opt.add(x.ge(0), y.ge(0));
opt.add(x.le(1), y.le(1));
opt.addSoft(x.eq(1), 2);
opt.addSoft(y.eq(1), 1);
opt.add(z.eq(x.mul(5).add(y.mul(5))));
opt.add(z.le(5));
opt.minimize(z);
const result = await opt.check()
expect(result).toStrictEqual('sat');
const model = opt.model();
expect(model.eval(x).eqIdentity(Int.val(1))).toBeTruthy();
expect(model.eval(y).eqIdentity(Int.val(0))).toBeTruthy();
expect(model.eval(z).eqIdentity(Int.val(5))).toBeTruthy();
});
});
});

File diff suppressed because it is too large Load diff

View file

@ -5,13 +5,14 @@ import {
Z3_context,
Z3_decl_kind,
Z3_func_decl,
Z3_func_entry,
Z3_func_interp,
Z3_model,
Z3_probe,
Z3_solver,
Z3_optimize,
Z3_sort,
Z3_sort_kind,
Z3_symbol,
Z3_tactic,
} from '../low-level';
@ -21,7 +22,7 @@ export type AnySort<Name extends string = 'main'> =
| BoolSort<Name>
| ArithSort<Name>
| BitVecSort<number, Name>
| SMTArraySort<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
| SMTArraySort<Name>;
/** @hidden */
export type AnyExpr<Name extends string = 'main'> =
| Expr<Name>
@ -31,53 +32,64 @@ export type AnyExpr<Name extends string = 'main'> =
| RatNum<Name>
| BitVec<number, Name>
| BitVecNum<number, Name>
| SMTArray<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
| SMTArray<Name>;
/** @hidden */
export type AnyAst<Name extends string = 'main'> = AnyExpr<Name> | AnySort<Name> | FuncDecl<Name>;
/** @hidden */
export type SortToExprMap<S extends AnySort<Name>, Name extends string = 'main'> =
S extends BoolSort
? Bool<Name>
: S extends ArithSort<Name>
? Arith<Name>
: S extends BitVecSort<infer Size, Name>
? BitVec<Size, Name>
: S extends SMTArraySort<Name, infer DomainSort, infer RangeSort>
? SMTArray<Name, DomainSort, RangeSort>
: S extends Sort<Name>
? Expr<Name, S, Z3_ast>
: never;
export type SortToExprMap<S extends AnySort<Name>, Name extends string = 'main'> = S extends BoolSort
? Bool<Name>
: S extends ArithSort<Name>
? Arith<Name>
: S extends BitVecSort<infer Size, Name>
? BitVec<Size, Name>
: S extends SMTArraySort<Name, infer DomainSort, infer RangeSort>
? SMTArray<Name, DomainSort, RangeSort>
: S extends Sort<Name>
? Expr<Name, S, Z3_ast>
: never;
/** @hidden */
export type CoercibleToExprMap<S extends CoercibleToExpr<Name>, Name extends string = 'main'> =
S extends bigint
? ArithSort<Name>
: S extends number | CoercibleRational
? RatNum<Name>
: S extends boolean
? Bool<Name>
: S extends Expr<Name>
? S
: never;
export type CoercibleFromMap<S extends CoercibleToExpr<Name>, Name extends string = 'main'> = S extends bigint
? Arith<Name>
: S extends number | CoercibleRational
? RatNum<Name>
: S extends boolean
? Bool<Name>
: S extends Expr<Name>
? S
: never;
/** @hidden */
export type CoercibleFromMap<S extends AnyExpr<Name>, Name extends string = 'main'> =
S extends Bool<Name>
? (boolean | Bool<Name>)
: S extends IntNum<Name>
? (bigint | number | IntNum<Name>)
: S extends RatNum<Name>
? (bigint | number | CoercibleRational | RatNum<Name>)
: S extends Arith<Name>
? (bigint | number | CoercibleRational | Arith<Name>)
: S extends BitVec<infer Size, Name>
? (number | BitVec<Size, Name>)
: S extends SMTArray<Name, infer DomainSort, infer RangeSort>
? SMTArray<Name, DomainSort, RangeSort>
: S extends Expr<Name>
? Expr<Name>
: never;
export type CoercibleToBitVec<Bits extends number = number, Name extends string = 'main'> =
| bigint
| number
| BitVec<Bits, Name>;
export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number };
/** @hidden */
export type CoercibleToExpr<Name extends string = 'main'> = number | bigint | boolean | CoercibleRational | Expr<Name>;
/** @hidden */
export type CoercibleToArith<Name extends string = 'main'> = number | string | bigint | CoercibleRational | Arith<Name>;
/** @hidden */
export type CoercibleToMap<T extends AnyExpr<Name>, Name extends string = 'main'> = T extends Bool<Name>
? boolean | Bool<Name>
: T extends IntNum<Name>
? bigint | number | IntNum<Name>
: T extends RatNum<Name>
? bigint | number | CoercibleRational | RatNum<Name>
: T extends Arith<Name>
? CoercibleToArith<Name>
: T extends BitVec<infer Size, Name>
? CoercibleToBitVec<Size, Name>
: T extends SMTArray<Name, infer DomainSort, infer RangeSort>
? SMTArray<Name, DomainSort, RangeSort>
: T extends Expr<Name>
? Expr<Name>
: never;
/**
* Used to create a Real constant
@ -97,16 +109,10 @@ export type CoercibleFromMap<S extends AnyExpr<Name>, Name extends string = 'mai
* @see {@link Context.from}
* @category Global
*/
export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number };
/** @hidden */
export type CoercibleToExpr<Name extends string = 'main'> = number | bigint | boolean | CoercibleRational | Expr<Name>;
export class Z3Error extends Error {}
export class Z3Error extends Error {
}
export class Z3AssertionError extends Z3Error {
}
export class Z3AssertionError extends Z3Error {}
/** @category Global */
export type CheckSatResult = 'sat' | 'unsat' | 'unknown';
@ -149,6 +155,9 @@ export interface Context<Name extends string = 'main'> {
/** @category Functions */
isFuncDecl(obj: unknown): obj is FuncDecl<Name>;
/** @category Functions */
isFuncInterp(obj: unknown): obj is FuncInterp<Name>;
/** @category Functions */
isApp(obj: unknown): boolean;
@ -191,6 +200,9 @@ export interface Context<Name extends string = 'main'> {
/** @category Functions */
isDistinct(obj: unknown): boolean;
/** @category Functions */
isQuantifier(obj: unknown): obj is Quantifier<Name>;
/** @category Functions */
isArith(obj: unknown): obj is Arith<Name>;
@ -225,10 +237,10 @@ export interface Context<Name extends string = 'main'> {
isBitVecVal(obj: unknown): obj is BitVecNum<number, Name>;
/** @category Functions */
isArraySort(obj: unknown): obj is SMTArraySort<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
isArraySort(obj: unknown): obj is SMTArraySort<Name>;
/** @category Functions */
isArray(obj: unknown): obj is SMTArray<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
isArray(obj: unknown): obj is SMTArray<Name>;
/** @category Functions */
isConstArray(obj: unknown): boolean;
@ -306,6 +318,9 @@ export interface Context<Name extends string = 'main'> {
* @category Classes
*/
readonly Solver: new (logic?: string) => Solver<Name>;
readonly Optimize: new () => Optimize<Name>;
/**
* Creates an empty Model
* @see {@link Solver.model} for common usage of Model
@ -315,7 +330,11 @@ export interface Context<Name extends string = 'main'> {
/** @category Classes */
readonly AstVector: new <Item extends Ast<Name> = AnyAst<Name>>() => AstVector<Name, Item>;
/** @category Classes */
readonly AstMap: new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>() => AstMap<Name, Key, Value>;
readonly AstMap: new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>() => AstMap<
Name,
Key,
Value
>;
/** @category Classes */
readonly Tactic: new (name: string) => Tactic<Name>;
@ -363,7 +382,7 @@ export interface Context<Name extends string = 'main'> {
condition: Bool<Name> | boolean,
onTrue: OnTrueRef,
onFalse: OnFalseRef,
): CoercibleToExprMap<OnTrueRef | OnFalseRef, Name>;
): CoercibleFromMap<OnTrueRef | OnFalseRef, Name>;
/** @category Operations */
Distinct(...args: CoercibleToExpr<Name>[]): Bool<Name>;
@ -371,6 +390,9 @@ export interface Context<Name extends string = 'main'> {
/** @category Operations */
Implies(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>;
/** @category Operations */
Iff(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>;
/** @category Operations */
Eq(a: CoercibleToExpr<Name>, b: CoercibleToExpr<Name>): Bool<Name>;
@ -407,6 +429,28 @@ export interface Context<Name extends string = 'main'> {
/** @category Operations */
Or(...args: Probe<Name>[]): Probe<Name>;
// Quantifiers
/** @category Operations */
ForAll<QVarSorts extends NonEmptySortArray<Name>>(
quantifiers: ArrayIndexType<Name, QVarSorts>,
body: Bool<Name>,
weight?: number,
): Quantifier<Name, QVarSorts, BoolSort<Name>> & Bool<Name>;
/** @category Operations */
Exists<QVarSorts extends NonEmptySortArray<Name>>(
quantifiers: ArrayIndexType<Name, QVarSorts>,
body: Bool<Name>,
weight?: number,
): Quantifier<Name, QVarSorts, BoolSort<Name>> & Bool<Name>;
/** @category Operations */
Lambda<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
quantifiers: ArrayIndexType<Name, DomainSort>,
expr: SortToExprMap<RangeSort, Name>,
): Quantifier<Name, DomainSort, SMTArraySort<Name, DomainSort, RangeSort>> & SMTArray<Name, DomainSort, RangeSort>;
// Arithmetic
/** @category Operations */
ToReal(expr: Arith<Name> | bigint): Arith<Name>;
@ -437,7 +481,7 @@ export interface Context<Name extends string = 'main'> {
* // a**(1/2)
* ```
* @category Operations */
Sqrt(a: Arith<Name> | number | bigint | string | CoercibleRational): Arith<Name>;
Sqrt(a: CoercibleToArith<Name>): Arith<Name>;
/**
* Returns a Z3 expression representing cubic root of a
@ -449,7 +493,7 @@ export interface Context<Name extends string = 'main'> {
* // a**(1/3)
* ```
* @category Operations */
Cbrt(a: Arith<Name> | number | bigint | string | CoercibleRational): Arith<Name>;
Cbrt(a: CoercibleToArith<Name>): Arith<Name>;
// Bit Vectors
/** @category Operations */
@ -462,7 +506,102 @@ export interface Context<Name extends string = 'main'> {
Concat(...bitvecs: BitVec<number, Name>[]): BitVec<number, Name>;
/** @category Operations */
Cond(probe: Probe<Name>, onTrue: Tactic<Name>, onFalse: Tactic<Name>): Tactic<Name>
Cond(probe: Probe<Name>, onTrue: Tactic<Name>, onFalse: Tactic<Name>): Tactic<Name>;
// Arith
/** @category Operations */
LT(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
/** @category Operations */
GT(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
/** @category Operations */
LE(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
/** @category Operations */
GE(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
// Bit Vectors
/** @category Operations */
ULT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
UGT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
ULE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
UGE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
SLT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
SGT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
SGE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
SLE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
/** @category Operations */
Sum(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>;
Sum<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>;
Sub(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>;
Sub<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>;
Product(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>;
Product<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>;
Div(arg0: Arith<Name>, arg1: CoercibleToArith<Name>): Arith<Name>;
Div<Bits extends number>(arg0: BitVec<Bits, Name>, arg1: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>;
BUDiv<Bits extends number>(arg0: BitVec<Bits, Name>, arg1: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>;
Neg(a: Arith<Name>): Arith<Name>;
Neg<Bits extends number>(a: BitVec<Bits, Name>): BitVec<Bits, Name>;
Mod(a: Arith<Name>, b: CoercibleToArith<Name>): Arith<Name>;
Mod<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>;
// Arrays
/** @category Operations */
Select<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(
array: SMTArray<Name, DomainSort, RangeSort>,
...indices: CoercibleToArrayIndexType<Name, DomainSort>
): SortToExprMap<RangeSort, Name>;
/** @category Operations */
Store<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(
array: SMTArray<Name, DomainSort, RangeSort>,
...indicesAndValue: [
...CoercibleToArrayIndexType<Name, DomainSort>,
CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>,
]
): SMTArray<Name, DomainSort, RangeSort>;
/** @category Operations */
Extract<Bits extends number>(hi: number, lo: number, val: BitVec<Bits, Name>): BitVec<number, Name>;
/** @category Operations */
ast_from_string(s: string): Ast<Name>;
/** @category Operations */
substitute(t: Expr<Name>, ...substitutions: [Expr<Name>, Expr<Name>][]): Expr<Name>;
simplify(expr: Expr<Name>): Promise<Expr<Name>>;
}
export interface Ast<Name extends string = 'main', Ptr = unknown> {
@ -490,7 +629,7 @@ export interface Ast<Name extends string = 'main', Ptr = unknown> {
/** @hidden */
export interface SolverCtor<Name extends string> {
new(): Solver<Name>;
new (): Solver<Name>;
}
export interface Solver<Name extends string = 'main'> {
@ -500,10 +639,11 @@ export interface Solver<Name extends string = 'main'> {
readonly ctx: Context<Name>;
readonly ptr: Z3_solver;
/* TODO(ritave): Decide on how to discern between integer and float parameters
set(key: string, value: any): void;
set(params: Record<string, any>): void;
*/
/* TODO(ritave): Decide on how to discern between integer and float parameters
set(params: Record<string, any>): void;
*/
push(): void;
pop(num?: number): void;
@ -525,9 +665,42 @@ export interface Solver<Name extends string = 'main'> {
model(): Model<Name>;
}
export interface Optimize<Name extends string = 'main'> {
/** @hidden */
readonly __typename: 'Optimize';
readonly ctx: Context<Name>;
readonly ptr: Z3_optimize;
set(key: string, value: any): void;
push(): void;
pop(num?: number): void;
add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): void;
addSoft(expr: Bool<Name>, weight: number | bigint | string | CoercibleRational, id?: number | string): void;
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string): void;
assertions(): AstVector<Name, Bool<Name>>;
fromString(s: string): void;
maximize(expr: Arith<Name>): void;
minimize(expr: Arith<Name>): void;
check(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): Promise<CheckSatResult>;
model(): Model<Name>;
}
/** @hidden */
export interface ModelCtor<Name extends string> {
new(): Model<Name>;
new (): Model<Name>;
}
export interface Model<Name extends string = 'main'> extends Iterable<FuncDecl<Name>> {
@ -566,6 +739,13 @@ export interface Model<Name extends string = 'main'> extends Iterable<FuncDecl<N
get(constant: Expr<Name>): Expr<Name>;
get(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>;
updateValue(decl: FuncDecl<Name> | Expr<Name>, a: Ast<Name> | FuncInterp<Name>): void;
addFuncInterp<DomainSort extends Sort<Name>[] = Sort<Name>[], RangeSort extends Sort<Name> = Sort<Name>>(
decl: FuncDecl<Name, DomainSort, RangeSort>,
defaultValue: CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>,
): FuncInterp<Name>;
}
/**
@ -608,6 +788,23 @@ export interface Sort<Name extends string = 'main'> extends Ast<Name, Z3_sort> {
name(): string | number;
}
/**
* @category Functions
*/
export interface FuncEntry<Name extends string = 'main'> {
/** @hidden */
readonly __typename: 'FuncEntry';
readonly ctx: Context<Name>;
readonly ptr: Z3_func_entry;
numArgs(): number;
argValue(i: number): Expr<Name>;
value(): Expr<Name>;
}
/**
* @category Functions
*/
@ -617,6 +814,16 @@ export interface FuncInterp<Name extends string = 'main'> {
readonly ctx: Context<Name>;
readonly ptr: Z3_func_interp;
elseValue(): Expr<Name>;
numEntries(): number;
arity(): number;
entry(i: number): FuncEntry<Name>;
addEntry(args: Expr<Name>[], value: Expr<Name>): void;
}
/** @hidden */
@ -639,9 +846,14 @@ export interface FuncDeclCreation<Name extends string> {
* @param name Name of the function
* @param signature The domains, and last parameter - the range of the function
*/
declare(name: string, ...signature: FuncDeclSignature<Name>): FuncDecl<Name>;
declare<DomainSort extends Sort<Name>[], RangeSort extends Sort<Name>>(
name: string,
...signature: [...DomainSort, RangeSort]
): FuncDecl<Name, DomainSort, RangeSort>;
fresh(...signature: FuncDeclSignature<Name>): FuncDecl<Name>;
fresh<DomainSort extends Sort<Name>[], RangeSort extends Sort<Name>>(
...signature: [...DomainSort, RangeSort]
): FuncDecl<Name, DomainSort, RangeSort>;
}
/**
@ -656,7 +868,11 @@ export interface RecFuncCreation<Name extends string> {
/**
* @category Functions
*/
export interface FuncDecl<Name extends string = 'main'> extends Ast<Name, Z3_func_decl> {
export interface FuncDecl<
Name extends string = 'main',
DomainSort extends Sort<Name>[] = Sort<Name>[],
RangeSort extends Sort<Name> = Sort<Name>,
> extends Ast<Name, Z3_func_decl> {
/** @hidden */
readonly __typename: 'FuncDecl';
@ -664,21 +880,26 @@ export interface FuncDecl<Name extends string = 'main'> extends Ast<Name, Z3_fun
arity(): number;
domain(i: number): Sort<Name>;
domain<T extends number>(i: T): DomainSort[T];
range(): Sort<Name>;
range(): RangeSort;
kind(): Z3_decl_kind;
params(): (number | string | Z3_symbol | Sort<Name> | Expr<Name> | FuncDecl<Name>)[];
params(): (number | string | Sort<Name> | Expr<Name> | FuncDecl<Name>)[];
call(...args: CoercibleToExpr<Name>[]): AnyExpr<Name>;
call(...args: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
}
export interface Expr<Name extends string = 'main', S extends Sort<Name> = AnySort<Name>, Ptr = unknown>
extends Ast<Name, Ptr> {
/** @hidden */
readonly __typename: 'Expr' | Bool['__typename'] | Arith['__typename'] | BitVec['__typename'] | SMTArray['__typename'];
readonly __typename:
| 'Expr'
| Bool['__typename']
| Arith['__typename']
| BitVec['__typename']
| SMTArray['__typename'];
get sort(): S;
@ -688,6 +909,8 @@ export interface Expr<Name extends string = 'main', S extends Sort<Name> = AnySo
params(): ReturnType<FuncDecl<Name>['params']>;
name(): ReturnType<FuncDecl<Name>['name']>;
decl(): FuncDecl<Name>;
numArgs(): number;
@ -725,7 +948,7 @@ export interface BoolCreation<Name extends string = 'main'> {
/** @category Booleans */
export interface Bool<Name extends string = 'main'> extends Expr<Name, BoolSort<Name>, Z3_ast> {
/** @hidden */
readonly __typename: 'Bool';
readonly __typename: 'Bool' | 'NonLambdaQuantifier';
not(): Bool<Name>;
@ -738,6 +961,13 @@ export interface Bool<Name extends string = 'main'> extends Expr<Name, BoolSort<
implies(other: Bool<Name> | boolean): Bool<Name>;
}
// TODO: properly implement pattern
/** @category Quantifiers */
export interface Pattern<Name extends string = 'main'> {
/** @hidden */
readonly __typename: 'Pattern';
}
/**
* A Sort that represents Integers or Real numbers
* @category Arithmetic
@ -798,17 +1028,17 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
/**
* Adds two numbers together
*/
add(other: Arith<Name> | number | bigint | string): Arith<Name>;
add(other: CoercibleToArith<Name>): Arith<Name>;
/**
* Multiplies two numbers together
*/
mul(other: Arith<Name> | number | bigint | string): Arith<Name>;
mul(other: CoercibleToArith<Name>): Arith<Name>;
/**
* Subtract second number from the first one
*/
sub(other: Arith<Name> | number | bigint | string): Arith<Name>;
sub(other: CoercibleToArith<Name>): Arith<Name>;
/**
* Applies power to the number
@ -820,12 +1050,12 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
* // x=-2
* ```
*/
pow(exponent: Arith<Name> | number | bigint | string): Arith<Name>;
pow(exponent: CoercibleToArith<Name>): Arith<Name>;
/**
* Divides the number by the second one
*/
div(other: Arith<Name> | number | bigint | string): Arith<Name>;
div(other: CoercibleToArith<Name>): Arith<Name>;
/**
* Returns a number modulo second one
@ -837,7 +1067,7 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
* // x=8
* ```
*/
mod(other: Arith<Name> | number | bigint | string): Arith<Name>;
mod(other: CoercibleToArith<Name>): Arith<Name>;
/**
* Returns a negation of the number
@ -847,22 +1077,22 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
/**
* Return whether the number is less or equal than the second one (`<=`)
*/
le(other: Arith<Name> | number | bigint | string): Bool<Name>;
le(other: CoercibleToArith<Name>): Bool<Name>;
/**
* Returns whether the number is less than the second one (`<`)
*/
lt(other: Arith<Name> | number | bigint | string): Bool<Name>;
lt(other: CoercibleToArith<Name>): Bool<Name>;
/**
* Returns whether the number is greater than the second one (`>`)
*/
gt(other: Arith<Name> | number | bigint | string): Bool<Name>;
gt(other: CoercibleToArith<Name>): Bool<Name>;
/**
* Returns whether the number is greater or equal than the second one (`>=`)
*/
ge(other: Arith<Name> | number | bigint | string): Bool<Name>;
ge(other: CoercibleToArith<Name>): Bool<Name>;
}
/**
@ -939,12 +1169,6 @@ export interface BitVecSort<Bits extends number = number, Name extends string =
cast(other: CoercibleToExpr<Name>): Expr<Name>;
}
/** @hidden */
export type CoercibleToBitVec<Bits extends number = number, Name extends string = 'main'> =
| bigint
| number
| BitVec<Bits, Name>;
/** @category Bit Vectors */
export interface BitVecCreation<Name extends string> {
sort<Bits extends number = number>(bits: Bits): BitVecSort<Bits, Name>;
@ -1213,10 +1437,11 @@ export interface BitVecNum<Bits extends number = number, Name extends string = '
* @typeParam RangeSort The sort of the array range
* @category Arrays
*/
export interface SMTArraySort<Name extends string = 'main',
DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
export interface SMTArraySort<
Name extends string = 'main',
DomainSort extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
RangeSort extends AnySort<Name> = AnySort<Name>,
> extends Sort<Name> {
> extends Sort<Name> {
/** @hidden */
readonly __typename: 'ArraySort';
@ -1236,36 +1461,47 @@ export interface SMTArraySort<Name extends string = 'main',
* The sort of the range
*/
range(): RangeSort;
}
/** @category Arrays */
export interface SMTArrayCreation<Name extends string> {
sort<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
sort<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
...sig: [...DomainSort, RangeSort]
): SMTArraySort<Name, DomainSort, RangeSort>;
const<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
name: string, ...sig: [...DomainSort, RangeSort]
const<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
name: string,
...sig: [...DomainSort, RangeSort]
): SMTArray<Name, DomainSort, RangeSort>;
consts<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
consts<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
names: string | string[],
...sig: [...DomainSort, RangeSort]
): SMTArray<Name, DomainSort, RangeSort>[];
K<DomainSort extends AnySort<Name>, RangeSort extends AnySort<Name>>(
domain: DomainSort,
value: SortToExprMap<RangeSort, Name>
value: SortToExprMap<RangeSort, Name>,
): SMTArray<Name, [DomainSort], RangeSort>;
}
export type ArrayIndexType<Name extends string = 'main',
DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]]> = [...{
[Index in keyof DomainSort]: DomainSort[Index] extends AnySort<Name> ?
CoercibleFromMap<SortToExprMap<DomainSort[Index], Name>, Name> :
DomainSort[Index];
}]
export type NonEmptySortArray<Name extends string = 'main'> = [Sort<Name>, ...Array<Sort<Name>>];
export type ArrayIndexType<Name extends string, DomainSort extends Sort<Name>[]> = [
...{
[Key in keyof DomainSort]: DomainSort[Key] extends AnySort<Name>
? SortToExprMap<DomainSort[Key], Name>
: DomainSort[Key];
},
];
export type CoercibleToArrayIndexType<Name extends string, DomainSort extends Sort<Name>[]> = [
...{
[Key in keyof DomainSort]: DomainSort[Key] extends AnySort<Name>
? CoercibleToMap<SortToExprMap<DomainSort[Key], Name>, Name>
: DomainSort[Key];
},
];
/**
* Represents Array expression
@ -1274,13 +1510,13 @@ export type ArrayIndexType<Name extends string = 'main',
* @typeParam RangeSort The sort of the array range
* @category Arrays
*/
export interface SMTArray<Name extends string = 'main',
DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
RangeSort extends AnySort<Name> = AnySort<Name>>
extends Expr<Name, SMTArraySort<Name, DomainSort, RangeSort>, Z3_ast> {
export interface SMTArray<
Name extends string = 'main',
DomainSort extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
RangeSort extends Sort<Name> = Sort<Name>,
> extends Expr<Name, SMTArraySort<Name, DomainSort, RangeSort>, Z3_ast> {
/** @hidden */
readonly __typename: 'Array';
readonly __typename: 'Array' | 'Lambda';
domain(): DomainSort[0];
@ -1288,7 +1524,7 @@ export interface SMTArray<Name extends string = 'main',
range(): RangeSort;
select(...indices: ArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
select(...indices: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
/**
* value should be coercible to RangeSort
@ -1297,11 +1533,60 @@ export interface SMTArray<Name extends string = 'main',
*/
store(
...indicesAndValue: [
...ArrayIndexType<Name, DomainSort>,
CoercibleFromMap<SortToExprMap<RangeSort, Name>, Name>
...CoercibleToArrayIndexType<Name, DomainSort>,
CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>,
]
): SMTArray<Name, DomainSort, RangeSort>;
}
/**
* Defines the expression type of the body of a quantifier expression
*
* @category Quantifiers
*/
export type BodyT<
Name extends string = 'main',
QVarSorts extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts> = BoolSort<Name> | SMTArraySort<Name, QVarSorts>,
> = QSort extends BoolSort<Name>
? Bool<Name>
: QSort extends SMTArray<Name, QVarSorts, infer RangeSort>
? SortToExprMap<RangeSort, Name>
: never;
/** @category Quantifiers */
export interface Quantifier<
Name extends string = 'main',
QVarSorts extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts> = BoolSort<Name> | SMTArraySort<Name, QVarSorts>,
> extends Expr<Name, QSort> {
readonly __typename: 'NonLambdaQuantifier' | 'Lambda';
is_forall(): boolean;
is_exists(): boolean;
is_lambda(): boolean;
weight(): number;
num_patterns(): number;
pattern(i: number): Pattern<Name>;
num_no_patterns(): number;
no_pattern(i: number): Expr<Name>;
body(): BodyT<Name, QVarSorts, QSort>;
num_vars(): number;
var_name(i: number): string | number;
var_sort<T extends number>(i: T): QVarSorts[T];
children(): [BodyT<Name, QVarSorts, QSort>];
}
export interface Probe<Name extends string = 'main'> {
@ -1314,7 +1599,7 @@ export interface Probe<Name extends string = 'main'> {
/** @hidden */
export interface TacticCtor<Name extends string> {
new(name: string): Tactic<Name>;
new (name: string): Tactic<Name>;
}
export interface Tactic<Name extends string = 'main'> {
@ -1327,7 +1612,7 @@ export interface Tactic<Name extends string = 'main'> {
/** @hidden */
export interface AstVectorCtor<Name extends string> {
new<Item extends Ast<Name> = AnyAst<Name>>(): AstVector<Name, Item>;
new <Item extends Ast<Name> = AnyAst<Name>>(): AstVector<Name, Item>;
}
/**
@ -1378,7 +1663,7 @@ export interface AstVector<Name extends string = 'main', Item extends Ast<Name>
/** @hidden */
export interface AstMapCtor<Name extends string> {
new<Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>(): AstMap<Name, Key, Value>;
new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>(): AstMap<Name, Key, Value>;
}
/**
@ -1402,8 +1687,11 @@ export interface AstMapCtor<Name extends string> {
* // 0
* ```
*/
export interface AstMap<Name extends string = 'main', Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>
extends Iterable<[Key, Value]> {
export interface AstMap<
Name extends string = 'main',
Key extends Ast<Name> = AnyAst<Name>,
Value extends Ast<Name> = AnyAst<Name>,
> extends Iterable<[Key, Value]> {
/** @hidden */
readonly __typename: 'AstMap';

View file

@ -1253,7 +1253,9 @@ struct
let mk_re_sort = Z3native.mk_re_sort
let is_re_sort = Z3native.is_re_sort
let mk_string_sort = Z3native.mk_string_sort
let mk_char_sort = Z3native.mk_char_sort
let is_string_sort = Z3native.is_string_sort
let is_char_sort = Z3native.is_char_sort
let mk_string = Z3native.mk_string
let is_string = Z3native.is_string
let get_string = Z3native.get_string
@ -1274,6 +1276,10 @@ struct
let mk_str_le = Z3native.mk_str_le
let mk_str_lt = Z3native.mk_str_lt
let mk_int_to_str = Z3native.mk_int_to_str
let mk_string_to_code = Z3native.mk_string_to_code
let mk_string_from_code = Z3native.mk_string_from_code
let mk_ubv_to_str = Z3native.mk_ubv_to_str
let mk_sbv_to_str = Z3native.mk_sbv_to_str
let mk_seq_to_re = Z3native.mk_seq_to_re
let mk_seq_in_re = Z3native.mk_seq_in_re
let mk_re_plus = Z3native.mk_re_plus
@ -1287,6 +1293,12 @@ struct
let mk_re_complement = Z3native.mk_re_complement
let mk_re_empty = Z3native.mk_re_empty
let mk_re_full = Z3native.mk_re_full
let mk_char = Z3native.mk_char
let mk_char_le = Z3native.mk_char_le
let mk_char_to_int = Z3native.mk_char_to_int
let mk_char_to_bv = Z3native.mk_char_to_bv
let mk_char_from_bv = Z3native.mk_char_from_bv
let mk_char_is_digit = Z3native.mk_char_is_digit
end
module FloatingPoint =
@ -1542,7 +1554,7 @@ struct
let to_string (x:func_entry) =
let a = get_args x in
let f c p = (p ^ (Expr.to_string c) ^ ", ") in
let f c p = ((Expr.to_string c) ^ ", " ^ p) in
"[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]")
end

View file

@ -1881,9 +1881,15 @@ sig
(** create string sort *)
val mk_string_sort : context -> Sort.sort
(** create char sort *)
val mk_char_sort : context -> Sort.sort
(** test if sort is a string sort (a sequence of 8-bit bit-vectors) *)
val is_string_sort : context -> Sort.sort -> bool
(** test if sort is a char sort *)
val is_char_sort : context -> Sort.sort -> bool
(** create a string literal *)
val mk_string : context -> string -> Expr.expr
@ -1936,6 +1942,7 @@ sig
(** retrieve integer expression encoded in string *)
val mk_str_to_int : context -> Expr.expr -> Expr.expr
(** compare strings less-than-or-equal *)
val mk_str_le : context -> Expr.expr -> Expr.expr -> Expr.expr
@ -1945,6 +1952,18 @@ sig
(** convert an integer expression to a string *)
val mk_int_to_str : context -> Expr.expr -> Expr.expr
(** [mk_string_to_code ctx s] convert a unit length string [s] to integer code *)
val mk_string_to_code : context -> Expr.expr -> Expr.expr
(** [mk_string_from_code ctx c] convert code [c] to a string *)
val mk_string_from_code : context -> Expr.expr -> Expr.expr
(** [mk_ubv_to_str ctx ubv] convert a unsigned bitvector [ubv] to a string *)
val mk_ubv_to_str : context -> Expr.expr -> Expr.expr
(** [mk_sbv_to_str ctx sbv] convert a signed bitvector [sbv] to a string *)
val mk_sbv_to_str : context -> Expr.expr -> Expr.expr
(** create regular expression that accepts the argument sequence *)
val mk_seq_to_re : context -> Expr.expr -> Expr.expr
@ -1984,6 +2003,24 @@ sig
(** the regular expression that accepts all sequences *)
val mk_re_full : context -> Sort.sort -> Expr.expr
(** [mk_char ctx i] converts an integer to a character *)
val mk_char : context -> int -> Expr.expr
(** [mk_char_le ctx lc rc] compares two characters *)
val mk_char_le : context -> Expr.expr -> Expr.expr -> Expr.expr
(** [mk_char_to_int ctx c] converts the character [c] to an integer *)
val mk_char_to_int : context -> Expr.expr -> Expr.expr
(** [mk_char_to_bv ctx c] converts the character [c] to a bitvector *)
val mk_char_to_bv : context -> Expr.expr -> Expr.expr
(** [mk_char_from_bv ctx bv] converts the bitvector [bv] to a character *)
val mk_char_from_bv : context -> Expr.expr -> Expr.expr
(** [mk_char_is_digit ctx c] checks if the character [c] is a digit *)
val mk_char_is_digit: context -> Expr.expr -> Expr.expr
end
(** Floating-Point Arithmetic *)

View file

@ -3173,12 +3173,8 @@ def _to_int_str(val):
return "1"
else:
return "0"
elif _is_int(val):
else:
return str(val)
elif isinstance(val, str):
return val
if z3_debug():
_z3_assert(False, "Python value cannot be used as a Z3 integer")
def IntVal(val, ctx=None):
@ -11343,7 +11339,7 @@ def Range(lo, hi, ctx=None):
return ReRef(Z3_mk_re_range(lo.ctx_ref(), lo.ast, hi.ast), lo.ctx)
def Diff(a, b, ctx=None):
"""Create the difference regular epression
"""Create the difference regular expression
"""
return ReRef(Z3_mk_re_diff(a.ctx_ref(), a.ast, b.ast), a.ctx)

View file

@ -365,7 +365,6 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
case OP_MOD: return m_i_mod_decl;
case OP_DIV0: return m_manager->mk_func_decl(symbol("/0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_DIV0));
case OP_IDIV0: return m_manager->mk_func_decl(symbol("div0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_IDIV0));
case OP_REM0: return m_manager->mk_func_decl(symbol("rem0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_REM0));
case OP_MOD0: return m_manager->mk_func_decl(symbol("mod0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_MOD0));
case OP_POWER0:
if (is_real) {
@ -612,7 +611,6 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
op_names.push_back(builtin_name("euler", OP_E));
op_names.push_back(builtin_name("/0",OP_DIV0));
op_names.push_back(builtin_name("div0",OP_IDIV0));
op_names.push_back(builtin_name("rem0",OP_REM0));
op_names.push_back(builtin_name("mod0",OP_MOD0));
}
}
@ -821,7 +819,7 @@ bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* con
}
if (is_decl_of(f, arith_family_id, OP_REM) && n == 2 && is_numeral(args[1], r) && r.is_zero()) {
sort* rs[2] = { mk_int(), mk_int() };
f_out = m_manager.mk_func_decl(arith_family_id, OP_REM0, 0, nullptr, 2, rs, mk_int());
f_out = m_manager.mk_func_decl(arith_family_id, OP_MOD0, 0, nullptr, 2, rs, mk_int());
return true;
}
if (is_decl_of(f, arith_family_id, OP_POWER) && n == 2 && is_numeral(args[1], r) && r.is_zero() && is_numeral(args[0], r) && r.is_zero()) {
@ -857,7 +855,7 @@ func_decl* arith_util::mk_idiv0() {
func_decl* arith_util::mk_rem0() {
sort* rs[2] = { mk_int(), mk_int() };
return m_manager.mk_func_decl(arith_family_id, OP_REM0, 0, nullptr, 2, rs, mk_int());
return m_manager.mk_func_decl(arith_family_id, OP_MOD0, 0, nullptr, 2, rs, mk_int());
}
func_decl* arith_util::mk_mod0() {
@ -942,7 +940,6 @@ bool arith_util::is_underspecified(expr* e) const {
case OP_MOD:
case OP_DIV0:
case OP_IDIV0:
case OP_REM0:
case OP_MOD0:
return true;
default:

View file

@ -50,7 +50,6 @@ enum arith_op_kind {
OP_IDIVIDES,
OP_REM,
OP_MOD,
OP_REM0,
OP_MOD0,
OP_TO_REAL,
OP_TO_INT,
@ -216,7 +215,6 @@ public:
case OP_U_ACOS:
case OP_DIV0:
case OP_IDIV0:
case OP_REM0:
case OP_MOD0:
case OP_POWER0:
return true;
@ -270,7 +268,7 @@ public:
bool is_div0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_DIV0); }
bool is_idiv0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_IDIV0); }
bool is_rem0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_REM0); }
bool is_rem0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_MOD0); }
bool is_mod0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_MOD0); }
bool is_power0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_POWER0); }
bool is_power(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_POWER); }
@ -296,7 +294,7 @@ public:
bool is_mod(expr const * n) const { return is_app_of(n, arith_family_id, OP_MOD); }
bool is_rem(expr const * n) const { return is_app_of(n, arith_family_id, OP_REM); }
bool is_mod0(expr const * n) const { return is_app_of(n, arith_family_id, OP_MOD0); }
bool is_rem0(expr const * n) const { return is_app_of(n, arith_family_id, OP_REM0); }
bool is_rem0(expr const * n) const { return is_app_of(n, arith_family_id, OP_MOD0); }
bool is_to_real(expr const * n) const { return is_app_of(n, arith_family_id, OP_TO_REAL); }
bool is_to_int(expr const * n) const { return is_app_of(n, arith_family_id, OP_TO_INT); }
bool is_is_int(expr const * n) const { return is_app_of(n, arith_family_id, OP_IS_INT); }
@ -355,7 +353,7 @@ public:
MATCH_BINARY(is_div);
MATCH_BINARY(is_idiv);
MATCH_BINARY(is_mod0);
MATCH_BINARY(is_rem0);
// MATCH_BINARY(is_rem0);
MATCH_BINARY(is_div0);
MATCH_BINARY(is_idiv0);
MATCH_BINARY(is_power);
@ -465,7 +463,7 @@ public:
app * mk_mod(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_MOD, arg1, arg2); }
app * mk_div0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_DIV0, arg1, arg2); }
app * mk_idiv0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_IDIV0, arg1, arg2); }
app * mk_rem0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_REM0, arg1, arg2); }
app * mk_rem0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_MOD0, arg1, arg2); }
app * mk_mod0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_MOD0, arg1, arg2); }
app * mk_to_real(expr * arg1) { return m_manager.mk_app(arith_family_id, OP_TO_REAL, arg1); }
app * mk_to_int(expr * arg1) { return m_manager.mk_app(arith_family_id, OP_TO_INT, arg1); }

View file

@ -315,13 +315,13 @@ func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domain, unsigned i) {
if (arity != 2 || domain[0] != domain[1]) {
UNREACHABLE();
m_manager->raise_exception("incorrect arguments passed to array-ext");
return nullptr;
}
sort * s = domain[0];
unsigned num_parameters = s->get_num_parameters();
if (num_parameters == 0 || i >= num_parameters - 1) {
UNREACHABLE();
m_manager->raise_exception("incorrect arguments passed to array-ext");
return nullptr;
}
sort * r = to_sort(s->get_parameter(i).get_ast());

View file

@ -2322,6 +2322,14 @@ func_decl * ast_manager::mk_fresh_func_decl(symbol const & prefix, symbol const
return d;
}
bool ast_manager::is_parametric_function(func_decl* f, func_decl *& g) const {
// is-as-array
// is-map
// is-transitive-closure
return false;
}
sort * ast_manager::mk_fresh_sort(char const * prefix) {
string_buffer<32> buffer;
buffer << prefix << "!" << m_fresh_id;
@ -3296,7 +3304,7 @@ proof * ast_manager::mk_redundant_del(expr* e) {
return mk_clause_trail_elem(nullptr, e, PR_REDUNDANT_DEL);
}
proof * ast_manager::mk_clause_trail(unsigned n, proof* const* ps) {
proof * ast_manager::mk_clause_trail(unsigned n, expr* const* ps) {
ptr_buffer<expr> args;
args.append(n, (expr**) ps);
return mk_app(basic_family_id, PR_CLAUSE_TRAIL, 0, nullptr, args.size(), args.data());

View file

@ -180,13 +180,13 @@ public:
*/
void del_eh(ast_manager & m, family_id fid);
int get_int() const { return std::get<int>(m_val); }
ast * get_ast() const { return std::get<ast*>(m_val); }
symbol get_symbol() const { return std::get<symbol>(m_val); }
rational const & get_rational() const { return *std::get<rational*>(m_val); }
zstring const& get_zstring() const { return *std::get<zstring*>(m_val); }
double get_double() const { return std::get<double>(m_val); }
unsigned get_ext_id() const { return std::get<unsigned>(m_val); }
int get_int() const { SASSERT(is_int()); return std::get<int>(m_val); }
ast * get_ast() const { SASSERT(is_ast()); return std::get<ast*>(m_val); }
symbol get_symbol() const { SASSERT(is_symbol()); return std::get<symbol>(m_val); }
rational const & get_rational() const { SASSERT(is_rational()); return *std::get<rational*>(m_val); }
zstring const& get_zstring() const { SASSERT(is_zstring()); return *std::get<zstring*>(m_val); }
double get_double() const { SASSERT(is_double()); return std::get<double>(m_val); }
unsigned get_ext_id() const { SASSERT(is_external()); return std::get<unsigned>(m_val); }
bool operator==(parameter const & p) const;
bool operator!=(parameter const & p) const { return !operator==(p); }
@ -1924,6 +1924,8 @@ public:
return mk_fresh_func_decl(symbol(prefix), symbol::null, arity, domain, range, skolem);
}
bool is_parametric_function(func_decl* f, func_decl *& g) const;
app * mk_fresh_const(char const * prefix, sort * s, bool skolem = true) {
return mk_const(mk_fresh_func_decl(prefix, 0, nullptr, s, skolem));
}
@ -2335,7 +2337,7 @@ public:
proof * mk_th_assumption_add(proof* pr, expr* e);
proof * mk_th_lemma_add(proof* pr, expr* e);
proof * mk_redundant_del(expr* e);
proof * mk_clause_trail(unsigned n, proof* const* ps);
proof * mk_clause_trail(unsigned n, expr* const* ps);
proof * mk_def_axiom(expr * ax);
proof * mk_unit_resolution(unsigned num_proofs, proof * const * proofs);

View file

@ -43,11 +43,11 @@ void ast_pp_util::display_decls(std::ostream& out) {
for (unsigned i = m_sorts; i < n; ++i)
pp.display_sort_decl(out, coll.get_sorts()[i], seen);
m_sorts = n;
n = coll.get_num_decls();
for (unsigned i = m_decls; i < n; ++i) {
func_decl* f = coll.get_func_decls()[i];
if (f->get_family_id() == null_family_id && !m_removed.contains(f))
if (coll.should_declare(f) && !m_removed.contains(f))
ast_smt2_pp(out, f, m_env) << "\n";
}
m_decls = n;
@ -80,7 +80,7 @@ void ast_pp_util::display_skolem_decls(std::ostream& out) {
unsigned n = coll.get_num_decls();
for (unsigned i = m_decls; i < n; ++i) {
func_decl* f = coll.get_func_decls()[i];
if (f->get_family_id() == null_family_id && !m_removed.contains(f) && f->is_skolem())
if (coll.should_declare(f) && !m_removed.contains(f) && f->is_skolem())
ast_smt2_pp(out, f, m_env) << "\n";
}
m_decls = n;

View file

@ -121,8 +121,10 @@ format * smt2_pp_environment::pp_fdecl_params(format * fname, func_decl * f) {
std::string str = f->get_parameter(i).get_rational().to_string();
fs.push_back(mk_string(get_manager(), str));
}
else
fs.push_back(pp_fdecl_ref(to_func_decl(f->get_parameter(i).get_ast())));
else {
unsigned len;
fs.push_back(pp_fdecl_name(to_func_decl(f->get_parameter(i).get_ast()), len));
}
}
return mk_seq1(get_manager(), fs.begin(), fs.end(), f2f(), "_");
}

View file

@ -34,6 +34,7 @@ Revision History:
#include "ast/for_each_ast.h"
#include "ast/decl_collector.h"
#include "math/polynomial/algebraic_numbers.h"
#include "ast/pp_params.hpp"
// ---------------------------------------
@ -911,7 +912,9 @@ ast_smt_pp::ast_smt_pp(ast_manager& m):
void ast_smt_pp::display_expr_smt2(std::ostream& strm, expr* n, unsigned indent, unsigned num_var_names, char const* const* var_names) {
ptr_vector<quantifier> ql;
smt_renaming rn;
smt_printer p(strm, m_manager, ql, rn, m_logic, false, m_simplify_implies, indent, num_var_names, var_names);
pp_params params;
bool no_lets = params.no_lets();
smt_printer p(strm, m_manager, ql, rn, m_logic, no_lets, m_simplify_implies, indent, num_var_names, var_names);
p(n);
}

View file

@ -118,9 +118,22 @@ void bv_decl_plugin::finalize() {
DEC_REF(m_bv_redand);
DEC_REF(m_bv_comp);
DEC_REF(m_bv_mul_no_ovfl);
DEC_REF(m_bv_smul_no_ovfl);
DEC_REF(m_bv_smul_no_udfl);
DEC_REF(m_bv_mul_ovfl);
DEC_REF(m_bv_smul_ovfl);
DEC_REF(m_bv_smul_udfl);
DEC_REF(m_bv_neg_ovfl);
DEC_REF(m_bv_uadd_ovfl);
DEC_REF(m_bv_sadd_ovfl);
DEC_REF(m_bv_usub_ovfl);
DEC_REF(m_bv_ssub_ovfl);
DEC_REF(m_bv_sdiv_ovfl);
DEC_REF(m_bv_shl);
DEC_REF(m_bv_lshr);
@ -245,6 +258,16 @@ func_decl * bv_decl_plugin::mk_bv2int(unsigned bv_size, unsigned num_parameters,
return m_bv2int[bv_size];
}
func_decl * bv_decl_plugin::mk_unary_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size) {
force_ptr_array_size(decls, bv_size+1);
if (decls[bv_size] == 0) {
decls[bv_size] = m_manager->mk_func_decl(symbol(name), get_bv_sort(bv_size), m_manager->mk_bool_sort(), func_decl_info(m_family_id, k));
m_manager->inc_ref(decls[bv_size]);
}
return decls[bv_size];
}
func_decl * bv_decl_plugin::mk_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size) {
force_ptr_array_size(decls, bv_size + 1);
@ -289,6 +312,7 @@ func_decl * bv_decl_plugin::mk_comp(unsigned bv_size) {
func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned bv_size) {
switch (k) {
case OP_BNEG: return mk_unary(m_bv_neg, k, "bvneg", bv_size);
case OP_BNEG_OVFL: return mk_unary_pred(m_bv_neg_ovfl, k, "bvnego", bv_size);
case OP_BADD: return mk_binary(m_bv_add, k, "bvadd", bv_size, true);
case OP_BSUB: return mk_binary(m_bv_sub, k, "bvsub", bv_size, false);
case OP_BMUL: return mk_binary(m_bv_mul, k, "bvmul", bv_size, true);
@ -327,9 +351,16 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned bv_size) {
case OP_BREDOR: return mk_reduction(m_bv_redor, k, "bvredor", bv_size);
case OP_BREDAND: return mk_reduction(m_bv_redand, k, "bvredand", bv_size);
case OP_BCOMP: return mk_comp(bv_size);
case OP_BUMUL_NO_OVFL: return mk_pred(m_bv_mul_ovfl, k, "bvumul_noovfl", bv_size);
case OP_BSMUL_NO_OVFL: return mk_pred(m_bv_smul_ovfl, k, "bvsmul_noovfl", bv_size);
case OP_BSMUL_NO_UDFL: return mk_pred(m_bv_smul_udfl, k, "bvsmul_noudfl", bv_size);
case OP_BUMUL_NO_OVFL: return mk_pred(m_bv_mul_no_ovfl, k, "bvumul_noovfl", bv_size);
case OP_BSMUL_NO_OVFL: return mk_pred(m_bv_smul_no_ovfl, k, "bvsmul_noovfl", bv_size);
case OP_BSMUL_NO_UDFL: return mk_pred(m_bv_smul_no_udfl, k, "bvsmul_noudfl", bv_size);
case OP_BUMUL_OVFL: return mk_pred(m_bv_mul_ovfl, k, "bvumulo", bv_size);
case OP_BSMUL_OVFL: return mk_pred(m_bv_smul_ovfl, k, "bvsmulo", bv_size);
case OP_BSDIV_OVFL: return mk_pred(m_bv_sdiv_ovfl, k, "bvsdivo", bv_size);
case OP_BUADD_OVFL: return mk_pred(m_bv_uadd_ovfl, k, "bvuaddo", bv_size);
case OP_BSADD_OVFL: return mk_pred(m_bv_sadd_ovfl, k, "bvsaddo", bv_size);
case OP_BUSUB_OVFL: return mk_pred(m_bv_usub_ovfl, k, "bvusubo", bv_size);
case OP_BSSUB_OVFL: return mk_pred(m_bv_ssub_ovfl, k, "bvssubo", bv_size);
case OP_BSHL: return mk_binary(m_bv_shl, k, "bvshl", bv_size, false);
case OP_BLSHR: return mk_binary(m_bv_lshr, k, "bvlshr", bv_size, false);
@ -681,10 +712,18 @@ void bv_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
op_names.push_back(builtin_name("bit1",OP_BIT1));
op_names.push_back(builtin_name("bit0",OP_BIT0));
op_names.push_back(builtin_name("bvneg",OP_BNEG));
op_names.push_back(builtin_name("bvnego", OP_BNEG_OVFL));
op_names.push_back(builtin_name("bvadd",OP_BADD));
op_names.push_back(builtin_name("bvuaddo",OP_BUADD_OVFL));
op_names.push_back(builtin_name("bvsaddo",OP_BSADD_OVFL));
op_names.push_back(builtin_name("bvsub",OP_BSUB));
op_names.push_back(builtin_name("bvusubo",OP_BUSUB_OVFL));
op_names.push_back(builtin_name("bvssubo",OP_BSSUB_OVFL));
op_names.push_back(builtin_name("bvmul",OP_BMUL));
op_names.push_back(builtin_name("bvumulo",OP_BUMUL_OVFL));
op_names.push_back(builtin_name("bvsmulo",OP_BSMUL_OVFL));
op_names.push_back(builtin_name("bvsdiv",OP_BSDIV));
op_names.push_back(builtin_name("bvsdivo",OP_BSDIV_OVFL));
op_names.push_back(builtin_name("bvudiv",OP_BUDIV));
op_names.push_back(builtin_name("bvsrem",OP_BSREM));
op_names.push_back(builtin_name("bvurem",OP_BUREM));

View file

@ -93,6 +93,19 @@ enum bv_op_kind {
OP_BSMUL_NO_OVFL, // no signed multiplication overflow predicate
OP_BSMUL_NO_UDFL, // no signed multiplication underflow predicate
OP_BUMUL_OVFL, // unsigned multiplication overflow predicate (negation of OP_BUMUL_NO_OVFL)
OP_BSMUL_OVFL, // signed multiplication over/underflow predicate
OP_BSDIV_OVFL, // signed division overflow perdicate
OP_BNEG_OVFL, // negation overflow predicate
OP_BUADD_OVFL, // unsigned addition overflow predicate
OP_BSADD_OVFL, // signed addition overflow predicate
OP_BUSUB_OVFL, // unsigned subtraction overflow predicate
OP_BSSUB_OVFL, // signed subtraction overflow predicate
OP_BIT2BOOL, // predicate
OP_MKBV, // bools to bv
OP_INT2BV,
@ -189,9 +202,22 @@ protected:
ptr_vector<func_decl> m_bv_redand;
ptr_vector<func_decl> m_bv_comp;
ptr_vector<func_decl> m_bv_mul_ovfl;
ptr_vector<func_decl> m_bv_smul_ovfl;
ptr_vector<func_decl> m_bv_smul_udfl;
ptr_vector<func_decl> m_bv_mul_no_ovfl;
ptr_vector<func_decl> m_bv_smul_no_ovfl;
ptr_vector<func_decl> m_bv_smul_no_udfl;
ptr_vector<func_decl> m_bv_mul_ovfl;
ptr_vector<func_decl> m_bv_smul_ovfl;
ptr_vector<func_decl> m_bv_sdiv_ovfl;
ptr_vector<func_decl> m_bv_neg_ovfl;
ptr_vector<func_decl> m_bv_uadd_ovfl;
ptr_vector<func_decl> m_bv_sadd_ovfl;
ptr_vector<func_decl> m_bv_usub_ovfl;
ptr_vector<func_decl> m_bv_ssub_ovfl;
ptr_vector<func_decl> m_bv_shl;
ptr_vector<func_decl> m_bv_lshr;
@ -213,6 +239,7 @@ protected:
func_decl * mk_unary(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size);
func_decl * mk_pred(ptr_vector<func_decl> & decls, decl_kind k,
char const * name, unsigned bv_size);
func_decl * mk_unary_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size);
func_decl * mk_reduction(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size);
func_decl * mk_comp(unsigned bv_size);
bool get_bv_size(sort * t, int & result);
@ -490,9 +517,19 @@ public:
app * mk_bv2int(expr* e);
// TODO: all these binary ops commute (right?) but it'd be more logical to swap `n` & `m` in the `return`
app * mk_bvsmul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_OVFL, n, m); }
app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }
app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); }
app * mk_bvsmul_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_OVFL, n, m); }
app * mk_bvumul_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_OVFL, n, m); }
app * mk_bvsdiv_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSDIV_OVFL, m, n); }
app * mk_bvneg_ovfl(expr* m) { return m_manager.mk_app(get_fid(), OP_BNEG_OVFL, m); }
app * mk_bvuadd_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUADD_OVFL, n, m); }
app * mk_bvsadd_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSADD_OVFL, n, m); }
app * mk_bvusub_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUSUB_OVFL, m, n); }
app * mk_bvssub_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSSUB_OVFL, m, n); }
app * mk_bit2bool(expr* e, unsigned idx) { parameter p(idx); return m_manager.mk_app(get_fid(), OP_BIT2BOOL, 1, &p, 1, &e); }
private:

View file

@ -19,6 +19,7 @@ Author:
#include "ast/ast_ll_pp.h"
#include "ast/ast_util.h"
#include "ast/arith_decl_plugin.h"
#include "ast/seq_decl_plugin.h"
#include "ast/converters/expr_inverter.h"
class basic_expr_inverter : public iexpr_inverter {
@ -742,6 +743,54 @@ public:
};
class seq_expr_inverter : public iexpr_inverter {
seq_util seq;
public:
seq_expr_inverter(ast_manager& m) : iexpr_inverter(m), seq(m) {}
family_id get_fid() const override { return seq.get_family_id(); }
bool operator()(func_decl* f, unsigned num, expr* const* args, expr_ref& r) override {
switch (f->get_decl_kind()) {
case _OP_STRING_CONCAT:
case OP_SEQ_CONCAT: {
expr* x, *y;
if (uncnstr(args[0]) && num == 2 &&
args[1]->get_ref_count() == 1 &&
seq.str.is_concat(args[1], x, y) &&
uncnstr(x)) {
mk_fresh_uncnstr_var_for(f, r);
if (m_mc) {
add_def(args[0], seq.str.mk_empty(args[0]->get_sort()));
add_def(x, r);
}
r = seq.str.mk_concat(r, y);
return true;
}
if (!uncnstr(num, args))
return false;
mk_fresh_uncnstr_var_for(f, r);
if (m_mc) {
add_def(args[0], r);
for (unsigned i = 1; i < num; ++i)
add_def(args[i], seq.str.mk_empty(args[0]->get_sort()));
}
return true;
}
default:
return false;
}
}
bool mk_diff(expr* t, expr_ref& r) override {
return false;
}
};
expr_inverter::~expr_inverter() {
for (auto* v : m_inverters)
@ -796,6 +845,7 @@ expr_inverter::expr_inverter(ast_manager& m): iexpr_inverter(m) {
add(alloc(array_expr_inverter, m, *this));
add(alloc(dt_expr_inverter, m));
add(alloc(basic_expr_inverter, m, *this));
add(alloc(seq_expr_inverter, m));
}

View file

@ -24,7 +24,7 @@ Revision History:
void decl_collector::visit_sort(sort * n) {
SASSERT(!m_visited.is_marked(n));
family_id fid = n->get_family_id();
if (m().is_uninterp(n))
if (m.is_uninterp(n))
m_sorts.push_back(n);
else if (fid == m_dt_fid) {
m_sorts.push_back(n);
@ -43,7 +43,7 @@ void decl_collector::visit_sort(sort * n) {
}
bool decl_collector::is_bool(sort * s) {
return m().is_bool(s);
return m.is_bool(s);
}
void decl_collector::visit_func(func_decl * n) {
@ -51,10 +51,10 @@ void decl_collector::visit_func(func_decl * n) {
if (!m_visited.is_marked(n)) {
family_id fid = n->get_family_id();
if (fid == null_family_id)
if (should_declare(n))
m_decls.push_back(n);
else if (fid == m_rec_fid) {
recfun::util u(m());
recfun::util u(m);
if (u.has_def(n)) {
m_rec_decls.push_back(n);
m_todo.push_back(u.get_def(n).get_rhs());
@ -69,12 +69,17 @@ void decl_collector::visit_func(func_decl * n) {
}
}
bool decl_collector::should_declare(func_decl* f) const {
return f->get_family_id() == null_family_id || m.is_model_value(f);
}
decl_collector::decl_collector(ast_manager & m):
m_manager(m),
m(m),
m_trail(m),
m_dt_util(m),
m_ar_util(m) {
m_basic_fid = m_manager.get_basic_family_id();
m_basic_fid = m.get_basic_family_id();
m_dt_fid = m_dt_util.get_family_id();
recfun::util rec_util(m);
m_rec_fid = rec_util.get_family_id();
@ -83,7 +88,7 @@ decl_collector::decl_collector(ast_manager & m):
void decl_collector::visit(ast* n) {
if (m_visited.is_marked(n))
return;
datatype_util util(m());
datatype_util util(m);
m_todo.push_back(n);
while (!m_todo.empty()) {
n = m_todo.back();

View file

@ -26,7 +26,7 @@ Revision History:
#include "ast/array_decl_plugin.h"
class decl_collector {
ast_manager & m_manager;
ast_manager & m;
lim_svector<sort*> m_sorts;
lim_svector<func_decl*> m_decls;
lim_svector<func_decl*> m_rec_decls;
@ -48,10 +48,10 @@ class decl_collector {
void collect_deps(top_sort<sort>& st);
void collect_deps(sort* s, sort_set& set);
public:
decl_collector(ast_manager & m);
ast_manager & m() { return m_manager; }
bool should_declare(func_decl* f) const;
void reset() { m_sorts.reset(); m_decls.reset(); m_visited.reset(); m_trail.reset(); }
void visit_func(func_decl* n);

View file

@ -47,6 +47,8 @@ struct dimacs_pp {
}
for (unsigned j = 0; j < num_lits; j++) {
expr * l = lits[j];
if (m.is_false(l))
continue;
if (m.is_not(l))
l = to_app(l)->get_arg(0);
if (!is_uninterp_const(l))
@ -101,6 +103,12 @@ struct dimacs_pp {
}
for (unsigned j = 0; j < num_lits; j++) {
expr * l = lits[j];
if (m.is_false(l))
continue;
if (m.is_true(l)) {
out << "1 -1 ";
continue;
}
if (m.is_not(l)) {
out << "-";
l = to_app(l)->get_arg(0);

View file

@ -67,6 +67,8 @@ namespace euf {
}
enode_bool_pair egraph::insert_table(enode* p) {
TRACE("euf", tout << bpp(p) << "\n");
//SASSERT(!m_table.contains_ptr(p));
auto rc = m_table.insert(p);
p->m_cg = rc.first;
return rc;
@ -280,6 +282,7 @@ namespace euf {
if (!m.is_bool(n->get_sort()))
return;
if (enable_merge_tf != n->merge_tf()) {
TRACE("euf", tout << "set tf " << enable_merge_tf << " " << bpp(n) << "\n");
n->set_merge_tf(enable_merge_tf);
m_updates.push_back(update_record(n, update_record::toggle_merge_tf()));
}
@ -487,6 +490,7 @@ namespace euf {
}
void egraph::remove_parents(enode* r) {
TRACE("euf", tout << bpp(r) << "\n");
for (enode* p : enode_parents(r)) {
if (p->is_marked1())
continue;
@ -496,6 +500,7 @@ namespace euf {
SASSERT(m_table.contains_ptr(p));
p->mark1();
erase_from_table(p);
CTRACE("euf", m_table.contains_ptr(p), tout << bpp(p) << "\n"; display(tout));
SASSERT(!m_table.contains_ptr(p));
}
else if (p->is_equality())

View file

@ -44,6 +44,49 @@ unsigned get_num_exprs(expr * n) {
return get_num_exprs(n, visited);
}
void get_num_internal_exprs(unsigned_vector& counts, ptr_vector<expr>& todo, expr * n) {
counts.reserve(n->get_id() + 1);
unsigned& rc = counts[n->get_id()];
if (rc > 0) {
--rc;
return;
}
rc = n->get_ref_count() - 1;
unsigned i = todo.size();
todo.push_back(n);
for (; i < todo.size(); ++i) {
n = todo[i];
if (!is_app(n))
continue;
for (expr* arg : *to_app(n)) {
unsigned id = arg->get_id();
counts.reserve(id + 1);
unsigned& rc = counts[id];
if (rc > 0) {
--rc;
continue;
}
rc = arg->get_ref_count() - 1;
todo.push_back(arg);
}
}
}
unsigned count_internal_nodes(unsigned_vector& counts, ptr_vector<expr>& todo) {
unsigned internal_nodes = 0;
for (expr* t : todo) {
if (counts[t->get_id()] == 0)
++internal_nodes;
else
counts[t->get_id()] = 0;
}
todo.reset();
return internal_nodes;
}
namespace has_skolem_functions_ns {
struct found {};
struct proc {

View file

@ -163,10 +163,13 @@ struct for_each_expr_proc : public EscapeProc {
unsigned get_num_exprs(expr * n);
unsigned get_num_exprs(expr * n, expr_mark & visited);
unsigned get_num_exprs(expr * n, expr_fast_mark1 & visited);
void get_num_internal_exprs(unsigned_vector& counts, ptr_vector<expr>& todo, expr * n);
unsigned count_internal_nodes(unsigned_vector& counts, ptr_vector<expr>& todo);
bool has_skolem_functions(expr * n);
// pre-order traversal of subterms
class subterms {
bool m_include_bound = false;
expr_ref_vector m_es;

View file

@ -149,7 +149,7 @@ class skolemizer {
p = nullptr;
if (m_proofs_enabled) {
if (q->get_kind() == forall_k)
p = m.mk_skolemization(mk_not(m, q), mk_not(m, r));
p = m.mk_skolemization(mk_not(m, q), m.mk_not(r));
else
p = m.mk_skolemization(q, r);
}

View file

@ -405,6 +405,44 @@ bool pattern_inference_cfg::pattern_weight_lt::operator()(expr * n1, expr * n2)
return num_free_vars1 > num_free_vars2 || (num_free_vars1 == num_free_vars2 && i1.m_size < i2.m_size);
}
app* pattern_inference_cfg::mk_pattern(app* candidate) {
auto has_var_arg = [&](expr* e) {
if (!is_app(e))
return false;
for (expr* arg : *to_app(e))
if (is_var(arg))
return true;
return false;
};
if (has_var_arg(candidate))
return m.mk_pattern(candidate);
m_args.reset();
for (expr* arg : *candidate) {
if (!is_app(arg))
return m.mk_pattern(candidate);
m_args.push_back(to_app(arg));
}
for (unsigned i = 0; i < m_args.size(); ++i) {
app* arg = m_args[i];
if (has_var_arg(arg))
continue;
m_args[i] = m_args.back();
--i;
m_args.pop_back();
if (is_ground(arg))
continue;
for (expr* e : *to_app(arg)) {
if (!is_app(e))
return m.mk_pattern(candidate);
m_args.push_back(to_app(e));
}
}
return m.mk_pattern(m_args.size(), m_args.data());
}
/**
\brief Create unary patterns (single expressions that contain all
bound variables). If a candidate does not contain all bound
@ -418,7 +456,7 @@ void pattern_inference_cfg::candidates2unary_patterns(ptr_vector<app> const & ca
expr2info::obj_map_entry * e = m_candidates_info.find_core(candidate);
info const & i = e->get_data().m_value;
if (i.m_free_vars.num_elems() == m_num_bindings) {
app * new_pattern = m.mk_pattern(candidate);
app * new_pattern = mk_pattern(candidate);
result.push_back(new_pattern);
}
else {

View file

@ -188,6 +188,9 @@ class pattern_inference_cfg : public default_rewriter_cfg {
ptr_vector<pre_pattern> m_pre_patterns;
expr_pattern_match m_database;
ptr_buffer<app> m_args;
app* mk_pattern(app* candidate);
void candidates2unary_patterns(ptr_vector<app> const & candidate_patterns,
ptr_vector<app> & remaining_candidate_patterns,
app_ref_buffer & result);

View file

@ -6,6 +6,7 @@ def_module_params('pp',
('max_width', UINT, 80, 'max. width in pretty printer'),
('max_ribbon', UINT, 80, 'max. ribbon (width - indentation) in pretty printer'),
('max_depth', UINT, 5, 'max. term depth (when pretty printing SMT2 terms/formulas)'),
('no_lets', BOOL, False, 'dont print lets in low level SMT printer'),
('min_alias_size', UINT, 10, 'min. size for creating an alias for a shared term (when pretty printing SMT2 terms/formulas)'),
('decimal', BOOL, False, 'pretty print real numbers using decimal notation (the output may be truncated). Z3 adds a ? if the value is not precise'),
('decimal_precision', UINT, 10, 'maximum number of decimal places to be used when pp.decimal=true'),

View file

@ -492,7 +492,7 @@ namespace recfun {
def* plugin::mk_def(replace& subst, bool is_macro,
symbol const& name, unsigned n, sort ** params, sort * range,
unsigned n_vars, var ** vars, expr * rhs) {
promise_def d = mk_def(name, n, params, range);
promise_def d = mk_def(name, n, params, range, false);
SASSERT(! m_defs.contains(d.get_def()->get_decl()));
set_definition(subst, d, is_macro, n_vars, vars, rhs);
return d.get_def();
@ -581,7 +581,7 @@ namespace recfun {
}
symbol fresh_name("fold-rec-" + std::to_string(m().mk_fresh_id()));
auto pd = mk_def(fresh_name, n, domain.data(), max_expr->get_sort());
auto pd = mk_def(fresh_name, n, domain.data(), max_expr->get_sort(), false);
func_decl* f = pd.get_def()->get_decl();
expr_ref new_body(m().mk_app(f, n, args.data()), m());
set_definition(subst, pd, false, n, vars, max_expr);

View file

@ -192,9 +192,9 @@ namespace recfun {
void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false);
promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated);
promise_def ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false);
promise_def ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated);
void set_definition(replace& r, promise_def & d, bool is_macro, unsigned n_vars, var * const * vars, expr * rhs);
@ -248,6 +248,7 @@ namespace recfun {
bool is_defined(expr * e) const { return is_app_of(e, m_fid, OP_FUN_DEFINED); }
bool is_defined(func_decl* f) const { return is_decl_of(f, m_fid, OP_FUN_DEFINED); }
bool is_generated(func_decl* f) const { return is_defined(f) && f->get_parameter(0).get_int() == 1; }
bool is_macro(func_decl* f) { return is_defined(f) && get_def(f).is_macro(); }
bool is_num_rounds(expr * e) const { return is_app_of(e, m_fid, OP_NUM_ROUNDS); }
bool owns_app(app * e) const { return e->get_family_id() == m_fid; }

View file

@ -16,6 +16,7 @@ Author:
Notes:
--*/
#include "params/arith_rewriter_params.hpp"
#include "ast/rewriter/arith_rewriter.h"
#include "ast/rewriter/poly_rewriter_def.h"
@ -1046,19 +1047,21 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
set_curr_sort(arg1->get_sort());
numeral v1, v2;
bool is_int;
if (m_util.is_numeral(arg1, v1, is_int) && m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) {
bool is_num1 = m_util.is_numeral(arg1, v1, is_int);
bool is_num2 = m_util.is_numeral(arg2, v2, is_int);
if (is_num1 && is_num2 && !v2.is_zero()) {
result = m_util.mk_numeral(div(v1, v2), is_int);
return BR_DONE;
}
if (m_util.is_numeral(arg2, v2, is_int) && v2.is_one()) {
if (is_num2 && v2.is_one()) {
result = arg1;
return BR_DONE;
}
if (m_util.is_numeral(arg2, v2, is_int) && v2.is_minus_one()) {
if (is_num2 && v2.is_minus_one()) {
result = m_util.mk_mul(m_util.mk_int(-1), arg1);
return BR_REWRITE1;
}
if (m_util.is_numeral(arg2, v2, is_int) && v2.is_zero()) {
if (is_num2 && v2.is_zero()) {
return BR_FAILED;
}
if (arg1 == arg2) {
@ -1066,7 +1069,7 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
result = m.mk_ite(m.mk_eq(arg1, zero), m_util.mk_idiv(zero, zero), m_util.mk_int(1));
return BR_REWRITE3;
}
if (m_util.is_numeral(arg2, v2, is_int) && v2.is_pos() && m_util.is_add(arg1)) {
if (is_num2 && v2.is_pos() && m_util.is_add(arg1)) {
expr_ref_buffer args(m);
bool change = false;
rational add(0);
@ -1092,7 +1095,14 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
expr_ref zero(m_util.mk_int(0), m);
result = m.mk_ite(m.mk_eq(zero, arg2), m_util.mk_idiv(arg1, zero), result);
return BR_REWRITE_FULL;
}
}
#if 0
expr* x = nullptr, *y = nullptr, *z = nullptr;
if (is_num2 && m_util.is_idiv(arg1, x, y) && m_util.is_numeral(y, v1) && v1 > 0 && v2 > 0) {
result = m_util.mk_idiv(x, m_util.mk_numeral(v1*v2, is_int));
return BR_DONE;
}
#endif
return BR_FAILED;
}

View file

@ -20,6 +20,7 @@ Notes:
#include "params/bool_rewriter_params.hpp"
#include "ast/rewriter/rewriter_def.h"
#include "ast/ast_lt.h"
#include "ast/for_each_expr.h"
#include <algorithm>
void bool_rewriter::updt_params(params_ref const & _p) {
@ -32,6 +33,7 @@ void bool_rewriter::updt_params(params_ref const & _p) {
m_blast_distinct = p.blast_distinct();
m_blast_distinct_threshold = p.blast_distinct_threshold();
m_ite_extra_rules = p.ite_extra_rules();
m_hoist.set_elim_and(m_elim_and);
}
void bool_rewriter::get_param_descrs(param_descrs & r) {
@ -269,13 +271,26 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args
#if 1
br_status st;
st = m_hoist.mk_or(buffer.size(), buffer.data(), result);
expr_ref r(m());
st = m_hoist.mk_or(buffer.size(), buffer.data(), r);
if (st != BR_FAILED) {
m_counts1.reserve(m().get_num_asts() + 1);
m_counts2.reserve(m().get_num_asts() + 1);
get_num_internal_exprs(m_counts1, m_todo1, r);
for (unsigned i = 0; i < num_args; ++i)
get_num_internal_exprs(m_counts2, m_todo2, args[i]);
unsigned count1 = count_internal_nodes(m_counts1, m_todo1);
unsigned count2 = count_internal_nodes(m_counts2, m_todo2);
if (count1 > count2)
st = BR_FAILED;
}
if (st != BR_FAILED)
result = r;
if (st == BR_DONE)
return BR_REWRITE1;
if (st != BR_FAILED)
return st;
#endif
if (s) {
ast_lt lt;
std::sort(buffer.begin(), buffer.end(), lt);

View file

@ -62,6 +62,8 @@ class bool_rewriter {
unsigned m_local_ctx_limit;
unsigned m_local_ctx_cost;
bool m_elim_ite;
ptr_vector<expr> m_todo1, m_todo2;
unsigned_vector m_counts1, m_counts2;
br_status mk_flat_and_core(unsigned num_args, expr * const * args, expr_ref & result);
br_status mk_flat_or_core(unsigned num_args, expr * const * args, expr_ref & result);
@ -81,7 +83,9 @@ class bool_rewriter {
void push_new_arg(expr* arg, expr_ref_vector& new_args, expr_fast_mark1& neg_lits, expr_fast_mark2& pos_lits);
public:
bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_hoist(m), m_local_ctx_cost(0) { updt_params(p); }
bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_hoist(m), m_local_ctx_cost(0) {
updt_params(p);
}
ast_manager & m() const { return m_manager; }
family_id get_fid() const { return m().get_basic_family_id(); }
bool is_eq(expr * t) const { return m().is_eq(t); }

View file

@ -185,7 +185,7 @@ namespace bv {
m_args.push_back(arg);
continue;
}
if (!m_bv.is_extract(arg) && m_bound.find(arg, b)) {
if (!m_bv.is_extract(arg) && m_bound.find(arg, b) && b.lo() <= b.hi()) {
unsigned num_bits = b.hi().get_num_bits();
unsigned bv_size = m_bv.get_bv_size(arg);
if (0 < num_bits && num_bits < bv_size) {
@ -202,6 +202,7 @@ namespace bv {
if (simplified) {
result = m.mk_app(to_app(t)->get_decl(), m_args);
TRACE("bv", tout << mk_pp(t, m) << " -> " << result << "\n");
return true;
}

View file

@ -94,6 +94,10 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
case OP_BNEG:
SASSERT(num_args == 1);
return mk_uminus(args[0], result);
case OP_BNEG_OVFL:
SASSERT(num_args == 1);
return mk_bvneg_overflow(args[0], result);
case OP_BSHL:
SASSERT(num_args == 2);
return mk_bv_shl(args[0], args[1], result);
@ -200,6 +204,20 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
return mk_bvsmul_no_overflow(num_args, args, false, result);
case OP_BUMUL_NO_OVFL:
return mk_bvumul_no_overflow(num_args, args, result);
case OP_BSMUL_OVFL:
return mk_bvsmul_overflow(num_args, args, result);
case OP_BUMUL_OVFL:
return mk_bvumul_overflow(num_args, args, result);
case OP_BSDIV_OVFL:
return mk_bvsdiv_overflow(num_args, args, result);
case OP_BUADD_OVFL:
return mk_bvuadd_overflow(num_args, args, result);
case OP_BSADD_OVFL:
return mk_bvsadd_over_underflow(num_args, args, result);
case OP_BUSUB_OVFL:
return mk_bvusub_underflow(num_args, args, result);
case OP_BSSUB_OVFL:
return mk_bvssub_overflow(num_args, args, result);
default:
return BR_FAILED;
}
@ -1555,7 +1573,7 @@ br_status bv_rewriter::mk_concat(unsigned num_args, expr * const * args, expr_re
if (eq_args) {
if (m.is_ite(new_args.back(), x, y, z)) {
ptr_buffer<expr> args1, args2;
for (expr* arg : new_args)
for (unsigned i = 0; i < new_args.size(); ++i)
args1.push_back(y), args2.push_back(z);
result = m.mk_ite(x, m_util.mk_concat(args1), m_util.mk_concat(args2));
return BR_REWRITE2;
@ -2925,6 +2943,21 @@ br_status bv_rewriter::mk_distinct(unsigned num_args, expr * const * args, expr_
return BR_DONE;
}
br_status bv_rewriter::mk_bvsmul_overflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
result = m.mk_or(
m.mk_not(m_util.mk_bvsmul_no_ovfl(args[0], args[1])),
m.mk_not(m_util.mk_bvsmul_no_udfl(args[0], args[1]))
);
return BR_REWRITE_FULL;
}
br_status bv_rewriter::mk_bvumul_overflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
result = m.mk_not(m_util.mk_bvumul_no_ovfl(args[0], args[1]));
return BR_REWRITE2;
}
br_status bv_rewriter::mk_bvsmul_no_overflow(unsigned num, expr * const * args, bool is_overflow, expr_ref & result) {
SASSERT(num == 2);
unsigned bv_sz;
@ -2984,5 +3017,95 @@ br_status bv_rewriter::mk_bvumul_no_overflow(unsigned num, expr * const * args,
return BR_FAILED;
}
br_status bv_rewriter::mk_bvneg_overflow(expr * const arg, expr_ref & result) {
unsigned int sz = get_bv_size(arg);
auto maxUnsigned = mk_numeral(rational::power_of_two(sz)-1, sz);
result = m.mk_eq(arg, maxUnsigned);
return BR_REWRITE3;
}
br_status bv_rewriter::mk_bvuadd_overflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
unsigned sz = get_bv_size(args[0]);
auto a1 = mk_zero_extend(1, args[0]);
auto a2 = mk_zero_extend(1, args[1]);
auto r = mk_bv_add(a1, a2);
auto extract = m_mk_extract(sz, sz, r);
result = m.mk_eq(extract, mk_one(1));
return BR_REWRITE_FULL;
}
br_status bv_rewriter::mk_bvsadd_overflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
unsigned sz = get_bv_size(args[0]);
auto zero = mk_zero(sz);
auto r = mk_bv_add(args[0], args[1]);
auto l1 = m_util.mk_slt(zero, args[0]);
auto l2 = m_util.mk_slt(zero, args[1]);
auto args_pos = m.mk_and(l1, l2);
auto non_pos_sum = m_util.mk_sle(r, zero);
result = m.mk_and(args_pos, non_pos_sum);
return BR_REWRITE_FULL;
}
br_status bv_rewriter::mk_bvsadd_underflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
unsigned sz = get_bv_size(args[0]);
auto zero = mk_zero(sz);
auto r = mk_bv_add(args[0], args[1]);
auto l1 = m_util.mk_slt(args[0], zero);
auto l2 = m_util.mk_slt(args[1], zero);
auto args_neg = m.mk_and(l1, l2);
expr_ref non_neg_sum{m};
auto res_rewrite = mk_sge(r, zero, non_neg_sum);
SASSERT(res_rewrite != BR_FAILED); (void)res_rewrite;
result = m.mk_and(args_neg, non_neg_sum);
return BR_REWRITE_FULL;
}
br_status bv_rewriter::mk_bvsadd_over_underflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
expr_ref l1{m};
expr_ref l2{m};
(void)mk_bvsadd_overflow(2, args, l1);
(void)mk_bvsadd_underflow(2, args, l2);
result = m.mk_or(l1, l2);
return BR_REWRITE_FULL;
}
br_status bv_rewriter::mk_bvusub_underflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
br_status status = mk_ult(args[0], args[1], result);
SASSERT(status != BR_FAILED);
return status;
}
br_status bv_rewriter::mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
auto sz = get_bv_size(args[0]);
auto minSigned = mk_numeral(-rational::power_of_two(sz-1), sz);
expr_ref bvsaddo {m};
expr * args2[2] = { args[0], m_util.mk_bv_neg(args[1]) };
auto bvsaddo_stat = mk_bvsadd_overflow(2, args2, bvsaddo);
SASSERT(bvsaddo_stat != BR_FAILED); (void)bvsaddo_stat;
auto first_arg_ge_zero = m_util.mk_sle(mk_zero(sz), args[0]);
result = m.mk_ite(m.mk_eq(args[1], minSigned), first_arg_ge_zero, bvsaddo);
return BR_REWRITE_FULL;
}
br_status bv_rewriter::mk_bvsdiv_overflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
auto sz = get_bv_size(args[1]);
auto minSigned = mk_numeral(-rational::power_of_two(sz-1), sz);
auto minusOne = mk_numeral(rational::power_of_two(sz) - 1, sz);
result = m.mk_and(m.mk_eq(args[0], minSigned), m.mk_eq(args[1], minusOne));
return BR_REWRITE_FULL;
}
template class poly_rewriter<bv_rewriter_core>;

View file

@ -139,6 +139,22 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
br_status mk_mkbv(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsmul_no_overflow(unsigned num, expr * const * args, bool is_overflow, expr_ref & result);
br_status mk_bvumul_no_overflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsmul_overflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvumul_overflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsdiv_overflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvneg_overflow(expr * const arg, expr_ref & result);
br_status mk_bvuadd_overflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsadd_overflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsadd_underflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsadd_over_underflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvusub_underflow(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result);
bool is_minus_one_times_t(expr * arg);
void mk_t1_add_t2_eq_c(expr * t1, expr * t2, expr * c, expr_ref & result);

View file

@ -197,9 +197,10 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
m_pos2var.reserve(num_args, -1);
// Find all disequalities
// Find all equalities/disequalities
for (unsigned i = 0; i < num_args; i++) {
is_eq = is_forall(q) ? is_var_diseq(literals.get(i), num_decls, v, t) : is_var_eq(literals.get(i), num_decls, v, t);
expr* arg = literals.get(i);
is_eq = is_forall(q) ? is_var_diseq(arg, num_decls, v, t) : is_var_eq(arg, num_decls, v, t);
if (is_eq) {
unsigned idx = v->get_idx();
if (m_map.get(idx, nullptr) == nullptr) {

View file

@ -22,6 +22,7 @@ Revision History:
#include "ast/used_vars.h"
#include "util/obj_hashtable.h"
#include "ast/rewriter/rewriter_def.h"
#include "ast/rewriter/var_subst.h"
#include "ast/rewriter/elim_bounds.h"
#include "ast/ast_pp.h"

View file

@ -17,16 +17,36 @@ Author:
#include "ast/rewriter/hoist_rewriter.h"
#include "ast/rewriter/bool_rewriter.h"
#include "ast/ast_util.h"
#include "ast/ast_pp.h"
#include "ast/ast_ll_pp.h"
hoist_rewriter::hoist_rewriter(ast_manager & m, params_ref const & p):
m(m), m_args1(m), m_args2(m), m_subst(m) {
m(m), m_args1(m), m_args2(m), m_refs(m), m_subst(m) {
updt_params(p);
}
expr_ref hoist_rewriter::mk_and(expr_ref_vector const& args) {
if (m_elim_and) {
expr_ref_vector negs(m);
for (expr* a : args)
if (m.is_false(a))
return expr_ref(m.mk_false(), m);
else if (m.is_true(a))
continue;
else
negs.push_back(::mk_not(m, a));
return ::mk_not(mk_or(negs));
}
else
return ::mk_and(args);
}
expr_ref hoist_rewriter::mk_or(expr_ref_vector const& args) {
return ::mk_or(args);
}
br_status hoist_rewriter::mk_or(unsigned num_args, expr * const * es, expr_ref & result) {
if (num_args < 2)
return BR_FAILED;
@ -144,28 +164,26 @@ unsigned hoist_rewriter::mk_var(expr* e) {
}
expr_ref hoist_rewriter::hoist_predicates(obj_hashtable<expr> const& preds, unsigned num_args, expr* const* es) {
expr_ref result(m);
expr_ref_vector args(m), fmls(m);
expr_ref_vector args(m), args1(m), fmls(m);
for (unsigned i = 0; i < num_args; ++i) {
VERIFY(is_and(es[i], &m_args1));
VERIFY(is_and(es[i], &args1));
fmls.reset();
for (expr* e : m_args1)
for (expr* e : args1)
if (!preds.contains(e))
fmls.push_back(e);
args.push_back(::mk_and(fmls));
args.push_back(mk_and(fmls));
}
fmls.reset();
fmls.push_back(::mk_or(args));
fmls.push_back(mk_or(args));
for (auto* p : preds)
fmls.push_back(p);
result = ::mk_and(fmls);
return result;
return mk_and(fmls);
}
br_status hoist_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
switch (f->get_decl_kind()) {
case OP_OR:
case OP_OR:
return mk_or(num_args, args, result);
default:
return BR_FAILED;
@ -173,6 +191,33 @@ br_status hoist_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
}
bool hoist_rewriter::is_and(expr * e, expr_ref_vector* args) {
#if 0
if (!args)
return m.is_and(e) || (m.is_not(e, e) && m.is_or(e));
expr_fast_mark1 visited;
args->reset();
args->push_back(e);
m_refs.reset();
for (unsigned i = 0; i < args->size(); ++i) {
e = args->get(i);
if (visited.is_marked(e))
goto drop;
m_refs.push_back(e);
visited.mark(e, true);
if (m.is_and(e))
args->append(to_app(e)->get_num_args(), to_app(e)->get_args());
else if (m.is_not(e, e) && m.is_or(e))
for (expr* arg : *to_app(e))
args->push_back(::mk_not(m, arg));
else
continue;
drop:
(*args)[i] = args->back();
args->pop_back();
--i;
}
return args->size() > 1;
#else
if (m.is_and(e)) {
if (args) {
args->reset();
@ -185,9 +230,11 @@ bool hoist_rewriter::is_and(expr * e, expr_ref_vector* args) {
args->reset();
for (expr* arg : *to_app(e))
args->push_back(::mk_not(m, arg));
TRACE("hoist", tout << args << " " << * args << "\n");
}
return true;
}
#endif
return false;
}

View file

@ -25,9 +25,11 @@ Notes:
#include "util/union_find.h"
#include "util/obj_hashtable.h"
class bool_rewriter;
class hoist_rewriter {
ast_manager & m;
expr_ref_vector m_args1, m_args2;
expr_ref_vector m_args1, m_args2, m_refs;
obj_hashtable<expr> m_preds1, m_preds2;
basic_union_find m_uf1, m_uf2, m_uf0;
ptr_vector<expr> m_es;
@ -37,8 +39,11 @@ class hoist_rewriter {
obj_map<expr, unsigned> m_expr2var;
ptr_vector<expr> m_var2expr;
expr_mark m_mark;
bool m_elim_and = false;
bool is_and(expr* e, expr_ref_vector* args);
expr_ref mk_and(expr_ref_vector const& args);
expr_ref mk_or(expr_ref_vector const& args);
bool is_var(expr* e) { return m_expr2var.contains(e); }
expr* mk_expr(unsigned v) { return m_var2expr[v]; }
@ -48,6 +53,7 @@ class hoist_rewriter {
expr_ref hoist_predicates(obj_hashtable<expr> const& p, unsigned num_args, expr* const* args);
public:
hoist_rewriter(ast_manager & m, params_ref const & p = params_ref());
family_id get_fid() const { return m.get_basic_family_id(); }
@ -56,6 +62,7 @@ public:
static void get_param_descrs(param_descrs & r) {}
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
br_status mk_or(unsigned num_args, expr * const * args, expr_ref & result);
void set_elim_and(bool b) { m_elim_and = b; }
};
struct hoist_rewriter_cfg : public default_rewriter_cfg {

View file

@ -92,7 +92,7 @@ br_status maximize_ac_sharing::reduce_app(func_decl * f, unsigned num_args, expr
else {
result = m.mk_app(f, numeral, _args[0]);
}
TRACE("ac_sharing_detail", tout << "result: " << mk_pp(result, m) << "\n";);
TRACE("ac_sharing_detail", tout << "result: " << result << "\n";);
return BR_DONE;
}
}

View file

@ -825,16 +825,17 @@ struct pb2bv_rewriter::imp {
if (a->get_family_id() == au.get_family_id()) {
switch (a->get_decl_kind()) {
case OP_ADD:
for (unsigned i = 0; i < sz; ++i) {
if (!is_pb(a->get_arg(i), mul)) return false;
}
for (unsigned i = 0; i < sz; ++i)
if (!is_pb(a->get_arg(i), mul))
return false;
return true;
case OP_SUB: {
if (!is_pb(a->get_arg(0), mul)) return false;
if (!is_pb(a->get_arg(0), mul))
return false;
r = -mul;
for (unsigned i = 1; i < sz; ++i) {
if (!is_pb(a->get_arg(1), r)) return false;
}
for (unsigned i = 1; i < sz; ++i)
if (!is_pb(a->get_arg(i), r))
return false;
return true;
}
case OP_UMINUS:

View file

@ -18,6 +18,7 @@ Revision History:
--*/
#include "ast/rewriter/push_app_ite.h"
#include "ast/rewriter/rewriter_def.h"
#include "ast/ast_pp.h"

View file

@ -347,7 +347,7 @@ public:
Config & cfg() { return m_cfg; }
Config const & cfg() const { return m_cfg; }
~rewriter_tpl() override;
~rewriter_tpl() override {};
void reset();
void cleanup();

View file

@ -640,10 +640,6 @@ rewriter_tpl<Config>::rewriter_tpl(ast_manager & m, bool proof_gen, Config & cfg
m_pr2(m) {
}
template<typename Config>
rewriter_tpl<Config>::~rewriter_tpl() {
}
template<typename Config>
void rewriter_tpl<Config>::reset() {
m_cfg.reset();

View file

@ -513,8 +513,8 @@ namespace seq {
!contains(t, s) => i = -1
|t| = 0 => |s| = 0 or i = -1
|t| = 0 & |s| = 0 => i = 0
|t| != 0 & contains(t, s) => t = xsy & i = len(x)
|s| = 0 => i = len(t)
|s| = 0 or s = s_head*s_tail
|s| = 0 or !contains(s_tail*y, s)
@ -540,7 +540,7 @@ namespace seq {
add_clause(cnt, i_eq_m1);
add_clause(~t_eq_empty, s_eq_empty, i_eq_m1);
add_clause(~t_eq_empty, ~s_eq_empty, i_eq_0);
add_clause(~s_eq_empty, mk_eq(i, mk_len(t)));
add_clause(t_eq_empty, ~cnt, mk_seq_eq(t, xsy));
add_clause(t_eq_empty, ~cnt, mk_eq(i, mk_len(x)));
add_clause(s_eq_empty, mk_eq(s, mk_concat(s_head, s_tail)));
@ -928,7 +928,6 @@ namespace seq {
e1 < e2 => prefix(e1, e2) or e1 = xcy
e1 < e2 => prefix(e1, e2) or c < d
e1 < e2 => prefix(e1, e2) or e2 = xdz
e1 < e2 => e1 != e2
!(e1 < e2) => prefix(e2, e1) or e2 = xdz
!(e1 < e2) => prefix(e2, e1) or d < c
!(e1 < e2) => prefix(e2, e1) or e1 = xcy
@ -938,6 +937,7 @@ namespace seq {
e1 < e2 or e1 = e2 or e2 < e1
!(e1 = e2) or !(e2 < e1)
!(e1 < e2) or !(e2 < e1)
*/
void axioms::lt_axiom(expr* n) {
expr* _e1 = nullptr, *_e2 = nullptr;
@ -948,6 +948,7 @@ namespace seq {
sort* char_sort = nullptr;
VERIFY(seq.is_seq(s, char_sort));
expr_ref lt = expr_ref(n, m);
expr_ref gt = expr_ref(seq.str.mk_lex_lt(e2, e1), m);
expr_ref x = m_sk.mk("str.<.x", e1, e2);
expr_ref y = m_sk.mk("str.<.y", e1, e2);
expr_ref z = m_sk.mk("str.<.z", e1, e2);
@ -969,6 +970,7 @@ namespace seq {
add_clause(lt, pref21, ltdc);
add_clause(lt, pref21, e2xdz);
add_clause(~eq, ~lt);
add_clause(eq, lt, gt);
}
/**
@ -1235,7 +1237,7 @@ namespace seq {
seq.str.is_string(x)) {
expr_ref len(n, m);
m_rewrite(len);
SASSERT(n != len);
SASSERT(m.limit().is_canceled() || n != len);
add_clause(mk_eq(len, n));
}
else {

View file

@ -190,8 +190,8 @@ namespace seq {
expr_ref digit = m_ax.sk().mk_digit2int(u);
add_consequence(m_ax.mk_ge(digit, 1));
}
expr_ref y(seq.str.mk_concat(es, es[0]->get_sort()), m);
ctx.add_solution(seq.str.mk_itos(n), y);
expr_ref y(seq.str.mk_concat(es, es[0]->get_sort()), m);
ctx.add_solution(seq.str.mk_itos(n), y);
return true;
}

View file

@ -5024,12 +5024,14 @@ br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
* (re.range c_1 c_n)
*/
br_status seq_rewriter::mk_re_range(expr* lo, expr* hi, expr_ref& result) {
zstring s;
zstring slo, shi;
unsigned len = 0;
bool is_empty = false;
if (str().is_string(lo, s) && s.length() != 1)
if (str().is_string(lo, slo) && slo.length() != 1)
is_empty = true;
if (str().is_string(hi, s) && s.length() != 1)
if (str().is_string(hi, shi) && shi.length() != 1)
is_empty = true;
if (slo.length() == 1 && shi.length() == 1 && slo[0] > shi[0])
is_empty = true;
len = min_length(lo).second;
if (len > 1)
@ -5246,7 +5248,17 @@ br_status seq_rewriter::reduce_re_is_empty(expr* r, expr_ref& result) {
else if (re().is_range(r, r1, r2) &&
str().is_string(r1, s1) && str().is_string(r2, s2) &&
s1.length() == 1 && s2.length() == 1) {
result = m().mk_bool_val(s1[0] <= s2[0]);
result = m().mk_bool_val(s1[0] > s2[0]);
return BR_DONE;
}
else if (re().is_range(r, r1, r2) &&
str().is_string(r1, s1) && s1.length() != 1) {
result = m().mk_true();
return BR_DONE;
}
else if (re().is_range(r, r1, r2) &&
str().is_string(r2, s2) && s2.length() != 1) {
result = m().mk_true();
return BR_DONE;
}
else if ((re().is_loop(r, r1, lo) ||
@ -5307,6 +5319,7 @@ br_status seq_rewriter::mk_le_core(expr * l, expr * r, expr_ref & result) {
}
br_status seq_rewriter::mk_eq_core(expr * l, expr * r, expr_ref & result) {
TRACE("seq", tout << mk_pp(l, m()) << " == " << mk_pp(r, m()) << "\n");
expr_ref_vector res(m());
expr_ref_pair_vector new_eqs(m());
if (m_util.is_re(l)) {
@ -5518,6 +5531,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
reduce_front(ls, rs, eqs) &&
reduce_itos(ls, rs, eqs) &&
reduce_itos(rs, ls, eqs) &&
reduce_value_clash(ls, rs, eqs) &&
reduce_by_length(ls, rs, eqs) &&
reduce_subsequence(ls, rs, eqs) &&
reduce_non_overlap(ls, rs, eqs) &&
@ -5943,6 +5957,47 @@ bool seq_rewriter::reduce_non_overlap(expr_ref_vector& ls, expr_ref_vector& rs,
return true;
}
/**
* partial check for value clash.
* checks that elements that do not occur in
* other sequence are non-values.
* The check could be extended to take non-value
* characters (units) into account.
*/
bool seq_rewriter::reduce_value_clash(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
ptr_buffer<expr> es;
if (ls.empty() || rs.empty())
return true;
es.append(ls.size(), ls.data());
auto remove = [&](expr* r) {
for (unsigned i = 0; i < es.size(); ++i) {
if (r == es[i]) {
es[i] = es.back();
es.pop_back();
return true;
}
}
return false;
};
auto is_unit_value = [&](expr* r) {
return m().is_value(r) && str().is_unit(r);
};
for (expr* r : rs) {
if (remove(r))
continue;
if (!is_unit_value(r))
return true;
}
if (es.empty())
return true;
for (expr* e : es)
if (!is_unit_value(e))
return true;
return false;
}
bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
if (ls.size() > rs.size())

View file

@ -340,6 +340,7 @@ class seq_rewriter {
bool is_sequence(expr* e, expr_ref_vector& seq);
bool is_sequence(eautomaton& aut, expr_ref_vector& seq);
bool get_lengths(expr* e, expr_ref_vector& lens, rational& pos);
bool reduce_value_clash(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
bool reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
bool reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
void remove_empty_and_concats(expr_ref_vector& es);

View file

@ -31,6 +31,7 @@ Notes:
#include "ast/rewriter/seq_rewriter.h"
#include "ast/rewriter/rewriter_def.h"
#include "ast/rewriter/var_subst.h"
#include "ast/rewriter/der.h"
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/expr_substitution.h"
#include "ast/ast_smt2_pp.h"
@ -54,6 +55,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
recfun_rewriter m_rec_rw;
arith_util m_a_util;
bv_util m_bv_util;
der m_der;
expr_safe_replace m_rep;
expr_ref_vector m_pinned;
// substitution support
@ -821,6 +823,26 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << result << " " << result_pr << "\n" ;);
proof_ref p2(m());
expr_ref r(m());
bool der_change = false;
if (is_quantifier(result) && to_quantifier(result)->get_num_patterns() == 0) {
m_der(to_quantifier(result), r, p2);
der_change = result.get() != r.get();
if (m().proofs_enabled() && der_change)
result_pr = m().mk_transitivity(result_pr, p2);
result = r;
}
if (der_change) {
th_rewriter rw(m());
rw(result, r, p2);
if (m().proofs_enabled() && result.get() != r.get())
result_pr = m().mk_transitivity(result_pr, p2);
result = r;
}
SASSERT(old_q->get_sort() == result->get_sort());
return true;
}
@ -839,6 +861,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
m_rec_rw(m),
m_a_util(m),
m_bv_util(m),
m_der(m),
m_rep(m),
m_pinned(m),
m_used_dependencies(m) {
@ -944,17 +967,41 @@ void th_rewriter::reset() {
}
void th_rewriter::operator()(expr_ref & term) {
expr_ref result(term.get_manager());
m_imp->operator()(term, result);
term = std::move(result);
expr_ref result(term.get_manager());
try {
m_imp->operator()(term, result);
term = std::move(result);
}
catch (...) {
if (!term.get_manager().inc())
return;
throw;
}
}
void th_rewriter::operator()(expr * t, expr_ref & result) {
m_imp->operator()(t, result);
try {
m_imp->operator()(t, result);
}
catch (...) {
result = t;
if (!result.get_manager().inc())
return;
throw;
}
}
void th_rewriter::operator()(expr * t, expr_ref & result, proof_ref & result_pr) {
m_imp->operator()(t, result, result_pr);
try {
m_imp->operator()(t, result, result_pr);
}
catch (...) {
result = t;
result_pr = nullptr;
if (!result.get_manager().inc())
return;
throw;
}
}
expr_ref th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings) {

View file

@ -663,19 +663,21 @@ void seq_decl_plugin::add_map_sig() {
m_sigs[OP_SEQ_MAP] = alloc(psig, m, "seq.map", 2, 2, arrABseqA, seqB);
m_sigs[OP_SEQ_MAPI] = alloc(psig, m, "seq.mapi", 2, 3, arrIABintTseqA, seqB);
m_sigs[OP_SEQ_FOLDL] = alloc(psig, m, "seq.fold_left", 2, 3, arrBAB_BseqA, B);
m_sigs[OP_SEQ_FOLDLI] = alloc(psig, m, "seq.fold_leftli", 2, 4, arrIBABintTBseqA, B);
m_sigs[OP_SEQ_FOLDLI] = alloc(psig, m, "seq.fold_lefti", 2, 4, arrIBABintTBseqA, B);
}
void seq_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
init();
for (unsigned i = 0; i < m_sigs.size(); ++i) {
if (m_sigs[i])
op_names.push_back(builtin_name(m_sigs[i]->m_name.str(), i));
if (m_sigs[i])
op_names.push_back(builtin_name(m_sigs[i]->m_name.str(), i));
}
op_names.push_back(builtin_name("seq.map", OP_SEQ_MAP));
op_names.push_back(builtin_name("seq.mapi", OP_SEQ_MAPI));
op_names.push_back(builtin_name("seq.foldl", OP_SEQ_FOLDL));
op_names.push_back(builtin_name("seq.foldli", OP_SEQ_FOLDLI));
op_names.push_back(builtin_name("seq.fold_lefti", OP_SEQ_FOLDLI));
op_names.push_back(builtin_name("seq.fold_left", OP_SEQ_FOLDL));
op_names.push_back(builtin_name("str.in.re", _OP_STRING_IN_REGEXP));
op_names.push_back(builtin_name("str.in-re", _OP_STRING_IN_REGEXP));
op_names.push_back(builtin_name("str.to.re", _OP_STRING_TO_REGEXP));

View file

@ -81,7 +81,7 @@ void dependent_expr_state::freeze_recfun() {
ast_mark visited;
for (func_decl* f : rec.get_rec_funs()) {
auto& d = rec.get_def(f);
if (!d.is_macro())
if (!d.is_macro() && d.get_rhs())
freeze_terms(d.get_rhs(), false, visited);
}
m_trail.push(value_trail(m_num_recfun));

View file

@ -41,7 +41,7 @@ class dominator_simplifier : public dependent_expr_simplifier {
bool is_subexpr(expr * a, expr * b);
expr_ref get_cached(expr* t) { expr* r = nullptr; if (!m_result.find(t, r)) r = t; return expr_ref(r, m); }
void cache(expr *t, expr* r) { m_result.insert(t, r); m_trail.push_back(r); }
void cache(expr *t, expr* r) { m_result.insert(t, r); m_trail.push_back(r); m_trail.push_back(t); }
void reset_cache() { m_result.reset(); }
ptr_vector<expr> const & tree(expr * e);

View file

@ -52,9 +52,9 @@ monotonicity or reflexivity rules.
#include "ast/simplifiers/elim_unconstrained.h"
elim_unconstrained::elim_unconstrained(ast_manager& m, dependent_expr_state& fmls) :
dependent_expr_simplifier(m, fmls), m_inverter(m), m_lt(*this), m_heap(1024, m_lt), m_trail(m) {
dependent_expr_simplifier(m, fmls), m_inverter(m), m_lt(*this), m_heap(1024, m_lt), m_trail(m), m_args(m) {
std::function<bool(expr*)> is_var = [&](expr* e) {
return is_uninterp_const(e) && !m_fmls.frozen(e) && get_node(e).m_refcount <= 1;
return is_uninterp_const(e) && !m_fmls.frozen(e) && is_node(e) && get_node(e).m_refcount <= 1;
};
m_inverter.set_is_var(is_var);
}
@ -73,7 +73,7 @@ void elim_unconstrained::eliminate() {
node& n = get_node(v);
if (n.m_refcount == 0)
continue;
if (n.m_refcount > 1)
if (n.m_refcount > 1)
return;
if (n.m_parents.empty()) {
@ -90,10 +90,10 @@ void elim_unconstrained::eliminate() {
unsigned sz = m_args.size();
for (expr* arg : *to_app(t))
m_args.push_back(reconstruct_term(get_node(arg)));
bool inverted = m_inverter(t->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz, r);
bool inverted = m_inverter(t->get_decl(), t->get_num_args(), m_args.data() + sz, r);
proof_ref pr(m);
if (inverted && m_enable_proofs) {
expr * s = m.mk_app(t->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz);
expr * s = m.mk_app(t->get_decl(), t->get_num_args(), m_args.data() + sz);
expr * eq = m.mk_eq(s, r);
proof * pr1 = m.mk_def_intro(eq);
proof * pr = m.mk_apply_def(s, r, pr1);
@ -114,7 +114,7 @@ void elim_unconstrained::eliminate() {
gc(e);
invalidate_parents(e);
freeze_rec(r);
m_root.setx(r->get_id(), e->get_id(), UINT_MAX);
get_node(e).m_term = r;
get_node(e).m_proof = pr;
@ -291,7 +291,7 @@ expr_ref elim_unconstrained::reconstruct_term(node& n0) {
unsigned sz0 = todo.size();
if (is_app(t)) {
for (expr* arg : *to_app(t))
if (get_node(arg).m_dirty)
if (get_node(arg).m_dirty || !get_node(arg).m_term)
todo.push_back(arg);
if (todo.size() != sz0)
continue;
@ -300,18 +300,20 @@ expr_ref elim_unconstrained::reconstruct_term(node& n0) {
for (expr* arg : *to_app(t))
m_args.push_back(get_node(arg).m_term);
n.m_term = m.mk_app(to_app(t)->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz);
m_args.shrink(sz);
}
else if (is_quantifier(t)) {
expr* body = to_quantifier(t)->get_expr();
node& n2 = get_node(body);
if (n2.m_dirty) {
if (n2.m_dirty || !n2.m_term) {
todo.push_back(body);
continue;
}
n.m_term = m.update_quantifier(to_quantifier(t), n2.m_term);
}
m_trail.push_back(n.m_term);
m_root.setx(n.m_term->get_id(), n.m_term->get_id(), UINT_MAX);
todo.pop_back();
n.m_dirty = false;
}

View file

@ -22,6 +22,8 @@ Author:
class elim_unconstrained : public dependent_expr_simplifier {
friend class seq_simplifier;
struct node {
unsigned m_refcount = 0;
expr* m_term = nullptr;
@ -46,13 +48,15 @@ class elim_unconstrained : public dependent_expr_simplifier {
var_lt m_lt;
heap<var_lt> m_heap;
expr_ref_vector m_trail;
ptr_vector<expr> m_args;
expr_ref_vector m_args;
stats m_stats;
unsigned_vector m_root;
bool m_created_compound = false;
bool m_enable_proofs = false;
bool is_var_lt(int v1, int v2) const;
bool is_node(unsigned n) const { return m_nodes.size() > n; }
bool is_node(expr* t) const { return is_node(t->get_id()); }
node& get_node(unsigned n) { return m_nodes[n]; }
node const& get_node(unsigned n) const { return m_nodes[n]; }
node& get_node(expr* t) { return m_nodes[root(t)]; }

View file

@ -174,7 +174,7 @@ bool eliminate_predicates::can_be_quasi_macro_head(expr* _head, unsigned num_bou
// then replace (f x y z) by (if (= z (+ x y)) s (f' x y z))
//
void eliminate_predicates::insert_quasi_macro(app* head, expr* body, clause const& cl) {
void eliminate_predicates::insert_quasi_macro(app* head, expr* body, clause& cl) {
expr_ref _body(body, m);
uint_set indices;
expr_ref_vector args(m), eqs(m);
@ -205,9 +205,10 @@ void eliminate_predicates::insert_quasi_macro(app* head, expr* body, clause cons
// forall vars . f(args) = if eqs then body else f'(args)
f1 = m.mk_fresh_func_decl(f->get_name(), symbol::null, sorts.size(), sorts.data(), f->get_range());
lhs = m.mk_app(f, args);
rhs = m.mk_ite(mk_and(eqs), body, m.mk_app(f1, args));
insert_macro(lhs, rhs, cl.m_dep);
insert_macro(lhs, rhs, cl);
}
@ -310,6 +311,12 @@ bool eliminate_predicates::is_macro_safe(expr* e) {
return true;
}
void eliminate_predicates::insert_macro(app* head, expr* def, clause& cl) {
insert_macro(head, def, cl.m_dep);
TRACE("elim_predicates", tout << "remove " << cl << "\n");
cl.m_alive = false;
}
void eliminate_predicates::insert_macro(app* head, expr* def, expr_dependency* dep) {
unsigned num = head->get_num_args();
ptr_buffer<expr> vars, subst_args;
@ -334,7 +341,7 @@ void eliminate_predicates::insert_macro(app* head, expr* def, expr_dependency* d
auto* info = alloc(macro_def, _head, _def, _dep);
m_macros.insert(head->get_decl(), info);
m_fmls.model_trail().push(head->get_decl(), _def, _dep, {}); // augment with definition for head
m_is_macro.mark(head->get_decl(), true);
m_is_macro.mark(head->get_decl(), true);
TRACE("elim_predicates", tout << "insert " << _head << " " << _def << "\n");
++m_stats.m_num_macros;
}
@ -367,26 +374,22 @@ void eliminate_predicates::try_find_macro(clause& cl) {
// (= (f x) t)
if (cl.is_unit() && !cl.sign(0) && m.is_eq(cl.atom(0), x, y)) {
if (can_be_def(x, y)) {
insert_macro(to_app(x), y, cl.m_dep);
cl.m_alive = false;
insert_macro(to_app(x), y, cl);
return;
}
if (can_be_def(y, x)) {
insert_macro(to_app(y), x, cl.m_dep);
cl.m_alive = false;
insert_macro(to_app(y), x, cl);
return;
}
}
// not (= (p x) t) -> (p x) = (not t)
if (cl.is_unit() && cl.sign(0) && m.is_iff(cl.atom(0), x, y)) {
if (can_be_def(x, y)) {
insert_macro(to_app(x), m.mk_not(y), cl.m_dep);
cl.m_alive = false;
insert_macro(to_app(x), m.mk_not(y), cl);
return;
}
if (can_be_def(y, x)) {
insert_macro(to_app(y), m.mk_not(x), cl.m_dep);
cl.m_alive = false;
insert_macro(to_app(y), m.mk_not(x), cl);
return;
}
}
@ -413,8 +416,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
m_fmls.model_trail().hide(fn); // hide definition of fn
k = m.mk_app(fn, f->get_num_args(), f->get_args());
def = m.mk_ite(cond, t, k);
insert_macro(f, def, cl.m_dep);
cl.m_alive = false;
insert_macro(f, def, cl);
fml = m.mk_not(m.mk_eq(k, t));
clause* new_cl = init_clause(fml, cl.m_dep, UINT_MAX);
add_use_list(*new_cl);
@ -531,8 +533,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
expr_ref y1 = subtract(y, to_app(x), i);
if (inv)
y1 = uminus(y1);
insert_macro(to_app(arg), y1, cl.m_dep);
cl.m_alive = false;
insert_macro(to_app(arg), y1, cl);
return true;
}
next:
@ -572,7 +573,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
!occurs(x->get_decl(), y);
};
if (cl.is_unit() && m.is_eq(cl.atom(0), x, y)) {
if (cl.is_unit() && m.is_eq(cl.atom(0), x, y) && !cl.m_bound.empty()) {
if (!cl.sign(0) && can_be_qdef(x, y)) {
insert_quasi_macro(to_app(x), y, cl);
return;
@ -590,7 +591,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
return;
}
}
if (cl.is_unit()) {
if (cl.is_unit() && !cl.m_bound.empty()) {
expr* body = cl.sign(0) ? m.mk_false() : m.mk_true();
expr* x = cl.atom(0);
if (can_be_qdef(x, body)) {
@ -736,6 +737,7 @@ void eliminate_predicates::update_model(func_decl* p) {
}
rewrite(def);
TRACE("elim_predicates", tout << "insert " << p->get_name() << " " << def << "\n");
m_fmls.model_trail().push(p, def, dep, deleted);
}
@ -1008,8 +1010,6 @@ void eliminate_predicates::reset() {
void eliminate_predicates::reduce() {
if (!m_fmls.has_quantifiers())
return;
reset();
init_clauses();
find_definitions();

View file

@ -111,9 +111,10 @@ private:
bool try_find_binary_definition(func_decl* p, app_ref& head, expr_ref& def, expr_dependency_ref& dep);
void try_resolve_definition(func_decl* p);
void insert_macro(app* head, expr* def, expr_dependency* dep);
void insert_macro(app* head, expr* def, clause& cl);
expr_ref bind_free_variables_in_def(clause& cl, app* head, expr* def);
bool can_be_macro_head(expr* head, unsigned num_bound);
void insert_quasi_macro(app* head, expr* body, clause const& cl);
void insert_quasi_macro(app* head, expr* body, clause& cl);
bool can_be_quasi_macro_head(expr* head, unsigned num_bound);
bool is_macro_safe(expr* e);
void try_find_macro(clause& cl);

View file

@ -262,6 +262,47 @@ namespace euf {
}
}
void solve_eqs::collect_num_occs(expr * t, expr_fast_mark1 & visited) {
ptr_buffer<app, 128> stack;
auto visit = [&](expr* arg) {
if (is_uninterp_const(arg))
m_num_occs.insert_if_not_there(arg, 0)++;
if (!visited.is_marked(arg) && is_app(arg)) {
visited.mark(arg, true);
stack.push_back(to_app(arg));
}
};
visit(t);
while (!stack.empty()) {
app * t = stack.back();
stack.pop_back();
for (expr* arg : *t)
visit(arg);
}
}
void solve_eqs::collect_num_occs() {
if (m_config.m_max_occs == UINT_MAX)
return; // no need to compute num occs
m_num_occs.reset();
expr_fast_mark1 visited;
for (unsigned i : indices())
collect_num_occs(m_fmls[i].fml(), visited);
}
// Check if the number of occurrences of t is below the specified threshold :solve-eqs-max-occs
bool solve_eqs::check_occs(expr * t) const {
if (m_config.m_max_occs == UINT_MAX)
return true;
unsigned num = 0;
m_num_occs.find(t, num);
TRACE("solve_eqs_check_occs", tout << mk_ismt2_pp(t, m) << " num_occs: " << num << " max: " << m_config.m_max_occs << "\n";);
return num <= m_config.m_max_occs;
}
void solve_eqs::save_subst(vector<dependent_expr> const& old_fmls) {
if (!m_subst->empty())
m_fmls.model_trail().push(m_subst.detach(), old_fmls);

View file

@ -56,10 +56,12 @@ namespace euf {
expr_mark m_unsafe_vars; // expressions that cannot be replaced
ptr_vector<expr> m_todo;
expr_mark m_visited;
obj_map<expr, unsigned> m_num_occs;
bool is_var(expr* e) const { return e->get_id() < m_var2id.size() && m_var2id[e->get_id()] != UINT_MAX; }
unsigned var2id(expr* v) const { return m_var2id[v->get_id()]; }
bool can_be_var(expr* e) const { return is_uninterp_const(e) && !m_unsafe_vars.is_marked(e); }
bool can_be_var(expr* e) const { return is_uninterp_const(e) && !m_unsafe_vars.is_marked(e) && check_occs(e); }
void get_eqs(dep_eq_vector& eqs);
void filter_unsafe_vars();
void extract_subst();
@ -67,6 +69,9 @@ namespace euf {
void normalize();
void apply_subst(vector<dependent_expr>& old_fmls);
void save_subst(vector<dependent_expr> const& old_fmls);
void collect_num_occs(expr * t, expr_fast_mark1 & visited);
void collect_num_occs();
bool check_occs(expr* t) const;
public:

View file

@ -3,7 +3,7 @@ Copyright (c) 2022 Microsoft Corporation
Module Name:
seq_simplifier.h
then_simplifier.h
Abstract:
@ -21,7 +21,7 @@ Author:
#include "ast/simplifiers/dependent_expr_state.h"
class seq_simplifier : public dependent_expr_simplifier {
class then_simplifier : public dependent_expr_simplifier {
scoped_ptr_vector<dependent_expr_simplifier> m_simplifiers;
struct collect_stats {
@ -53,7 +53,7 @@ class seq_simplifier : public dependent_expr_simplifier {
public:
seq_simplifier(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
then_simplifier(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
dependent_expr_simplifier(m, fmls) {
}

View file

@ -47,6 +47,7 @@ func_decl * special_relations_decl_plugin::mk_func_decl(
if (!m_manager->is_bool(range)) {
m_manager->raise_exception("range type is expected to be Boolean for special relations");
}
m_has_special_relation = true;
func_decl_info info(m_family_id, k, num_parameters, parameters);
symbol name;
switch(k) {
@ -54,7 +55,11 @@ func_decl * special_relations_decl_plugin::mk_func_decl(
case OP_SPECIAL_RELATION_LO: name = m_lo; break;
case OP_SPECIAL_RELATION_PLO: name = m_plo; break;
case OP_SPECIAL_RELATION_TO: name = m_to; break;
case OP_SPECIAL_RELATION_TC: name = m_tc; break;
case OP_SPECIAL_RELATION_TC:
name = m_tc;
if (num_parameters != 1 || !parameters[0].is_ast() || !is_func_decl(parameters[0].get_ast()))
m_manager->raise_exception("parameter to transitive closure should be a function declaration");
break;
}
return m_manager->mk_func_decl(name, arity, domain, range, info);
}

View file

@ -37,6 +37,7 @@ class special_relations_decl_plugin : public decl_plugin {
symbol m_plo;
symbol m_to;
symbol m_tc;
bool m_has_special_relation = false;
public:
special_relations_decl_plugin();
@ -50,6 +51,8 @@ public:
void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { return nullptr; }
bool has_special_relation() const { return m_has_special_relation; }
};
enum sr_property {
@ -71,15 +74,19 @@ class special_relations_util {
ast_manager& m;
mutable family_id m_fid;
func_decl* mk_rel_decl(func_decl* f, decl_kind k) {
SASSERT(f);
parameter p(f); SASSERT(f->get_arity() == 2);
return m.mk_func_decl(fid(), k, 1, &p, 2, f->get_domain(), f->get_range());
}
family_id fid() const {
if (null_family_id == m_fid) m_fid = m.get_family_id("specrels");
if (null_family_id == m_fid)
m_fid = m.get_family_id("specrels");
return m_fid;
}
public:
special_relations_util(ast_manager& m) : m(m), m_fid(null_family_id) { }
bool has_special_relation() const { return static_cast<special_relations_decl_plugin*>(m.get_plugin(m.mk_family_id("specrels")))->has_special_relation(); }
bool is_special_relation(func_decl* f) const { return f->get_family_id() == fid(); }
bool is_special_relation(app* e) const { return is_special_relation(e->get_decl()); }
@ -99,6 +106,12 @@ public:
bool is_to(expr const * e) const { return is_app_of(e, fid(), OP_SPECIAL_RELATION_TO); }
bool is_tc(expr const * e) const { return is_app_of(e, fid(), OP_SPECIAL_RELATION_TC); }
bool is_lo(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_LO); }
bool is_po(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_PO); }
bool is_plo(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_PLO); }
bool is_to(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_TO); }
bool is_tc(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_TC); }
app * mk_lo (expr * arg1, expr * arg2) { return m.mk_app( fid(), OP_SPECIAL_RELATION_LO, arg1, arg2); }
app * mk_po (expr * arg1, expr * arg2) { return m.mk_app( fid(), OP_SPECIAL_RELATION_PO, arg1, arg2); }
app * mk_plo(expr * arg1, expr * arg2) { return m.mk_app( fid(), OP_SPECIAL_RELATION_PLO, arg1, arg2); }

View file

@ -361,7 +361,7 @@ void cmd_context::insert_macro(symbol const& s, unsigned arity, sort*const* doma
vars.push_back(m().mk_var(i, domain[i]));
rvars.push_back(m().mk_var(i, domain[arity - i - 1]));
}
recfun::promise_def d = p.ensure_def(s, arity, domain, t->get_sort());
recfun::promise_def d = p.ensure_def(s, arity, domain, t->get_sort(), false);
// recursive functions have opposite calling convention from macros!
var_subst sub(m(), true);
@ -984,7 +984,7 @@ recfun::decl::plugin& cmd_context::get_recfun_plugin() {
recfun::promise_def cmd_context::decl_rec_fun(const symbol &name, unsigned int arity, sort *const *domain, sort *range) {
SASSERT(logic_has_recfun());
return get_recfun_plugin().mk_def(name, arity, domain, range);
return get_recfun_plugin().mk_def(name, arity, domain, range, false);
}
void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, svector<symbol> const& ids, expr* rhs) {
@ -1237,7 +1237,10 @@ bool cmd_context::try_mk_pdecl_app(symbol const & s, unsigned num_args, expr * c
if (num_args != 1)
return false;
for (auto* a : dt.plugin().get_accessors(s)) {
if (!dt.is_datatype(args[0]->get_sort()))
return false;
for (auto* a : dt.plugin().get_accessors(s)) {
fn = a->instantiate(args[0]->get_sort());
r = m().mk_app(fn, num_args, args);
return true;
@ -1979,23 +1982,28 @@ void cmd_context::complete_model(model_ref& md) const {
}
}
for (auto kd : m_func_decls) {
symbol const & k = kd.m_key;
func_decls & v = kd.m_value;
for (auto& [k, v] : m_func_decls) {
IF_VERBOSE(12, verbose_stream() << "(model.completion " << k << ")\n"; );
for (unsigned i = 0; i < v.get_num_entries(); i++) {
func_decl * f = v.get_entry(i);
if (!md->has_interpretation(f)) {
sort * range = f->get_range();
expr * some_val = m().get_some_value(range);
if (f->get_arity() > 0) {
func_interp * fi = alloc(func_interp, m(), f->get_arity());
fi->set_else(some_val);
md->register_decl(f, fi);
}
else
md->register_decl(f, some_val);
if (md->has_interpretation(f))
continue;
macro_decls decls;
expr* body = nullptr;
if (m_macros.find(k, decls))
body = decls.find(f->get_arity(), f->get_domain());
sort * range = f->get_range();
if (!body)
body = m().get_some_value(range);
if (f->get_arity() > 0) {
func_interp * fi = alloc(func_interp, m(), f->get_arity());
fi->set_else(body);
md->register_decl(f, fi);
}
else
md->register_decl(f, body);
}
}
}
@ -2201,21 +2209,18 @@ void cmd_context::display_statistics(bool show_total_time, double total_time) {
}
expr_ref_vector cmd_context::tracked_assertions() {
expr_ref_vector result(m());
vector<std::pair<expr*,expr*>> cmd_context::tracked_assertions() {
vector<std::pair<expr*,expr*>> result;
if (assertion_names().size() == assertions().size()) {
for (unsigned i = 0; i < assertions().size(); ++i) {
expr* an = assertion_names()[i];
expr* asr = assertions()[i];
if (an)
result.push_back(m().mk_implies(an, asr));
else
result.push_back(asr);
result.push_back({ asr, an });
}
}
else {
for (expr * e : assertions())
result.push_back(e);
result.push_back({ e, nullptr});
}
return result;
}

View file

@ -523,7 +523,7 @@ public:
ptr_vector<expr> const& assertions() const { return m_assertions; }
ptr_vector<expr> const& assertion_names() const { return m_assertion_names; }
expr_ref_vector tracked_assertions();
vector<std::pair<expr*,expr*>> tracked_assertions();
void reset_tracked_assertions();
/**

View file

@ -21,7 +21,7 @@ Author:
#include "cmd_context/parametric_cmd.h"
#include "model/model_smt2_pp.h"
#include "ast/ast_smt2_pp.h"
#include "ast/simplifiers/seq_simplifier.h"
#include "ast/simplifiers/then_simplifier.h"
#include "solver/simplifier_solver.h"
typedef dependent_expr_simplifier simplifier;
@ -37,7 +37,7 @@ static simplifier_factory mk_and_then(cmd_context & ctx, sexpr * n) {
for (unsigned i = 1; i < num_children; i++)
args.push_back(sexpr2simplifier(ctx, n->get_child(i)));
simplifier_factory result = [args](ast_manager& m, const params_ref& p, dependent_expr_state& st) {
scoped_ptr<seq_simplifier> s = alloc(seq_simplifier, m, p, st);
scoped_ptr<then_simplifier> s = alloc(then_simplifier, m, p, st);
for (auto & simp : args)
s->add_simplifier(simp(m, p, st));
return s.detach();

View file

@ -72,6 +72,7 @@ public:
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; }
@ -184,6 +185,14 @@ public:
bool upper_is_open(interval const & a) const { return m_c.upper_is_open(a); }
bool lower_is_inf(interval const & a) const { return m_c.lower_is_inf(a); }
bool upper_is_inf(interval const & a) const { return m_c.upper_is_inf(a); }
bool is_empty(interval const& a) const {
if (lower_is_inf(a) || upper_is_inf(a))
return false;
ext_numeral_kind lk = lower_kind(a), uk = upper_kind(a);
if (lower_is_open(a) || upper_is_open(a))
return !(::lt(m(), lower(a), lk, upper(a), uk));
return ::lt(m(), upper(a), uk, lower(a), lk);
}
bool lower_is_neg(interval const & a) const { return ::is_neg(m(), lower(a), lower_kind(a)); }
bool lower_is_pos(interval const & a) const { return ::is_pos(m(), lower(a), lower_kind(a)); }

View file

@ -681,7 +681,7 @@ void interval_manager<C>::set(interval & t, interval const & s) {
}
set_lower_is_open(t, lower_is_open(s));
set_upper_is_open(t, upper_is_open(s));
SASSERT(check_invariant(t));
SASSERT(is_empty(t) || check_invariant(t));
}
template<typename C>
@ -813,7 +813,7 @@ void interval_manager<C>::add(interval const & a, interval const & b, interval &
set_upper_is_inf(c, new_u_kind == EN_PLUS_INFINITY);
set_lower_is_open(c, lower_is_open(a) || lower_is_open(b));
set_upper_is_open(c, upper_is_open(a) || upper_is_open(b));
SASSERT(check_invariant(c));
SASSERT(is_empty(a) || is_empty(b) || check_invariant(c));
}
template<typename C>

View file

@ -1,10 +1,7 @@
z3_add_component(lp
SOURCES
binary_heap_priority_queue.cpp
binary_heap_upair_queue.cpp
core_solver_pretty_printer.cpp
dense_matrix.cpp
eta_matrix.cpp
emonics.cpp
factorization.cpp
factorization_factory_imp.cpp
@ -19,14 +16,8 @@ z3_add_component(lp
lar_solver.cpp
lar_core_solver.cpp
lp_core_solver_base.cpp
lp_dual_core_solver.cpp
lp_dual_simplex.cpp
lp_primal_core_solver.cpp
lp_primal_simplex.cpp
lp_settings.cpp
lp_solver.cpp
lu.cpp
lp_utils.cpp
matrix.cpp
mon_eq.cpp
monomial_bounds.cpp
@ -45,10 +36,6 @@ z3_add_component(lp
nra_solver.cpp
permutation_matrix.cpp
random_updater.cpp
row_eta_matrix.cpp
scaler.cpp
square_dense_submatrix.cpp
square_sparse_matrix.cpp
static_matrix.cpp
COMPONENT_DEPENDENCIES
util

View file

@ -1,41 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#include "math/lp/numeric_pair.h"
#include "math/lp/binary_heap_priority_queue_def.h"
namespace lp {
template binary_heap_priority_queue<int>::binary_heap_priority_queue(unsigned int);
template unsigned binary_heap_priority_queue<int>::dequeue();
template void binary_heap_priority_queue<int>::enqueue(unsigned int, int const&);
template void binary_heap_priority_queue<double>::enqueue(unsigned int, double const&);
template void binary_heap_priority_queue<mpq>::enqueue(unsigned int, mpq const&);
template void binary_heap_priority_queue<int>::remove(unsigned int);
template unsigned binary_heap_priority_queue<numeric_pair<mpq> >::dequeue();
template unsigned binary_heap_priority_queue<double>::dequeue();
template unsigned binary_heap_priority_queue<mpq>::dequeue();
template void binary_heap_priority_queue<numeric_pair<mpq> >::enqueue(unsigned int, numeric_pair<mpq> const&);
template void binary_heap_priority_queue<numeric_pair<mpq> >::resize(unsigned int);
template void lp::binary_heap_priority_queue<double>::resize(unsigned int);
template binary_heap_priority_queue<unsigned int>::binary_heap_priority_queue(unsigned int);
template void binary_heap_priority_queue<unsigned>::resize(unsigned int);
template unsigned binary_heap_priority_queue<unsigned int>::dequeue();
template void binary_heap_priority_queue<unsigned int>::enqueue(unsigned int, unsigned int const&);
template void binary_heap_priority_queue<unsigned int>::remove(unsigned int);
template void lp::binary_heap_priority_queue<mpq>::resize(unsigned int);
}

View file

@ -1,83 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include "util/vector.h"
#include "util/debug.h"
#include "math/lp/lp_utils.h"
namespace lp {
// the elements with the smallest priority are dequeued first
template <typename T>
class binary_heap_priority_queue {
vector<T> m_priorities;
// indexing for A starts from 1
vector<unsigned> m_heap; // keeps the elements of the queue
vector<int> m_heap_inverse; // o = m_heap[m_heap_inverse[o]]
unsigned m_heap_size;
// is is the child place in heap
void swap_with_parent(unsigned i);
void put_at(unsigned i, unsigned h);
void decrease_priority(unsigned o, T newPriority);
public:
#ifdef Z3DEBUG
bool is_consistent() const;
#endif
public:
void remove(unsigned o);
unsigned size() const { return m_heap_size; }
binary_heap_priority_queue(): m_heap(1), m_heap_size(0) {} // the empty constructror
// n is the initial queue capacity.
// The capacity will be enlarged each time twice if needed
binary_heap_priority_queue(unsigned n);
void clear() {
for (unsigned i = 0; i < m_heap_size; i++) {
unsigned o = m_heap[i+1];
m_heap_inverse[o] = -1;
}
m_heap_size = 0;
}
void resize(unsigned n);
void put_to_heap(unsigned i, unsigned o);
void enqueue_new(unsigned o, const T& priority);
// This method can work with an element that is already in the queue.
// In this case the priority will be changed and the queue adjusted.
void enqueue(unsigned o, const T & priority);
void change_priority_for_existing(unsigned o, const T & priority);
T get_priority(unsigned o) const { return m_priorities[o]; }
bool is_empty() const { return m_heap_size == 0; }
/// return the first element of the queue and removes it from the queue
unsigned dequeue_and_get_priority(T & priority);
void fix_heap_under(unsigned i);
void put_the_last_at_the_top_and_fix_the_heap();
/// return the first element of the queue and removes it from the queue
unsigned dequeue();
unsigned peek() const {
lp_assert(m_heap_size > 0);
return m_heap[1];
}
void print(std::ostream & out);
};
}

View file

@ -1,214 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include "util/vector.h"
#include "math/lp/binary_heap_priority_queue.h"
namespace lp {
// "i" is the child's place in the heap
template <typename T> void binary_heap_priority_queue<T>::swap_with_parent(unsigned i) {
unsigned parent = m_heap[i >> 1];
put_at(i >> 1, m_heap[i]);
put_at(i, parent);
}
template <typename T> void binary_heap_priority_queue<T>::put_at(unsigned i, unsigned h) {
m_heap[i] = h;
m_heap_inverse[h] = i;
}
template <typename T> void binary_heap_priority_queue<T>::decrease_priority(unsigned o, T newPriority) {
m_priorities[o] = newPriority;
int i = m_heap_inverse[o];
while (i > 1) {
if (m_priorities[m_heap[i]] < m_priorities[m_heap[i >> 1]])
swap_with_parent(i);
else
break;
i >>= 1;
}
}
#ifdef Z3DEBUG
template <typename T> bool binary_heap_priority_queue<T>::is_consistent() const {
for (int i = 0; i < m_heap_inverse.size(); i++) {
int i_index = m_heap_inverse[i];
lp_assert(i_index <= static_cast<int>(m_heap_size));
lp_assert(i_index == -1 || m_heap[i_index] == i);
}
for (unsigned i = 1; i < m_heap_size; i++) {
unsigned ch = i << 1;
for (int k = 0; k < 2; k++) {
if (ch > m_heap_size) break;
if (!(m_priorities[m_heap[i]] <= m_priorities[m_heap[ch]])){
return false;
}
ch++;
}
}
return true;
}
#endif
template <typename T> void binary_heap_priority_queue<T>::remove(unsigned o) {
T priority_of_o = m_priorities[o];
int o_in_heap = m_heap_inverse[o];
if (o_in_heap == -1) {
return; // nothing to do
}
lp_assert(static_cast<unsigned>(o_in_heap) <= m_heap_size);
if (static_cast<unsigned>(o_in_heap) < m_heap_size) {
put_at(o_in_heap, m_heap[m_heap_size--]);
if (m_priorities[m_heap[o_in_heap]] > priority_of_o) {
fix_heap_under(o_in_heap);
} else { // we need to propagate the m_heap[o_in_heap] up
unsigned i = o_in_heap;
while (i > 1) {
unsigned ip = i >> 1;
if (m_priorities[m_heap[i]] < m_priorities[m_heap[ip]])
swap_with_parent(i);
else
break;
i = ip;
}
}
} else {
lp_assert(static_cast<unsigned>(o_in_heap) == m_heap_size);
m_heap_size--;
}
m_heap_inverse[o] = -1;
// lp_assert(is_consistent());
}
// n is the initial queue capacity.
// The capacity will be enlarged two times automatically if needed
template <typename T> binary_heap_priority_queue<T>::binary_heap_priority_queue(unsigned n) :
m_priorities(n),
m_heap(n + 1), // because the indexing for A starts from 1
m_heap_inverse(n, -1),
m_heap_size(0)
{ }
template <typename T> void binary_heap_priority_queue<T>::resize(unsigned n) {
m_priorities.resize(n);
m_heap.resize(n + 1);
m_heap_inverse.resize(n, -1);
}
template <typename T> void binary_heap_priority_queue<T>::put_to_heap(unsigned i, unsigned o) {
m_heap[i] = o;
m_heap_inverse[o] = i;
}
template <typename T> void binary_heap_priority_queue<T>::enqueue_new(unsigned o, const T& priority) {
m_heap_size++;
int i = m_heap_size;
lp_assert(o < m_priorities.size());
m_priorities[o] = priority;
put_at(i, o);
while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) {
swap_with_parent(i);
i >>= 1;
}
}
// This method can work with an element that is already in the queue.
// In this case the priority will be changed and the queue adjusted.
template <typename T> void binary_heap_priority_queue<T>::enqueue(unsigned o, const T & priority) {
if (o >= m_priorities.size()) {
if (o == 0)
resize(2);
else
resize(o << 1); // make the size twice larger
}
if (m_heap_inverse[o] == -1)
enqueue_new(o, priority);
else
change_priority_for_existing(o, priority);
}
template <typename T> void binary_heap_priority_queue<T>::change_priority_for_existing(unsigned o, const T & priority) {
if (m_priorities[o] > priority) {
decrease_priority(o, priority);
} else {
m_priorities[o] = priority;
fix_heap_under(m_heap_inverse[o]);
}
}
/// return the first element of the queue and removes it from the queue
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue_and_get_priority(T & priority) {
lp_assert(m_heap_size != 0);
int ret = m_heap[1];
priority = m_priorities[ret];
put_the_last_at_the_top_and_fix_the_heap();
return ret;
}
template <typename T> void binary_heap_priority_queue<T>::fix_heap_under(unsigned i) {
while (true) {
unsigned smallest = i;
unsigned l = i << 1;
if (l <= m_heap_size && m_priorities[m_heap[l]] < m_priorities[m_heap[i]])
smallest = l;
unsigned r = l + 1;
if (r <= m_heap_size && m_priorities[m_heap[r]] < m_priorities[m_heap[smallest]])
smallest = r;
if (smallest != i)
swap_with_parent(smallest);
else
break;
i = smallest;
}
}
template <typename T> void binary_heap_priority_queue<T>::put_the_last_at_the_top_and_fix_the_heap() {
if (m_heap_size > 1) {
put_at(1, m_heap[m_heap_size--]);
fix_heap_under(1);
} else {
m_heap_size--;
}
}
/// return the first element of the queue and removes it from the queue
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue() {
lp_assert(m_heap_size > 0);
int ret = m_heap[1];
put_the_last_at_the_top_and_fix_the_heap();
m_heap_inverse[ret] = -1;
return ret;
}
template <typename T> void binary_heap_priority_queue<T>::print(std::ostream & out) {
vector<int> index;
vector<T> prs;
while (size()) {
T prior;
int j = dequeue_and_get_priority(prior);
index.push_back(j);
prs.push_back(prior);
out << "(" << j << ", " << prior << ")";
}
out << std::endl;
// restore the queue
for (int i = 0; i < index.size(); i++)
enqueue(index[i], prs[i]);
}
}

View file

@ -1,32 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#include "math/lp/binary_heap_upair_queue_def.h"
namespace lp {
template binary_heap_upair_queue<int>::binary_heap_upair_queue(unsigned int);
template binary_heap_upair_queue<unsigned int>::binary_heap_upair_queue(unsigned int);
template unsigned binary_heap_upair_queue<int>::dequeue_available_spot();
template unsigned binary_heap_upair_queue<unsigned int>::dequeue_available_spot();
template void binary_heap_upair_queue<int>::enqueue(unsigned int, unsigned int, int const&);
template void binary_heap_upair_queue<int>::remove(unsigned int, unsigned int);
template void binary_heap_upair_queue<unsigned int>::remove(unsigned int, unsigned int);
template void binary_heap_upair_queue<int>::dequeue(unsigned int&, unsigned int&);
template void binary_heap_upair_queue<unsigned int>::enqueue(unsigned int, unsigned int, unsigned int const&);
template void binary_heap_upair_queue<unsigned int>::dequeue(unsigned int&, unsigned int&);
}

View file

@ -1,65 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include "util/vector.h"
#include <set>
#include <utility>
#include "math/lp/binary_heap_priority_queue.h"
typedef std::pair<unsigned, unsigned> upair;
namespace lp {
template <typename T>
class binary_heap_upair_queue {
binary_heap_priority_queue<T> m_q;
std::unordered_map<upair, unsigned> m_pairs_to_index;
svector<upair> m_pairs; // inverse to index
svector<unsigned> m_available_spots;
public:
binary_heap_upair_queue(unsigned size);
unsigned dequeue_available_spot();
bool is_empty() const { return m_q.is_empty(); }
unsigned size() const {return m_q.size(); }
bool contains(unsigned i, unsigned j) const { return m_pairs_to_index.find(std::make_pair(i, j)) != m_pairs_to_index.end();
}
void remove(unsigned i, unsigned j);
bool ij_index_is_new(unsigned ij_index) const;
void enqueue(unsigned i, unsigned j, const T & priority);
void dequeue(unsigned & i, unsigned &j);
T get_priority(unsigned i, unsigned j) const;
#ifdef Z3DEBUG
bool pair_to_index_is_a_bijection() const;
bool available_spots_are_correct() const;
bool is_correct() const {
return m_q.is_consistent() && pair_to_index_is_a_bijection() && available_spots_are_correct();
}
#endif
void resize(unsigned size) { m_q.resize(size); }
};
}

View file

@ -1,126 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
#include <set>
#include "math/lp/lp_utils.h"
#include "math/lp/binary_heap_upair_queue.h"
namespace lp {
template <typename T> binary_heap_upair_queue<T>::binary_heap_upair_queue(unsigned size) : m_q(size), m_pairs(size) {
for (unsigned i = 0; i < size; i++)
m_available_spots.push_back(i);
}
template <typename T> unsigned
binary_heap_upair_queue<T>::dequeue_available_spot() {
lp_assert(m_available_spots.empty() == false);
unsigned ret = m_available_spots.back();
m_available_spots.pop_back();
return ret;
}
template <typename T> void binary_heap_upair_queue<T>::remove(unsigned i, unsigned j) {
upair p(i, j);
auto it = m_pairs_to_index.find(p);
if (it == m_pairs_to_index.end())
return; // nothing to do
m_q.remove(it->second);
m_available_spots.push_back(it->second);
m_pairs_to_index.erase(it);
}
template <typename T> bool binary_heap_upair_queue<T>::ij_index_is_new(unsigned ij_index) const {
for (auto it : m_pairs_to_index) {
if (it.second == ij_index)
return false;
}
return true;
}
template <typename T> void binary_heap_upair_queue<T>::enqueue(unsigned i, unsigned j, const T & priority) {
upair p(i, j);
auto it = m_pairs_to_index.find(p);
unsigned ij_index;
if (it == m_pairs_to_index.end()) {
// it is a new pair, let us find a spot for it
if (m_available_spots.empty()) {
// we ran out of empty spots
unsigned size_was = static_cast<unsigned>(m_pairs.size());
unsigned new_size = size_was << 1;
for (unsigned i = size_was; i < new_size; i++)
m_available_spots.push_back(i);
m_pairs.resize(new_size);
}
ij_index = dequeue_available_spot();
// lp_assert(ij_index<m_pairs.size() && ij_index_is_new(ij_index));
m_pairs[ij_index] = p;
m_pairs_to_index[p] = ij_index;
} else {
ij_index = it->second;
}
m_q.enqueue(ij_index, priority);
}
template <typename T> void binary_heap_upair_queue<T>::dequeue(unsigned & i, unsigned &j) {
lp_assert(!m_q.is_empty());
unsigned ij_index = m_q.dequeue();
upair & p = m_pairs[ij_index];
i = p.first;
j = p.second;
m_available_spots.push_back(ij_index);
m_pairs_to_index.erase(p);
}
template <typename T> T binary_heap_upair_queue<T>::get_priority(unsigned i, unsigned j) const {
auto it = m_pairs_to_index.find(std::make_pair(i, j));
if (it == m_pairs_to_index.end())
return T(0xFFFFFF); // big number
return m_q.get_priority(it->second);
}
#ifdef Z3DEBUG
template <typename T> bool binary_heap_upair_queue<T>::pair_to_index_is_a_bijection() const {
std::set<int> tmp;
for (auto p : m_pairs_to_index) {
unsigned j = p.second;
unsigned size = tmp.size();
tmp.insert(j);
if (tmp.size() == size)
return false;
}
return true;
}
template <typename T> bool binary_heap_upair_queue<T>::available_spots_are_correct() const {
std::set<int> tmp;
for (auto p : m_available_spots){
tmp.insert(p);
}
if (tmp.size() != m_available_spots.size())
return false;
for (auto it : m_pairs_to_index)
if (tmp.find(it.second) != tmp.end())
return false;
return true;
}
#endif
}

View file

@ -54,32 +54,40 @@ public :
{}
static void analyze_row(const C & row,
static unsigned analyze_row(const C & row,
unsigned bj, // basis column for the row
const numeric_pair<mpq>& rs,
unsigned row_or_term_index,
B & bp) {
bound_analyzer_on_row a(row, bj, rs, row_or_term_index, bp);
a.analyze();
return a.analyze();
}
private:
void analyze() {
unsigned analyze() {
unsigned num_prop = 0;
for (const auto & c : m_row) {
if ((m_column_of_l == -2) && (m_column_of_u == -2))
return;
return 0;
analyze_bound_on_var_on_coeff(c.var(), c.coeff());
}
++num_prop;
if (m_column_of_u >= 0)
limit_monoid_u_from_below();
else if (m_column_of_u == -1)
limit_all_monoids_from_below();
else
--num_prop;
++num_prop;
if (m_column_of_l >= 0)
limit_monoid_l_from_above();
else if (m_column_of_l == -1)
limit_all_monoids_from_above();
else
--num_prop;
return num_prop;
}
bool bound_is_available(unsigned j, bool lower_bound) {

View file

@ -1,35 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
namespace lp {
enum breakpoint_type {
low_break, upper_break, fixed_break
};
template <typename X>
struct breakpoint {
unsigned m_j; // the basic column
breakpoint_type m_type;
X m_delta;
breakpoint(){}
breakpoint(unsigned j, X delta, breakpoint_type type):m_j(j), m_type(type), m_delta(delta) {}
};
}

View file

@ -1,58 +0,0 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
<name>
Abstract:
<abstract>
Author:
Lev Nachmanson (levnach)
Revision History:
--*/
#pragma once
namespace lp {
template <typename V>
struct conversion_helper {
static V get_lower_bound(const column_info<mpq> & ci) {
return V(ci.get_lower_bound(), ci.lower_bound_is_strict()? 1 : 0);
}
static V get_upper_bound(const column_info<mpq> & ci) {
return V(ci.get_upper_bound(), ci.upper_bound_is_strict()? -1 : 0);
}
};
template<>
struct conversion_helper <double> {
static double get_upper_bound(const column_info<mpq> & ci) {
if (!ci.upper_bound_is_strict())
return ci.get_upper_bound().get_double();
double eps = 0.00001;
if (!ci.lower_bound_is_set())
return ci.get_upper_bound().get_double() - eps;
eps = std::min((ci.get_upper_bound() - ci.get_lower_bound()).get_double() / 1000, eps);
return ci.get_upper_bound().get_double() - eps;
}
static double get_lower_bound(const column_info<mpq> & ci) {
if (!ci.lower_bound_is_strict())
return ci.get_lower_bound().get_double();
double eps = 0.00001;
if (!ci.upper_bound_is_set())
return ci.get_lower_bound().get_double() + eps;
eps = std::min((ci.get_upper_bound() - ci.get_lower_bound()).get_double() / 1000, eps);
return ci.get_lower_bound().get_double() + eps;
}
};
}

View file

@ -19,9 +19,6 @@ Revision History:
--*/
#include "math/lp/numeric_pair.h"
#include "math/lp/core_solver_pretty_printer_def.h"
template lp::core_solver_pretty_printer<double, double>::core_solver_pretty_printer(const lp::lp_core_solver_base<double, double> &, std::ostream & out);
template void lp::core_solver_pretty_printer<double, double>::print();
template lp::core_solver_pretty_printer<double, double>::~core_solver_pretty_printer();
template lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::core_solver_pretty_printer(const lp::lp_core_solver_base<lp::mpq, lp::mpq> &, std::ostream & out);
template void lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::print();
template lp::core_solver_pretty_printer<lp::mpq, lp::mpq>::~core_solver_pretty_printer();

View file

@ -59,7 +59,7 @@ class core_solver_pretty_printer {
unsigned m_artificial_start;
indexed_vector<T> m_w_buff;
indexed_vector<T> m_ed_buff;
vector<T> m_exact_column_norms;
public:
core_solver_pretty_printer(const lp_core_solver_base<T, X > & core_solver, std::ostream & out);
@ -85,14 +85,7 @@ public:
}
unsigned get_column_width(unsigned column);
unsigned regular_cell_width(unsigned row, unsigned column, const std::string & name) {
return regular_cell_string(row, column, name).size();
}
std::string regular_cell_string(unsigned row, unsigned column, std::string name);
void set_coeff(vector<string>& row, vector<string> & row_signs, unsigned col, const T & t, string name);
void print_x();
@ -105,13 +98,7 @@ public:
void print_lows();
void print_upps();
string get_exact_column_norm_string(unsigned col) {
return T_to_string(m_exact_column_norms[col]);
}
void print_exact_norms();
void print_approx_norms();
void print();

View file

@ -37,9 +37,8 @@ core_solver_pretty_printer<T, X>::core_solver_pretty_printer(const lp_core_solve
m_signs(core_solver.m_A.row_count(), vector<string>(core_solver.m_A.column_count(), " ")),
m_costs(ncols(), ""),
m_cost_signs(ncols(), " "),
m_rs(ncols(), zero_of_type<X>()),
m_w_buff(core_solver.m_w),
m_ed_buff(core_solver.m_ed) {
m_rs(ncols(), zero_of_type<X>())
{
m_lower_bounds_title = "low";
m_upp_bounds_title = "upp";
m_exact_norm_title = "exact cn";
@ -59,22 +58,13 @@ core_solver_pretty_printer<T, X>::core_solver_pretty_printer(const lp_core_solve
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_costs() {
if (!m_core_solver.use_tableau()) {
vector<T> local_y(m_core_solver.m_m());
m_core_solver.solve_yB(local_y);
for (unsigned i = 0; i < ncols(); i++) {
if (m_core_solver.m_basis_heading[i] < 0) {
T t = m_core_solver.m_costs[i] - m_core_solver.m_A.dot_product_with_column(local_y, i);
set_coeff(m_costs, m_cost_signs, i, t, m_core_solver.column_name(i));
}
}
} else {
for (unsigned i = 0; i < ncols(); i++) {
if (m_core_solver.m_basis_heading[i] < 0) {
set_coeff(m_costs, m_cost_signs, i, m_core_solver.m_d[i], m_core_solver.column_name(i));
}
}
}
}
template <typename T, typename X> core_solver_pretty_printer<T, X>::~core_solver_pretty_printer() {
@ -89,15 +79,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_rs
}
}
template <typename T, typename X> T core_solver_pretty_printer<T, X>::current_column_norm() {
T ret = zero_of_type<T>();
for (auto i : m_core_solver.m_ed.m_index)
ret += m_core_solver.m_ed[i] * m_core_solver.m_ed[i];
return ret;
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_m_A_and_signs() {
if (numeric_traits<T>::precise() && m_core_solver.m_settings.use_tableau()) {
for (unsigned column = 0; column < ncols(); column++) {
vector<T> t(nrows(), zero_of_type<T>());
for (const auto & c : m_core_solver.m_A.m_columns[column]){
@ -124,24 +106,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_m_
name);
m_rs[row] += t[row] * m_core_solver.m_x[column];
}
}
} else {
for (unsigned column = 0; column < ncols(); column++) {
m_core_solver.solve_Bd(column, m_ed_buff, m_w_buff); // puts the result into m_core_solver.m_ed
string name = m_core_solver.column_name(column);
for (unsigned row = 0; row < nrows(); row ++) {
set_coeff(
m_A[row],
m_signs[row],
column,
m_ed_buff[row],
name);
m_rs[row] += m_ed_buff[row] * m_core_solver.m_x[column];
}
if (!m_core_solver.use_tableau())
m_exact_column_norms.push_back(current_column_norm() + T(1)); // a conversion missing 1 -> T
}
}
}
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::init_column_widths() {
@ -174,7 +139,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_
case column_type::free_column:
break;
default:
lp_assert(false);
UNREACHABLE();
break;
}
}
@ -190,21 +155,10 @@ template <typename T, typename X> unsigned core_solver_pretty_printer<T, X>:: ge
w = cellw;
}
}
if (!m_core_solver.use_tableau()) {
w = std::max(w, (unsigned)T_to_string(m_exact_column_norms[column]).size());
if (!m_core_solver.m_column_norms.empty())
w = std::max(w, (unsigned)T_to_string(m_core_solver.m_column_norms[column]).size());
}
return w;
}
template <typename T, typename X> std::string core_solver_pretty_printer<T, X>::regular_cell_string(unsigned row, unsigned /* column */, std::string name) {
T t = fabs(m_core_solver.m_ed[row]);
if ( t == 1) return name;
return T_to_string(t) + name;
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::set_coeff(vector<string>& row, vector<string> & row_signs, unsigned col, const T & t, string name) {
if (numeric_traits<T>::is_zero(t)) {
return;
@ -315,41 +269,15 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_u
m_out << std::endl;
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_exact_norms() {
if (m_core_solver.use_tableau()) return;
int blanks = m_title_width + 1 - static_cast<int>(m_exact_norm_title.size());
m_out << m_exact_norm_title;
print_blanks_local(blanks, m_out);
for (unsigned i = 0; i < ncols(); i++) {
string s = get_exact_column_norm_string(i);
int blanks = m_column_widths[i] - static_cast<int>(s.size());
print_blanks_local(blanks, m_out);
m_out << s << " ";
}
m_out << std::endl;
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::print_approx_norms() {
if (m_core_solver.use_tableau()) return;
int blanks = m_title_width + 1 - static_cast<int>(m_approx_norm_title.size());
m_out << m_approx_norm_title;
print_blanks_local(blanks, m_out);
for (unsigned i = 0; i < ncols(); i++) {
string s = T_to_string(m_core_solver.m_column_norms[i]);
int blanks = m_column_widths[i] - static_cast<int>(s.size());
print_blanks_local(blanks, m_out);
m_out << s << " ";
}
m_out << std::endl;
return;
}
template <typename T, typename X> void core_solver_pretty_printer<T, X>::print() {
for (unsigned i = 0; i < nrows(); i++) {
print_row(i);
}
print_exact_norms();
if (!m_core_solver.m_column_norms.empty())
print_approx_norms();
m_out << std::endl;
if (m_core_solver.inf_set().size()) {
m_out << "inf columns: ";

View file

@ -21,11 +21,6 @@ Revision History:
#include "math/lp/dense_matrix_def.h"
#ifdef Z3DEBUG
#include "util/vector.h"
template lp::dense_matrix<double, double> lp::operator*<double, double>(lp::matrix<double, double>&, lp::matrix<double, double>&);
template void lp::dense_matrix<double, double>::apply_from_left(vector<double> &);
template lp::dense_matrix<double, double>::dense_matrix(lp::matrix<double, double> const*);
template lp::dense_matrix<double, double>::dense_matrix(unsigned int, unsigned int);
template lp::dense_matrix<double, double>& lp::dense_matrix<double, double>::operator=(lp::dense_matrix<double, double> const&);
template lp::dense_matrix<lp::mpq, lp::mpq>::dense_matrix(unsigned int, unsigned int);
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dense_matrix(lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> > const*);
template void lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::apply_from_left(vector<lp::mpq>&);
@ -35,6 +30,5 @@ template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::dense_matrix(uns
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >& lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> >::operator=(lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> > const&);
template lp::dense_matrix<lp::mpq, lp::numeric_pair<lp::mpq> > lp::operator*<lp::mpq, lp::numeric_pair<lp::mpq> >(lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&, lp::matrix<lp::mpq, lp::numeric_pair<lp::mpq> >&);
template void lp::dense_matrix<lp::mpq, lp::numeric_pair< lp::mpq> >::apply_from_right( vector< lp::mpq> &);
template void lp::dense_matrix<double,double>::apply_from_right(vector<double> &);
template void lp::dense_matrix<lp::mpq, lp::mpq>::apply_from_left(vector<lp::mpq>&);
#endif

View file

@ -90,11 +90,7 @@ public:
void set_elem(unsigned i, unsigned j, const T& val) { m_values[i * m_n + j] = val; }
// This method pivots row i to row i0 by muliplying row i by
// alpha and adding it to row i0.
void pivot_row_to_row(unsigned i, const T& alpha, unsigned i0,
const double & pivot_epsilon);
// This method pivots
void swap_columns(unsigned a, unsigned b);
void swap_rows(unsigned a, unsigned b);

View file

@ -150,17 +150,6 @@ template <typename T, typename X> void dense_matrix<T, X>::apply_from_left_to_X(
}
}
// This method pivots row i to row i0 by muliplying row i by
// alpha and adding it to row i0.
template <typename T, typename X> void dense_matrix<T, X>::pivot_row_to_row(unsigned i, const T& alpha, unsigned i0,
const double & pivot_epsilon) {
for (unsigned j = 0; j < m_n; j++) {
m_values[i0 * m_n + j] += m_values[i * m_n + j] * alpha;
if (fabs(m_values[i0 + m_n + j]) < pivot_epsilon) {
m_values[i0 + m_n + j] = numeric_traits<T>::zero();;
}
}
}
template <typename T, typename X> void dense_matrix<T, X>::swap_columns(unsigned a, unsigned b) {
for (unsigned i = 0; i < m_m; i++) {

View file

@ -68,8 +68,8 @@ void emonics::pop(unsigned n) {
TRACE("nla_solver_mons", tout << "pop: " << n << "\n";);
SASSERT(invariant());
for (unsigned i = 0; i < n; ++i) {
m_u_f_stack.pop_scope(1);
m_ve.pop(1);
m_u_f_stack.pop_scope(1);
}
SASSERT(invariant());
SASSERT(monics_are_canonized());

Some files were not shown because too many files have changed in this diff Show more