3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-20 07:36:38 +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

4
.gitignore vendored
View file

@ -9,9 +9,12 @@ callgrind.out.*
.z3-trace
# OCaml generated files
*.a
*.o
*.cma
*.cmo
*.cmi
*.cmx
*.byte
*.cmxa
ocamlz3
# Java generated files
@ -22,6 +25,7 @@ ocamlz3
# Directories with generated code and documentation
release/*
build/*
trace/*
build-dist/*
dist/*
src/out/*

View file

@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 3.4)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake")
project(Z3 VERSION 4.12.2.0 LANGUAGES CXX C)
project(Z3 VERSION 4.12.3.0 LANGUAGES CXX C)
################################################################################
# Project version

View file

@ -90,6 +90,37 @@ CFLAGS="-m32" CXXFLAGS="-m32" CC=gcc CXX=g++ cmake ../
Note like with the ``CC`` and ``CXX`` flags this must be done on the very first invocation
to CMake in the build directory.
### Adding Z3 as a dependency to a CMAKE Project
CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) allows
the fetching and populating of an external project. This is useful when a certain version
of z3 is required that may not match with the system version. With the following code in the
cmake file of your project, z3 version 4.12.1 is downloaded to the build directory and the
cmake targets are added to the project:
```
FetchContent_Declare(z3
GIT_REPOSITORY https://github.com/Z3Prover/z3
GIT_TAG z3-4.12.1
)
FetchContent_MakeAvailable(z3)
```
The header files can be added to the included directories as follows:
```
include_directories( ${z3_SOURCE_DIR}/src/api )
```
Finally, the z3 library can be linked to a `yourTarget` using
```
target_link_libraries(yourTarget libz3)
```
Note that this is `libz3` not `z3` (`libz3` refers to the library target from `src/CMakeLists.txt`).
### Ninja
[Ninja](https://ninja-build.org/) is a simple build system that is built for speed.

View file

@ -10,6 +10,9 @@ Version 4.next
- native word level bit-vector solving.
- introduction of simple induction lemmas to handle a limited repertoire of induction proofs.
Version 4.12.3
==============
Version 4.12.2
==============
@ -27,6 +30,10 @@ Version 4.12.2
and `elim-predicates` that go beyond incremental pre-processing used internally. The advantage of using `solve-eqs` during pre-processing
can be significant. Incremental pre-processing simplification using `solve-eqs` and other simplifiers that change interpretations
was not possible before.
- Optimize added to JS API, thanks to gbagan
- SMTLIB2 proposal for bit-vector overflow predicates added, thanks to aehyvari
- bug fixes, thanks to Clemens Eisenhofer, hgvk94, Lev Nachmanson, and others
Version 4.12.1
==============

View file

@ -37,7 +37,7 @@ def help(ous):
out = subprocess.Popen([z3_exe, "-pm"],stdout=subprocess.PIPE).communicate()[0]
modules = ["global"]
if out != None:
out = out.decode(sys.stdout.encoding)
out = out.decode(sys.getdefaultencoding())
module_re = re.compile(r"\[module\] (.*)\,")
lines = out.split("\n")
for line in lines:
@ -48,7 +48,7 @@ def help(ous):
out = subprocess.Popen([z3_exe, "-pmmd:%s" % module],stdout=subprocess.PIPE).communicate()[0]
if out == None:
continue
out = out.decode(sys.stdout.encoding)
out = out.decode(sys.getdefaultencoding())
out = out.replace("\r","")
ous.write(out)

View file

@ -28,7 +28,7 @@ def extract_params(ous, tac):
out = subprocess.Popen([z3_exe, f"-tacticsmd:{tac}"], stdout=subprocess.PIPE).communicate()[0]
if not out:
return
out = out.decode(sys.stdout.encoding)
out = out.decode(sys.getdefaultencoding())
if is_ws(out):
return
ous.write("### Parameters\n\n")

View file

@ -2259,6 +2259,24 @@ class JavaExample
System.out.println(e1.equals(e3));
}
public void stringExample() {
System.out.println("String example");
Context ctx = new Context();
Expr a = ctx.mkToRe(ctx.mkString("abcd"));
Expr b = ctx.mkFullRe(ctx.mkReSort(ctx.mkStringSort()));
System.out.println(a);
System.out.println(b);
System.out.println(a.getSort());
System.out.println(b.getSort());
Expr c = ctx.mkConcat(ctx.mkToRe(ctx.mkString("abc")),
ctx.mkFullRe(ctx.mkReSort(ctx.mkStringSort())),
ctx.mkEmptyRe(ctx.mkReSort(ctx.mkStringSort())),
ctx.mkAllcharRe(ctx.mkReSort(ctx.mkStringSort())),
ctx.mkToRe(ctx.mkString("d")));
System.out.println(c);
}
public static void main(String[] args)
{
JavaExample p = new JavaExample();
@ -2274,12 +2292,15 @@ class JavaExample
System.out.print("Z3 Full Version String: ");
System.out.println(Version.getFullVersion());
p.stringExample();
p.simpleExample();
{ // These examples need model generation turned on.
HashMap<String, String> cfg = new HashMap<String, String>();
cfg.put("model", "true");
Context ctx = new Context(cfg);
p.optimizeExample(ctx);
p.basicTests(ctx);

View file

@ -24,8 +24,8 @@ def mk_dir(d):
os_info = { 'ubuntu-latest' : ('so', 'linux-x64'),
'ubuntu-18' : ('so', 'linux-x64'),
'ubuntu-20' : ('so', 'linux-x64'),
'glibc-2.31' : ('so', 'linux-x64'),
'glibc' : ('so', 'linux-x64'),
#'glibc-2.35' : ('so', 'linux-x64'),
'x64-win' : ('dll', 'win-x64'),
'x86-win' : ('dll', 'win-x86'),
'x64-osx' : ('dylib', 'osx-x64'),

View file

@ -8,7 +8,7 @@
from mk_util import *
def init_version():
set_version(4, 12, 2, 0) # express a default build version or pick up ci build version
set_version(4, 12, 3, 0) # express a default build version or pick up ci build version
# Z3 Project definition
def init_project_def():

View file

@ -122,7 +122,7 @@ FPMATH_ENABLED=getenv("FPMATH_ENABLED", "True")
def check_output(cmd):
out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
if out != None:
enc = sys.stdout.encoding
enc = sys.getdefaultencoding()
if enc != None: return out.decode(enc).rstrip('\r\n')
else: return out.rstrip('\r\n')
else:

View file

@ -1,7 +1,7 @@
variables:
Major: '4'
Minor: '12'
Patch: '2'
Patch: '3'
AssemblyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId)
NightlyVersion: $(AssemblyVersion)-$(Build.DefinitionName)
@ -35,6 +35,20 @@ stages:
artifactName: 'MacArm64'
targetPath: $(Build.ArtifactStagingDirectory)
- job: Ubuntu20
displayName: "Ubuntu20 build"
pool:
vmImage: "ubuntu-20.04"
steps:
- script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
- script: git clone https://github.com/z3prover/z3test z3test
- script: python z3test/scripts/test_benchmarks.py build-dist/z3 z3test/regressions/smt2
- script: cp dist/*.zip $(Build.ArtifactStagingDirectory)/.
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Ubuntu-20.04'
targetPath: $(Build.ArtifactStagingDirectory)
- job: Ubuntu
displayName: "Ubuntu build"
pool:
@ -512,6 +526,11 @@ stages:
inputs:
artifactName: 'Ubuntu'
targetPath: tmp
- task: DownloadPipelineArtifact@2
displayName: "Download Ubuntu-20.04"
inputs:
artifactName: 'Ubuntu-20.04'
targetPath: tmp
- task: DownloadPipelineArtifact@2
displayName: "Download Doc"
inputs:

View file

@ -6,7 +6,7 @@
trigger: none
variables:
ReleaseVersion: '4.12.2'
ReleaseVersion: '4.12.3'
stages:
@ -85,6 +85,35 @@ stages:
artifactName: 'UbuntuBuild'
targetPath: $(Build.ArtifactStagingDirectory)
- job: UbuntuBuild20
displayName: "Ubuntu build 20"
pool:
vmImage: "ubuntu-20.04"
steps:
- task: PythonScript@0
displayName: Build
inputs:
scriptSource: 'filepath'
scriptPath: scripts/mk_unix_dist.py
arguments: --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
- script: git clone https://github.com/z3prover/z3test z3test
displayName: 'Clone z3test'
- task: PythonScript@0
displayName: Test
inputs:
scriptSource: 'filepath'
scriptPath: z3test/scripts/test_benchmarks.py
arguments: build-dist/z3 z3test/regressions/smt2
- task: CopyFiles@2
inputs:
sourceFolder: dist
contents: '*.zip'
targetFolder: $(Build.ArtifactStagingDirectory)
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'UbuntuBuild20'
targetPath: $(Build.ArtifactStagingDirectory)
- job: UbuntuDoc
displayName: "Ubuntu Doc build"
pool:
@ -191,6 +220,11 @@ stages:
inputs:
artifact: 'UbuntuBuild'
path: $(Agent.TempDirectory)\package
- task: DownloadPipelineArtifact@2
displayName: 'Download Ubuntu20 Build'
inputs:
artifact: 'UbuntuBuild20'
path: $(Agent.TempDirectory)\package
- task: DownloadPipelineArtifact@2
displayName: 'Download macOS Build'
inputs:
@ -436,6 +470,11 @@ stages:
pool:
vmImage: "windows-latest"
steps:
- task: DownloadPipelineArtifact@2
displayName: 'Download Ubuntu Build'
inputs:
artifact: 'UbuntuBuild20'
path: $(Agent.TempDirectory)
- task: DownloadPipelineArtifact@2
displayName: 'Download Ubuntu Build'
inputs:

View file

@ -633,7 +633,72 @@ def mk_java(java_src, java_dir, package_name):
java_native.write(' }\n')
java_native.write(' }\n')
java_native.write(' }\n')
java_native.write("""
public static native long propagateInit(Object o, long ctx, long solver);
public static native void propagateRegisterCreated(Object o, long ctx, long solver);
public static native void propagateRegisterFixed(Object o, long ctx, long solver);
public static native void propagateRegisterEq(Object o, long ctx, long solver);
public static native void propagateRegisterDecide(Object o, long ctx, long solver);
public static native void propagateRegisterFinal(Object o, long ctx, long solver);
public static native void propagateConflict(Object o, long ctx, long solver, long javainfo, int num_fixed, long[] fixed, long num_eqs, long[] eq_lhs, long[] eq_rhs, long conseq);
public static native void propagateAdd(Object o, long ctx, long solver, long javainfo, long e);
public static native void propagateNextSplit(Object o, long ctx, long solver, long javainfo, long e, long idx, long phase);
public static native void propagateDestroy(Object o, long ctx, long solver, long javainfo);
public static abstract class UserPropagatorBase implements AutoCloseable {
protected long ctx;
protected long solver;
protected long javainfo;
public UserPropagatorBase(long _ctx, long _solver) {
ctx = _ctx;
solver = _solver;
javainfo = propagateInit(this, ctx, solver);
}
@Override
public void close() {
Native.propagateDestroy(this, ctx, solver, javainfo);
javainfo = 0;
solver = 0;
ctx = 0;
}
protected final void registerCreated() {
Native.propagateRegisterCreated(this, ctx, solver);
}
protected final void registerFixed() {
Native.propagateRegisterFixed(this, ctx, solver);
}
protected final void registerEq() {
Native.propagateRegisterEq(this, ctx, solver);
}
protected final void registerDecide() {
Native.propagateRegisterDecide(this, ctx, solver);
}
protected final void registerFinal() {
Native.propagateRegisterFinal(this, ctx, solver);
}
protected abstract void pushWrapper();
protected abstract void popWrapper(int number);
protected abstract void finWrapper();
protected abstract void eqWrapper(long lx, long ly);
protected abstract UserPropagatorBase freshWrapper(long lctx);
protected abstract void createdWrapper(long le);
protected abstract void fixedWrapper(long lvar, long lvalue);
}
""")
java_native.write('\n')
for name, result, params in _dotnet_decls:
java_native.write(' protected static native %s INTERNAL%s(' % (type2java(result), java_method_name(name)))
@ -1825,6 +1890,7 @@ if _lib is None:
else:
print(" import builtins")
print(" builtins.Z3_LIB_DIRS = [ '/path/to/libz3.%s' ] " % _ext)
print(_failures)
raise Z3Exception("libz3.%s not found." % _ext)
@ -1836,14 +1902,14 @@ if sys.version < '3':
else:
def _str_to_bytes(s):
if isinstance(s, str):
enc = sys.stdout.encoding
enc = sys.getdefaultencoding()
return s.encode(enc if enc != None else 'latin-1')
else:
return s
def _to_pystr(s):
if s != None:
enc = sys.stdout.encoding
enc = sys.getdefaultencoding()
return s.decode(enc if enc != None else 'latin-1')
else:
return ""

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]);
}
}

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