3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-05 05:41:23 +00:00

merge with master

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2022-04-16 18:30:03 +02:00
commit 3533bf486f
223 changed files with 7175 additions and 2167 deletions

30
.github/workflows/cross-build.yml vendored Normal file
View file

@ -0,0 +1,30 @@
name: RISC V and PowerPC 64
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
container: ubuntu:jammy
strategy:
fail-fast: false
matrix:
arch: [ aarch64, riscv64, powerpc64 ]
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install cross build tools
run: apt update && apt install -y ninja-build cmake python3 g++-11-${{ matrix.arch }}-linux-gnu
env:
DEBIAN_FRONTEND: noninteractive
- name: Configure CMake and build
run: |
mkdir build && cd build
cmake -DCMAKE_CXX_COMPILER=${{ matrix.arch }}-linux-gnu-g++-11 ../
make -j$(nproc)

1
.gitignore vendored
View file

@ -81,6 +81,7 @@ src/api/js/build/
src/api/js/**/*.d.ts
!src/api/js/scripts/*.js
!src/api/js/src/*.js
debug/*
out/**
*.bak

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.8.15.0 LANGUAGES CXX C)
project(Z3 VERSION 4.8.16.0 LANGUAGES CXX C)
################################################################################
# Project version
@ -198,7 +198,9 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "GNU")
message(STATUS "Platform: GNU/Hurd")
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_HURD_")
elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# Does macOS really not need any special flags?
if (TARGET_ARCHITECTURE STREQUAL "arm64")
set(CMAKE_OSX_ARCHITECTURES "arm64")
endif()
message(STATUS "Platform: Darwin")
elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
message(STATUS "Platform: FreeBSD")
@ -431,6 +433,11 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " /RELEASE")
endif()
################################################################################
# Check atomic linking as needed
################################################################################
include(${PROJECT_SOURCE_DIR}/cmake/check_link_atomic.cmake)
################################################################################
# Report default CMake flags
################################################################################

View file

@ -80,7 +80,7 @@ A 32 bit build should work similarly (but is untested); the same is true for 32/
By default, it will install z3 executable at ``PREFIX/bin``, libraries at
``PREFIX/lib``, and include files at ``PREFIX/include``, where ``PREFIX``
installation prefix if inferred by the ``mk_make.py`` script. It is usually
installation prefix is inferred by the ``mk_make.py`` script. It is usually
``/usr`` for most Linux distros, and ``/usr/local`` for FreeBSD and macOS. Use
the ``--prefix=`` command line option to change the install prefix. For example:
@ -158,7 +158,7 @@ You can install the Python wrapper for Z3 for the latest release from pypi using
Use the ``--python`` command line flag with ``mk_make.py`` to enable building these.
Note that is required on certain platforms that the Python package directory
Note that it is required on certain platforms that the Python package directory
(``site-packages`` on most distributions and ``dist-packages`` on Debian based
distributions) live under the install prefix. If you use a non standard prefix
you can use the ``--pypkgdir`` option to change the Python package directory
@ -199,6 +199,11 @@ The Julia package [Z3.jl](https://github.com/ahumenberger/Z3.jl) wraps the C++ A
A WebAssembly build with associated TypeScript typings is published on npm as [z3-solver](https://www.npmjs.com/package/z3-solver). Information about building these bindings can be found in [src/api/js](src/api/js).
### Smalltalk (``Pharo`` / ``Smalltalk/X``)
Project [MachineArithmetic](https://github.com/shingarov/MachineArithmetic) provides Smalltalk interface
to Z3's C API. For more information, see [MachineArithmetic/README.md](https://github.com/shingarov/MachineArithmetic/blob/pure-z3/MachineArithmetic/README.md)
## System Overview
![System Diagram](https://github.com/Z3Prover/doc/blob/master/programmingz3/images/Z3Overall.jpg)
@ -215,5 +220,6 @@ A WebAssembly build with associated TypeScript typings is published on npm as [z
* C
* OCaml
* [Julia](https://github.com/ahumenberger/Z3.jl)
* [Smalltalk](https://github.com/shingarov/MachineArithmetic/blob/pure-z3/MachineArithmetic/README.md) (supports Pharo and Smalltalk/X)

View file

@ -10,6 +10,10 @@ Version 4.8.next
- native word level bit-vector solving.
- introduction of simple induction lemmas to handle a limited repertoire of induction proofs.
Version 4.8.15
==============
- elaborate user propagator API. Change id based scheme to expressions
- includes a Web Assembly ffi API thanks to Kevin Gibbons
Version 4.8.14
==============

View file

@ -217,12 +217,12 @@ jobs:
$(setupCmd1)
$(setupCmd2)
$(setupCmd3)
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" $(arch)
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" $(arch)
cmake $(bindings) -G "NMake Makefiles" ../
nmake
cd ..
- script: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" $(arch)
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" $(arch)
pushd build\python
python z3test.py z3
python z3test.py z3num

View file

@ -0,0 +1,23 @@
set(ATOMIC_TEST_SOURCE "
#include <atomic>
std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
std::atomic<long long> w;
int main() {
++z;
++y;
++w;
return ++x;
}")
CHECK_CXX_SOURCE_COMPILES("${ATOMIC_TEST_SOURCE}" BUILTIN_ATOMIC)
if (NOT BUILTIN_ATOMIC)
set(CMAKE_REQUIRED_LIBRARIES atomic)
CHECK_CXX_SOURCE_COMPILES("${ATOMIC_TEST_SOURCE}" ATOMICS_REQUIRE_LIBATOMIC)
unset(CMAKE_REQUIRED_LIBRARIES)
if (ATOMICS_REQUIRE_LIBATOMIC)
list(APPEND Z3_DEPENDENT_LIBS atomic)
else()
message(FATAL_ERROR "Host compiler must support std::atomic!")
endif()
endif()

View file

@ -5,6 +5,10 @@
#error CMAKE_TARGET_ARCH_i686
#elif defined(__x86_64__) || defined(_M_X64)
#error CMAKE_TARGET_ARCH_x86_64
#elif defined(__ARM_ARCH_ISA_A64)
#error CMAKE_TARGET_ARCH_arm64
#elif defined(__ARM_ARCH)
#error CMAKE_TARGET_ARCH_arm
#else
#error CMAKE_TARGET_ARCH_unknown
#endif

View file

@ -4,11 +4,10 @@
Z3 is a high-performance theorem prover being developed at <a class="el"
href="http://research.microsoft.com">Microsoft Research</a>.
<b>The Z3 website is at <a class="el" href="http://github.com/z3prover">http://github.com/z3prover.</a>.</b>
<b>The Z3 website is at <a class="el" href="http://github.com/z3prover">http://github.com/z3prover</a>.</b>
This website hosts the automatically generated documentation for the Z3 APIs.
- \ref @C_API@
- \ref @CPP_API@ @DOTNET_API@ @JAVA_API@ @PYTHON_API@ @OCAML_API@
- Try Z3 online at <a href="http://rise4fun.com/z3">RiSE4Fun</a>.
*/

View file

@ -270,8 +270,7 @@ ALIASES = "beginfaq=<ul>" \
"emph{1}=<em>\1</em>" \
"extdoc{2}=<a class=\"el\" href=\"\1\">\2</a>" \
"nicebox{1}=<div class=\"fragment\"><pre class=\"fragment\">\1</pre></div>" \
"ccode{1}=<tt>\1</tt>" \
"zframe=<iframe allowtransparency=\"true\" frameborder=\"0\" style=\"width:600px;height:600px\" src=\"http://rise4fun.com/z3?frame=1&menu=0\"> </iframe>"
"ccode{1}=<tt>\1</tt>"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"

View file

@ -64,8 +64,7 @@ ALIASES = "beginfaq=<ul>" \
"emph{1}=<em>\1</em>" \
"extdoc{2}=<a class=\"el\" href=\"\1\">\2</a>" \
"nicebox{1}=<div class=\"fragment\"><pre class=\"fragment\">\1</pre></div>" \
"ccode{1}=<tt>\1</tt>" \
"zframe=<iframe allowtransparency=\"true\" frameborder=\"0\" style=\"width:600px;height:600px\" src=\"http://rise4fun.com/z3?frame=1&menu=0\"> </iframe>"
"ccode{1}=<tt>\1</tt>"
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO

View file

@ -1868,7 +1868,7 @@ class JavaExample
}
} else
{
System.out.println("BUG, the constraints are satisfiable.");
System.out.println("BUG, the constraints are not satisfiable.");
}
}

View file

@ -5,43 +5,34 @@ from z3.z3util import get_vars
Modified from the example in pysmt
https://github.com/pysmt/pysmt/blob/97088bf3b0d64137c3099ef79a4e153b10ccfda7/examples/efsmt.py
'''
def efsmt(y, phi, maxloops=None):
"""Solving exists x. forall y. phi(x, y)"""
vars = get_vars(phi)
x = [item for item in vars if item not in y]
esolver = Solver()
fsolver = Solver()
esolver.add(BoolVal(True))
def efsmt(ys, phi, maxloops = None):
"""Solving exists xs. forall ys. phi(x, y)"""
xs = [x for x in get_vars(phi) if x not in ys]
E = Solver()
F = Solver()
E.add(BoolVal(True))
loops = 0
while maxloops is None or loops <= maxloops:
loops += 1
eres = esolver.check()
if eres == unsat:
return unsat
else:
emodel = esolver.model()
tau = [emodel.eval(var, True) for var in x]
sub_phi = phi
for i in range(len(x)):
sub_phi = simplify(substitute(sub_phi, (x[i], tau[i])))
fsolver.add(Not(sub_phi))
if fsolver.check() == sat:
fmodel = fsolver.model()
sigma = [fmodel.eval(v, True) for v in y]
sub_phi = phi
for j in range(len(y)):
sub_phi = simplify(substitute(sub_phi, (y[j], sigma[j])))
esolver.add(sub_phi)
eres = E.check()
if eres == sat:
emodel = E.model()
sub_phi = substitute(phi, [(x, emodel.eval(x, True)) for x in xs])
F.push()
F.add(Not(sub_phi))
fres = F.check()
if fres == sat:
fmodel = F.model()
sub_phi = substitute(phi, [(y, fmodel.eval(y, True)) for y in ys])
E.add(sub_phi)
else:
return sat
return fres, [(x, emodel.eval(x, True)) for x in xs]
F.pop()
else:
return eres
return unknown
def test():
x, y, z = Reals("x y z")
fmla = Implies(And(y > 0, y < 10), y - 2 * x < 7)
fmlb = And(y > 3, x == 1)
print(efsmt([y], fmla))
print(efsmt([y], fmlb))
test()
x, y, z = Reals("x y z")
print(efsmt([y], Implies(And(y > 0, y < 10), y - 2 * x < 7)))
print(efsmt([y], And(y > 3, x == 1)))

View file

@ -17,13 +17,71 @@ def visitor(e, seen):
yield e
return
x, y = Ints('x y')
fml = x + x + y > 2
seen = {}
for e in visitor(fml, seen):
if is_const(e) and e.decl().kind() == Z3_OP_UNINTERPRETED:
print("Variable", e)
else:
print(e)
def modify(e, fn):
seen = {}
def visit(e):
if e in seen:
pass
elif fn(e) is not None:
seen[e] = fn(e)
elif is_and(e):
chs = [visit(ch) for ch in e.children()]
seen[e] = And(chs)
elif is_or(e):
chs = [visit(ch) for ch in e.children()]
seen[e] = Or(chs)
elif is_app(e):
chs = [visit(ch) for ch in e.children()]
seen[e] = e.decl()(chs)
elif is_quantifier(e):
# Note: does not work for Lambda that requires a separate case
body = visit(e.body())
is_forall = e.is_forall()
num_pats = e.num_patterns()
pats = (Pattern * num_pats)()
for i in range(num_pats):
pats[i] = e.pattern(i).ast
num_decls = e.num_vars()
sorts = (Sort * num_decls)()
names = (Symbol * num_decls)()
for i in range(num_decls):
sorts[i] = e.var_sort(i).ast
names[i] = to_symbol(e.var_name(i), e.ctx)
r = QuantifierRef(Z3_mk_quantifier(e.ctx_ref(), is_forall, e.weight(), num_pats, pats, num_decls, sorts, names, body.ast), e.ctx)
seen[e] = r
else:
seen[e] = e
return seen[e]
return visit(e)
if __name__ == "__main__":
x, y = Ints('x y')
fml = x + x + y > 2
seen = {}
for e in visitor(fml, seen):
if is_const(e) and e.decl().kind() == Z3_OP_UNINTERPRETED:
print("Variable", e)
else:
print(e)
s = SolverFor("HORN")
inv = Function('inv', IntSort(), IntSort(), BoolSort())
i, ip, j, jp = Ints('i ip j jp')
s.add(ForAll([i, j], Implies(i == 0, inv(i, j))))
s.add(ForAll([i, ip, j, jp], Implies(And(inv(i, j), i < 10, ip == i + 1), inv(ip, jp))))
s.add(ForAll([i, j], Implies(And(inv(i, j), i >= 10), i == 10)))
a0, a1, a2 = Ints('a0 a1 a2')
b0, b1, b2 = Ints('b0 b1 b2')
x = Var(0, IntSort())
y = Var(1, IntSort())
template = And(a0 + a1*x + a2*y >= 0, b0 + b1*x + b2*y >= 0)
def update(e):
if is_app(e) and eq(e.decl(), inv):
return substitute_vars(template, (e.arg(0)), e.arg(1))
return None
for f in s.assertions():
f_new = modify(f, update)
print(f_new)

View file

@ -24,7 +24,15 @@ message(STATUS "Z3_FOUND: ${Z3_FOUND}")
message(STATUS "Found Z3 ${Z3_VERSION_STRING}")
message(STATUS "Z3_DIR: ${Z3_DIR}")
add_executable(user_propagator_example example.cpp)
add_executable(user_propagator_example
example.cpp
common.h
user_propagator.h
user_propagator_with_theory.h
user_propagator_subquery_maximisation.h
user_propagator_internal_maximisation.h
user_propagator_created_maximisation.h)
target_include_directories(user_propagator_example PRIVATE ${Z3_CXX_INCLUDE_DIRS})
target_link_libraries(user_propagator_example PRIVATE ${Z3_LIBRARIES})

View file

@ -0,0 +1,77 @@
#pragma once
#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstring>
#include <optional>
#include "z3++.h"
using std::to_string;
#define SIZE(x) std::extent<decltype(x)>::value
// #define VERBOSE // Log events
#ifdef VERBOSE
#define WriteEmptyLine std::cout << std::endl
#define WriteLine(x) std::cout << (x) << std::endl
#define Write(x) std::cout << x
#else
#define WriteEmptyLine
#define WriteLine(x)
#define Write(x)
#endif
int log2i(unsigned n) {
if (n <= 0) {
return 0;
}
if (n <= 2) {
return 1;
}
unsigned l = 1;
int i = 0;
while (l < n) {
l <<= 1;
i++;
}
return i;
}
typedef std::vector<unsigned> simple_model;
// For putting z3 expressions in hash-tables
namespace std {
template<>
struct hash<simple_model> {
std::size_t operator()(const simple_model &m) const {
size_t hash = 0;
for (unsigned i = 0; i < m.size(); i++) {
hash *= m.size();
hash += m[i];
}
return hash;
}
};
template<>
struct hash<z3::expr> {
std::size_t operator()(const z3::expr &k) const {
return k.hash();
}
};
// Do not use Z3's == operator in the hash table
template<>
struct equal_to<z3::expr> {
bool operator()(const z3::expr &lhs, const z3::expr &rhs) const {
return z3::eq(lhs, rhs);
}
};
}

View file

@ -1,13 +1,8 @@
#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstring>
#include "z3++.h"
#include "user_propagator.h"
#include "user_propagator_with_theory.h"
#include "user_propagator_subquery_maximisation.h"
#include "user_propagator_internal_maximisation.h"
#include "user_propagator_created_maximisation.h"
/**
* The program solves the n-queens problem (number of solutions) with 4 different approaches
@ -20,206 +15,57 @@
*/
using namespace std::chrono;
using std::to_string;
#define QUEEN
#define REPETITIONS 5
#define SIZE(x) std::extent<decltype(x)>::value
#define MIN_BOARD 4
#define MAX_BOARD1 12
#define MAX_BOARD2 12
#ifdef LOG
#define WriteEmptyLine std::cout << std::endl
#define WriteLine(x) std::cout << (x) << std::endl
#define Write(x) std::cout << x
#else
#define WriteEmptyLine
#define WriteLine(x)
#define Write(x)
#endif
typedef std::vector<unsigned> model;
struct model_hash_function {
std::size_t operator()(const model &m) const {
size_t hash = 0;
for (unsigned i = 0; i < m.size(); i++) {
hash *= m.size();
hash += m[i];
}
return hash;
}
};
class user_propagator : public z3::user_propagator_base {
protected:
unsigned board;
std::unordered_map<unsigned, unsigned>& id_mapping;
model currentModel;
std::unordered_set<model, model_hash_function> modelSet;
std::vector<unsigned> fixedValues;
std::stack<unsigned> fixedCnt;
int solutionId = 1;
public:
int getModelCount() const {
return solutionId - 1;
}
void final() final {
this->conflict((unsigned) fixedValues.size(), fixedValues.data());
if (modelSet.find(currentModel) != modelSet.end()) {
WriteLine("Got already computed model");
return;
}
Write("Model #" << solutionId << ":\n");
solutionId++;
#ifdef LOG
for (unsigned i = 0; i < fixedValues.size(); i++) {
unsigned id = fixedValues[i];
WriteLine("q" + to_string(id_mapping[id]) + " = " + to_string(currentModel[id]));
}
#endif
modelSet.insert(currentModel);
WriteEmptyLine;
}
static unsigned bvToInt(z3::expr e) {
return (unsigned)e.get_numeral_int();
}
void fixed(unsigned id, z3::expr const &e) override {
fixedValues.push_back(id);
unsigned value = bvToInt(e);
currentModel[id_mapping[id]] = value;
}
user_propagator(z3::solver *s, std::unordered_map<unsigned, unsigned>& idMapping, unsigned board)
: user_propagator_base(s), board(board), id_mapping(idMapping), currentModel(board, (unsigned)-1) {
this->register_fixed();
this->register_final();
}
virtual ~user_propagator() = default;
void push() override {
fixedCnt.push((unsigned) fixedValues.size());
}
void pop(unsigned num_scopes) override {
for (unsigned i = 0; i < num_scopes; i++) {
unsigned lastCnt = fixedCnt.top();
fixedCnt.pop();
for (auto j = fixedValues.size(); j > lastCnt; j--) {
currentModel[fixedValues[j - 1]] = (unsigned)-1;
}
fixedValues.resize(lastCnt);
}
}
user_propagator_base *fresh(Z3_context) override { return this; }
};
class user_propagator_with_theory : public user_propagator {
public:
void fixed(unsigned id, z3::expr const &e) override {
unsigned queenId = id_mapping[id];
unsigned queenPos = bvToInt(e);
if (queenPos >= board) {
this->conflict(1, &id);
return;
}
for (unsigned fixed : fixedValues) {
unsigned otherId = id_mapping[fixed];
unsigned otherPos = currentModel[fixed];
if (queenPos == otherPos) {
const unsigned conflicting[] = {id, fixed};
this->conflict(2, conflicting);
continue;
}
#ifdef QUEEN
int diffY = abs((int)queenId - (int)otherId);
int diffX = abs((int)queenPos - (int)otherPos);
if (diffX == diffY) {
const unsigned conflicting[] = {id, fixed};
this->conflict(2, conflicting);
}
#endif
}
fixedValues.push_back(id);
currentModel[id_mapping[id]] = queenPos;
}
user_propagator_with_theory(z3::solver *s, std::unordered_map<unsigned, unsigned>& idMapping, unsigned board)
: user_propagator(s, idMapping, board) {}
};
int log2i(unsigned n) {
if (n <= 0) {
return 0;
}
if (n <= 2) {
return 1;
}
unsigned l = 1;
int i = 0;
while (l < n) {
l <<= 1;
i++;
}
return i;
}
std::vector<z3::expr> createQueens(z3::context &context, unsigned num) {
std::vector<z3::expr> queens;
int bits = log2i(num) + 1 /*to detect potential overflow in the diagonal*/;
z3::expr_vector createQueens(z3::context &context, unsigned num, int bits, std::string prefix) {
z3::expr_vector queens(context);
for (unsigned i = 0; i < num; i++) {
queens.push_back(context.bv_const((std::string("q") + to_string(i)).c_str(), bits));
queens.push_back(context.bv_const((prefix + "q" + to_string(i)).c_str(), bits));
}
return queens;
}
void createConstraints(z3::context &context, z3::solver &solver, const std::vector<z3::expr> &queens) {
z3::expr_vector createQueens(z3::context &context, unsigned num) {
return createQueens(context, num, log2i(num) + 1, "");
}
z3::expr createConstraints(z3::context &context, const z3::expr_vector &queens) {
z3::expr_vector assertions(context);
for (unsigned i = 0; i < queens.size(); i++) {
// assert column range
solver.add(z3::uge(queens[i], 0));
solver.add(z3::ule(queens[i], (int) (queens.size() - 1)));
assertions.push_back(z3::uge(queens[i], 0));
assertions.push_back(z3::ule(queens[i], (int) (queens.size() - 1)));
}
z3::expr_vector distinct(context);
for (const z3::expr &queen : queens) {
for (const z3::expr &queen: queens) {
distinct.push_back(queen);
}
solver.add(z3::distinct(distinct));
assertions.push_back(z3::distinct(distinct));
#ifdef QUEEN
for (unsigned i = 0; i < queens.size(); i++) {
for (unsigned j = i + 1; j < queens.size(); j++) {
solver.add((int)(j - i) != (queens[j] - queens[i]));
solver.add((int)(j - i) != (queens[i] - queens[j]));
assertions.push_back((int) (j - i) != (queens[j] - queens[i]));
assertions.push_back((int) (j - i) != (queens[i] - queens[j]));
}
}
#endif
return z3::mk_and(assertions);
}
int test01(unsigned num, bool simple) {
z3::context context;
z3::solver solver(context, !simple ? Z3_mk_solver(context) : Z3_mk_simple_solver(context));
std::vector<z3::expr> queens = createQueens(context, num);
z3::expr_vector queens = createQueens(context, num);
createConstraints(context, solver, queens);
solver.add(createConstraints(context, queens));
int solutionId = 1;
@ -260,8 +106,8 @@ inline int test1(unsigned num) {
int test23(unsigned num, bool withTheory) {
z3::context context;
z3::solver solver(context, Z3_mk_simple_solver(context));
std::unordered_map<unsigned, unsigned> idMapping;
z3::solver solver(context, z3::solver::simple());
std::unordered_map<z3::expr, unsigned> idMapping;
user_propagator *propagator;
if (!withTheory) {
@ -271,15 +117,15 @@ int test23(unsigned num, bool withTheory) {
propagator = new user_propagator_with_theory(&solver, idMapping, num);
}
std::vector<z3::expr> queens = createQueens(context, num);
z3::expr_vector queens = createQueens(context, num);
for (unsigned i = 0; i < queens.size(); i++) {
unsigned id = propagator->add(queens[i]);
idMapping[id] = i;
propagator->add(queens[i]);
idMapping[queens[i]] = i;
}
if (!withTheory) {
createConstraints(context, solver, queens);
solver.add(createConstraints(context, queens));
}
solver.check();
@ -296,50 +142,246 @@ inline int test3(unsigned num) {
return test23(num, true);
}
int test4(unsigned num) {
z3::context context;
z3::solver solver(context, z3::solver::simple());
z3::expr_vector queens1 = createQueens(context, num, log2i(num * num), ""); // square to avoid overflow during summation
z3::expr valid1 = createConstraints(context, queens1);
z3::expr_vector queens2 = createQueens(context, num, log2i(num * num), "forall_");
z3::expr valid2 = createConstraints(context, queens2);
z3::expr manhattanSum1 = context.bv_val(0, queens1[0].get_sort().bv_size());
z3::expr manhattanSum2 = context.bv_val(0, queens2[0].get_sort().bv_size());
for (int i = 1; i < queens1.size(); i++) {
manhattanSum1 = manhattanSum1 + z3::ite(z3::uge(queens1[i], queens1[i - 1]), queens1[i] - queens1[i - 1], queens1[i - 1] - queens1[i]);
manhattanSum2 = manhattanSum2 + z3::ite(z3::uge(queens2[i], queens2[i - 1]), queens2[i] - queens2[i - 1], queens2[i - 1] - queens2[i]);
}
solver.add(valid1 && z3::forall(queens2, z3::implies(valid2, manhattanSum1 >= manhattanSum2)));
solver.check();
z3::model model = solver.get_model();
int max = 0;
int prev, curr;
curr = model.eval(queens1[0]).get_numeral_int();
for (unsigned i = 1; i < num; i++) {
prev = curr;
curr = model.eval(queens1[i]).get_numeral_int();
max += abs(curr - prev);
}
return max;
}
int test5(unsigned num) {
z3::context context;
z3::solver solver(context, z3::solver::simple());
std::unordered_map<z3::expr, unsigned> idMapping;
z3::expr_vector queens = createQueens(context, num, log2i(num * num), "");
solver.add(createConstraints(context, queens));
user_propagator_subquery_maximisation propagator(&solver, idMapping, num, queens);
for (unsigned i = 0; i < queens.size(); i++) {
propagator.add(queens[i]);
idMapping[queens[i]] = i;
}
solver.check();
z3::model model = solver.get_model();
int max = 0;
int prev, curr;
curr = model.eval(queens[0]).get_numeral_int();
for (unsigned i = 1; i < num; i++) {
prev = curr;
curr = model.eval(queens[i]).get_numeral_int();
max += abs(curr - prev);
}
return max;
}
int test6(unsigned num) {
z3::context context;
z3::solver solver(context, z3::solver::simple());
std::unordered_map<z3::expr, unsigned> idMapping;
z3::expr_vector queens = createQueens(context, num, log2i(num * num), "");
solver.add(createConstraints(context, queens));
user_propagator_internal_maximisation propagator(&solver, idMapping, num, queens);
for (unsigned i = 0; i < queens.size(); i++) {
propagator.add(queens[i]);
idMapping[queens[i]] = i;
}
solver.check();
return propagator.best;
}
int test7(unsigned num) {
z3::context context;
z3::solver solver(context, z3::solver::simple());
z3::expr_vector queens1 = createQueens(context, num, log2i(num * num), "");
z3::expr_vector queens2 = createQueens(context, num, log2i(num * num), "forall_");
z3::expr manhattanSum1 = context.bv_val(0, queens1[0].get_sort().bv_size());
z3::expr manhattanSum2 = context.bv_val(0, queens2[0].get_sort().bv_size());
for (int i = 1; i < queens1.size(); i++) {
manhattanSum1 = manhattanSum1 + z3::ite(z3::uge(queens1[i], queens1[i - 1]), queens1[i] - queens1[i - 1], queens1[i - 1] - queens1[i]);
manhattanSum2 = manhattanSum2 + z3::ite(z3::uge(queens2[i], queens2[i - 1]), queens2[i] - queens2[i - 1], queens2[i - 1] - queens2[i]);
}
z3::sort_vector domain(context);
for (int i = 0; i < queens1.size(); i++) {
domain.push_back(queens1[i].get_sort());
}
z3::func_decl validFunc = context.user_propagate_function(context.str_symbol("valid"), domain, context.bool_sort());
solver.add(validFunc(queens1) && z3::forall(queens2, z3::implies(validFunc(queens2), manhattanSum1 >= manhattanSum2)));
user_propagator_created_maximisation propagator(&solver, num);
solver.check();
z3::model model = solver.get_model();
int max = 0;
int prev, curr;
curr = model.eval(queens1[0]).get_numeral_int();
for (unsigned i = 1; i < num; i++) {
prev = curr;
curr = model.eval(queens1[i]).get_numeral_int();
max += abs(curr - prev);
}
return max;
}
int main() {
for (int num = 4; num <= 11; num++) {
for (int num = MIN_BOARD; num <= MAX_BOARD1; num++) {
std::cout << "num = " << num << ":\n" << std::endl;
unsigned seed = (unsigned) high_resolution_clock::now().time_since_epoch().count();
const char *testName[] =
{
"BV + Blocking clauses (Default solver)",
"BV + Blocking clauses (Simple solver)",
"BV + Adding conflicts",
"Custom theory + conflicts",
};
int permutation[4] = {0, 1, 2, 3,};
double timeResults[REPETITIONS * SIZE(permutation)];
for (int rep = 0; rep < REPETITIONS; rep++) {
// Execute strategies in a randomised order
std::shuffle(&permutation[0], &permutation[SIZE(permutation) - 1], std::default_random_engine(seed));
for (int i : permutation) {
int modelCount = -1;
auto now1 = high_resolution_clock::now();
switch (i) {
case 0:
modelCount = test0(num);
break;
case 1:
modelCount = test1(num);
break;
case 2:
modelCount = test2(num);
break;
case 3:
modelCount = test3(num);
break;
default:
WriteLine("Unknown case");
break;
}
auto now2 = high_resolution_clock::now();
duration<double, std::milli> ms = now2 - now1;
std::cout << testName[i] << " took " << ms.count() << "ms (" << modelCount << " models)" << std::endl;
timeResults[rep * SIZE(permutation) + i] = ms.count();
WriteLine("-------------");
}
}
std::cout << "\n" << std::endl;
for (unsigned i = 0; i < SIZE(permutation); i++) {
std::cout << testName[i];
double sum = 0;
for (int j = 0; j < REPETITIONS; j++) {
std::cout << " " << timeResults[j * SIZE(permutation) + i] << "ms";
sum += timeResults[j * SIZE(permutation) + i];
}
std::cout << " | avg: " << sum / REPETITIONS << "ms" << std::endl;
}
std::cout << std::endl;
}
z3::set_param("smt.ematching", "false");
z3::set_param("smt.mbqi", "true");
std::cout << "\nMaximal distance:" << std::endl;
for (int num = MIN_BOARD; num <= MAX_BOARD2; num++) {
std::cout << "num = " << num << ":\n" << std::endl;
unsigned seed = (unsigned) high_resolution_clock::now().time_since_epoch().count();
const char *testName[] =
{
"BV + Blocking clauses (Default solver)",
"BV + Blocking clauses (Simple solver)",
"BV + Adding conflicts",
"Custom theory + conflicts",
};
int permutation[4] =
{
0,
1,
2,
3,
"Ordinary/Direct Encoding",
"SubQuery in final",
"Assert Smaller in final",
"created",
};
int permutation[4] = {0, 1, 2, 3,};
double timeResults[REPETITIONS * SIZE(permutation)];
for (int rep = 0; rep < REPETITIONS; rep++) {
// Execute strategies in a randomised order
std::shuffle(&permutation[0], &permutation[SIZE(permutation) - 1], std::default_random_engine(seed));
for (int i : permutation) {
int modelCount = -1;
for (int i: permutation) {
int max = -1;
auto now1 = high_resolution_clock::now();
switch (i) {
case 0:
modelCount = test0(num);
switch (i + 4) {
case 4:
max = test4(num);
break;
case 1:
modelCount = test1(num);
case 5:
max = test5(num);
break;
case 2:
modelCount = test2(num);
case 6:
max = test6(num);
break;
case 3:
modelCount = test3(num);
case 7:
max = test7(num);
break;
default:
WriteLine("Unknown case");
@ -347,7 +389,7 @@ int main() {
}
auto now2 = high_resolution_clock::now();
duration<double, std::milli> ms = now2 - now1;
std::cout << testName[i] << " took " << ms.count() << "ms (" << modelCount << " models)" << std::endl;
std::cout << testName[i] << " took " << ms.count() << "ms. Max: " << max << std::endl;
timeResults[rep * SIZE(permutation) + i] = ms.count();
WriteLine("-------------");
}

Binary file not shown.

View file

@ -0,0 +1,87 @@
#pragma once
#include "common.h"
class user_propagator : public z3::user_propagator_base {
protected:
unsigned board;
std::unordered_map<z3::expr, unsigned> &queenToY;
simple_model currentModel;
std::unordered_set<simple_model> modelSet;
z3::expr_vector fixedValues;
std::stack<unsigned> fixedCnt;
int solutionNr = 1;
public:
int getModelCount() const {
return solutionNr - 1;
}
void final() override {
this->conflict(fixedValues);
if (modelSet.find(currentModel) != modelSet.end()) {
WriteLine("Got already computed model");
return;
}
Write("Model #" << solutionNr << ":\n");
solutionNr++;
#ifdef VERBOSE
for (unsigned i = 0; i < fixedValues.size(); i++) {
z3::expr fixed = fixedValues[i];
WriteLine("q" + to_string(queenToY[fixed]) + " = " + to_string(currentModel[queenToY[fixed]]));
}
#endif
modelSet.insert(currentModel);
WriteEmptyLine;
}
static unsigned bvToInt(z3::expr const &e) {
return (unsigned) e.get_numeral_int();
}
void fixed(z3::expr const &ast, z3::expr const &value) override {
fixedValues.push_back(ast);
unsigned valueBv = bvToInt(value);
currentModel[queenToY[ast]] = valueBv;
}
user_propagator(z3::context &c, std::unordered_map<z3::expr, unsigned> &queenToY, unsigned board)
: user_propagator_base(c), board(board), queenToY(queenToY), fixedValues(c), currentModel(board, (unsigned) -1) {
this->register_fixed();
this->register_final();
}
user_propagator(z3::solver *s, std::unordered_map<z3::expr, unsigned> &idMapping, unsigned board)
: user_propagator_base(s), board(board), queenToY(idMapping), fixedValues(s->ctx()), currentModel(board, (unsigned) -1) {
this->register_fixed();
this->register_final();
}
~user_propagator() = default;
void push() override {
fixedCnt.push((unsigned) fixedValues.size());
}
void pop(unsigned num_scopes) override {
for (unsigned i = 0; i < num_scopes; i++) {
unsigned lastCnt = fixedCnt.top();
fixedCnt.pop();
// Remove fixed values from model
for (unsigned j = fixedValues.size(); j > lastCnt; j--) {
currentModel[queenToY[fixedValues[j - 1]]] = (unsigned) -1;
}
fixedValues.resize(lastCnt);
}
}
user_propagator_base *fresh(z3::context &) override {
return this;
}
};

View file

@ -0,0 +1,338 @@
#pragma once
#include "common.h"
class user_propagator_created_maximisation : public z3::user_propagator_base {
std::unordered_map<z3::expr, z3::expr_vector> argToFcts;
std::unordered_map<z3::expr, z3::expr_vector> fctToArgs;
std::unordered_map<z3::expr, unsigned> currentModel;
z3::expr_vector fixedValues;
std::vector<unsigned> fixedCnt;
user_propagator_created_maximisation* childPropagator = nullptr;
user_propagator_created_maximisation* parentPropagator = nullptr;
int board;
int nesting; // Just for logging (0 ... main solver; 1 ... sub-solver)
public:
user_propagator_created_maximisation(z3::context &c, user_propagator_created_maximisation* parentPropagator, unsigned board, int nesting) :
z3::user_propagator_base(c), fixedValues(c), parentPropagator(parentPropagator), board(board), nesting(nesting) {
this->register_fixed();
this->register_final();
this->register_created();
}
user_propagator_created_maximisation(z3::solver *s, unsigned board) :
z3::user_propagator_base(s), fixedValues(s->ctx()), board(board), nesting(0) {
this->register_fixed();
this->register_final();
this->register_created();
}
~user_propagator_created_maximisation() {
delete childPropagator;
}
void final() override {
WriteLine("Final (" + to_string(nesting) + ")");
}
void push() override {
WriteLine("Push (" + to_string(nesting) + ")");
fixedCnt.push_back((unsigned) fixedValues.size());
}
void pop(unsigned num_scopes) override {
WriteLine("Pop (" + to_string(nesting) + ")");
for (unsigned i = 0; i < num_scopes; i++) {
unsigned lastCnt = fixedCnt.back();
fixedCnt.pop_back();
for (auto j = fixedValues.size(); j > lastCnt; j--) {
currentModel.erase(fixedValues[j - 1]);
}
fixedValues.resize(lastCnt);
}
}
void checkValidPlacement(std::vector<z3::expr_vector> &conflicts, const z3::expr &fct, const z3::expr_vector &args, const std::vector<unsigned> &argValues, int pos) {
unsigned queenId = pos;
unsigned queenPos = argValues[pos];
z3::expr queenPosExpr = args[pos];
if (queenPos >= board) {
z3::expr_vector conflicting(ctx());
conflicting.push_back(fct);
conflicting.push_back(queenPosExpr);
conflicts.push_back(conflicting);
return;
}
for (unsigned otherId = 0; otherId < argValues.size(); otherId++) {
if (otherId == pos)
continue;
unsigned otherPos = argValues[otherId];
z3::expr otherPosExpr = args[otherId];
if (otherPos == (unsigned)-1)
continue; // We apparently do not have this value
if (queenPos == otherPos) {
z3::expr_vector conflicting(ctx());
conflicting.push_back(fct);
conflicting.push_back(queenPosExpr);
conflicting.push_back(otherPosExpr);
conflicts.push_back(conflicting);
}
int diffY = abs((int) queenId - (int) otherId);
int diffX = abs((int) queenPos - (int) otherPos);
if (diffX == diffY) {
z3::expr_vector conflicting(ctx());
conflicting.push_back(fct);
conflicting.push_back(queenPosExpr);
conflicting.push_back(otherPosExpr);
conflicts.push_back(conflicting);
}
}
}
unsigned getValues(const z3::expr &fct, std::vector<unsigned> &argValues) const {
z3::expr_vector args = fctToArgs.at(fct);
unsigned fixed = 0;
for (const z3::expr &arg: args) {
if (currentModel.contains(arg)) {
argValues.push_back(currentModel.at(arg));
fixed++;
}
else
argValues.push_back((unsigned) -1); // no value so far
}
return fixed;
}
user_propagator_base *fresh(z3::context &ctx) override {
WriteLine("Fresh context");
childPropagator = new user_propagator_created_maximisation(ctx, this, board, nesting + 1);
return childPropagator;
}
void fixed(const z3::expr &expr, const z3::expr &value) override {
// Could be optimized!
WriteLine("Fixed (" + to_string(nesting) + ") " + expr.to_string() + " to " + value.to_string());
unsigned v = value.is_true() ? 1 : (value.is_false() ? 0 : value.get_numeral_uint());
currentModel[expr] = v;
fixedValues.push_back(expr);
z3::expr_vector effectedFcts(ctx());
bool fixedFct = fctToArgs.contains(expr);
if (fixedFct) {
// fixed the value of a function
effectedFcts.push_back(expr);
}
else {
// fixed the value of a function's argument
effectedFcts = argToFcts.at(expr);
}
for (const z3::expr& fct : effectedFcts) {
if (!currentModel.contains(fct))
// we do not know yet whether to expect a valid or invalid placement
continue;
std::vector<unsigned> values;
unsigned fixedArgsCnt = getValues(fct, values);
bool fctValue = currentModel[fct];
z3::expr_vector args = fctToArgs.at(fct);
if (!fctValue) {
// expect invalid placement ...
if (fixedArgsCnt != board)
// we expect an invalid placement, but not all queen positions have been placed yet
return;
std::vector<z3::expr_vector> conflicts;
for (unsigned i = 0; i < args.size(); i++) {
if (values[i] != (unsigned)-1)
checkValidPlacement(conflicts, expr, args, values, i);
}
if (conflicts.empty()) {
// ... but we got a valid one
z3::expr_vector conflicting(ctx());
conflicting.push_back(fct);
for (const z3::expr &arg: args) {
if (!arg.is_numeral())
conflicting.push_back(arg);
}
this->conflict(conflicting);
}
else {
// ... and everything is fine; we have at least one conflict
}
}
else {
// expect valid placement ...
std::vector<z3::expr_vector> conflicts;
if (fixedFct){
for (unsigned i = 0; i < args.size(); i++) {
if (values[i] != (unsigned)-1) // check all set queens
checkValidPlacement(conflicts, expr, args, values, i);
}
}
else {
for (unsigned i = 0; i < args.size(); i++) {
if (z3::eq(args[i], expr)) // only check newly fixed values
checkValidPlacement(conflicts, fct, args, values, i);
}
}
if (conflicts.size() > 0) {
// ... but we got an invalid one
for (const z3::expr_vector &conflicting: conflicts)
this->conflict(conflicting);
}
else {
// ... and everything is fine; no conflict
}
}
}
}
// void fixed(const z3::expr &expr, const z3::expr &value) override {
// WriteLine("Fixed (" + to_string(nesting) + ") " + expr.to_string() + " to " + value.to_string());
// unsigned v = value.is_true() ? 1 : (value.is_false() ? 0 : value.get_numeral_uint());
// currentModel[expr] = v;
// fixedValues.push_back(expr);
//
// if (fctToArgs.contains(expr)) {
// // fixed the value of a function
//
// std::vector<unsigned> values;
// unsigned fixedArgsCnt = getValues(expr, values);
//
// if (!v && fixedArgsCnt != board)
// // we expect an invalid placement, but not all queen positions have been placed yet
// return;
//
// z3::expr_vector args = fctToArgs.at(expr);
//
// std::vector<z3::expr_vector> conflicts;
// for (unsigned i = 0; i < args.size(); i++) {
// if (values[i] != (unsigned)-1)
// checkValidPlacement(conflicts, expr, args, values, i);
// }
// if (v) {
// //we expected a valid queen placement
// if (conflicts.size() > 0) {
// // ... but we got an invalid one
// for (const z3::expr_vector &conflicting: conflicts)
// this->conflict(conflicting);
// }
// else {
// // everything fine; no conflict
// }
// }
// else {
// // we expect an invalid queen placement
// if (conflicts.empty()) {
// // ... but we got a valid one
// z3::expr_vector conflicting(ctx());
// conflicting.push_back(expr);
// for (const z3::expr &arg: args) {
// if (!arg.is_numeral())
// conflicting.push_back(arg);
// }
// this->conflict(conflicting);
// }
// else {
// // everything fine; we have at least one conflict
// }
// }
// }
// else {
// // fixed the value of a function argument
//
// z3::expr_vector effectedFcts = argToFcts.at(expr);
//
// for (const z3::expr& fct : effectedFcts) {
// if (!currentModel.contains(fct))
// // we do not know yet whether to expect a valid or invalid placement
// continue;
//
// std::vector<unsigned> values;
// unsigned fixedArgsCnt = getValues(fct, values);
// bool fctValue = currentModel[fct];
// z3::expr_vector args = fctToArgs.at(fct);
//
// if (!fctValue) {
// // expect invalid placement
// if (fixedArgsCnt != board)
// // we expect an invalid placement, but not all queen positions have been placed yet
// return;
// std::vector<z3::expr_vector> conflicts;
// for (unsigned i = 0; i < args.size(); i++) {
// if (values[i] != (unsigned)-1)
// checkValidPlacement(conflicts, expr, args, values, i);
// }
//
// if (conflicts.empty()) {
// // ... but we got a valid one
// z3::expr_vector conflicting(ctx());
// conflicting.push_back(fct);
// for (const z3::expr &arg: args) {
// if (!arg.is_numeral())
// conflicting.push_back(arg);
// }
// this->conflict(conflicting);
// }
// else {
// // everything fine; we have at least one conflict
// }
// }
// else {
// // expect valid placement
// std::vector<z3::expr_vector> conflicts;
// for (unsigned i = 0; i < args.size(); i++) {
// if (z3::eq(args[i], expr)) // only check newly fixed values
// checkValidPlacement(conflicts, fct, args, values, i);
// }
// if (conflicts.size() > 0) {
// // ... but we got an invalid one
// for (const z3::expr_vector &conflicting: conflicts)
// this->conflict(conflicting);
// }
// else {
// // everything fine; no conflict
// }
// }
// }
// }
// }
void created(const z3::expr &func) override {
WriteLine("Created (" + to_string(nesting) + "): " + func.to_string());
z3::expr_vector args = func.args();
for (unsigned i = 0; i < args.size(); i++) {
z3::expr arg = args[i];
if (!arg.is_numeral()) {
WriteLine("Registered " + arg.to_string());
this->add(arg);
}
else {
currentModel[arg] = arg.get_numeral_uint();
// Skip registering as argument is a fixed BV;
}
argToFcts.try_emplace(arg, ctx()).first->second.push_back(func);
}
fctToArgs.emplace(std::make_pair(func, args));
}
};

View file

@ -0,0 +1,30 @@
#pragma once
#include "user_propagator_with_theory.h"
class user_propagator_internal_maximisation : public user_propagator_with_theory {
z3::expr manhattanSum;
public:
int best = -1;
user_propagator_internal_maximisation(z3::solver *s, std::unordered_map<z3::expr, unsigned> &idMapping, unsigned board, z3::expr_vector queens)
: user_propagator_with_theory(s, idMapping, board),
manhattanSum(s->ctx().bv_val(0, queens[0].get_sort().bv_size())) {
for (int i = 1; i < queens.size(); i++) {
manhattanSum = manhattanSum + z3::ite(z3::uge(queens[i], queens[i - 1]), queens[i] - queens[i - 1], queens[i - 1] - queens[i]);
}
}
void final() override {
int current = 0;
for (unsigned i = 1; i < board; i++) {
current += abs((signed) currentModel[i] - (signed) currentModel[i - 1]);
}
best = std::max(current, best);
this->propagate(z3::expr_vector(ctx()), z3::ugt(manhattanSum, best));
}
};

View file

@ -0,0 +1,51 @@
#pragma once
#include "user_propagator.h"
class user_propagator_subquery_maximisation : public user_propagator {
z3::expr assertion;
z3::expr_vector queens;
z3::expr manhattanSum;
public:
user_propagator_subquery_maximisation(z3::solver *s, std::unordered_map<z3::expr, unsigned> &idMapping, unsigned board, z3::expr_vector queens)
: user_propagator(s, idMapping, board),
assertion(mk_and(s->assertions())),
queens(queens), manhattanSum(s->ctx().bv_val(0, queens[0].get_sort().bv_size())) {
for (int i = 1; i < queens.size(); i++) {
manhattanSum = manhattanSum + z3::ite(z3::uge(queens[i], queens[i - 1]), queens[i] - queens[i - 1], queens[i - 1] - queens[i]);
}
}
void final() override {
int max1 = 0;
for (unsigned i = 1; i < board; i++) {
max1 += abs((signed) currentModel[i] - (signed) currentModel[i - 1]);
}
z3::expr_vector vec(ctx());
int max2 = 0;
z3::solver subquery(ctx(), z3::solver::simple());
subquery.add(assertion);
subquery.add(z3::ugt(manhattanSum, max1));
if (subquery.check() == z3::unsat)
return; // model is already maximal
z3::model counterExample = subquery.get_model();
int prev, curr = -1;
for (int i = 0; i < queens.size(); i++) {
prev = curr;
curr = counterExample.eval(queens[i]).get_numeral_int();
if (i == 0) continue;
max2 += abs(curr - prev);
}
this->propagate(vec, z3::uge(manhattanSum, max2));
}
};

View file

@ -0,0 +1,50 @@
#pragma once
#include "user_propagator.h"
class user_propagator_with_theory : public user_propagator {
public:
user_propagator_with_theory(z3::context &c, std::unordered_map<z3::expr, unsigned> &idMapping, unsigned board)
: user_propagator(c, idMapping, board) {}
user_propagator_with_theory(z3::solver *s, std::unordered_map<z3::expr, unsigned> &idMapping, unsigned board)
: user_propagator(s, idMapping, board) {}
void fixed(z3::expr const &ast, z3::expr const &value) override {
unsigned queenId = queenToY[ast];
unsigned queenPos = bvToInt(value);
if (queenPos >= board) {
z3::expr_vector conflicting(ast.ctx());
conflicting.push_back(ast);
this->conflict(conflicting);
return;
}
for (const z3::expr &fixed: fixedValues) {
unsigned otherId = queenToY[fixed];
unsigned otherPos = currentModel[queenToY[fixed]];
if (queenPos == otherPos) {
z3::expr_vector conflicting(ast.ctx());
conflicting.push_back(ast);
conflicting.push_back(fixed);
this->conflict(conflicting);
continue;
}
int diffY = abs((int) queenId - (int) otherId);
int diffX = abs((int) queenPos - (int) otherPos);
if (diffX == diffY) {
z3::expr_vector conflicting(ast.ctx());
conflicting.push_back(ast);
conflicting.push_back(fixed);
this->conflict(conflicting);
}
}
fixedValues.push_back(ast);
currentModel[queenToY[ast]] = queenPos;
}
};

View file

@ -18,7 +18,7 @@ jobs:
displayName: Build
inputs:
script:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{parameters.BuildArchitecture}} &&
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{parameters.BuildArchitecture}} &&
python scripts\mk_win_dist.py
--${{parameters.BuildArchitecture}}-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk

View file

@ -644,7 +644,7 @@ def mk_gparams_register_modules_internal(h_files_full_path, path):
for code in cmds:
fout.write('{ param_descrs d; %s(d); gparams::register_global(d); }\n' % code)
for (mod, code) in mod_cmds:
fout.write('{ std::function<param_descrs *(void)> f = []() { auto* d = alloc(param_descrs); %s(*d); return d; }; gparams::register_module("%s", f); }\n' % (code, mod))
fout.write('{ auto f = []() { auto* d = alloc(param_descrs); %s(*d); return d; }; gparams::register_module("%s", f); }\n' % (code, mod))
for (mod, descr) in mod_descrs:
fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr))
fout.write('}\n')

View file

@ -8,7 +8,7 @@
from mk_util import *
def init_version():
set_version(4, 8, 15, 0)
set_version(4, 8, 16, 0)
# Z3 Project definition
def init_project_def():

View file

@ -56,6 +56,7 @@ def display_help():
print(" -f, --force force script to regenerate Makefiles.")
print(" --nodotnet do not include .NET bindings in the binary distribution files.")
print(" --dotnet-key=<file> sign the .NET assembly with the private key in <file>.")
print(" --arch=<arch> set architecture (to arm64) to force arm64 build")
print(" --nojava do not include Java bindings in the binary distribution files.")
print(" --nopython do not include Python bindings in the binary distribution files.")
print(" --githash include git hash in the Zip file.")
@ -72,6 +73,7 @@ def parse_options():
'nojava',
'nodotnet',
'dotnet-key=',
'arch=',
'githash',
'nopython'
])
@ -96,6 +98,11 @@ def parse_options():
JAVA_ENABLED = False
elif opt == '--githash':
GIT_HASH = True
elif opt == '--arch':
if arg == "arm64":
mk_util.IS_ARCH_ARM64 = True
else:
raise MKException("Invalid architecture directive '%s'. Legal directives: arm64" % arg)
else:
raise MKException("Invalid command line option '%s'" % opt)
set_build_dir(path)
@ -119,6 +126,8 @@ def mk_build_dir(path):
opts.append('--git-describe')
if PYTHON_ENABLED:
opts.append('--python')
if mk_util.IS_ARCH_ARM64:
opts.append('--arm64=true')
if subprocess.call(opts) != 0:
raise MKException("Failed to generate build directory at '%s'" % path)
@ -172,7 +181,9 @@ def get_os_name():
def get_z3_name():
major, minor, build, revision = get_version()
if sys.maxsize >= 2**32:
if mk_util.IS_ARCH_ARM64:
platform = "arm64"
elif sys.maxsize >= 2**32:
platform = "x64"
else:
platform = "x86"

View file

@ -69,6 +69,7 @@ IS_WINDOWS=False
IS_LINUX=False
IS_HURD=False
IS_OSX=False
IS_ARCH_ARM64=False
IS_FREEBSD=False
IS_NETBSD=False
IS_OPENBSD=False
@ -114,6 +115,7 @@ ALWAYS_DYNAMIC_BASE=False
FPMATH="Default"
FPMATH_FLAGS="-mfpmath=sse -msse -msse2"
FPMATH_ENABLED=getenv("FPMATH_ENABLED", "True")
def check_output(cmd):
@ -277,7 +279,13 @@ def test_gmp(cc):
def test_fpmath(cc):
global FPMATH_FLAGS
global FPMATH_FLAGS, IS_ARCH_ARM64, IS_OSX
if FPMATH_ENABLED == "False":
FPMATH_FLAGS=""
return "Disabled"
if IS_ARCH_ARM64 and IS_OSX:
FPMATH_FLAGS = ""
return "Disabled-ARM64"
if is_verbose():
print("Testing floating point support...")
t = TempFile('tstsse.cpp')
@ -618,6 +626,10 @@ elif os.name == 'posix':
LINUX_X64=False
if os.name == 'posix' and os.uname()[4] == 'arm64':
IS_ARCH_ARM64 = True
def display_help(exit_code):
print("mk_make.py: Z3 Makefile generator\n")
print("This script generates the Makefile for the Z3 theorem prover.")
@ -640,6 +652,7 @@ def display_help(exit_code):
print(" -x, --x64 create 64 binary when using Visual Studio.")
else:
print(" --x86 force 32-bit x86 build on x64 systems.")
print(" --arm64=<bool> forcearm64 bit build on/off (supported for Darwin).")
print(" -m, --makefiles generate only makefiles.")
if IS_WINDOWS:
print(" -v, --vsproj generate Visual Studio Project Files.")
@ -682,11 +695,11 @@ def parse_options():
global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM
global DOTNET_CORE_ENABLED, DOTNET_KEY_FILE, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, STATIC_BIN, PREFIX, GMP, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH, GIT_DESCRIBE, PYTHON_INSTALL_ENABLED, PYTHON_ENABLED
global LINUX_X64, SLOW_OPTIMIZE, LOG_SYNC, SINGLE_THREADED
global GUARD_CF, ALWAYS_DYNAMIC_BASE
global GUARD_CF, ALWAYS_DYNAMIC_BASE, IS_ARCH_ARM64
try:
options, remainder = getopt.gnu_getopt(sys.argv[1:],
'b:df:sxhmcvtnp:gj',
['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'guardcf',
'b:df:sxa:hmcvtnp:gj',
['build=', 'debug', 'silent', 'x64', 'arm64=', 'help', 'makefiles', 'showcpp', 'vsproj', 'guardcf',
'trace', 'dotnet', 'dotnet-key=', 'staticlib', 'prefix=', 'gmp', 'java', 'parallel=', 'gprof', 'js',
'githash=', 'git-describe', 'x86', 'ml', 'optimize', 'pypkgdir=', 'python', 'staticbin', 'log-sync', 'single-threaded'])
except:
@ -709,6 +722,8 @@ def parse_options():
VS_X64 = True
elif opt in ('--x86'):
LINUX_X64=False
elif opt in ('--arm64'):
IS_ARCH_ARM64 = arg in ('true','on','True','TRUE')
elif opt in ('-h', '--help'):
display_help(0)
elif opt in ('-m', '--makefiles'):
@ -1678,6 +1693,7 @@ class DotNetDLLComponent(Component):
<PropertyGroup>
<TargetFramework>netstandard1.4</TargetFramework>
<LangVersion>8.0</LangVersion>
<DefineConstants>$(DefineConstants);DOTNET_CORE</DefineConstants>
<DebugType>portable</DebugType>
<AssemblyName>Microsoft.Z3</AssemblyName>
@ -1995,7 +2011,7 @@ class MLComponent(Component):
LIBZ3 = LIBZ3 + ' ' + ' '.join(map(lambda x: '-cclib ' + x, LDFLAGS.split()))
stubs_install_path = '$$(%s printconf path)/stublibs' % OCAMLFIND
stubs_install_path = '$$(%s printconf destdir)/stublibs' % OCAMLFIND
if not STATIC_LIB:
loadpath = '-ccopt -L' + stubs_install_path
dllpath = '-dllpath ' + stubs_install_path
@ -2076,7 +2092,7 @@ class MLComponent(Component):
out.write(' %s' % ((os.path.join(self.sub_dir, 'z3ml.cmxa'))))
out.write(' %s' % ((os.path.join(self.sub_dir, 'z3ml.cmxs'))))
out.write(' %s' % ((os.path.join(self.sub_dir, 'dllz3ml'))))
if is_windows() or is_cygwin_mingw():
if is_windows() or is_cygwin_mingw() or is_msys2():
out.write('.dll')
else:
out.write('.so') # .so also on OSX!
@ -2426,7 +2442,7 @@ def mk_config():
if ONLY_MAKEFILES:
return
config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w')
global CXX, CC, GMP, GUARD_CF, STATIC_BIN, GIT_HASH, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, LOG_SYNC, SINGLE_THREADED
global CXX, CC, GMP, GUARD_CF, STATIC_BIN, GIT_HASH, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, LOG_SYNC, SINGLE_THREADED, IS_ARCH_ARM64
if IS_WINDOWS:
CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:c++17'
config.write(
@ -2624,13 +2640,18 @@ def mk_config():
SLIBFLAGS = '%s -m32' % SLIBFLAGS
if TRACE or DEBUG_MODE:
CPPFLAGS = '%s -D_TRACE' % CPPFLAGS
if is_cygwin_mingw():
if is_cygwin_mingw() or is_msys2():
# when cross-compiling with MinGW, we need to statically link its standard libraries
# and to make it create an import library.
SLIBEXTRAFLAGS = '%s -static-libgcc -static-libstdc++ -Wl,--out-implib,libz3.dll.a' % SLIBEXTRAFLAGS
LDFLAGS = '%s -static-libgcc -static-libstdc++' % LDFLAGS
if sysname == 'Linux' and machine.startswith('armv7') or machine.startswith('armv8'):
CXXFLAGS = '%s -fpic' % CXXFLAGS
if IS_OSX and IS_ARCH_ARM64:
print("Setting arm64")
CXXFLAGS = '%s -arch arm64' % CXXFLAGS
LDFLAGS = '%s -arch arm64' % LDFLAGS
SLIBEXTRAFLAGS = '%s -arch arm64' % SLIBEXTRAFLAGS
config.write('PREFIX=%s\n' % PREFIX)
config.write('CC=%s\n' % CC)

View file

@ -1,5 +1,9 @@
variables:
ReleaseVersion: '4.8.15'
Major: '4'
Minor: '8'
Patch: '16'
NightlyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId)-$(Build.DefinitionName)
stages:
- stage: Build
@ -19,6 +23,21 @@ stages:
artifactName: 'Mac'
targetPath: $(Build.ArtifactStagingDirectory)
- job: MacArm64
displayName: "Mac ARM64 Build"
pool:
vmImage: "macOS-latest"
steps:
- script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --arch=arm64
- script: git clone https://github.com/z3prover/z3test z3test
- script: cp dist/*.zip $(Build.ArtifactStagingDirectory)/.
- task: PublishPipelineArtifact@1
inputs:
artifactName: 'MacArm64'
targetPath: $(Build.ArtifactStagingDirectory)
- job: Ubuntu
displayName: "Ubuntu build"
pool:
@ -92,7 +111,7 @@ stages:
- task: CmdLine@2
inputs:
script:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86 &
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86 &
python scripts\mk_win_dist.py
--x86-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
@ -115,7 +134,7 @@ stages:
- task: CmdLine@2
inputs:
script:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 &
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 &
python scripts\mk_win_dist.py
--x64-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
@ -130,6 +149,8 @@ stages:
targetPath: $(Build.ArtifactStagingDirectory)
artifactName: 'Windows64'
- stage: Package
jobs:
- job: NuGet64
@ -158,6 +179,11 @@ stages:
inputs:
artifact: 'Mac'
path: $(Agent.TempDirectory)\package
- task: DownloadPipelineArtifact@2
displayName: 'Download macOS Arm64 Build'
inputs:
artifact: 'MacArm64'
path: $(Agent.TempDirectory)\package
- task: NuGetToolInstaller@0
inputs:
versionSpec: 5.x
@ -170,7 +196,7 @@ stages:
workingDirectory: $(Agent.TempDirectory)\package
arguments:
$(Agent.TempDirectory)\package
$(ReleaseVersion)
$(NightlyVersion)
$(Build.Repository.Uri)
$(Build.SourceBranchName)
$(Build.SourceVersion)
@ -180,13 +206,18 @@ stages:
displayName: 'NuGet Pack Symbols'
inputs:
command: custom
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.sym.nuspec -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
versioningScheme: byPrereleaseNumber
majorVersion: $(Major)
minorVersion: $(Minor)
patchVersion: $(Patch)
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.sym.nuspec -Version $(NightlyVersion) -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
continueOnError: true
displayName: 'Sign Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: $(Build.ArtifactStagingDirectory)
Pattern: Microsoft.Z3.$(ReleaseVersion).nupkg
Pattern: Microsoft.Z3.$(NightlyVersion).nupkg
signConfigType: 'inlineSignParams'
inlineOperation: |
[
@ -209,11 +240,12 @@ stages:
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
continueOnError: true
displayName: 'Sign Symbol Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: $(Build.ArtifactStagingDirectory)
Pattern: Microsoft.Z3.$(ReleaseVersion).snupkg
Pattern: Microsoft.Z3.$(NightlyVersion).snupkg
signConfigType: 'inlineSignParams'
inlineOperation: |
[
@ -268,7 +300,7 @@ stages:
workingDirectory: $(Agent.TempDirectory)\package
arguments:
$(Agent.TempDirectory)\package
$(ReleaseVersion)
$(NightlyVersion)
$(Build.Repository.Uri)
$(Build.SourceBranchName)
$(Build.SourceVersion)
@ -279,13 +311,18 @@ stages:
displayName: 'NuGet Pack Symbols'
inputs:
command: custom
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.x86.sym.nuspec -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
versioningScheme: byPrereleaseNumber
majorVersion: $(Major)
minorVersion: $(Minor)
patchVersion: $(Patch)
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.x86.sym.nuspec -Version $(NightlyVersion) -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
continueOnError: true
displayName: 'Sign Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: $(Build.ArtifactStagingDirectory)
Pattern: Microsoft.Z3.x86.$(ReleaseVersion).nupkg
Pattern: Microsoft.Z3.x86.$(NightlyVersion).nupkg
signConfigType: 'inlineSignParams'
inlineOperation: |
[
@ -308,11 +345,12 @@ stages:
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
continueOnError: true
displayName: 'Sign Symbol Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: $(Build.ArtifactStagingDirectory)
Pattern: Microsoft.Z3.x86.$(ReleaseVersion).snupkg
Pattern: Microsoft.Z3.x86.$(NightlyVersion).snupkg
signConfigType: 'inlineSignParams'
inlineOperation: |
[
@ -361,7 +399,12 @@ stages:
inputs:
artifactName: 'Mac'
targetPath: $(Agent.TempDirectory)
- script: cd $(Agent.TempDirectory); mkdir osx-bin; cd osx-bin; unzip ../*osx*.zip
- task: DownloadPipelineArtifact@2
inputs:
artifactName: 'MacArm64'
targetPath: $(Agent.TempDirectory)
- script: cd $(Agent.TempDirectory); mkdir osx-x64-bin; cd osx-x64-bin; unzip ../*x64-osx*.zip
- script: cd $(Agent.TempDirectory); mkdir osx-arm64-bin; cd osx-arm64-bin; unzip ../*arm64-osx*.zip
- script: cd $(Agent.TempDirectory); mkdir linux-bin; cd linux-bin; unzip ../*glibc*.zip
- script: cd $(Agent.TempDirectory); mkdir win32-bin; cd win32-bin; unzip ../*x86-win*.zip
- script: cd $(Agent.TempDirectory); mkdir win64-bin; cd win64-bin; unzip ../*x64-win*.zip
@ -371,16 +414,19 @@ stages:
- script: cd src/api/python; echo $(Agent.TempDirectory)/linux-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel
- script: cd src/api/python; echo $(Agent.TempDirectory)/win32-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel
- script: cd src/api/python; echo $(Agent.TempDirectory)/win64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel
- script: cd src/api/python; echo $(Agent.TempDirectory)/osx-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel
- script: cd src/api/python; echo $(Agent.TempDirectory)/osx-x64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel
- script: cd src/api/python; echo $(Agent.TempDirectory)/osx-arm64-bin/* | xargs printf 'PACKAGE_FROM_RELEASE=%s\n' | xargs -I '{}' env '{}' python3 setup.py bdist_wheel
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Python packages'
targetPath: src/api/python/dist
- stage: Deployment
jobs:
- job: Deploy
displayName: "Deploy into GitHub"
continueOnError: true
pool:
vmImage: "ubuntu-latest"
steps:
@ -399,6 +445,11 @@ stages:
inputs:
artifactName: 'Mac'
targetPath: tmp
- task: DownloadPipelineArtifact@2
displayName: "Download MacArm64"
inputs:
artifactName: 'MacArm64'
targetPath: tmp
- task: DownloadPipelineArtifact@2
displayName: "Download Ubuntu"
inputs:
@ -425,6 +476,7 @@ stages:
artifactName: 'NuGet32'
targetPath: tmp
- task: GitHubRelease@0
continueOnError: true
inputs:
gitHubConnection: Z3GitHub
repositoryName: 'Z3Prover/z3'
@ -433,6 +485,7 @@ stages:
tagSource: 'manual'
tag: 'Nightly'
- task: GitHubRelease@0
continueOnError: true
inputs:
gitHubConnection: Z3GitHub
repositoryName: 'Z3Prover/z3'
@ -448,5 +501,41 @@ stages:
isDraft: false
isPreRelease: true
- stage: NugetPublishNightly
jobs:
# Publish to nightly feed on Azure
- job: NuGetPublishNightly
displayName: "Push nuget packages to Azure Feed"
steps:
- task: NuGetAuthenticate@0
displayName: 'NuGet Authenticate'
- task: NuGetToolInstaller@0
inputs:
versionSpec: 5.x
checkLatest: false
- task: DownloadPipelineArtifact@2
displayName: 'Download NuGet x86 Package'
inputs:
artifact: 'NuGet32'
path: $(Agent.TempDirectory)/x86
- task: DownloadPipelineArtifact@2
displayName: 'Download NuGet x64 Package'
inputs:
artifact: 'NuGet'
path: $(Agent.TempDirectory)/x64
- task: NuGetCommand@2
displayName: 'NuGet Nightly x64 push'
inputs:
command: push
publishVstsFeed: 'Z3Nightly'
packagesToPush: $(Agent.TempDirectory)/x64/*.nupkg
allowPackageConflicts: true
- task: NuGetCommand@2
displayName: 'NuGet Nightly x86 push'
inputs:
command: push
publishVstsFeed: 'Z3Nightly'
packagesToPush: $(Agent.TempDirectory)/x86/*.nupkg
allowPackageConflicts: true
# TBD: run regression tests on generated binaries.

View file

@ -6,7 +6,7 @@
trigger: none
variables:
ReleaseVersion: '4.8.15'
ReleaseVersion: '4.8.16'
stages:
@ -155,8 +155,8 @@ stages:
- stage: Package
jobs:
- job: NuGetPackage
displayName: "NuGet packaging"
- job: NuGet64
displayName: "NuGet 64 packaging"
pool:
vmImage: "windows-latest"
steps:
@ -171,11 +171,6 @@ stages:
inputs:
artifact: 'WindowsBuild-x64'
path: $(Agent.TempDirectory)\package
- task: DownloadPipelineArtifact@2
displayName: 'Download Win32 Build'
inputs:
artifact: 'WindowsBuild-x86'
path: $(Agent.TempDirectory)\package
- task: DownloadPipelineArtifact@2
displayName: 'Download Ubuntu Build'
inputs:
@ -186,6 +181,10 @@ stages:
inputs:
artifact: 'macOSBuild'
path: $(Agent.TempDirectory)\package
- task: NuGetToolInstaller@0
inputs:
versionSpec: 5.x
checkLatest: false
- task: PythonScript@0
displayName: 'Python: assemble files'
inputs:
@ -200,10 +199,6 @@ stages:
$(Build.SourceVersion)
$(Build.SourcesDirectory)
symbols
- task: NuGetToolInstaller@0
inputs:
versionSpec: 5.x
checkLatest: false
- task: NugetCommand@2
displayName: 'NuGet Pack Symbols'
inputs:
@ -266,7 +261,107 @@ stages:
- task: PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)
artifactName: 'NuGetPackage'
artifactName: 'NuGet'
- job: NuGet32
displayName: "NuGet 32 packaging"
pool:
vmImage: "windows-latest"
steps:
- powershell: write-host $(System.DefinitionId)
displayName: 'System.DefinitionId'
- powershell: write-host $(Build.BuildId)
displayName: 'Build.BuildId'
- powershell: write-host $(System.TeamProjectId)
displayName: 'System.TeamProjectId'
- task: DownloadPipelineArtifact@2
displayName: 'Download Win32 Build'
inputs:
artifact: 'WindowsBuild-x86'
path: $(Agent.TempDirectory)\package
- task: NuGetToolInstaller@0
inputs:
versionSpec: 5.x
checkLatest: false
- task: PythonScript@0
displayName: 'Python: assemble files'
inputs:
scriptSource: 'filepath'
scriptPath: scripts\mk_nuget_task.py
workingDirectory: $(Agent.TempDirectory)\package
arguments:
$(Agent.TempDirectory)\package
$(ReleaseVersion)
$(Build.Repository.Uri)
$(Build.SourceBranchName)
$(Build.SourceVersion)
$(Build.SourcesDirectory)
symbols
x86
- task: NugetCommand@2
displayName: 'NuGet Pack Symbols'
inputs:
command: custom
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.x86.sym.nuspec -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
displayName: 'Sign Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: $(Build.ArtifactStagingDirectory)
Pattern: Microsoft.Z3.x86.$(ReleaseVersion).nupkg
signConfigType: 'inlineSignParams'
inlineOperation: |
[
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetSign",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
},
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
}
]
SessionTimeout: '60'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
displayName: 'Sign Symbol Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: $(Build.ArtifactStagingDirectory)
Pattern: Microsoft.Z3.x86.$(ReleaseVersion).snupkg
signConfigType: 'inlineSignParams'
inlineOperation: |
[
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetSign",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
},
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
}
]
SessionTimeout: '60'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: PublishPipelineArtifact@1
inputs:
targetPath: $(Build.ArtifactStagingDirectory)
artifactName: 'NuGet32'
- job: PythonPackage
displayName: "Python packaging"
@ -350,9 +445,14 @@ stages:
artifact: 'WindowsBuild-x64'
path: $(Agent.TempDirectory)
- task: DownloadPipelineArtifact@2
displayName: 'Download NuGet Package'
displayName: 'Download NuGet64 Package'
inputs:
artifact: 'NuGetPackage'
artifact: 'NuGet'
path: $(Agent.TempDirectory)
- task: DownloadPipelineArtifact@2
displayName: 'Download NuGet32 Package'
inputs:
artifact: 'NuGet32'
path: $(Agent.TempDirectory)
- task: GitHubRelease@0
inputs:

View file

@ -1820,13 +1820,13 @@ _error_handler_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint)
_lib.Z3_set_error_handler.restype = None
_lib.Z3_set_error_handler.argtypes = [ContextObj, _error_handler_type]
push_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
pop_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint)
push_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p)
pop_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint)
fresh_eh_type = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
fixed_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_void_p)
fixed_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
final_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p)
eq_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_uint)
eq_eh_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
_lib.Z3_solver_propagate_init.restype = None
_lib.Z3_solver_propagate_init.argtypes = [ContextObj, SolverObj, ctypes.c_void_p, push_eh_type, pop_eh_type, fresh_eh_type]

View file

@ -309,6 +309,22 @@ extern "C" {
Z3_CATCH_RETURN(nullptr);
}
Z3_sort Z3_API Z3_get_array_sort_domain_n(Z3_context c, Z3_sort t, unsigned idx) {
Z3_TRY;
LOG_Z3_get_array_sort_domain_n(c, t, idx);
RESET_ERROR_CODE();
CHECK_VALID_AST(t, nullptr);
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
to_sort(t)->get_decl_kind() == ARRAY_SORT &&
get_array_arity(to_sort(t)) > idx) {
Z3_sort r = reinterpret_cast<Z3_sort>(get_array_domain(to_sort(t), idx));
RETURN_Z3(r);
}
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
RETURN_Z3(nullptr);
Z3_CATCH_RETURN(nullptr);
}
Z3_sort Z3_API Z3_get_array_sort_range(Z3_context c, Z3_sort t) {
Z3_TRY;
LOG_Z3_get_array_sort_range(c, t);

View file

@ -164,7 +164,7 @@ extern "C" {
return;
}
recfun_replace replace(m);
p.set_definition(replace, pd, true, n, _vars.data(), abs_body);
p.set_definition(replace, pd, false, n, _vars.data(), abs_body);
Z3_CATCH;
}
@ -355,7 +355,7 @@ extern "C" {
return mk_c(c)->mk_external_string(buffer.str());
}
else {
return mk_c(c)->mk_external_string(_s.bare_str());
return mk_c(c)->mk_external_string(_s.str());
}
Z3_CATCH_RETURN("");
}
@ -1224,15 +1224,21 @@ extern "C" {
case OP_RE_PLUS: return Z3_OP_RE_PLUS;
case OP_RE_STAR: return Z3_OP_RE_STAR;
case OP_RE_OPTION: return Z3_OP_RE_OPTION;
case OP_RE_RANGE: return Z3_OP_RE_RANGE;
case OP_RE_CONCAT: return Z3_OP_RE_CONCAT;
case OP_RE_UNION: return Z3_OP_RE_UNION;
case OP_RE_DIFF: return Z3_OP_RE_DIFF;
case OP_RE_POWER: return Z3_OP_RE_POWER;
case OP_RE_INTERSECT: return Z3_OP_RE_INTERSECT;
case OP_RE_LOOP: return Z3_OP_RE_LOOP;
case OP_RE_FULL_SEQ_SET: return Z3_OP_RE_FULL_SET;
//case OP_RE_FULL_CHAR_SET: return Z3_OP_RE_FULL_SET;
case OP_RE_POWER: return Z3_OP_RE_POWER;
case OP_RE_COMPLEMENT: return Z3_OP_RE_COMPLEMENT;
case OP_RE_EMPTY_SET: return Z3_OP_RE_EMPTY_SET;
case OP_RE_FULL_SEQ_SET: return Z3_OP_RE_FULL_SET;
case OP_RE_FULL_CHAR_SET: return Z3_OP_RE_FULL_CHAR_SET;
case OP_RE_OF_PRED: return Z3_OP_RE_OF_PRED;
case OP_RE_REVERSE: return Z3_OP_RE_REVERSE;
case OP_RE_DERIVATIVE: return Z3_OP_RE_DERIVATIVE;
default:
return Z3_OP_INTERNAL;
}
@ -1323,6 +1329,9 @@ extern "C" {
}
}
if (mk_c(c)->recfun().get_family_id() == _d->get_family_id())
return Z3_OP_RECURSIVE;
return Z3_OP_UNINTERPRETED;
Z3_CATCH_RETURN(Z3_OP_UNINTERPRETED);
}

View file

@ -88,7 +88,7 @@ void Sy(Z3_symbol sym) {
*g_z3_log << "# " << s.get_num();
}
else {
*g_z3_log << "$ |" << ll_escaped{s.bare_str()} << '|';
*g_z3_log << "$ |" << ll_escaped{s.str().c_str()} << '|';
}
*g_z3_log << std::endl;
}

View file

@ -315,6 +315,17 @@ extern "C" {
Z3_CATCH_RETURN(nullptr);
}
Z3_ast Z3_API Z3_mk_re_power(Z3_context c, Z3_ast r, unsigned n) {
Z3_TRY;
LOG_Z3_mk_re_power(c, r, n);
RESET_ERROR_CODE();
app* a = mk_c(c)->sutil().re.mk_power(to_expr(r), n);
mk_c(c)->save_ast_trail(a);
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(nullptr);
}
MK_UNARY(Z3_mk_re_plus, mk_c(c)->get_seq_fid(), OP_RE_PLUS, SKIP);
MK_UNARY(Z3_mk_re_star, mk_c(c)->get_seq_fid(), OP_RE_STAR, SKIP);
MK_UNARY(Z3_mk_re_option, mk_c(c)->get_seq_fid(), OP_RE_OPTION, SKIP);

View file

@ -114,7 +114,7 @@ extern "C" {
}
solver2smt2_pp::solver2smt2_pp(ast_manager& m, const std::string& file):
m_pp_util(m), m_out(file), m_tracked(m) {
m_pp_util(m), m_out(file, std::ofstream::trunc | std::ofstream::out), m_tracked(m) {
if (!m_out) {
throw default_exception("could not open " + file + " for output");
}
@ -564,7 +564,7 @@ extern "C" {
init_solver(c, s);
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
mk_c(c)->save_object(v);
expr_ref_vector trail = to_solver_ref(s)->get_trail();
expr_ref_vector trail = to_solver_ref(s)->get_trail(UINT_MAX);
for (expr* f : trail) {
v->m_ast_vector.push_back(f);
}
@ -883,8 +883,8 @@ extern "C" {
Z3_TRY;
RESET_ERROR_CODE();
init_solver(c, s);
user_propagator::push_eh_t _push = push_eh;
user_propagator::pop_eh_t _pop = pop_eh;
user_propagator::push_eh_t _push = (void(*)(void*,user_propagator::callback*)) push_eh;
user_propagator::pop_eh_t _pop = (void(*)(void*,user_propagator::callback*,unsigned)) pop_eh;
user_propagator::fresh_eh_t _fresh = [=](void * user_ctx, ast_manager& m, user_propagator::context_obj*& _ctx) {
ast_context_params params;
params.set_foreign_manager(&m);
@ -902,7 +902,7 @@ extern "C" {
Z3_fixed_eh fixed_eh) {
Z3_TRY;
RESET_ERROR_CODE();
user_propagator::fixed_eh_t _fixed = (void(*)(void*,user_propagator::callback*,unsigned,expr*))fixed_eh;
user_propagator::fixed_eh_t _fixed = (void(*)(void*,user_propagator::callback*,expr*,expr*))fixed_eh;
to_solver_ref(s)->user_propagate_register_fixed(_fixed);
Z3_CATCH;
}
@ -924,7 +924,7 @@ extern "C" {
Z3_eq_eh eq_eh) {
Z3_TRY;
RESET_ERROR_CODE();
user_propagator::eq_eh_t _eq = (void(*)(void*,user_propagator::callback*,unsigned,unsigned))eq_eh;
user_propagator::eq_eh_t _eq = (void(*)(void*,user_propagator::callback*,expr*,expr*))eq_eh;
to_solver_ref(s)->user_propagate_register_eq(_eq);
Z3_CATCH;
}
@ -935,43 +935,54 @@ extern "C" {
Z3_eq_eh diseq_eh) {
Z3_TRY;
RESET_ERROR_CODE();
user_propagator::eq_eh_t _diseq = (void(*)(void*,user_propagator::callback*,unsigned,unsigned))diseq_eh;
user_propagator::eq_eh_t _diseq = (void(*)(void*,user_propagator::callback*,expr*,expr*))diseq_eh;
to_solver_ref(s)->user_propagate_register_diseq(_diseq);
Z3_CATCH;
}
unsigned Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e) {
void Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e) {
Z3_TRY;
LOG_Z3_solver_propagate_register(c, s, e);
RESET_ERROR_CODE();
return to_solver_ref(s)->user_propagate_register_expr(to_expr(e));
Z3_CATCH_RETURN(0);
to_solver_ref(s)->user_propagate_register_expr(to_expr(e));
Z3_CATCH;
}
unsigned Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback s, Z3_ast e) {
void Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback s, Z3_ast e) {
Z3_TRY;
LOG_Z3_solver_propagate_register_cb(c, s, e);
RESET_ERROR_CODE();
return reinterpret_cast<user_propagator::callback*>(s)->register_cb(to_expr(e));
Z3_CATCH_RETURN(0);
reinterpret_cast<user_propagator::callback*>(s)->register_cb(to_expr(e));
Z3_CATCH;
}
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback s, unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, unsigned const* eq_lhs, unsigned const* eq_rhs, Z3_ast conseq) {
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback s, unsigned num_fixed, Z3_ast const* fixed_ids, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq) {
Z3_TRY;
LOG_Z3_solver_propagate_consequence(c, s, num_fixed, fixed_ids, num_eqs, eq_lhs, eq_rhs, conseq);
RESET_ERROR_CODE();
reinterpret_cast<user_propagator::callback*>(s)->propagate_cb(num_fixed, fixed_ids, num_eqs, eq_lhs, eq_rhs, to_expr(conseq));
expr* const * _fixed_ids = (expr* const*) fixed_ids;
expr* const * _eq_lhs = (expr*const*) eq_lhs;
expr* const * _eq_rhs = (expr*const*) eq_rhs;
reinterpret_cast<user_propagator::callback*>(s)->propagate_cb(num_fixed, _fixed_ids, num_eqs, _eq_lhs, _eq_rhs, to_expr(conseq));
Z3_CATCH;
}
void Z3_API Z3_solver_propagate_created(Z3_context c, Z3_solver s, Z3_created_eh created_eh) {
Z3_TRY;
RESET_ERROR_CODE();
user_propagator::created_eh_t c = (void(*)(void*, user_propagator::callback*, expr*, unsigned))created_eh;
user_propagator::created_eh_t c = (void(*)(void*, user_propagator::callback*, expr*))created_eh;
to_solver_ref(s)->user_propagate_register_created(c);
Z3_CATCH;
}
void Z3_API Z3_solver_propagate_decide(Z3_context c, Z3_solver s, Z3_decide_eh decide_eh) {
Z3_TRY;
RESET_ERROR_CODE();
user_propagator::decide_eh_t c = (void(*)(void*, user_propagator::callback*, expr**, unsigned*, lbool*))decide_eh;
to_solver_ref(s)->user_propagate_register_decide(c);
Z3_CATCH;
}
Z3_func_decl Z3_API Z3_solver_propagate_declare(Z3_context c, Z3_symbol name, unsigned n, Z3_sort* domain, Z3_sort range) {
Z3_TRY;
LOG_Z3_solver_propagate_declare(c, name, n, domain, range);

View file

@ -332,7 +332,7 @@ extern "C" {
SET_ERROR_CODE(Z3_IOB, nullptr);
return "";
}
return mk_c(c)->get_tactic(idx)->get_name().bare_str();
return mk_c(c)->mk_external_string(mk_c(c)->get_tactic(idx)->get_name().str().c_str());
Z3_CATCH_RETURN("");
}
@ -352,7 +352,7 @@ extern "C" {
SET_ERROR_CODE(Z3_IOB, nullptr);
return "";
}
return mk_c(c)->get_probe(idx)->get_name().bare_str();
return mk_c(c)->mk_external_string(mk_c(c)->get_probe(idx)->get_name().str().c_str());
Z3_CATCH_RETURN("");
}

View file

@ -25,6 +25,7 @@ Notes:
#include<string>
#include<sstream>
#include<memory>
#include<vector>
#include<z3.h>
#include<limits.h>
#include<functional>
@ -155,9 +156,10 @@ namespace z3 {
class context {
private:
friend class user_propagator_base;
bool m_enable_exceptions;
rounding_mode m_rounding_mode;
Z3_context m_ctx;
Z3_context m_ctx = nullptr;
void init(config & c) {
set_context(Z3_mk_context_rc(c));
}
@ -173,7 +175,6 @@ namespace z3 {
context(context const &) = delete;
context & operator=(context const &) = delete;
friend class scoped_context;
context(Z3_context c) { set_context(c); }
void detach() { m_ctx = nullptr; }
public:
@ -394,14 +395,6 @@ namespace z3 {
expr_vector parse_file(char const* s, sort_vector const& sorts, func_decl_vector const& decls);
};
class scoped_context final {
context m_ctx;
public:
scoped_context(Z3_context c): m_ctx(c) {}
~scoped_context() { m_ctx.detach(); }
context& operator()() { return m_ctx; }
};
template<typename T>
class array {
@ -509,7 +502,7 @@ namespace z3 {
ast(context & c):object(c), m_ast(0) {}
ast(context & c, Z3_ast n):object(c), m_ast(n) { Z3_inc_ref(ctx(), m_ast); }
ast(ast const & s) :object(s), m_ast(s.m_ast) { Z3_inc_ref(ctx(), m_ast); }
~ast() { if (m_ast) Z3_dec_ref(*m_ctx, m_ast); }
~ast() { if (m_ast) { Z3_dec_ref(*m_ctx, m_ast); } }
operator Z3_ast() const { return m_ast; }
operator bool() const { return m_ast != 0; }
ast & operator=(ast const & s) {
@ -550,7 +543,7 @@ namespace z3 {
~ast_vector_tpl() { Z3_ast_vector_dec_ref(ctx(), m_vector); }
operator Z3_ast_vector() const { return m_vector; }
unsigned size() const { return Z3_ast_vector_size(ctx(), m_vector); }
T operator[](int i) const { assert(0 <= i); Z3_ast r = Z3_ast_vector_get(ctx(), m_vector, i); check_error(); return cast_ast<T>()(ctx(), r); }
T operator[](unsigned i) const { Z3_ast r = Z3_ast_vector_get(ctx(), m_vector, i); check_error(); return cast_ast<T>()(ctx(), r); }
void push_back(T const & e) { Z3_ast_vector_push(ctx(), m_vector, e); check_error(); }
void resize(unsigned sz) { Z3_ast_vector_resize(ctx(), m_vector, sz); check_error(); }
T back() const { return operator[](size() - 1); }
@ -1157,6 +1150,19 @@ namespace z3 {
\pre i < num_args()
*/
expr arg(unsigned i) const { Z3_ast r = Z3_get_app_arg(ctx(), *this, i); check_error(); return expr(ctx(), r); }
/**
\brief Return a vector of all the arguments of this application.
This method assumes the expression is an application.
\pre is_app()
*/
expr_vector args() const {
expr_vector vec(ctx());
unsigned argCnt = num_args();
for (unsigned i = 0; i < argCnt; i++)
vec.push_back(arg(i));
return vec;
}
/**
\brief Return the 'body' of this quantifier.
@ -2327,7 +2333,7 @@ namespace z3 {
inline expr pble(expr_vector const& es, int const* coeffs, int bound) {
assert(es.size() > 0);
context& ctx = es[0].ctx();
context& ctx = es[0u].ctx();
array<Z3_ast> _es(es);
Z3_ast r = Z3_mk_pble(ctx, _es.size(), _es.ptr(), coeffs, bound);
ctx.check_error();
@ -2335,7 +2341,7 @@ namespace z3 {
}
inline expr pbge(expr_vector const& es, int const* coeffs, int bound) {
assert(es.size() > 0);
context& ctx = es[0].ctx();
context& ctx = es[0u].ctx();
array<Z3_ast> _es(es);
Z3_ast r = Z3_mk_pbge(ctx, _es.size(), _es.ptr(), coeffs, bound);
ctx.check_error();
@ -2343,7 +2349,7 @@ namespace z3 {
}
inline expr pbeq(expr_vector const& es, int const* coeffs, int bound) {
assert(es.size() > 0);
context& ctx = es[0].ctx();
context& ctx = es[0u].ctx();
array<Z3_ast> _es(es);
Z3_ast r = Z3_mk_pbeq(ctx, _es.size(), _es.ptr(), coeffs, bound);
ctx.check_error();
@ -2351,7 +2357,7 @@ namespace z3 {
}
inline expr atmost(expr_vector const& es, unsigned bound) {
assert(es.size() > 0);
context& ctx = es[0].ctx();
context& ctx = es[0u].ctx();
array<Z3_ast> _es(es);
Z3_ast r = Z3_mk_atmost(ctx, _es.size(), _es.ptr(), bound);
ctx.check_error();
@ -2359,7 +2365,7 @@ namespace z3 {
}
inline expr atleast(expr_vector const& es, unsigned bound) {
assert(es.size() > 0);
context& ctx = es[0].ctx();
context& ctx = es[0u].ctx();
array<Z3_ast> _es(es);
Z3_ast r = Z3_mk_atleast(ctx, _es.size(), _es.ptr(), bound);
ctx.check_error();
@ -2367,7 +2373,7 @@ namespace z3 {
}
inline expr sum(expr_vector const& args) {
assert(args.size() > 0);
context& ctx = args[0].ctx();
context& ctx = args[0u].ctx();
array<Z3_ast> _args(args);
Z3_ast r = Z3_mk_add(ctx, _args.size(), _args.ptr());
ctx.check_error();
@ -2376,7 +2382,7 @@ namespace z3 {
inline expr distinct(expr_vector const& args) {
assert(args.size() > 0);
context& ctx = args[0].ctx();
context& ctx = args[0u].ctx();
array<Z3_ast> _args(args);
Z3_ast r = Z3_mk_distinct(ctx, _args.size(), _args.ptr());
ctx.check_error();
@ -2405,14 +2411,14 @@ namespace z3 {
Z3_ast r;
assert(args.size() > 0);
if (args.size() == 1) {
return args[0];
return args[0u];
}
context& ctx = args[0].ctx();
context& ctx = args[0u].ctx();
array<Z3_ast> _args(args);
if (Z3_is_seq_sort(ctx, args[0].get_sort())) {
if (Z3_is_seq_sort(ctx, args[0u].get_sort())) {
r = Z3_mk_seq_concat(ctx, _args.size(), _args.ptr());
}
else if (Z3_is_re_sort(ctx, args[0].get_sort())) {
else if (Z3_is_re_sort(ctx, args[0u].get_sort())) {
r = Z3_mk_re_concat(ctx, _args.size(), _args.ptr());
}
else {
@ -2442,7 +2448,7 @@ namespace z3 {
inline expr mk_xor(expr_vector const& args) {
if (args.empty())
return args.ctx().bool_val(false);
expr r = args[0];
expr r = args[0u];
for (unsigned i = 1; i < args.size(); ++i)
r = r ^ args[i];
return r;
@ -2581,9 +2587,9 @@ namespace z3 {
friend std::ostream & operator<<(std::ostream & out, model const & m);
std::string to_string() const { return std::string(Z3_model_to_string(ctx(), m_model)); }
std::string to_string() const { return m_model ? std::string(Z3_model_to_string(ctx(), m_model)) : "null"; }
};
inline std::ostream & operator<<(std::ostream & out, model const & m) { out << Z3_model_to_string(m.ctx(), m); return out; }
inline std::ostream & operator<<(std::ostream & out, model const & m) { return out << m.to_string(); }
class stats : public object {
Z3_stats m_stats;
@ -2627,7 +2633,8 @@ namespace z3 {
Z3_solver m_solver;
void init(Z3_solver s) {
m_solver = s;
Z3_solver_inc_ref(ctx(), s);
if (s)
Z3_solver_inc_ref(ctx(), s);
}
public:
struct simple {};
@ -2636,7 +2643,7 @@ namespace z3 {
solver(context & c, simple):object(c) { init(Z3_mk_simple_solver(c)); }
solver(context & c, Z3_solver s):object(c) { init(s); }
solver(context & c, char const * logic):object(c) { init(Z3_mk_solver_for_logic(c, c.str_symbol(logic))); }
solver(context & c, solver const& src, translate): object(c) { init(Z3_solver_translate(src.ctx(), src, c)); }
solver(context & c, solver const& src, translate): object(c) { Z3_solver s = Z3_solver_translate(src.ctx(), src, c); check_error(); init(s); }
solver(solver const & s):object(s) { init(s.m_solver); }
~solver() { Z3_solver_dec_ref(ctx(), m_solver); }
operator Z3_solver() const { return m_solver; }
@ -2764,7 +2771,7 @@ namespace z3 {
assert(!m_end && !m_empty);
m_cube = m_solver.cube(m_vars, m_cutoff);
m_cutoff = 0xFFFFFFFF;
if (m_cube.size() == 1 && m_cube[0].is_false()) {
if (m_cube.size() == 1 && m_cube[0u].is_false()) {
m_cube = z3::expr_vector(m_solver.ctx());
m_end = true;
}
@ -2998,7 +3005,7 @@ namespace z3 {
}
array<Z3_tactic> buffer(n);
for (unsigned i = 0; i < n; ++i) buffer[i] = tactics[i];
return tactic(tactics[0].ctx(), Z3_tactic_par_or(tactics[0].ctx(), n, buffer.ptr()));
return tactic(tactics[0u].ctx(), Z3_tactic_par_or(tactics[0u].ctx(), n, buffer.ptr()));
}
inline tactic par_and_then(tactic const & t1, tactic const & t2) {
@ -3797,7 +3804,7 @@ namespace z3 {
}
inline expr re_intersect(expr_vector const& args) {
assert(args.size() > 0);
context& ctx = args[0].ctx();
context& ctx = args[0u].ctx();
array<Z3_ast> _args(args);
Z3_ast r = Z3_mk_re_intersect(ctx, _args.size(), _args.ptr());
ctx.check_error();
@ -3932,22 +3939,22 @@ namespace z3 {
class user_propagator_base {
typedef std::function<void(unsigned, expr const&)> fixed_eh_t;
typedef std::function<void(expr const&, expr const&)> fixed_eh_t;
typedef std::function<void(void)> final_eh_t;
typedef std::function<void(unsigned, unsigned)> eq_eh_t;
typedef std::function<void(unsigned, expr const&)> created_eh_t;
typedef std::function<void(expr const&, expr const&)> eq_eh_t;
typedef std::function<void(expr const&)> created_eh_t;
typedef std::function<void(expr&, unsigned&, Z3_lbool&)> decide_eh_t;
final_eh_t m_final_eh;
eq_eh_t m_eq_eh;
fixed_eh_t m_fixed_eh;
created_eh_t m_created_eh;
decide_eh_t m_decide_eh;
solver* s;
Z3_context c;
Z3_solver_callback cb { nullptr };
context* c;
std::vector<z3::context*> subcontexts;
Z3_context ctx() {
return c ? c : (Z3_context)s->ctx();
}
Z3_solver_callback cb { nullptr };
struct scoped_cb {
user_propagator_base& p;
@ -3959,29 +3966,38 @@ namespace z3 {
}
};
static void push_eh(void* p) {
static void push_eh(void* _p, Z3_solver_callback cb) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
scoped_cb _cb(p, cb);
static_cast<user_propagator_base*>(p)->push();
}
static void pop_eh(void* p, unsigned num_scopes) {
static_cast<user_propagator_base*>(p)->pop(num_scopes);
}
static void* fresh_eh(void* p, Z3_context ctx) {
return static_cast<user_propagator_base*>(p)->fresh(ctx);
}
static void fixed_eh(void* _p, Z3_solver_callback cb, unsigned id, Z3_ast _value) {
static void pop_eh(void* _p, Z3_solver_callback cb, unsigned num_scopes) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
scoped_cb _cb(p, cb);
scoped_context ctx(p->ctx());
expr value(ctx(), _value);
static_cast<user_propagator_base*>(p)->m_fixed_eh(id, value);
static_cast<user_propagator_base*>(_p)->pop(num_scopes);
}
static void eq_eh(void* p, Z3_solver_callback cb, unsigned x, unsigned y) {
static void* fresh_eh(void* _p, Z3_context ctx) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
context* c = new context(ctx);
p->subcontexts.push_back(c);
return p->fresh(*c);
}
static void fixed_eh(void* _p, Z3_solver_callback cb, Z3_ast _var, Z3_ast _value) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
scoped_cb _cb(p, cb);
static_cast<user_propagator_base*>(p)->m_eq_eh(x, y);
expr value(p->ctx(), _value);
expr var(p->ctx(), _var);
p->m_fixed_eh(var, value);
}
static void eq_eh(void* _p, Z3_solver_callback cb, Z3_ast _x, Z3_ast _y) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
scoped_cb _cb(p, cb);
expr x(p->ctx(), _x), y(p->ctx(), _y);
p->m_eq_eh(x, y);
}
static void final_eh(void* p, Z3_solver_callback cb) {
@ -3989,26 +4005,42 @@ namespace z3 {
static_cast<user_propagator_base*>(p)->m_final_eh();
}
static void created_eh(void* _p, Z3_solver_callback cb, Z3_ast _e, unsigned id) {
static void created_eh(void* _p, Z3_solver_callback cb, Z3_ast _e) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
scoped_cb _cb(p, cb);
scoped_context ctx(p->ctx());
expr e(ctx(), _e);
static_cast<user_propagator_base*>(p)->m_created_eh(id, e);
expr e(p->ctx(), _e);
p->m_created_eh(e);
}
static void decide_eh(void* _p, Z3_solver_callback cb, Z3_ast* _val, unsigned* bit, Z3_lbool* is_pos) {
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
scoped_cb _cb(p, cb);
expr val(p->ctx(), *_val);
p->m_decide_eh(val, *bit, *is_pos);
// TBD: life time of val is within the scope of this callback.
*_val = val;
}
public:
user_propagator_base(Z3_context c) : s(nullptr), c(c) {}
user_propagator_base(context& c) : s(nullptr), c(&c) {}
user_propagator_base(solver* s): s(s), c(nullptr) {
Z3_solver_propagate_init(ctx(), *s, this, push_eh, pop_eh, fresh_eh);
Z3_solver_propagate_init(ctx(), *s, this, push_eh, pop_eh, fresh_eh);
}
virtual void push() = 0;
virtual void pop(unsigned num_scopes) = 0;
virtual ~user_propagator_base() = default;
virtual ~user_propagator_base() {
for (auto& subcontext : subcontexts) {
subcontext->detach(); // detach first; the subcontexts will be freed internally!
delete subcontext;
}
}
context& ctx() {
return c ? *c : s->ctx();
}
/**
\brief user_propagators created using \c fresh() are created during
@ -4018,7 +4050,7 @@ namespace z3 {
callbacks, such as \c fixed(), which contains expressions based on the
context.
*/
virtual user_propagator_base* fresh(Z3_context ctx) = 0;
virtual user_propagator_base* fresh(context& ctx) = 0;
/**
\brief register callbacks.
@ -4027,31 +4059,35 @@ namespace z3 {
*/
void register_fixed(fixed_eh_t& f) {
assert(s);
m_fixed_eh = f;
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
if (s) {
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
}
}
void register_fixed() {
assert(s);
m_fixed_eh = [this](unsigned id, expr const& e) {
m_fixed_eh = [this](expr const &id, expr const &e) {
fixed(id, e);
};
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
if (s) {
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
}
}
void register_eq(eq_eh_t& f) {
assert(s);
m_eq_eh = f;
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
if (s) {
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
}
}
void register_eq() {
assert(s);
m_eq_eh = [this](unsigned x, unsigned y) {
m_eq_eh = [this](expr const& x, expr const& y) {
eq(x, y);
};
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
if (s) {
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
}
}
/**
@ -4063,39 +4099,62 @@ namespace z3 {
*/
void register_final(final_eh_t& f) {
assert(s);
m_final_eh = f;
Z3_solver_propagate_final(ctx(), *s, final_eh);
if (s) {
Z3_solver_propagate_final(ctx(), *s, final_eh);
}
}
void register_final() {
assert(s);
m_final_eh = [this]() {
final();
};
Z3_solver_propagate_final(ctx(), *s, final_eh);
if (s) {
Z3_solver_propagate_final(ctx(), *s, final_eh);
}
}
void register_created(created_eh_t& c) {
assert(s);
m_created_eh = c;
Z3_solver_propagate_created(ctx(), *s, created_eh);
if (s) {
Z3_solver_propagate_created(ctx(), *s, created_eh);
}
}
void register_created() {
m_created_eh = [this](unsigned id, expr const& e) {
created(id, e);
m_created_eh = [this](expr const& e) {
created(e);
};
Z3_solver_propagate_created(ctx(), *s, created_eh);
if (s) {
Z3_solver_propagate_created(ctx(), *s, created_eh);
}
}
virtual void fixed(unsigned /*id*/, expr const& /*e*/) { }
void register_decide(decide_eh_t& c) {
m_decide_eh = c;
if (s) {
Z3_solver_propagate_decide(ctx(), *s, decide_eh);
}
}
virtual void eq(unsigned /*x*/, unsigned /*y*/) { }
void register_decide() {
m_decide_eh = [this](expr& val, unsigned& bit, Z3_lbool& is_pos) {
decide(val, bit, is_pos);
};
if (s) {
Z3_solver_propagate_decide(ctx(), *s, decide_eh);
}
}
virtual void fixed(expr const& /*id*/, expr const& /*e*/) { }
virtual void eq(expr const& /*x*/, expr const& /*y*/) { }
virtual void final() { }
virtual void created(unsigned /*id*/, expr const& /*e*/) {}
virtual void created(expr const& /*e*/) {}
virtual void decide(expr& /*val*/, unsigned& /*bit*/, Z3_lbool& /*is_pos*/) {}
/**
\brief tracks \c e by a unique identifier that is returned by the call.
@ -4111,40 +4170,43 @@ namespace z3 {
correspond to equalities that have been registered during a callback.
*/
unsigned add(expr const& e) {
void add(expr const& e) {
if (cb)
return Z3_solver_propagate_register_cb(ctx(), cb, e);
if (s)
return Z3_solver_propagate_register(ctx(), *s, e);
assert(false);
return 0;
Z3_solver_propagate_register_cb(ctx(), cb, e);
else if (s)
Z3_solver_propagate_register(ctx(), *s, e);
else
assert(false);
}
void conflict(unsigned num_fixed, unsigned const* fixed) {
void conflict(expr_vector const& fixed) {
assert(cb);
scoped_context _ctx(ctx());
expr conseq = _ctx().bool_val(false);
Z3_solver_propagate_consequence(ctx(), cb, num_fixed, fixed, 0, nullptr, nullptr, conseq);
expr conseq = ctx().bool_val(false);
array<Z3_ast> _fixed(fixed);
Z3_solver_propagate_consequence(ctx(), cb, fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
}
void propagate(unsigned num_fixed, unsigned const* fixed, expr const& conseq) {
void propagate(expr_vector const& fixed, expr const& conseq) {
assert(cb);
assert(conseq.ctx() == ctx());
Z3_solver_propagate_consequence(ctx(), cb, num_fixed, fixed, 0, nullptr, nullptr, conseq);
assert((Z3_context)conseq.ctx() == (Z3_context)ctx());
array<Z3_ast> _fixed(fixed);
Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
}
void propagate(unsigned num_fixed, unsigned const* fixed,
unsigned num_eqs, unsigned const* lhs, unsigned const * rhs,
void propagate(expr_vector const& fixed,
expr_vector const& lhs, expr_vector const& rhs,
expr const& conseq) {
assert(cb);
assert(conseq.ctx() == ctx());
Z3_solver_propagate_consequence(ctx(), cb, num_fixed, fixed, num_eqs, lhs, rhs, conseq);
assert((Z3_context)conseq.ctx() == (Z3_context)ctx());
assert(lhs.size() == rhs.size());
array<Z3_ast> _fixed(fixed);
array<Z3_ast> _lhs(lhs);
array<Z3_ast> _rhs(rhs);
Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), lhs.size(), _lhs.ptr(), _rhs.ptr(), conseq);
}
};
}
/**@}*/

View file

@ -100,7 +100,7 @@ namespace Microsoft.Z3
{
get
{
ASTVector res = new ASTVector(Context, Native.Z3_ast_map_keys(Context.nCtx, NativeObject));
using ASTVector res = new ASTVector(Context, Native.Z3_ast_map_keys(Context.nCtx, NativeObject));
return res.ToArray();
}
}

View file

@ -22,7 +22,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Microsoft.Z3
{
/// <summary>
@ -41,24 +40,48 @@ namespace Microsoft.Z3
#region Operators
private static ArithExpr MkNum(ArithExpr e, int i) { return (ArithExpr)e.Context.MkNumeral(i, e.Context.MkIntSort()); }
private static ArithExpr MkNum(ArithExpr e, int i)
{
using var sort = e.Context.MkIntSort();
return (ArithExpr)e.Context.MkNumeral(i, sort);
}
private static ArithExpr MkNum(ArithExpr e, double d) { return (ArithExpr)e.Context.MkNumeral(d.ToString(), e.Context.MkRealSort()); }
private static ArithExpr MkNum(ArithExpr e, double d)
{
using var sort = e.Context.MkRealSort();
return (ArithExpr)e.Context.MkNumeral(d.ToString(), sort);
}
/// <summary> Operator overloading for arithmetical division operator (over reals) </summary>
public static ArithExpr operator /(ArithExpr a, ArithExpr b) { return a.Context.MkDiv(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator /(ArithExpr a, int b) { return a / MkNum(a, b); }
public static ArithExpr operator /(ArithExpr a, int b)
{
using var denominator = MkNum(a, b);
return a / denominator;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator /(ArithExpr a, double b) { return a / MkNum(a, b); }
public static ArithExpr operator /(ArithExpr a, double b)
{
using var denominator = MkNum(a, b);
return a / denominator;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator /(int a, ArithExpr b) { return MkNum(b, a) / b; }
public static ArithExpr operator /(int a, ArithExpr b)
{
using var numerator = MkNum(b, a);
return numerator / b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator /(double a, ArithExpr b) { return MkNum(b, a) / b; }
public static ArithExpr operator /(double a, ArithExpr b)
{
using var numerator = MkNum(b, a);
return numerator / b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator -(ArithExpr a) { return a.Context.MkUnaryMinus(a); }
@ -67,106 +90,218 @@ namespace Microsoft.Z3
public static ArithExpr operator -(ArithExpr a, ArithExpr b) { return a.Context.MkSub(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator -(ArithExpr a, int b) { return a - MkNum(a, b); }
public static ArithExpr operator -(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a - rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator -(ArithExpr a, double b) { return a - MkNum(a, b); }
public static ArithExpr operator -(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a - rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator -(int a, ArithExpr b) { return MkNum(b, a) - b; }
public static ArithExpr operator -(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs - b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator -(double a, ArithExpr b) { return MkNum(b, a) - b; }
public static ArithExpr operator -(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs - b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator +(ArithExpr a, ArithExpr b) { return a.Context.MkAdd(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator +(ArithExpr a, int b) { return a + MkNum(a, b); }
public static ArithExpr operator +(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a + rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator +(ArithExpr a, double b) { return a + MkNum(a, b); }
public static ArithExpr operator +(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a + rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator +(int a, ArithExpr b) { return MkNum(b, a) + b; }
public static ArithExpr operator +(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs + b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator +(double a, ArithExpr b) { return MkNum(b, a) + b; }
public static ArithExpr operator +(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs + b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator *(ArithExpr a, ArithExpr b) { return a.Context.MkMul(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator *(ArithExpr a, int b) { return a * MkNum(a, b); }
public static ArithExpr operator *(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a * rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator *(ArithExpr a, double b) { return a * MkNum(a, b); }
public static ArithExpr operator *(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a * rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator *(int a, ArithExpr b) { return MkNum(b, a) * b; }
public static ArithExpr operator *(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs * b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static ArithExpr operator *(double a, ArithExpr b) { return MkNum(b, a) * b; }
public static ArithExpr operator *(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs * b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <=(ArithExpr a, ArithExpr b) { return a.Context.MkLe(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <=(ArithExpr a, int b) { return a <= MkNum(a, b); }
public static BoolExpr operator <=(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a <= rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <=(ArithExpr a, double b) { return a <= MkNum(a, b); }
public static BoolExpr operator <=(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a <= rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <=(int a, ArithExpr b) { return MkNum(b, a) <= b; }
public static BoolExpr operator <=(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs <= b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <=(double a, ArithExpr b) { return MkNum(b, a) <= b; }
public static BoolExpr operator <=(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs <= b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <(ArithExpr a, ArithExpr b) { return a.Context.MkLt(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <(ArithExpr a, int b) { return a < MkNum(a, b); }
public static BoolExpr operator <(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a < rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <(ArithExpr a, double b) { return a < MkNum(a, b); }
public static BoolExpr operator <(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a < rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <(int a, ArithExpr b) { return MkNum(b, a) < b; }
public static BoolExpr operator <(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs < b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator <(double a, ArithExpr b) { return MkNum(b, a) < b; }
public static BoolExpr operator <(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs < b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >(ArithExpr a, ArithExpr b) { return a.Context.MkGt(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >(ArithExpr a, int b) { return a > MkNum(a, b); }
public static BoolExpr operator >(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a > rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >(ArithExpr a, double b) { return a > MkNum(a, b); }
public static BoolExpr operator >(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a > rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >(int a, ArithExpr b) { return MkNum(b, a) > b; }
public static BoolExpr operator >(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs > b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >(double a, ArithExpr b) { return MkNum(b, a) > b; }
public static BoolExpr operator >(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs > b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >=(ArithExpr a, ArithExpr b) { return a.Context.MkGe(a, b); }
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >=(ArithExpr a, int b) { return a >= MkNum(a, b); }
public static BoolExpr operator >=(ArithExpr a, int b)
{
using var rhs = MkNum(a, b);
return a >= rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >=(ArithExpr a, double b) { return a >= MkNum(a, b); }
public static BoolExpr operator >=(ArithExpr a, double b)
{
using var rhs = MkNum(a, b);
return a >= rhs;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >=(int a, ArithExpr b) { return MkNum(b, a) >= b; }
public static BoolExpr operator >=(int a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs >= b;
}
/// <summary> Operator overloading for arithmetical operator </summary>
public static BoolExpr operator >=(double a, ArithExpr b) { return MkNum(b, a) >= b; }
public static BoolExpr operator >=(double a, ArithExpr b)
{
using var lhs = MkNum(b, a);
return lhs >= b;
}
#endregion
}

View file

@ -85,6 +85,10 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
ListSort.cs
Log.cs
Model.cs
NativeContext.cs
NativeFuncInterp.cs
NativeModel.cs
NativeSolver.cs
Optimize.cs
ParamDescrs.cs
Params.cs

View file

@ -18,10 +18,10 @@ Notes:
--*/
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
namespace Microsoft.Z3
{
@ -202,8 +202,8 @@ namespace Microsoft.Z3
/// </summary>
public UninterpretedSort MkUninterpretedSort(string str)
{
return MkUninterpretedSort(MkSymbol(str));
using var sym = MkSymbol(str);
return MkUninterpretedSort(sym);
}
/// <summary>
@ -231,7 +231,6 @@ namespace Microsoft.Z3
return new BitVecSort(this, Native.Z3_mk_bv_sort(nCtx, size));
}
/// <summary>
/// Create a new sequence sort.
/// </summary>
@ -314,7 +313,17 @@ namespace Microsoft.Z3
{
Debug.Assert(enumNames != null);
return new EnumSort(this, MkSymbol(name), MkSymbols(enumNames));
var enumSymbols = MkSymbols(enumNames);
try
{
using var symbol = MkSymbol(name);
return new EnumSort(this, symbol, enumSymbols);
}
finally
{
foreach (var enumSymbol in enumSymbols)
enumSymbol.Dispose();
}
}
/// <summary>
@ -338,7 +347,8 @@ namespace Microsoft.Z3
Debug.Assert(elemSort != null);
CheckContextMatch(elemSort);
return new ListSort(this, MkSymbol(name), elemSort);
using var symbol = MkSymbol(name);
return new ListSort(this, symbol, elemSort);
}
/// <summary>
@ -365,8 +375,8 @@ namespace Microsoft.Z3
/// <param name="size">The size of the sort</param>
public FiniteDomainSort MkFiniteDomainSort(string name, ulong size)
{
return new FiniteDomainSort(this, MkSymbol(name), size);
using var symbol = MkSymbol(name);
return new FiniteDomainSort(this, symbol, size);
}
@ -401,7 +411,18 @@ namespace Microsoft.Z3
public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null)
{
return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs);
using var nameSymbol = MkSymbol(name);
using var recognizerSymbol = MkSymbol(recognizer);
var fieldSymbols = MkSymbols(fieldNames);
try
{
return new Constructor(this, nameSymbol, recognizerSymbol, fieldSymbols, sorts, sortRefs);
}
finally
{
foreach (var fieldSymbol in fieldSymbols)
fieldSymbol.Dispose();
}
}
/// <summary>
@ -428,7 +449,8 @@ namespace Microsoft.Z3
Debug.Assert(constructors.All(c => c != null));
CheckContextMatch<Constructor>(constructors);
return new DatatypeSort(this, MkSymbol(name), constructors);
using var symbol = MkSymbol(name);
return new DatatypeSort(this, symbol, constructors);
}
/// <summary>
@ -477,7 +499,16 @@ namespace Microsoft.Z3
//Debug.Assert(Contract.ForAll(0, c.Length, j => c[j] != null));
//Debug.Assert(names.All(name => name != null));
return MkDatatypeSorts(MkSymbols(names), c);
var symbols = MkSymbols(names);
try
{
return MkDatatypeSorts(symbols, c);
}
finally
{
foreach (var symbol in symbols)
symbol.Dispose();
}
}
/// <summary>
@ -485,7 +516,7 @@ namespace Microsoft.Z3
/// The function performs a record update at t. The field
/// that is passed in as argument is updated with value v,
/// the remaining fields of t are unchanged.
/// </summary>
/// </summary>
public Expr MkUpdateField(FuncDecl field, Expr t, Expr v)
{
return Expr.Create(this, Native.Z3_datatype_update_field(
@ -538,7 +569,8 @@ namespace Microsoft.Z3
CheckContextMatch<Sort>(domain);
CheckContextMatch(range);
return new FuncDecl(this, MkSymbol(name), domain, range);
using var symbol = MkSymbol(name);
return new FuncDecl(this, symbol, domain, range);
}
/// <summary>
@ -551,7 +583,8 @@ namespace Microsoft.Z3
CheckContextMatch<Sort>(domain);
CheckContextMatch(range);
return new FuncDecl(this, MkSymbol(name), domain, range, true);
using var symbol = MkSymbol(name);
return new FuncDecl(this, symbol, domain, range, true);
}
/// <summary>
@ -560,14 +593,14 @@ namespace Microsoft.Z3
/// MkRecFuncDecl. The body may contain recursive uses of the function or
/// other mutually recursive functions.
/// </summary>
public void AddRecDef(FuncDecl f, Expr[] args, Expr body)
{
CheckContextMatch(f);
CheckContextMatch<Expr>(args);
CheckContextMatch(body);
public void AddRecDef(FuncDecl f, Expr[] args, Expr body)
{
CheckContextMatch(f);
CheckContextMatch<Expr>(args);
CheckContextMatch(body);
IntPtr[] argsNative = AST.ArrayToNative(args);
Native.Z3_add_rec_def(nCtx, f.NativeObject, (uint)args.Length, argsNative, body.NativeObject);
}
Native.Z3_add_rec_def(nCtx, f.NativeObject, (uint)args.Length, argsNative, body.NativeObject);
}
/// <summary>
/// Creates a new function declaration.
@ -579,8 +612,9 @@ namespace Microsoft.Z3
CheckContextMatch(domain);
CheckContextMatch(range);
using var symbol = MkSymbol(name);
Sort[] q = new Sort[] { domain };
return new FuncDecl(this, MkSymbol(name), q, range);
return new FuncDecl(this, symbol, q, range);
}
/// <summary>
@ -619,7 +653,8 @@ namespace Microsoft.Z3
Debug.Assert(range != null);
CheckContextMatch(range);
return new FuncDecl(this, MkSymbol(name), null, range);
using var symbol = MkSymbol(name);
return new FuncDecl(this, symbol, null, range);
}
/// <summary>
@ -687,7 +722,8 @@ namespace Microsoft.Z3
{
Debug.Assert(range != null);
return MkConst(MkSymbol(name), range);
using var symbol = MkSymbol(name);
return MkConst(symbol, range);
}
/// <summary>
@ -728,8 +764,8 @@ namespace Microsoft.Z3
/// </summary>
public BoolExpr MkBoolConst(string name)
{
return (BoolExpr)MkConst(MkSymbol(name), BoolSort);
using var symbol = MkSymbol(name);
return (BoolExpr)MkConst(symbol, BoolSort);
}
/// <summary>
@ -778,7 +814,8 @@ namespace Microsoft.Z3
{
Debug.Assert(name != null);
return (BitVecExpr)MkConst(name, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecExpr)MkConst(name, sort);
}
/// <summary>
@ -786,8 +823,8 @@ namespace Microsoft.Z3
/// </summary>
public BitVecExpr MkBVConst(string name, uint size)
{
return (BitVecExpr)MkConst(name, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecExpr)MkConst(name, sort);
}
#endregion
@ -811,7 +848,7 @@ namespace Microsoft.Z3
public Expr MkApp(FuncDecl f, IEnumerable<Expr> args)
{
Debug.Assert(f != null);
Debug.Assert(args == null || args.All( a => a != null));
Debug.Assert(args == null || args.All(a => a != null));
CheckContextMatch(f);
CheckContextMatch(args);
@ -948,16 +985,12 @@ namespace Microsoft.Z3
Debug.Assert(ts != null);
Debug.Assert(ts.All(a => a != null));
CheckContextMatch<BoolExpr>(ts);
BoolExpr r = null;
foreach (var t in ts) {
if (r == null)
r = t;
else
r = MkXor(r, t);
}
if (r == null)
r = MkTrue();
return r;
return ts.Aggregate(MkFalse(), (r, t) =>
{
using (r)
return MkXor(r, t);
});
}
/// <summary>
@ -2032,7 +2065,8 @@ namespace Microsoft.Z3
Debug.Assert(domain != null);
Debug.Assert(range != null);
return (ArrayExpr)MkConst(name, MkArraySort(domain, range));
using var sort = MkArraySort(domain, range);
return (ArrayExpr)MkConst(name, sort);
}
/// <summary>
@ -2043,7 +2077,9 @@ namespace Microsoft.Z3
Debug.Assert(domain != null);
Debug.Assert(range != null);
return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range));
using var symbol = MkSymbol(name);
using var sort = MkArraySort(domain, range);
return (ArrayExpr)MkConst(symbol, sort);
}
@ -2343,7 +2379,7 @@ namespace Microsoft.Z3
CheckContextMatch(elem);
CheckContextMatch(set);
return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_member(nCtx, elem.NativeObject, set.NativeObject));
return (BoolExpr)Expr.Create(this, Native.Z3_mk_set_member(nCtx, elem.NativeObject, set.NativeObject));
}
/// <summary>
@ -2356,7 +2392,7 @@ namespace Microsoft.Z3
CheckContextMatch(arg1);
CheckContextMatch(arg2);
return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_subset(nCtx, arg1.NativeObject, arg2.NativeObject));
return (BoolExpr)Expr.Create(this, Native.Z3_mk_set_subset(nCtx, arg1.NativeObject, arg2.NativeObject));
}
#endregion
@ -2413,7 +2449,8 @@ namespace Microsoft.Z3
/// <summary>
/// Convert a bit-vector expression, represented as an signed number, to a string.
/// </summary>
public SeqExpr SbvToString(Expr e) {
public SeqExpr SbvToString(Expr e)
{
Debug.Assert(e != null);
Debug.Assert(e is ArithExpr);
return new SeqExpr(this, Native.Z3_mk_sbv_to_str(nCtx, e.NativeObject));
@ -2449,7 +2486,7 @@ namespace Microsoft.Z3
public IntExpr MkLength(SeqExpr s)
{
Debug.Assert(s != null);
return (IntExpr) Expr.Create(this, Native.Z3_mk_seq_length(nCtx, s.NativeObject));
return (IntExpr)Expr.Create(this, Native.Z3_mk_seq_length(nCtx, s.NativeObject));
}
/// <summary>
@ -2497,7 +2534,7 @@ namespace Microsoft.Z3
}
/// <summary>
/// Check if the string s1 is lexicographically strictly less than s2.
/// Check if the string s1 is lexicographically less or equal to s2.
/// </summary>
public BoolExpr MkStringLe(SeqExpr s1, SeqExpr s2)
{
@ -2768,7 +2805,7 @@ namespace Microsoft.Z3
Debug.Assert(args != null);
CheckContextMatch<BoolExpr>(args);
var ts = args.ToArray();
return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) ts.Length,
return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint)ts.Length,
AST.ArrayToNative(ts), k));
}
@ -2780,7 +2817,7 @@ namespace Microsoft.Z3
Debug.Assert(args != null);
CheckContextMatch<BoolExpr>(args);
var ts = args.ToArray();
return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint) ts.Length,
return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint)ts.Length,
AST.ArrayToNative(ts), k));
}
@ -2789,13 +2826,13 @@ namespace Microsoft.Z3
/// </summary>
public BoolExpr MkPBLe(int[] coeffs, BoolExpr[] args, int k)
{
Debug.Assert(args != null);
Debug.Assert(coeffs != null);
Debug.Assert(args.Length == coeffs.Length);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length,
AST.ArrayToNative(args),
coeffs, k));
Debug.Assert(args != null);
Debug.Assert(coeffs != null);
Debug.Assert(args.Length == coeffs.Length);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint)args.Length,
AST.ArrayToNative(args),
coeffs, k));
}
/// <summary>
@ -2803,26 +2840,26 @@ namespace Microsoft.Z3
/// </summary>
public BoolExpr MkPBGe(int[] coeffs, BoolExpr[] args, int k)
{
Debug.Assert(args != null);
Debug.Assert(coeffs != null);
Debug.Assert(args.Length == coeffs.Length);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint) args.Length,
AST.ArrayToNative(args),
coeffs, k));
Debug.Assert(args != null);
Debug.Assert(coeffs != null);
Debug.Assert(args.Length == coeffs.Length);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint)args.Length,
AST.ArrayToNative(args),
coeffs, k));
}
/// <summary>
/// Create a pseudo-Boolean equal constraint.
/// </summary>
public BoolExpr MkPBEq(int[] coeffs, BoolExpr[] args, int k)
{
Debug.Assert(args != null);
Debug.Assert(coeffs != null);
Debug.Assert(args.Length == coeffs.Length);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pbeq(nCtx, (uint) args.Length,
AST.ArrayToNative(args),
coeffs, k));
Debug.Assert(args != null);
Debug.Assert(coeffs != null);
Debug.Assert(args.Length == coeffs.Length);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pbeq(nCtx, (uint)args.Length,
AST.ArrayToNative(args),
coeffs, k));
}
#endregion
@ -3040,8 +3077,8 @@ namespace Microsoft.Z3
/// <param name="size">the size of the bit-vector</param>
public BitVecNum MkBV(string v, uint size)
{
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecNum)MkNumeral(v, sort);
}
/// <summary>
@ -3051,8 +3088,8 @@ namespace Microsoft.Z3
/// <param name="size">the size of the bit-vector</param>
public BitVecNum MkBV(int v, uint size)
{
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecNum)MkNumeral(v, sort);
}
/// <summary>
@ -3062,8 +3099,8 @@ namespace Microsoft.Z3
/// <param name="size">the size of the bit-vector</param>
public BitVecNum MkBV(uint v, uint size)
{
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecNum)MkNumeral(v, sort);
}
/// <summary>
@ -3073,8 +3110,8 @@ namespace Microsoft.Z3
/// <param name="size">the size of the bit-vector</param>
public BitVecNum MkBV(long v, uint size)
{
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecNum)MkNumeral(v, sort);
}
/// <summary>
@ -3084,8 +3121,8 @@ namespace Microsoft.Z3
/// <param name="size">the size of the bit-vector</param>
public BitVecNum MkBV(ulong v, uint size)
{
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
using var sort = MkBitVecSort(size);
return (BitVecNum)MkNumeral(v, sort);
}
/// <summary>
@ -3332,7 +3369,7 @@ namespace Microsoft.Z3
uint cd = AST.ArrayLength(decls);
if (csn != cs || cdn != cd)
throw new Z3Exception("Argument size mismatch");
ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_string(nCtx, str,
using ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_string(nCtx, str,
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)));
return assertions.ToBoolExprArray();
@ -3351,7 +3388,7 @@ namespace Microsoft.Z3
uint cd = AST.ArrayLength(decls);
if (csn != cs || cdn != cd)
throw new Z3Exception("Argument size mismatch");
ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_file(nCtx, fileName,
using ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_file(nCtx, fileName,
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)));
return assertions.ToBoolExprArray();
@ -3836,8 +3873,8 @@ namespace Microsoft.Z3
/// <seealso cref="MkSolver(Symbol)"/>
public Solver MkSolver(string logic)
{
return MkSolver(MkSymbol(logic));
using var symbol = MkSymbol(logic);
return MkSolver(symbol);
}
/// <summary>
@ -4085,7 +4122,7 @@ namespace Microsoft.Z3
/// <param name="negative">indicates whether the result should be negative.</param>
public FPNum MkFPZero(FPSort s, bool negative)
{
return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, (byte)(negative ? 1 : 0)));
return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, (byte)(negative ? 1 : 0)));
}
/// <summary>
@ -4127,7 +4164,7 @@ namespace Microsoft.Z3
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s)
{
return new FPNum(this, Native.Z3_mk_fpa_numeral_int_uint(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
return new FPNum(this, Native.Z3_mk_fpa_numeral_int_uint(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
}
/// <summary>
@ -4139,7 +4176,7 @@ namespace Microsoft.Z3
/// <param name="s">FloatingPoint sort.</param>
public FPNum MkFPNumeral(bool sgn, Int64 exp, UInt64 sig, FPSort s)
{
return new FPNum(this, Native.Z3_mk_fpa_numeral_int64_uint64(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
return new FPNum(this, Native.Z3_mk_fpa_numeral_int64_uint64(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
}
/// <summary>
@ -4825,12 +4862,12 @@ namespace Microsoft.Z3
/// <summary>
/// ASTVector DRQ
/// </summary>
public IDecRefQueue ASTVector_DRQ { get { return m_ASTVector_DRQ; } }
public IDecRefQueue ASTVector_DRQ { get { return m_ASTVector_DRQ; } }
/// <summary>
/// ApplyResult DRQ
/// </summary>
public IDecRefQueue ApplyResult_DRQ { get { return m_ApplyResult_DRQ; } }
public IDecRefQueue ApplyResult_DRQ { get { return m_ApplyResult_DRQ; } }
/// <summary>
/// FuncEntry DRQ
@ -4926,10 +4963,16 @@ namespace Microsoft.Z3
Fixedpoint_DRQ.Clear(this);
Optimize_DRQ.Clear(this);
if (m_boolSort != null) m_boolSort.Dispose();
if (m_intSort != null) m_intSort.Dispose();
if (m_realSort != null) m_realSort.Dispose();
if (m_stringSort != null) m_stringSort.Dispose();
if (m_charSort != null) m_charSort.Dispose();
m_boolSort = null;
m_intSort = null;
m_realSort = null;
m_stringSort = null;
m_charSort = null;
if (refCount == 0 && m_ctx != IntPtr.Zero)
{
m_n_err_handler = null;

View file

@ -79,7 +79,7 @@ namespace Microsoft.Z3
FuncDecl[][] res = new FuncDecl[n][];
for (uint i = 0; i < n; i++)
{
FuncDecl fd = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i));
using FuncDecl fd = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i));
uint ds = fd.DomainSize;
FuncDecl[] tmp = new FuncDecl[ds];
for (uint j = 0; j < ds; j++)

View file

@ -74,7 +74,8 @@ namespace Microsoft.Z3
/// <returns></returns>
public Expr Const(uint inx)
{
return Context.MkApp(ConstDecl(inx));
using var decl = ConstDecl(inx);
return Context.MkApp(decl);
}
/// <summary>

View file

@ -255,7 +255,7 @@ namespace Microsoft.Z3
get
{
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_rules(Context.nCtx, NativeObject));
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_rules(Context.nCtx, NativeObject));
return av.ToBoolExprArray();
}
}
@ -268,7 +268,7 @@ namespace Microsoft.Z3
get
{
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject));
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject));
return av.ToBoolExprArray();
}
}
@ -292,7 +292,7 @@ namespace Microsoft.Z3
/// </summary>
public BoolExpr[] ParseFile(string file)
{
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_file(Context.nCtx, NativeObject, file));
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_file(Context.nCtx, NativeObject, file));
return av.ToBoolExprArray();
}
@ -301,7 +301,7 @@ namespace Microsoft.Z3
/// </summary>
public BoolExpr[] ParseString(string s)
{
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_string(Context.nCtx, NativeObject, s));
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_string(Context.nCtx, NativeObject, s));
return av.ToBoolExprArray();
}

View file

@ -203,8 +203,8 @@ namespace Microsoft.Z3
/// <remarks>Essentially invokes the `simplify' tactic on the goal.</remarks>
public Goal Simplify(Params p = null)
{
Tactic t = Context.MkTactic("simplify");
ApplyResult res = t.Apply(this, p);
using Tactic t = Context.MkTactic("simplify");
using ApplyResult res = t.Apply(this, p);
if (res.NumSubgoals == 0)
throw new Z3Exception("No subgoals");

View file

@ -32,6 +32,8 @@
<Authors>Microsoft</Authors>
<Company>Microsoft</Company>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<!-- Code contract & signing properties -->

View file

@ -87,7 +87,8 @@ namespace Microsoft.Z3
if (Native.Z3_is_as_array(Context.nCtx, n) == 0)
throw new Z3Exception("Argument was not an array constant");
IntPtr fd = Native.Z3_get_as_array_func_decl(Context.nCtx, n);
return FuncInterp(new FuncDecl(Context, fd));
using var decl = new FuncDecl(Context, fd);
return FuncInterp(decl);
}
}
else
@ -241,7 +242,7 @@ namespace Microsoft.Z3
/// Evaluate expression to a double, assuming it is a numeral already.
/// </summary>
public double Double(Expr t) {
var r = Eval(t, true);
using var r = Eval(t, true);
return Native.Z3_get_numeral_double(Context.nCtx, r.NativeObject);
}
@ -283,7 +284,7 @@ namespace Microsoft.Z3
{
Debug.Assert(s != null);
ASTVector av = new ASTVector(Context, Native.Z3_model_get_sort_universe(Context.nCtx, NativeObject, s.NativeObject));
using ASTVector av = new ASTVector(Context, Native.Z3_model_get_sort_universe(Context.nCtx, NativeObject, s.NativeObject));
return av.ToExprArray();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
NativeFuncInterp.cs
Abstract:
Z3 Managed API: Function Interpretations
Author:
Christoph Wintersteiger (cwinter) 2012-03-21
Notes:
--*/
using System.Diagnostics;
using System;
namespace Microsoft.Z3
{
using Z3_context = System.IntPtr;
using Z3_ast = System.IntPtr;
using Z3_app = System.IntPtr;
using Z3_sort = System.IntPtr;
using Z3_func_decl = System.IntPtr;
using Z3_model = System.IntPtr;
using Z3_func_interp = System.IntPtr;
using Z3_func_entry = System.IntPtr;
/// <summary>
/// A function interpretation is represented as a finite map and an 'else' value.
/// Each entry in the finite map represents the value of a function given a set of arguments.
/// </summary>
public class NativeFuncInterp
{
/// <summary>
/// Evaluation entry of a function
/// </summary>
public class Entry
{
/// <summary>
/// Argument values that define entry
/// </summary>
public Z3_ast[] Arguments;
/// <summary>
/// Result of applying function to Arguments in the interpretation
/// </summary>
public Z3_ast Result;
}
/// <summary>
/// Function that is interpreted
/// </summary>
public Z3_func_decl Declaration;
/// <summary>
/// Set of non-default entries defining the function graph
/// </summary>
public Entry[] Entries;
/// <summary>
/// Default cause of the function interpretation
/// </summary>
public Z3_ast Else;
#region Internal
internal NativeFuncInterp(NativeContext ctx, NativeModel mdl, Z3_func_decl decl, Z3_func_interp fi)
{
Debug.Assert(ctx != null);
Z3_context nCtx = ctx.nCtx;
Native.Z3_func_interp_inc_ref(nCtx, fi);
Declaration = decl;
Else = Native.Z3_func_interp_get_else(nCtx, fi);
uint numEntries = Native.Z3_func_interp_get_num_entries(nCtx, fi);
uint numArgs = Native.Z3_func_interp_get_arity(nCtx, fi);
Entries = new Entry[numEntries];
for (uint j = 0; j < numEntries; ++j)
{
var ntvEntry = Native.Z3_func_interp_get_entry(nCtx, fi, j);
Entries[j] = new Entry();
Native.Z3_func_entry_inc_ref(nCtx, ntvEntry);
Entries[j].Arguments = new Z3_ast[numArgs];
for (uint i = 0; i < numArgs; ++i)
Entries[j].Arguments[i] = Native.Z3_func_entry_get_arg(nCtx, ntvEntry, i);
Entries[j].Result = Native.Z3_func_entry_get_value(nCtx, ntvEntry);
Native.Z3_func_entry_dec_ref(nCtx, ntvEntry);
}
Native.Z3_func_interp_dec_ref(nCtx, fi);
}
#endregion
}
}

View file

@ -0,0 +1,383 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
NativeModel.cs
Abstract:
Z3 Managed API: Models
Native interface to model objects.
Author:
Christoph Wintersteiger (cwinter) 2012-03-21
Nikolaj Bjorner (nbjorner) 2022-03-01
Notes:
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
namespace Microsoft.Z3
{
using Z3_ast = System.IntPtr;
using Z3_func_decl = System.IntPtr;
using Z3_sort = System.IntPtr;
/// <summary>
/// A Model contains interpretations (assignments) of constants and functions.
/// </summary>
public class NativeModel : IDisposable
{
/// <summary>
/// Retrieves the interpretation (the assignment) of <paramref name="a"/> in the model.
/// </summary>
/// <param name="a">A Constant</param>
/// <returns>An expression if the constant has an interpretation in the model, null otherwise.</returns>
public Z3_ast ConstInterp(Z3_ast a) => ConstFuncInterp(Native.Z3_get_app_decl(ntvContext.nCtx, a));
/// <summary>
/// Retrieves the interpretation (the assignment) of <paramref name="f"/> in the model.
/// </summary>
/// <param name="f">A function declaration of zero arity</param>
/// <returns>An expression if the function has an interpretation in the model, null otherwise.</returns>
public Z3_ast ConstFuncInterp(Z3_func_decl f)
{
if (Native.Z3_get_arity(ntvContext.nCtx, f) != 0)
throw new Z3Exception("Non-zero arity functions have FunctionInterpretations as a model. Use FuncInterp.");
return Native.Z3_model_get_const_interp(ntvContext.nCtx, NativeObject, f);
}
/// <summary>
/// Retrieves the interpretation (the assignment) of a non-constant <paramref name="f"/> in the model.
/// </summary>
/// <param name="f">A function declaration of non-zero arity</param>
/// <returns>A FunctionInterpretation if the function has an interpretation in the model, null otherwise.</returns>
public NativeFuncInterp FuncInterp(Z3_func_decl f)
{
Z3_sort_kind sk = (Z3_sort_kind)Native.Z3_get_sort_kind(ntvContext.nCtx, Native.Z3_get_range(ntvContext.nCtx, f));
if (Native.Z3_get_arity(ntvContext.nCtx, f) == 0)
{
IntPtr n = Native.Z3_model_get_const_interp(ntvContext.nCtx, NativeObject, f);
if (sk == Z3_sort_kind.Z3_ARRAY_SORT)
{
if (n == IntPtr.Zero)
return null;
else
{
if (Native.Z3_is_as_array(ntvContext.nCtx, n) == 0)
throw new Z3Exception("Argument was not an array constant");
var fd = Native.Z3_get_as_array_func_decl(ntvContext.nCtx, n);
return new NativeFuncInterp(ntvContext, this, f, fd);
}
}
else
{
throw new Z3Exception("Constant functions do not have a function interpretation; use ConstInterp");
}
}
else
{
IntPtr n = Native.Z3_model_get_func_interp(ntvContext.nCtx, NativeObject, f);
if (n == IntPtr.Zero)
return null;
else
return new NativeFuncInterp(ntvContext, this, f, n);
}
}
/// <summary>
/// The number of constants that have an interpretation in the model.
/// </summary>
public uint NumConsts
{
get { return Native.Z3_model_get_num_consts(ntvContext.nCtx, NativeObject); }
}
/// <summary>
/// The function declarations of the constants in the model.
/// </summary>
public Z3_func_decl[] ConstDecls
{
get
{
uint n = NumConsts;
Z3_func_decl[] res = new Z3_func_decl[n];
for (uint i = 0; i < n; i++)
res[i] = Native.Z3_model_get_const_decl(ntvContext.nCtx, NativeObject, i);
return res;
}
}
/// <summary>
/// Enumerate constants in model.
/// </summary>
public IEnumerable<KeyValuePair<Z3_func_decl, Z3_ast>> Consts
{
get
{
uint nc = NumConsts;
for (uint i = 0; i < nc; ++i)
{
var f = Native.Z3_model_get_const_decl(ntvContext.nCtx, NativeObject, i);
IntPtr n = Native.Z3_model_get_const_interp(ntvContext.nCtx, NativeObject, f);
if (n == IntPtr.Zero) continue;
yield return new KeyValuePair<Z3_func_decl, Z3_ast>(f, n);
}
}
}
/// <summary>
/// The number of function interpretations in the model.
/// </summary>
public uint NumFuncs
{
get { return Native.Z3_model_get_num_funcs(ntvContext.nCtx, NativeObject); }
}
/// <summary>
/// The function declarations of the function interpretations in the model.
/// </summary>
public Z3_func_decl[] FuncDecls
{
get
{
uint n = NumFuncs;
Z3_func_decl[] res = new Z3_func_decl[n];
for (uint i = 0; i < n; i++)
res[i] = Native.Z3_model_get_func_decl(ntvContext.nCtx, NativeObject, i);
return res;
}
}
/// <summary>
/// All symbols that have an interpretation in the model.
/// </summary>
public Z3_func_decl[] Decls
{
get
{
uint nFuncs = NumFuncs;
uint nConsts = NumConsts;
uint n = nFuncs + nConsts;
Z3_func_decl[] res = new Z3_func_decl[n];
for (uint i = 0; i < nConsts; i++)
res[i] = Native.Z3_model_get_const_decl(ntvContext.nCtx, NativeObject, i);
for (uint i = 0; i < nFuncs; i++)
res[nConsts + i] = Native.Z3_model_get_func_decl(ntvContext.nCtx, NativeObject, i);
return res;
}
}
/// <summary>
/// A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model.
/// </summary>
public class ModelEvaluationFailedException : Z3Exception
{
/// <summary>
/// An exception that is thrown when model evaluation fails.
/// </summary>
public ModelEvaluationFailedException() : base() { }
}
/// <summary>
/// Evaluates the expression <paramref name="t"/> in the current model.
/// </summary>
/// <remarks>
/// This function may fail if <paramref name="t"/> contains quantifiers,
/// is partial (MODEL_PARTIAL enabled), or if <paramref name="t"/> is not well-sorted.
/// In this case a <c>ModelEvaluationFailedException</c> is thrown.
/// </remarks>
/// <param name="t">An expression</param>
/// <param name="completion">
/// When this flag is enabled, a model value will be assigned to any constant
/// or function that does not have an interpretation in the model.
/// </param>
/// <returns>The evaluation of <paramref name="t"/> in the model.</returns>
public Z3_ast Eval(Z3_ast t, bool completion = false)
{
IntPtr v = IntPtr.Zero;
if (Native.Z3_model_eval(ntvContext.nCtx, NativeObject, t, (byte)(completion ? 1 : 0), ref v) == (byte)0)
throw new ModelEvaluationFailedException();
else
return v;
}
/// <summary>
/// Alias for <c>Eval</c>.
/// </summary>
public Z3_ast Evaluate(Z3_ast t, bool completion = false) => Eval(t, completion);
/// <summary>
/// Evaluate expression to a double, assuming it is a numeral already.
/// </summary>
public double Double(Z3_ast t)
{
var r = Eval(t, true);
return Native.Z3_get_numeral_double(ntvContext.nCtx, r);
}
/// <summary>
/// An array value obtained by untangling a model assignment.
/// </summary>
public class ArrayValue
{
/// <summary>
/// One dimensional array of indices where the array is updated
/// </summary>
public KeyValuePair<Z3_ast, Z3_ast>[] Updates;
/// <summary>
/// default Else case
/// </summary>
public Z3_ast Else;
/// <summary>
/// Domain for array
/// Updates.Keys
/// </summary>
public Z3_ast[] Domain;
/// <summary>
/// Range for array
/// Updates.Values
/// </summary>
public Z3_ast[] Range;
}
/// <summary>
/// Convert the interpretation of t into a sequence of array updates
/// </summary>
/// <param name="t"></param>
/// <param name="result"></param>
/// <returns>null if the argument does evaluate to a sequence of stores to an array</returns>
public bool TryGetArrayValue(Z3_ast t, out ArrayValue result)
{
var r = Eval(t, true);
// check that r is a sequence of store over a constant default array.
var updates = new Dictionary<Z3_ast, Z3_ast>();
result = null;
while (true)
{
if (ntvContext.GetAstKind(r) != Z3_ast_kind.Z3_APP_AST)
return false;
Z3_func_decl f = ntvContext.GetAppDecl(r);
var kind = ntvContext.GetDeclKind(f);
if (kind == Z3_decl_kind.Z3_OP_CONST_ARRAY)
{
result = new ArrayValue();
result.Else = ntvContext.GetAppArg(r, 0);
result.Updates = updates.ToArray();
result.Domain = updates.Keys.ToArray();
result.Range = updates.Values.ToArray();
return true;
}
else if (kind == Z3_decl_kind.Z3_OP_STORE)
{
Debug.Assert(ntvContext.GetNumArgs(r) == 3);
updates[ntvContext.GetAppArg(r, 1)] = ntvContext.GetAppArg(r, 2);
r = ntvContext.GetAppArg(r, 0);
}
else
{
return false;
}
}
}
/// <summary>
/// The number of uninterpreted sorts that the model has an interpretation for.
/// </summary>
public uint NumSorts { get { return Native.Z3_model_get_num_sorts(ntvContext.nCtx, NativeObject); } }
/// <summary>
/// The uninterpreted sorts that the model has an interpretation for.
/// </summary>
/// <remarks>
/// Z3 also provides an interpretation for uninterpreted sorts used in a formula.
/// The interpretation for a sort is a finite set of distinct values. We say this finite set is
/// the "universe" of the sort.
/// </remarks>
/// <seealso cref="NumSorts"/>
public Z3_sort[] Sorts
{
get
{
uint n = NumSorts;
Z3_sort[] res = new Z3_sort[n];
for (uint i = 0; i < n; i++)
res[i] = Native.Z3_model_get_sort(ntvContext.nCtx, NativeObject, i);
return res;
}
}
/// <summary>
/// Conversion of models to strings.
/// </summary>
/// <returns>A string representation of the model.</returns>
public override string ToString()
{
return Native.Z3_model_to_string(ntvContext.nCtx, NativeObject);
}
IntPtr NativeObject;
NativeContext ntvContext;
internal NativeModel(NativeContext ctx, IntPtr obj)
{
ntvContext = ctx;
NativeObject = obj;
Debug.Assert(ctx != null);
Native.Z3_model_inc_ref(ctx.nCtx, obj);
}
/// <summary>
/// Finalizer.
/// </summary>
~NativeModel()
{
Dispose();
}
/// <summary>
/// Disposes of the underlying native Z3 object.
/// </summary>
public void Dispose()
{
if (NativeObject != IntPtr.Zero)
{
Native.Z3_model_dec_ref(ntvContext.nCtx, NativeObject);
NativeObject = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
}
}

View file

@ -0,0 +1,451 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
NativeSolver.cs
Abstract:
Z3 Managed API: Native Solver
Author:
Christoph Wintersteiger (cwinter) 2012-03-22
Nikolaj Bjorner (nbjorner) 2022-03-01
Notes:
--*/
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Z3
{
using Z3_ast = System.IntPtr;
using Z3_context = System.IntPtr;
using Z3_func_decl = System.IntPtr;
using Z3_params = System.IntPtr;
using Z3_solver = System.IntPtr;
using Z3_sort = System.IntPtr;
using Z3_symbol = System.IntPtr;
/// <summary>
/// Solvers.
/// </summary>
public class NativeSolver : IDisposable
{
/// <summary>
/// A string that describes all available solver parameters.
/// </summary>
public string Help => Native.Z3_solver_get_help(nCtx, z3solver);
private void SetParam(Action<Z3_params> setter)
{
Z3_params p = Native.Z3_mk_params(nCtx);
Native.Z3_params_inc_ref(nCtx, p);
setter(p);
Native.Z3_solver_set_params(nCtx, z3solver, p);
Native.Z3_params_dec_ref(nCtx, p);
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, bool value)
{
SetParam((Z3_params p) => Native.Z3_params_set_bool(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), (byte)(value ? 1 : 0)));
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, uint value)
{
SetParam((Z3_params p) => Native.Z3_params_set_uint(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), value));
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, double value)
{
SetParam((Z3_params p) => Native.Z3_params_set_double(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), value));
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, string value)
{
var value_sym = Native.Z3_mk_string_symbol(nCtx, value);
SetParam((Z3_params p) => Native.Z3_params_set_symbol(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), value_sym));
}
#if false
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, bool value) { Parameters = Context.MkParams().Add(name, value); }
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, uint value) { Parameters = Context.MkParams().Add(name, value); }
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, double value) { Parameters = Context.MkParams().Add(name, value); }
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, string value) { Parameters = Context.MkParams().Add(name, value); }
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
/// <summary>
/// Retrieves parameter descriptions for solver.
/// </summary>
public ParamDescrs ParameterDescriptions
{
get { return new ParamDescrs(Context, Native.Z3_solver_get_param_descrs(nCtx, NativeObject)); }
}
#endif
/// <summary>
/// The current number of backtracking points (scopes).
/// </summary>
/// <seealso cref="Pop"/>
/// <seealso cref="Push"/>
public uint NumScopes => Native.Z3_solver_get_num_scopes(nCtx, z3solver);
/// <summary>
/// Creates a backtracking point.
/// </summary>
/// <seealso cref="Pop"/>
public void Push() => Native.Z3_solver_push(nCtx, z3solver);
/// <summary>
/// Backtracks <paramref name="n"/> backtracking points.
/// </summary>
/// <remarks>Note that an exception is thrown if <paramref name="n"/> is not smaller than <c>NumScopes</c></remarks>
/// <seealso cref="Push"/>
public void Pop(uint n = 1) => Native.Z3_solver_pop(nCtx, z3solver, n);
/// <summary>
/// Resets the Solver.
/// </summary>
/// <remarks>This removes all assertions from the solver.</remarks>
public void Reset() => Native.Z3_solver_reset(nCtx, z3solver);
/// <summary>
/// Assert a constraint (or multiple) into the solver.
/// </summary>
public void Assert(params Z3_ast[] constraints)
{
Debug.Assert(constraints != null);
Debug.Assert(constraints.All(c => c != IntPtr.Zero));
foreach (Z3_ast a in constraints)
{
Native.Z3_solver_assert(nCtx, z3solver, a);
}
}
/// <summary>
/// Alias for Assert.
/// </summary>
public void Add(params Z3_ast[] constraints) => Assert(constraints);
/// <summary>
/// Alias for Assert.
/// </summary>
public void Add(IEnumerable<Z3_ast> constraints) => Assert(constraints.ToArray());
/// <summary>
/// Add constraints to ensure the function f can only be injective.
/// Example:
/// for function f : D1 x D2 -> R
/// assert axioms
/// forall (x1 : D1, x2 : D2) x1 = inv1(f(x1,x2))
/// forall (x1 : D1, x2 : D2) x2 = inv2(f(x1,x2))
/// </summary>
/// <param name="f"></param>
public void AssertInjective(Z3_func_decl f)
{
uint arity = Native.Z3_get_arity(nCtx, f);
Z3_sort range = Native.Z3_get_range(nCtx, f);
Z3_ast[] vars = new Z3_ast[arity];
Z3_sort[] sorts = new Z3_sort[arity];
Z3_symbol[] names = new Z3_symbol[arity];
for (uint i = 0; i < arity; ++i)
{
Z3_sort domain = Native.Z3_get_domain(nCtx, f, i);
vars[i] = ntvContext.MkBound(arity - i - 1, domain);
sorts[i] = domain;
names[i] = Native.Z3_mk_int_symbol(nCtx, (int)i);
}
Z3_ast app_f = IntPtr.Zero; // Context.MkApp(f, vars);
for (uint i = 0; i < arity; ++i)
{
Z3_sort domain = Native.Z3_get_domain(nCtx, f, i);
Z3_func_decl proj = ntvContext.MkFreshFuncDecl("inv", new Z3_sort[] { range }, domain);
Z3_ast body = ntvContext.MkEq(vars[i], ntvContext.MkApp(proj, app_f));
Z3_ast q = ntvContext.MkForall(names, sorts, body);
Assert(q);
}
}
/// <summary>
/// Assert multiple constraints into the solver, and track them (in the unsat) core
/// using the Boolean constants in ps.
/// </summary>
/// <remarks>
/// This API is an alternative to <see cref="Check(Z3_ast[])"/> with assumptions for extracting unsat cores.
/// Both APIs can be used in the same solver. The unsat core will contain a combination
/// of the Boolean variables provided using <see cref="AssertAndTrack(Z3_ast[],Z3_ast[])"/>
/// and the Boolean literals
/// provided using <see cref="Check(Z3_ast[])"/> with assumptions.
/// </remarks>
public void AssertAndTrack(Z3_ast[] constraints, Z3_ast[] ps)
{
Debug.Assert(constraints != null);
Debug.Assert(constraints.All(c => c != IntPtr.Zero));
Debug.Assert(ps.All(c => c != IntPtr.Zero));
if (constraints.Length != ps.Length)
throw new Z3Exception("Argument size mismatch");
for (int i = 0; i < constraints.Length; i++)
Native.Z3_solver_assert_and_track(nCtx, z3solver, constraints[i], ps[i]);
}
/// <summary>
/// Assert a constraint into the solver, and track it (in the unsat) core
/// using the Boolean constant p.
/// </summary>
/// <remarks>
/// This API is an alternative to <see cref="Check(Z3_ast[])"/> with assumptions for extracting unsat cores.
/// Both APIs can be used in the same solver. The unsat core will contain a combination
/// of the Boolean variables provided using <see cref="AssertAndTrack(Z3_ast[],Z3_ast[])"/>
/// and the Boolean literals
/// provided using <see cref="Check(Z3_ast[])"/> with assumptions.
/// </remarks>
public void AssertAndTrack(Z3_ast constraint, Z3_ast p)
{
Debug.Assert(constraint != null);
Debug.Assert(p != null);
Native.Z3_solver_assert_and_track(nCtx, z3solver, constraint, p);
}
/// <summary>
/// Load solver assertions from a file.
/// </summary>
public void FromFile(string file)
=> Native.Z3_solver_from_file(nCtx, z3solver, file);
/// <summary>
/// Load solver assertions from a string.
/// </summary>
public void FromString(string str)
=> Native.Z3_solver_from_string(nCtx, z3solver, str);
/// <summary>
/// The number of assertions in the solver.
/// </summary>
public uint NumAssertions
=> (uint)ntvContext.ToArray(Native.Z3_solver_get_assertions(nCtx, z3solver)).Length;
/// <summary>
/// The set of asserted formulas.
/// </summary>
public Z3_ast[] Assertions
=> ntvContext.ToArray(Native.Z3_solver_get_assertions(nCtx, z3solver));
/// <summary>
/// Currently inferred units.
/// </summary>
public Z3_ast[] Units
=> ntvContext.ToArray(Native.Z3_solver_get_units(nCtx, z3solver));
/// <summary>
/// Checks whether the assertions in the solver are consistent or not.
/// </summary>
/// <remarks>
/// <seealso cref="Model"/>
/// <seealso cref="UnsatCore"/>
/// <seealso cref="Proof"/>
/// </remarks>
public Status Check(params Z3_ast[] assumptions)
{
Z3_lbool r;
if (assumptions == null || assumptions.Length == 0)
r = (Z3_lbool)Native.Z3_solver_check(nCtx, z3solver);
else
r = (Z3_lbool)Native.Z3_solver_check_assumptions(nCtx, z3solver, (uint)assumptions.Length, assumptions);
return lboolToStatus(r);
}
/// <summary>
/// Checks whether the assertions in the solver are consistent or not.
/// </summary>
/// <remarks>
/// <seealso cref="Model"/>
/// <seealso cref="UnsatCore"/>
/// <seealso cref="Proof"/>
/// </remarks>
public Status Check(IEnumerable<Z3_ast> assumptions)
{
Z3_lbool r;
Z3_ast[] asms = assumptions.ToArray();
if (asms.Length == 0)
r = (Z3_lbool)Native.Z3_solver_check(nCtx, z3solver);
else
r = (Z3_lbool)Native.Z3_solver_check_assumptions(nCtx, z3solver, (uint)asms.Length, asms);
return lboolToStatus(r);
}
/// <summary>
/// The model of the last <c>Check(params Expr[] assumptions)</c>.
/// </summary>
/// <remarks>
/// The result is <c>null</c> if <c>Check(params Expr[] assumptions)</c> was not invoked before,
/// if its results was not <c>SATISFIABLE</c>, or if model production is not enabled.
/// </remarks>
public NativeModel Model
{
get
{
IntPtr x = Native.Z3_solver_get_model(nCtx, z3solver);
return x == IntPtr.Zero
? null
: new NativeModel(ntvContext, x);
}
}
/// <summary>
/// The proof of the last <c>Check(params Expr[] assumptions)</c>.
/// </summary>
/// <remarks>
/// The result is <c>null</c> if <c>Check(params Expr[] assumptions)</c> was not invoked before,
/// if its results was not <c>UNSATISFIABLE</c>, or if proof production is disabled.
/// </remarks>
public Z3_ast Proof
=> Native.Z3_solver_get_proof(nCtx, z3solver);
/// <summary>
/// The unsat core of the last <c>Check</c>.
/// </summary>
/// <remarks>
/// The unsat core is a subset of <c>Assertions</c>
/// The result is empty if <c>Check</c> was not invoked before,
/// if its results was not <c>UNSATISFIABLE</c>, or if core production is disabled.
/// </remarks>
public Z3_ast[] UnsatCore
=> ntvContext.ToArray(Native.Z3_solver_get_unsat_core(nCtx, z3solver));
/// <summary>
/// A brief justification of why the last call to <c>Check</c> returned <c>UNKNOWN</c>.
/// </summary>
public string ReasonUnknown
=> Native.Z3_solver_get_reason_unknown(nCtx, z3solver);
/// <summary>
/// Create a clone of the current solver with respect to <c>ctx</c>.
/// </summary>
public NativeSolver Translate(NativeContext ctx)
{
Debug.Assert(ctx != null);
return new NativeSolver(ctx, Native.Z3_solver_translate(nCtx, z3solver, ctx.nCtx));
}
/// <summary>
/// Import model converter from other solver.
/// </summary>
public void ImportModelConverter(NativeSolver src)
{
Debug.Assert(src != null);
Native.Z3_solver_import_model_converter(nCtx, src.z3solver, z3solver);
}
/// <summary>
/// Solver statistics.
/// </summary>
public Statistics.Entry[] Statistics
{
get
{
var stats = Native.Z3_solver_get_statistics(nCtx, z3solver);
return ntvContext.GetStatistics(stats);
}
}
/// <summary>
/// A string representation of the solver.
/// </summary>
public override string ToString()
{
return Native.Z3_solver_to_string(nCtx, z3solver);
}
#region Internal
readonly NativeContext ntvContext;
Z3_solver z3solver;
Z3_context nCtx => ntvContext.nCtx;
internal NativeSolver(NativeContext nativeCtx, Z3_solver z3solver)
{
Debug.Assert(nativeCtx != null);
Debug.Assert(z3solver != IntPtr.Zero);
this.ntvContext = nativeCtx;
this.z3solver = z3solver;
Native.Z3_solver_inc_ref(nCtx, z3solver);
}
/// <summary>
/// Finalizer.
/// </summary>
~NativeSolver()
{
Dispose();
}
/// <summary>
/// Disposes of the underlying native Z3 object.
/// </summary>
public void Dispose()
{
if (z3solver != IntPtr.Zero)
{
Native.Z3_solver_dec_ref(nCtx, z3solver);
z3solver = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
private Status lboolToStatus(Z3_lbool r)
{
switch (r)
{
case Z3_lbool.Z3_L_TRUE: return Status.SATISFIABLE;
case Z3_lbool.Z3_L_FALSE: return Status.UNSATISFIABLE;
default: return Status.UNKNOWN;
}
}
#endregion
}
}

View file

@ -212,7 +212,7 @@ namespace Microsoft.Z3
public Handle AssertSoft(BoolExpr constraint, uint weight, string group)
{
Context.CheckContextMatch(constraint);
Symbol s = Context.MkSymbol(group);
using Symbol s = Context.MkSymbol(group);
return new Handle(this, Native.Z3_optimize_assert_soft(Context.nCtx, NativeObject, constraint.NativeObject, weight.ToString(), s.NativeObject));
}
@ -289,7 +289,7 @@ namespace Microsoft.Z3
get
{
ASTVector core = new ASTVector(Context, Native.Z3_optimize_get_unsat_core(Context.nCtx, NativeObject));
using ASTVector core = new ASTVector(Context, Native.Z3_optimize_get_unsat_core(Context.nCtx, NativeObject));
return core.ToBoolExprArray();
}
}
@ -337,7 +337,7 @@ namespace Microsoft.Z3
/// </summary>
private Expr[] GetLowerAsVector(uint index)
{
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_lower_as_vector(Context.nCtx, NativeObject, index));
using ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_lower_as_vector(Context.nCtx, NativeObject, index));
return v.ToExprArray();
}
@ -347,7 +347,7 @@ namespace Microsoft.Z3
/// </summary>
private Expr[] GetUpperAsVector(uint index)
{
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_upper_as_vector(Context.nCtx, NativeObject, index));
using ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_upper_as_vector(Context.nCtx, NativeObject, index));
return v.ToExprArray();
}
@ -396,7 +396,7 @@ namespace Microsoft.Z3
get
{
ASTVector assertions = new ASTVector(Context, Native.Z3_optimize_get_assertions(Context.nCtx, NativeObject));
using ASTVector assertions = new ASTVector(Context, Native.Z3_optimize_get_assertions(Context.nCtx, NativeObject));
return assertions.ToBoolExprArray();
}
}
@ -409,7 +409,7 @@ namespace Microsoft.Z3
get
{
ASTVector objectives = new ASTVector(Context, Native.Z3_optimize_get_objectives(Context.nCtx, NativeObject));
using ASTVector objectives = new ASTVector(Context, Native.Z3_optimize_get_objectives(Context.nCtx, NativeObject));
return objectives.ToExprArray();
}
}

View file

@ -62,7 +62,7 @@ namespace Microsoft.Z3
{
get
{
IntNum n = Numerator;
using IntNum n = Numerator;
return BigInteger.Parse(n.ToString());
}
}
@ -74,7 +74,7 @@ namespace Microsoft.Z3
{
get
{
IntNum n = Denominator;
using IntNum n = Denominator;
return BigInteger.Parse(n.ToString());
}
}

View file

@ -58,43 +58,92 @@ namespace Microsoft.Z3
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, bool value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(string name, bool value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, uint value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(string name, uint value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, double value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(string name, double value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, string value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(string name, string value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(string name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(string name, Symbol value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, bool value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(Symbol name, bool value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, uint value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(Symbol name, uint value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, double value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(Symbol name, double value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, string value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(Symbol name, string value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
/// <summary>
/// Sets parameter on the solver
/// </summary>
public void Set(Symbol name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
public void Set(Symbol name, Symbol value)
{
using var parameters = Context.MkParams().Add(name, value);
Parameters = parameters;
}
@ -245,7 +294,7 @@ namespace Microsoft.Z3
{
get
{
ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
using ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
return assertions.Size;
}
}
@ -258,7 +307,7 @@ namespace Microsoft.Z3
get
{
ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
using ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
return assertions.ToBoolExprArray();
}
}
@ -271,7 +320,7 @@ namespace Microsoft.Z3
get
{
ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_units(Context.nCtx, NativeObject));
using ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_units(Context.nCtx, NativeObject));
return assertions.ToBoolExprArray();
}
}
@ -330,9 +379,9 @@ namespace Microsoft.Z3
/// </remarks>
public Status Consequences(IEnumerable<BoolExpr> assumptions, IEnumerable<Expr> variables, out BoolExpr[] consequences)
{
ASTVector result = new ASTVector(Context);
ASTVector asms = new ASTVector(Context);
ASTVector vars = new ASTVector(Context);
using ASTVector result = new ASTVector(Context);
using ASTVector asms = new ASTVector(Context);
using ASTVector vars = new ASTVector(Context);
foreach (var asm in assumptions) asms.Push(asm);
foreach (var v in variables) vars.Push(v);
Z3_lbool r = (Z3_lbool)Native.Z3_solver_get_consequences(Context.nCtx, NativeObject, asms.NativeObject, vars.NativeObject, result.NativeObject);
@ -391,7 +440,7 @@ namespace Microsoft.Z3
get
{
ASTVector core = new ASTVector(Context, Native.Z3_solver_get_unsat_core(Context.nCtx, NativeObject));
using ASTVector core = new ASTVector(Context, Native.Z3_solver_get_unsat_core(Context.nCtx, NativeObject));
return core.ToBoolExprArray();
}
}
@ -424,14 +473,14 @@ namespace Microsoft.Z3
/// </summary>
public IEnumerable<BoolExpr[]> Cube()
{
ASTVector cv = new ASTVector(Context);
using ASTVector cv = new ASTVector(Context);
if (CubeVariables != null)
foreach (var b in CubeVariables) cv.Push(b);
while (true) {
var lvl = BacktrackLevel;
BacktrackLevel = uint.MaxValue;
ASTVector r = new ASTVector(Context, Native.Z3_solver_cube(Context.nCtx, NativeObject, cv.NativeObject, lvl));
using ASTVector r = new ASTVector(Context, Native.Z3_solver_cube(Context.nCtx, NativeObject, cv.NativeObject, lvl));
var v = r.ToBoolExprArray();
CubeVariables = cv.ToBoolExprArray();
if (v.Length == 1 && v[0].IsFalse) {

View file

@ -23,6 +23,9 @@ using System.Diagnostics;
namespace Microsoft.Z3
{
using Z3_context = System.IntPtr;
using Z3_stats = System.IntPtr;
/// <summary>
/// Objects of this class track statistical information about solvers.
/// </summary>
@ -123,25 +126,29 @@ namespace Microsoft.Z3
{
get
{
uint n = Size;
Entry[] res = new Entry[n];
for (uint i = 0; i < n; i++)
{
Entry e;
string k = Native.Z3_stats_get_key(Context.nCtx, NativeObject, i);
if (Native.Z3_stats_is_uint(Context.nCtx, NativeObject, i) != 0)
e = new Entry(k, Native.Z3_stats_get_uint_value(Context.nCtx, NativeObject, i));
else if (Native.Z3_stats_is_double(Context.nCtx, NativeObject, i) != 0)
e = new Entry(k, Native.Z3_stats_get_double_value(Context.nCtx, NativeObject, i));
else
throw new Z3Exception("Unknown data entry value");
res[i] = e;
}
return res;
return NativeEntries(Context.nCtx, NativeObject);
}
}
internal static Entry[] NativeEntries(Z3_context ctx, Z3_stats stats)
{
uint n = Native.Z3_stats_size(ctx, stats);
Entry[] res = new Entry[n];
for (uint i = 0; i < n; i++)
{
Entry e;
string k = Native.Z3_stats_get_key(ctx, stats, i);
if (Native.Z3_stats_is_uint(ctx, stats, i) != 0)
e = new Entry(k, Native.Z3_stats_get_uint_value(ctx, stats, i));
else if (Native.Z3_stats_is_double(ctx, stats, i) != 0)
e = new Entry(k, Native.Z3_stats_get_double_value(ctx, stats, i));
else
throw new Z3Exception("Unknown data entry value");
res[i] = e;
}
return res;
}
/// <summary>
/// The statistical counters.
/// </summary>

View file

@ -2106,6 +2106,26 @@ public class Context implements AutoCloseable {
return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
}
/**
* Check if the string s1 is lexicographically strictly less than s2.
*/
public BoolExpr MkStringLt(SeqSort<CharSort> s1, SeqSort<CharSort> s2)
{
checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkStrLt(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
}
/**
* Check if the string s1 is lexicographically less or equal to s2.
*/
public BoolExpr MkStringLe(SeqSort<CharSort> s1, SeqSort<CharSort> s2)
{
checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkStrLe(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
}
/**
* Retrieve sequence of length one at index.
*/
@ -2180,6 +2200,14 @@ public class Context implements AutoCloseable {
return (ReExpr<R>) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
}
/**
* Create power regular expression.
*/
public <R extends Sort> ReExpr<R> mkPower(Expr<ReSort<R>> re, int n)
{
return (ReExpr<R>) Expr.create(this, Native.mkRePower(nCtx(), re.getNativeObject(), n));
}
/**
* Take the lower and upper-bounded Kleene star of a regular expression.
*/
@ -4038,6 +4066,37 @@ public class Context implements AutoCloseable {
return new BitVecExpr(this, Native.mkFpaToFpIntReal(nCtx(), rm.getNativeObject(), exp.getNativeObject(), sig.getNativeObject(), s.getNativeObject()));
}
/**
* Creates or a linear order.
* @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) {
return (FuncDecl<BoolSort>) FuncDecl.create(
this,
Native.mkLinearOrder(
nCtx(),
sort.getNativeObject(),
index
)
);
}
/**
* Creates or a partial order.
* @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) {
return (FuncDecl<BoolSort>) FuncDecl.create(
this,
Native.mkPartialOrder(
nCtx(),
sort.getNativeObject(),
index
)
);
}
/**
* Wraps an AST.

View file

@ -294,7 +294,8 @@ static struct custom_operations Z3_ast_plus_custom_ops = {
Z3_ast_compare_ext
};
MK_CTX_OF(ast, 16) // let's say 16 bytes per ast
// FUDGE
MK_CTX_OF(ast, 8) // let's say 16 bytes per ast
#define MK_PLUS_OBJ_NO_REF(X, USED) \
typedef struct { \
@ -410,25 +411,26 @@ MK_CTX_OF(ast, 16) // let's say 16 bytes per ast
\
MK_CTX_OF(X, USED)
MK_PLUS_OBJ_NO_REF(symbol, 32)
MK_PLUS_OBJ_NO_REF(constructor, 32)
MK_PLUS_OBJ_NO_REF(constructor_list, 32)
MK_PLUS_OBJ_NO_REF(rcf_num, 32)
MK_PLUS_OBJ(params, 128)
MK_PLUS_OBJ(param_descrs, 128)
MK_PLUS_OBJ(model, 512)
MK_PLUS_OBJ(func_interp, 128)
MK_PLUS_OBJ(func_entry, 128)
MK_PLUS_OBJ(goal, 128)
MK_PLUS_OBJ(tactic, 128)
MK_PLUS_OBJ(probe, 128)
MK_PLUS_OBJ(apply_result, 128)
MK_PLUS_OBJ(solver, 20 * 1000 * 1000) // pretend a solver is 20MB
MK_PLUS_OBJ(stats, 128)
MK_PLUS_OBJ(ast_map, 1024 * 2)
MK_PLUS_OBJ(ast_vector, 128)
MK_PLUS_OBJ(fixedpoint, 20 * 1000 * 1000)
MK_PLUS_OBJ(optimize, 20 * 1000 * 1000)
// FUDGE
MK_PLUS_OBJ_NO_REF(symbol, 16)
MK_PLUS_OBJ_NO_REF(constructor, 16)
MK_PLUS_OBJ_NO_REF(constructor_list, 16)
MK_PLUS_OBJ_NO_REF(rcf_num, 16)
MK_PLUS_OBJ(params, 64)
MK_PLUS_OBJ(param_descrs, 64)
MK_PLUS_OBJ(model, 64)
MK_PLUS_OBJ(func_interp, 32)
MK_PLUS_OBJ(func_entry, 32)
MK_PLUS_OBJ(goal, 64)
MK_PLUS_OBJ(tactic, 64)
MK_PLUS_OBJ(probe, 64)
MK_PLUS_OBJ(apply_result, 32)
MK_PLUS_OBJ(solver, 20 * 1000)
MK_PLUS_OBJ(stats, 32)
MK_PLUS_OBJ(ast_map, 32)
MK_PLUS_OBJ(ast_vector, 32)
MK_PLUS_OBJ(fixedpoint, 20 * 1000)
MK_PLUS_OBJ(optimize, 20 * 1000)
#ifdef __cplusplus
extern "C" {

View file

@ -42,8 +42,6 @@ add_custom_command(OUTPUT "${z3py_bindings_build_dest}/z3/z3core.py"
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
"${PROJECT_SOURCE_DIR}/scripts/update_api.py"
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
# FIXME: When update_api.py no longer uses ``mk_util`` drop this dependency
"${PROJECT_SOURCE_DIR}/scripts/mk_util.py"
COMMENT "Generating z3core.py"
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
)

View file

@ -5,3 +5,4 @@ recursive-include core *.cmake
recursive-include core/src *
recursive-include core/cmake *
recursive-include core/scripts *
include pyproject.toml

View file

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=46.4.0", "wheel", "cmake"]
build-backend = "setuptools.build_meta"

View file

@ -154,16 +154,10 @@ def _copy_bins():
_clean_bins()
python_dir = None
if RELEASE_DIR is not None:
python_dir = os.path.join(RELEASE_DIR, 'bin', 'python')
elif SRC_DIR == SRC_DIR_LOCAL:
python_dir = os.path.join(SRC_DIR, 'src', 'api', 'python')
if python_dir is not None:
py_z3_build_dir = os.path.join(BUILD_DIR, 'python', 'z3')
root_z3_dir = os.path.join(ROOT_DIR, 'z3')
shutil.copy(os.path.join(py_z3_build_dir, 'z3core.py'), root_z3_dir)
shutil.copy(os.path.join(py_z3_build_dir, 'z3consts.py'), root_z3_dir)
py_z3_build_dir = os.path.join(BUILD_DIR, 'python', 'z3')
root_z3_dir = os.path.join(ROOT_DIR, 'z3')
shutil.copy(os.path.join(py_z3_build_dir, 'z3core.py'), root_z3_dir)
shutil.copy(os.path.join(py_z3_build_dir, 'z3consts.py'), root_z3_dir)
# STEP 2: Copy the shared library, the executable and the headers
@ -184,6 +178,20 @@ def _copy_bins():
continue
shutil.copy(os.path.join(header_dir, fname), os.path.join(HEADERS_DIR, fname))
# This hack lets z3 installed libs link on M1 macs; it is a hack, not a proper fix
# @TODO: Linked issue: https://github.com/Z3Prover/z3/issues/5926
major_minor = '.'.join(_z3_version().split('.')[:2])
link_name = None
if BUILD_PLATFORM in ('win32', 'cygwin', 'win'):
pass # TODO: When windows VMs work on M1, fill this in
elif BUILD_PLATFORM in ('darwin', 'osx'):
split = LIBRARY_FILE.split('.')
link_name = split[0] + '.' + major_minor + '.' + split[1]
else:
link_name = LIBRARY_FILE + '.' + major_minor
if link_name:
os.symlink(LIBRARY_FILE, os.path.join(LIBS_DIR, link_name), True)
def _copy_sources():
"""
Prepare for a source distribution by assembling a minimal set of source files needed
@ -281,6 +289,8 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
osver = '.'.join(osver.split('.')[:2])
if arch == 'x64':
plat_name ='macosx_%s_x86_64' % osver.replace('.', '_')
elif arch == 'arm64':
plat_name ='macosx_%s_arm64' % osver.replace('.', '_')
else:
raise Exception(f"idk how os {distos} {osver} works. what goes here?")
else:
@ -291,7 +301,6 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
sys.argv.insert(idx + 1, plat_name)
sys.argv.insert(idx + 2, '--universal') # supports py2+py3. if --plat-name is not specified this will also mean that the package can be installed on any machine regardless of architecture, so watch out!
setup(
name='z3-solver',
version=_z3_version(),

View file

@ -12,8 +12,6 @@ Z3 is used in many applications such as: software/hardware verification and test
constraint solving, analysis of hybrid systems, security, biology (in silico analysis),
and geometrical problems.
Several online tutorials for Z3Py are available at:
http://rise4fun.com/Z3Py/tutorial/guide
Please send feedback, comments and/or corrections on the Issue tracker for
https://github.com/Z3prover/z3.git. Your comments are very valuable.
@ -103,9 +101,6 @@ def get_version():
def get_full_version():
return Z3_get_full_version()
# We use _z3_assert instead of the assert command because we want to
# produce nice error messages in Z3Py at rise4fun.com
def _z3_assert(cond, msg):
if not cond:
@ -1771,7 +1766,7 @@ def Xor(a, b, ctx=None):
>>> Xor(p, q)
Xor(p, q)
>>> simplify(Xor(p, q))
Not(p) == q
Not(p == q)
"""
ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx))
s = BoolSort(ctx)
@ -2015,8 +2010,7 @@ class QuantifierRef(BoolRef):
"""
if z3_debug():
_z3_assert(self.is_lambda(), "quantifier should be a lambda expression")
arg = self.sort().domain().cast(arg)
return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx)
return _array_select(self, arg)
def weight(self):
"""Return the weight annotation of `self`.
@ -2285,6 +2279,9 @@ class ArithSortRef(SortRef):
"""
return self.kind() == Z3_INT_SORT
def is_bool(self):
return False
def subsort(self, other):
"""Return `True` if `self` is a subsort of `other`."""
return self.is_int() and is_arith_sort(other) and other.is_real()
@ -4496,6 +4493,11 @@ class ArraySortRef(SortRef):
"""
return _to_sort_ref(Z3_get_array_sort_domain(self.ctx_ref(), self.ast), self.ctx)
def domain_n(self, i):
"""Return the domain of the array sort `self`.
"""
return _to_sort_ref(Z3_get_array_sort_domain_n(self.ctx_ref(), self.ast, i), self.ctx)
def range(self):
"""Return the range of the array sort `self`.
@ -4527,6 +4529,10 @@ class ArrayRef(ExprRef):
"""
return self.sort().domain()
def domain_n(self, i):
"""Shorthand for self.sort().domain_n(i)`."""
return self.sort().domain_n(i)
def range(self):
"""Shorthand for `self.sort().range()`.
@ -4546,13 +4552,21 @@ class ArrayRef(ExprRef):
>>> a[i].sexpr()
'(select a i)'
"""
arg = self.domain().cast(arg)
return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx)
return _array_select(self, arg)
def default(self):
return _to_expr_ref(Z3_mk_array_default(self.ctx_ref(), self.as_ast()), self.ctx)
def _array_select(ar, arg):
if isinstance(arg, tuple):
args = [ar.domain_n(i).cast(arg[i]) for i in range(len(arg))]
_args, sz = _to_ast_array(args)
return _to_expr_ref(Z3_mk_select_n(ar.ctx_ref(), ar.as_ast(), sz, _args), ar.ctx)
arg = ar.domain().cast(arg)
return _to_expr_ref(Z3_mk_select(ar.ctx_ref(), ar.as_ast(), arg.as_ast()), ar.ctx)
def is_array_sort(a):
return Z3_get_sort_kind(a.ctx.ref(), Z3_get_sort(a.ctx.ref(), a.ast)) == Z3_ARRAY_SORT
@ -4679,7 +4693,7 @@ def ArraySort(*sig):
return ArraySortRef(Z3_mk_array_sort_n(ctx.ref(), arity, dom, r.ast), ctx)
def Array(name, dom, rng):
def Array(name, *sorts):
"""Return an array constant named `name` with the given domain and range sorts.
>>> a = Array('a', IntSort(), IntSort())
@ -4688,12 +4702,12 @@ def Array(name, dom, rng):
>>> a[0]
a[0]
"""
s = ArraySort(dom, rng)
s = ArraySort(sorts)
ctx = s.ctx
return ArrayRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), s.ast), ctx)
def Update(a, i, v):
def Update(a, *args):
"""Return a Z3 store array expression.
>>> a = Array('a', IntSort(), IntSort())
@ -4709,10 +4723,20 @@ def Update(a, i, v):
"""
if z3_debug():
_z3_assert(is_array_sort(a), "First argument must be a Z3 array expression")
i = a.sort().domain().cast(i)
v = a.sort().range().cast(v)
args = _get_args(args)
ctx = a.ctx
return _to_expr_ref(Z3_mk_store(ctx.ref(), a.as_ast(), i.as_ast(), v.as_ast()), ctx)
if len(args) <= 1:
raise Z3Exception("array update requires index and value arguments")
if len(args) == 2:
i = args[0]
v = args[1]
i = a.sort().domain().cast(i)
v = a.sort().range().cast(v)
return _to_expr_ref(Z3_mk_store(ctx.ref(), a.as_ast(), i.as_ast(), v.as_ast()), ctx)
v = a.sort().range().cast(args[-1])
idxs = [a.sort().domain_n(i).cast(args[i]) for i in range(len(args)-1)]
_args, sz = _to_ast_array(idxs)
return _to_expr_ref(Z3_mk_store_n(ctx.ref(), a.as_ast(), sz, _args, v.as_ast()), ctx)
def Default(a):
@ -4726,7 +4750,7 @@ def Default(a):
return a.default()
def Store(a, i, v):
def Store(a, *args):
"""Return a Z3 store array expression.
>>> a = Array('a', IntSort(), IntSort())
@ -4740,10 +4764,10 @@ def Store(a, i, v):
>>> prove(Implies(i != j, s[j] == a[j]))
proved
"""
return Update(a, i, v)
return Update(a, args)
def Select(a, i):
def Select(a, *args):
"""Return a Z3 select array expression.
>>> a = Array('a', IntSort(), IntSort())
@ -4753,9 +4777,10 @@ def Select(a, i):
>>> eq(Select(a, i), a[i])
True
"""
args = _get_args(args)
if z3_debug():
_z3_assert(is_array_sort(a), "First argument must be a Z3 array expression")
return a[i]
return a[args]
def Map(f, *args):
@ -6569,6 +6594,19 @@ class ModelRef(Z3PPObject):
"""Update the interpretation of a constant"""
if is_expr(x):
x = x.decl()
if is_func_decl(x) and x.arity() != 0 and isinstance(value, FuncInterp):
fi1 = value.f
fi2 = Z3_add_func_interp(x.ctx_ref(), self.model, x.ast, value.else_value().ast);
fi2 = FuncInterp(fi2, x.ctx)
for i in range(value.num_entries()):
e = value.entry(i)
n = Z3_func_entry_get_num_args(x.ctx_ref(), e.entry)
v = AstVector()
for j in range(n):
v.push(entry.arg_value(j))
val = Z3_func_entry_get_value(x.ctx_ref(), e.entry)
Z3_func_interp_add_entry(x.ctx_ref(), fi2.f, v.vector, val)
return
if not is_func_decl(x) or x.arity() != 0:
raise Z3Exception("Expecting 0-ary function or constant expression")
value = _py2expr(value)
@ -8856,7 +8894,7 @@ def _pb_args_coeffs(args, default_ctx=None):
for i in range(len(coeffs)):
_z3_check_cint_overflow(coeffs[i], "coefficient")
_coeffs[i] = coeffs[i]
return ctx, sz, _args, _coeffs
return ctx, sz, _args, _coeffs, args
def PbLe(args, k):
@ -8866,7 +8904,7 @@ def PbLe(args, k):
>>> f = PbLe(((a,1),(b,3),(c,2)), 3)
"""
_z3_check_cint_overflow(k, "k")
ctx, sz, _args, _coeffs = _pb_args_coeffs(args)
ctx, sz, _args, _coeffs, args = _pb_args_coeffs(args)
return BoolRef(Z3_mk_pble(ctx.ref(), sz, _args, _coeffs, k), ctx)
@ -8877,7 +8915,7 @@ def PbGe(args, k):
>>> f = PbGe(((a,1),(b,3),(c,2)), 3)
"""
_z3_check_cint_overflow(k, "k")
ctx, sz, _args, _coeffs = _pb_args_coeffs(args)
ctx, sz, _args, _coeffs, args = _pb_args_coeffs(args)
return BoolRef(Z3_mk_pbge(ctx.ref(), sz, _args, _coeffs, k), ctx)
@ -8888,7 +8926,7 @@ def PbEq(args, k, ctx=None):
>>> f = PbEq(((a,1),(b,3),(c,2)), 3)
"""
_z3_check_cint_overflow(k, "k")
ctx, sz, _args, _coeffs = _pb_args_coeffs(args)
ctx, sz, _args, _coeffs, args = _pb_args_coeffs(args)
return BoolRef(Z3_mk_pbeq(ctx.ref(), sz, _args, _coeffs, k), ctx)
@ -8982,7 +9020,7 @@ def prove(claim, show=False, **keywords):
def _solve_html(*args, **keywords):
"""Version of function `solve` used in RiSE4Fun."""
"""Version of function `solve` that renders HTML output."""
show = keywords.pop("show", False)
s = Solver()
s.set(**keywords)
@ -9006,7 +9044,7 @@ def _solve_html(*args, **keywords):
def _solve_using_html(s, *args, **keywords):
"""Version of function `solve_using` used in RiSE4Fun."""
"""Version of function `solve_using` that renders HTML."""
show = keywords.pop("show", False)
if z3_debug():
_z3_assert(isinstance(s, Solver), "Solver object expected")
@ -9031,7 +9069,7 @@ def _solve_using_html(s, *args, **keywords):
def _prove_html(claim, show=False, **keywords):
"""Version of function `prove` used in RiSE4Fun."""
"""Version of function `prove` that renders HTML."""
if z3_debug():
_z3_assert(is_bool(claim), "Z3 Boolean expression expected")
s = Solver()
@ -11215,12 +11253,16 @@ def ensure_prop_closures():
_prop_closures = PropClosures()
def user_prop_push(ctx):
_prop_closures.get(ctx).push()
def user_prop_push(ctx, cb):
prop = _prop_closures.get(ctx)
prop.cb = cb
prop.push()
def user_prop_pop(ctx, num_scopes):
_prop_closures.get(ctx).pop(num_scopes)
def user_prop_pop(ctx, cb, num_scopes):
prop = _prop_closures.get(ctx)
prop.cb = cb
pop(num_scopes)
def user_prop_fresh(id, ctx):
@ -11230,31 +11272,38 @@ def user_prop_fresh(id, ctx):
_prop_closures.set(new_prop.id, new_prop)
return ctypes.c_void_p(new_prop.id)
def to_Ast(ptr,):
ast = Ast(ptr)
super(ctypes.c_void_p, ast).__init__(ptr)
return ast
def user_prop_fixed(ctx, cb, id, value):
prop = _prop_closures.get(ctx)
prop.cb = cb
prop.fixed(id, _to_expr_ref(ctypes.c_void_p(value), prop.ctx()))
id = _to_expr_ref(to_Ast(id), prop.ctx())
value = _to_expr_ref(to_Ast(value), prop.ctx())
prop.fixed(id, value)
prop.cb = None
def user_prop_final(ctx, cb):
prop = _prop_closures.get(ctx)
prop.cb = cb
prop.final()
prop.cb = None
def user_prop_eq(ctx, cb, x, y):
prop = _prop_closures.get(ctx)
prop.cb = cb
x = _to_expr_ref(to_Ast(x), prop.ctx())
y = _to_expr_ref(to_Ast(y), prop.ctx())
prop.eq(x, y)
prop.cb = None
def user_prop_diseq(ctx, cb, x, y):
prop = _prop_closures.get(ctx)
prop.cb = cb
x = _to_expr_ref(to_Ast(x), prop.ctx())
y = _to_expr_ref(to_Ast(y), prop.ctx())
prop.diseq(x, y)
prop.cb = None
@ -11352,24 +11401,18 @@ class UserPropagateBase:
def add(self, e):
assert self.solver
assert not self._ctx
return Z3_solver_propagate_register(self.ctx_ref(), self.solver.solver, e.ast)
Z3_solver_propagate_register(self.ctx_ref(), self.solver.solver, e.ast)
#
# Propagation can only be invoked as during a fixed or final callback.
#
def propagate(self, e, ids, eqs=[]):
num_fixed = len(ids)
_ids = (ctypes.c_uint * num_fixed)()
for i in range(num_fixed):
_ids[i] = ids[i]
_ids, num_fixed = _to_ast_array(ids)
num_eqs = len(eqs)
_lhs = (ctypes.c_uint * num_eqs)()
_rhs = (ctypes.c_uint * num_eqs)()
for i in range(num_eqs):
_lhs[i] = eqs[i][0]
_rhs[i] = eqs[i][1]
_lhs, _num_lhs = _to_ast_array([x for x, y in eqs])
_rhs, _num_rhs = _to_ast_array([y for x, y in eqs])
Z3_solver_propagate_consequence(e.ctx.ref(), ctypes.c_void_p(
self.cb), num_fixed, _ids, num_eqs, _lhs, _rhs, e.ast)
def conflict(self, ids):
self.propagate(BoolVal(False, self.ctx()), ids, eqs=[])
def conflict(self, deps):
self.propagate(BoolVal(False, self.ctx()), deps, eqs=[])

View file

@ -996,6 +996,8 @@ typedef enum
information is exposed. Tools may use the string representation of the
function declaration to obtain more information.
- Z3_OP_RECURSIVE: function declared as recursive
- Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols.
*/
typedef enum {
@ -1220,13 +1222,17 @@ typedef enum {
Z3_OP_RE_CONCAT,
Z3_OP_RE_UNION,
Z3_OP_RE_RANGE,
Z3_OP_RE_DIFF,
Z3_OP_RE_INTERSECT,
Z3_OP_RE_LOOP,
Z3_OP_RE_POWER,
Z3_OP_RE_INTERSECT,
Z3_OP_RE_DIFF,
Z3_OP_RE_COMPLEMENT,
Z3_OP_RE_EMPTY_SET,
Z3_OP_RE_FULL_SET,
Z3_OP_RE_COMPLEMENT,
Z3_OP_RE_FULL_CHAR_SET,
Z3_OP_RE_OF_PRED,
Z3_OP_RE_REVERSE,
Z3_OP_RE_DERIVATIVE,
// char
Z3_OP_CHAR_CONST,
@ -1316,6 +1322,7 @@ typedef enum {
Z3_OP_FPA_BV2RM,
Z3_OP_INTERNAL,
Z3_OP_RECURSIVE,
Z3_OP_UNINTERPRETED
} Z3_decl_kind;
@ -1430,13 +1437,14 @@ Z3_DECLARE_CLOSURE(Z3_error_handler, void, (Z3_context c, Z3_error_code e));
/**
\brief callback functions for user propagator.
*/
Z3_DECLARE_CLOSURE(Z3_push_eh, void, (void* ctx));
Z3_DECLARE_CLOSURE(Z3_pop_eh, void, (void* ctx, unsigned num_scopes));
Z3_DECLARE_CLOSURE(Z3_push_eh, void, (void* ctx, Z3_solver_callback cb));
Z3_DECLARE_CLOSURE(Z3_pop_eh, void, (void* ctx, Z3_solver_callback cb, unsigned num_scopes));
Z3_DECLARE_CLOSURE(Z3_fresh_eh, void*, (void* ctx, Z3_context new_context));
Z3_DECLARE_CLOSURE(Z3_fixed_eh, void, (void* ctx, Z3_solver_callback cb, unsigned id, Z3_ast value));
Z3_DECLARE_CLOSURE(Z3_eq_eh, void, (void* ctx, Z3_solver_callback cb, unsigned x, unsigned y));
Z3_DECLARE_CLOSURE(Z3_fixed_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast t, Z3_ast value));
Z3_DECLARE_CLOSURE(Z3_eq_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast s, Z3_ast t));
Z3_DECLARE_CLOSURE(Z3_final_eh, void, (void* ctx, Z3_solver_callback cb));
Z3_DECLARE_CLOSURE(Z3_created_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast e, unsigned id));
Z3_DECLARE_CLOSURE(Z3_created_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast t));
Z3_DECLARE_CLOSURE(Z3_decide_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast*, unsigned*, Z3_lbool*));
/**
@ -3817,6 +3825,13 @@ extern "C" {
*/
Z3_ast Z3_API Z3_mk_re_loop(Z3_context c, Z3_ast r, unsigned lo, unsigned hi);
/**
\brief Create a power regular expression.
def_API('Z3_mk_re_power', AST, (_in(CONTEXT), _in(AST), _in(UINT)))
*/
Z3_ast Z3_API Z3_mk_re_power(Z3_context c, Z3_ast, unsigned n);
/**
\brief Create the intersection of the regular languages.
@ -4358,11 +4373,27 @@ extern "C" {
\sa Z3_mk_array_sort
\sa Z3_get_sort_kind
\sa Z3_get_array_sort_domain_n
def_API('Z3_get_array_sort_domain', SORT, (_in(CONTEXT), _in(SORT)))
*/
Z3_sort Z3_API Z3_get_array_sort_domain(Z3_context c, Z3_sort t);
/**
\brief Return the i'th domain sort of an n-dimensional array.
\pre Z3_get_sort_kind(c, t) == Z3_ARRAY_SORT
\sa Z3_mk_array_sort
\sa Z3_get_sort_kind
\sa Z3_get_array_sort_domain
def_API('Z3_get_array_sort_domain_n', SORT, (_in(CONTEXT), _in(SORT), _in(UINT)))
*/
Z3_sort Z3_API Z3_get_array_sort_domain_n(Z3_context c, Z3_sort t, unsigned idx);
/**
\brief Return the range of the given array sort.
@ -6672,6 +6703,13 @@ extern "C" {
/**
\brief register a user-properator with the solver.
\param c - context.
\param s - solver object.
\param user_context - a context used to maintain state for callbacks.
\param push_eh - a callback invoked when scopes are pushed
\param pop_eh - a callback invoked when scopes are poped
\param fresh_eh - a solver may spawn new solvers internally. This callback is used to produce a fresh user_context to be associated with fresh solvers.
*/
void Z3_API Z3_solver_propagate_init(
@ -6694,11 +6732,15 @@ extern "C" {
/**
\brief register a callback on final check.
This provides freedom to the propagator to delay actions or implement a branch-and bound solver.
The final check is invoked when all decision variables have been assigned by the solver.
The final_eh callback takes as argument the original user_context that was used
when calling \c Z3_solver_propagate_init, and it takes a callback context for propagations.
If may use the callback context to invoke the \c Z3_solver_propagate_consequence function.
If the callback context gets used, the solver continues.
The \c final_eh callback takes as argument the original user_context that was used
when calling \c Z3_solver_propagate_init, and it takes a callback context with the
opaque type \c Z3_solver_callback.
The callback context is passed as argument to invoke the \c Z3_solver_propagate_consequence function.
The callback context can only be accessed (for propagation and for dynamically registering expressions) within a callback.
If the callback context gets used for propagation or conflicts, those propagations take effect and
may trigger new decision variables to be set.
*/
void Z3_API Z3_solver_propagate_final(Z3_context c, Z3_solver s, Z3_final_eh final_eh);
@ -6718,6 +6760,14 @@ extern "C" {
*/
void Z3_API Z3_solver_propagate_created(Z3_context c, Z3_solver s, Z3_created_eh created_eh);
/**
* \brief register a callback when a the solver decides to split on a registered expression
* The callback may set passed expression to another registered expression which will be selected instead.
* In case the expression is a bitvector the bit to split on is determined by the bit argument and the
* truth-value to try first is given by is_pos
*/
void Z3_API Z3_solver_propagate_decide(Z3_context c, Z3_solver s, Z3_decide_eh decide_eh);
/**
Create uninterpreted function declaration for the user propagator.
When expressions using the function are created by the solver invoke a callback
@ -6734,10 +6784,10 @@ extern "C" {
\brief register an expression to propagate on with the solver.
Only expressions of type Bool and type Bit-Vector can be registered for propagation.
def_API('Z3_solver_propagate_register', UINT, (_in(CONTEXT), _in(SOLVER), _in(AST)))
def_API('Z3_solver_propagate_register', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST)))
*/
unsigned Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e);
void Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e);
/**
\brief register an expression to propagate on with the solver.
@ -6745,9 +6795,9 @@ extern "C" {
Unlike \ref Z3_solver_propagate_register, this function takes a solver callback context
as argument. It can be invoked during a callback to register new expressions.
def_API('Z3_solver_propagate_register_cb', UINT, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(AST)))
def_API('Z3_solver_propagate_register_cb', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(AST)))
*/
unsigned Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback cb, Z3_ast e);
void Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback cb, Z3_ast e);
/**
\brief propagate a consequence based on fixed values.
@ -6755,10 +6805,10 @@ extern "C" {
The callback adds a propagation consequence based on the fixed values of the
\c ids.
def_API('Z3_solver_propagate_consequence', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, UINT), _in(UINT), _in_array(4, UINT), _in_array(4, UINT), _in(AST)))
def_API('Z3_solver_propagate_consequence', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, AST), _in(UINT), _in_array(4, AST), _in_array(4, AST), _in(AST)))
*/
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback, unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, unsigned const* eq_lhs, unsigned const* eq_rhs, Z3_ast conseq);
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
/**
\brief Check whether the assertions in a given solver are consistent or not.

View file

@ -82,7 +82,7 @@ extern "C" {
\param c - context
\param o - optimization context
\param a - formula
\param weight - a positive weight, penalty for violating soft constraint
\param weight - a penalty for violating soft constraint. Negative weights convert into rewards.
\param id - optional identifier to group soft constraints
\sa Z3_optimize_assert

View file

@ -27,6 +27,7 @@ Revision History:
#include "ast/ast_util.h"
#include "ast/ast_smt2_pp.h"
#include "ast/array_decl_plugin.h"
#include "ast/arith_decl_plugin.h"
#include "ast/ast_translation.h"
#include "util/z3_version.h"
@ -233,8 +234,7 @@ std::ostream& operator<<(std::ostream& out, sort_size const & ss) {
// -----------------------------------
std::ostream & operator<<(std::ostream & out, sort_info const & info) {
operator<<(out, static_cast<decl_info const&>(info));
out << " :size " << info.get_num_elements();
return out;
return out << " :size " << info.get_num_elements();
}
// -----------------------------------
@ -1758,13 +1758,13 @@ ast * ast_manager::register_node_core(ast * n) {
switch (n->get_kind()) {
case AST_SORT:
if (to_sort(n)->m_info != nullptr) {
to_sort(n)->m_info = alloc(sort_info, *(to_sort(n)->get_info()));
to_sort(n)->m_info = alloc(sort_info, std::move(*(to_sort(n)->get_info())));
to_sort(n)->m_info->init_eh(*this);
}
break;
case AST_FUNC_DECL:
if (to_func_decl(n)->m_info != nullptr) {
to_func_decl(n)->m_info = alloc(func_decl_info, *(to_func_decl(n)->get_info()));
to_func_decl(n)->m_info = alloc(func_decl_info, std::move(*(to_func_decl(n)->get_info())));
to_func_decl(n)->m_info->init_eh(*this);
}
inc_array_ref(to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain());
@ -1992,7 +1992,7 @@ sort * ast_manager::substitute(sort* s, unsigned n, sort * const * src, sort * c
return s;
}
decl_info dinfo(s->get_family_id(), s->get_decl_kind(), ps.size(), ps.data(), s->private_parameters());
sort_info sinfo(dinfo, s->get_num_elements());
sort_info sinfo(std::move(dinfo), s->get_num_elements());
return mk_sort(s->get_name(), &sinfo);
}
@ -2131,12 +2131,17 @@ bool ast_manager::coercion_needed(func_decl * decl, unsigned num_args, expr * co
expr* ast_manager::coerce_to(expr* e, sort* s) {
sort* se = e->get_sort();
if (s != se && s->get_family_id() == arith_family_id && se->get_family_id() == arith_family_id) {
if (s->get_decl_kind() == REAL_SORT) {
if (s->get_decl_kind() == REAL_SORT)
return mk_app(arith_family_id, OP_TO_REAL, e);
}
else {
else
return mk_app(arith_family_id, OP_TO_INT, e);
}
}
if (s != se && s->get_family_id() == arith_family_id && is_bool(e)) {
arith_util au(*this);
if (s->get_decl_kind() == REAL_SORT)
return mk_ite(e, au.mk_real(1), au.mk_real(0));
else
return mk_ite(e, au.mk_int(1), au.mk_int(0));
}
else {
return e;
@ -2231,7 +2236,7 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar
std::ostringstream buffer;
buffer << "Wrong number of arguments (" << num_args
<< ") passed to function " << mk_pp(decl, *this);
throw ast_exception(buffer.str());
throw ast_exception(std::move(buffer).str());
}
app * r = nullptr;
if (num_args == 1 && decl->is_chainable() && decl->get_arity() == 2) {

View file

@ -367,8 +367,8 @@ public:
decl_info(family_id, k, num_parameters, parameters, private_parameters), m_num_elements(num_elements) {
}
sort_info(decl_info const& di, sort_size const& num_elements) :
decl_info(di), m_num_elements(num_elements) {}
sort_info(decl_info && di, sort_size const& num_elements) :
decl_info(std::move(di)), m_num_elements(num_elements) {}
bool is_infinite() const { return m_num_elements.is_infinite(); }
bool is_very_big() const { return m_num_elements.is_very_big(); }

View file

@ -47,18 +47,14 @@ format * smt2_pp_environment::pp_fdecl_name(symbol const & s, unsigned & len, bo
len = static_cast<unsigned>(str.length());
return mk_string(m, str);
}
else if (s.is_numerical()) {
std::string str = s.str();
len = static_cast<unsigned>(str.length());
return mk_string(m, str);
}
else if (!s.bare_str()) {
else if (s.is_null()) {
len = 4;
return mk_string(m, "null");
}
else {
len = static_cast<unsigned>(strlen(s.bare_str()));
return mk_string(m, s.bare_str());
std::string str = s.str();
len = static_cast<unsigned>(str.length());
return mk_string(m, str);
}
}

View file

@ -170,12 +170,20 @@ void ast_translation::mk_func_decl(func_decl * f, frame & fr) {
new_fi.set_injective(fi->is_injective());
new_fi.set_skolem(fi->is_skolem());
new_fi.set_idempotent(fi->is_idempotent());
new_fi.set_lambda(fi->is_lambda());
new_f = m_to_manager.mk_func_decl(f->get_name(),
f->get_arity(),
new_domain,
new_range,
new_fi);
if (new_fi.is_lambda()) {
quantifier* q = from().is_lambda_def(f);
ast_translation tr(from(), to());
quantifier* new_q = tr(q);
to().add_lambda_def(new_f, new_q);
}
}
TRACE("ast_translation",
tout << f->get_name() << " "; if (fi) tout << *fi; tout << "\n";

View file

@ -886,8 +886,8 @@ app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
}
sort * bv_util::mk_sort(unsigned bv_size) {
parameter p[1] = { parameter(bv_size) };
return m_manager.mk_sort(get_fid(), BV_SORT, 1, p);
parameter p(bv_size);
return m_manager.mk_sort(get_fid(), BV_SORT, 1, &p);
}
unsigned bv_util::get_int2bv_size(parameter const& p) {

View file

@ -16,6 +16,7 @@ Author:
--*/
#include "util/gparams.h"
#include "ast/bv_decl_plugin.h"
#include "ast/char_decl_plugin.h"
#include "ast/arith_decl_plugin.h"
#include "ast/ast_pp.h"
@ -164,6 +165,14 @@ app* char_decl_plugin::mk_le(expr* a, expr* b) {
unsigned v1 = 0, v2 = 0;
if (a == b)
return m_manager->mk_true();
bv_util bv(*m_manager);
if (bv.is_bv(a))
return bv.mk_ule(a, b);
arith_util arith(*m_manager);
if (arith.is_int_real(a))
return arith.mk_le(a, b);
if (a->get_sort() != char_sort())
throw default_exception("range comparison is only supported for bit-vectors, int, real and characters");
bool c1 = is_const_char(a, v1);
bool c2 = is_const_char(b, v2);
if (c1 && c2)

View file

@ -69,8 +69,8 @@ namespace datatype {
domain.push_back(a->instantiate(ps)->get_range());
}
sort_ref range = get_def().instantiate(ps);
parameter pas[1] = { parameter(name()) };
return func_decl_ref(m.mk_func_decl(u().get_family_id(), OP_DT_CONSTRUCTOR, 1, pas, domain.size(), domain.data(), range), m);
parameter pas(name());
return func_decl_ref(m.mk_func_decl(u().get_family_id(), OP_DT_CONSTRUCTOR, 1, &pas, domain.size(), domain.data(), range), m);
}
func_decl_ref constructor::instantiate(sort* dt) const {
@ -1052,8 +1052,8 @@ namespace datatype {
func_decl * util::get_constructor_is(func_decl * con) {
SASSERT(is_constructor(con));
sort * datatype = con->get_range();
parameter ps[1] = { parameter(con)};
return m.mk_func_decl(fid(), OP_DT_IS, 1, ps, 1, &datatype);
parameter ps(con);
return m.mk_func_decl(fid(), OP_DT_IS, 1, &ps, 1, &datatype);
}
func_decl * util::get_constructor_recognizer(func_decl * con) {

View file

@ -293,11 +293,12 @@ namespace euf {
VERIFY(n->num_args() == 0 || !n->merge_enabled() || m_table.contains(n));
}
void egraph::set_value(enode* n, lbool value) {
void egraph::set_value(enode* n, lbool value, justification j) {
if (n->value() == l_undef) {
force_push();
TRACE("euf", tout << bpp(n) << " := " << value << "\n";);
n->set_value(value);
n->m_lit_justification = j;
m_updates.push_back(update_record(n, update_record::value_assignment()));
}
}
@ -657,6 +658,7 @@ namespace euf {
push_lca(n1->get_arg(1), n2->get_arg(0));
return;
}
TRACE("euf_verbose", tout << bpp(n1) << " " << bpp(n2) << "\n");
for (unsigned i = 0; i < n1->num_args(); ++i)
push_lca(n1->get_arg(i), n2->get_arg(i));
@ -713,6 +715,15 @@ namespace euf {
explain_todo(justifications);
}
template <typename T>
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j) {
if (j.is_external())
justifications.push_back(j.ext<T>());
else if (j.is_congruence())
push_congruence(a, b, j.is_commutative());
}
template <typename T>
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b) {
SASSERT(a->get_root() == b->get_root());
@ -746,11 +757,21 @@ namespace euf {
void egraph::explain_todo(ptr_vector<T>& justifications) {
for (unsigned i = 0; i < m_todo.size(); ++i) {
enode* n = m_todo[i];
if (n->m_target && !n->is_marked1()) {
if (n->is_marked1())
continue;
if (n->m_target) {
n->mark1();
CTRACE("euf_verbose", m_display_justification, n->m_justification.display(tout << n->get_expr_id() << " = " << n->m_target->get_expr_id() << " ", m_display_justification) << "\n";);
explain_eq(justifications, n, n->m_target, n->m_justification);
}
else if (!n->is_marked1() && n->value() != l_undef) {
n->mark1();
if (m.is_true(n->get_expr()) || m.is_false(n->get_expr()))
continue;
justification j = n->m_lit_justification;
SASSERT(j.is_external());
justifications.push_back(j.ext<T>());
}
}
}

View file

@ -226,12 +226,8 @@ namespace euf {
void erase_from_table(enode* p);
template <typename T>
void explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j) {
if (j.is_external())
justifications.push_back(j.ext<T>());
else if (j.is_congruence())
push_congruence(a, b, j.is_commutative());
}
void explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j);
template <typename T>
void explain_todo(ptr_vector<T>& justifications);
@ -295,7 +291,7 @@ namespace euf {
void add_th_var(enode* n, theory_var v, theory_id id);
void set_th_propagates_diseqs(theory_id id);
void set_merge_enabled(enode* n, bool enable_merge);
void set_value(enode* n, lbool value);
void set_value(enode* n, lbool value, justification j);
void set_bool_var(enode* n, unsigned v) { n->set_bool_var(v); }
void set_relevant(enode* n);
void set_default_relevant(bool b) { m_default_relevant = b; }

View file

@ -63,6 +63,7 @@ namespace euf {
enode* m_cg = nullptr;
th_var_list m_th_vars;
justification m_justification;
justification m_lit_justification;
unsigned m_num_args = 0;
signed char m_lbl_hash = -1; // It is different from -1, if enode is used in a pattern
approx_set m_lbls;
@ -133,6 +134,7 @@ namespace euf {
void del_th_var(theory_id id) { m_th_vars.del_var(id); }
void set_merge_enabled(bool m) { m_merge_enabled = m; }
void set_value(lbool v) { m_value = v; }
void set_justification(justification j) { m_justification = j; }
void set_is_equality() { m_is_equality = true; }
void set_bool_var(sat::bool_var v) { m_bool_var = v; }

View file

@ -33,11 +33,9 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
unsigned arity, sort * const * domain, sort * range) {
SASSERT(m_manager);
ast_manager& m = *m_manager;
for (unsigned i = 0; i < arity; ++i) {
if (!m.is_bool(domain[i])) {
m.raise_exception("invalid non-Boolean sort applied to 'at-most'");
}
}
for (unsigned i = 0; i < arity; ++i)
if (!m.is_bool(domain[i]))
m.raise_exception("invalid non-Boolean sort applied to Pseudo-Boolean relation");
symbol sym;
switch(k) {
case OP_AT_LEAST_K: sym = m_at_least_sym; break;
@ -50,9 +48,8 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
switch(k) {
case OP_AT_LEAST_K:
case OP_AT_MOST_K: {
if (num_parameters != 1 || !parameters[0].is_int() || parameters[0].get_int() < 0) {
if (num_parameters != 1 || !parameters[0].is_int() || parameters[0].get_int() < 0)
m.raise_exception("function expects one non-negative integer parameter");
}
func_decl_info info(m_family_id, k, 1, parameters);
return m.mk_func_decl(sym, arity, domain, m.mk_bool_sort(), info);
}
@ -93,11 +90,11 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
void pb_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
if (logic == symbol::null || logic == "QF_FD" || logic == "ALL" || logic == "HORN") {
op_names.push_back(builtin_name(m_at_most_sym.bare_str(), OP_AT_MOST_K));
op_names.push_back(builtin_name(m_at_least_sym.bare_str(), OP_AT_LEAST_K));
op_names.push_back(builtin_name(m_pble_sym.bare_str(), OP_PB_LE));
op_names.push_back(builtin_name(m_pbge_sym.bare_str(), OP_PB_GE));
op_names.push_back(builtin_name(m_pbeq_sym.bare_str(), OP_PB_EQ));
op_names.push_back(builtin_name(m_at_most_sym.str(), OP_AT_MOST_K));
op_names.push_back(builtin_name(m_at_least_sym.str(), OP_AT_LEAST_K));
op_names.push_back(builtin_name(m_pble_sym.str(), OP_PB_LE));
op_names.push_back(builtin_name(m_pbge_sym.str(), OP_PB_GE));
op_names.push_back(builtin_name(m_pbeq_sym.str(), OP_PB_EQ));
}
}

View file

@ -225,6 +225,11 @@ namespace recfun {
m_vars.append(n_vars, vars);
m_rhs = rhs;
if (!is_macro)
for (expr* e : subterms::all(m_rhs))
if (is_lambda(e))
throw default_exception("recursive definitions with lambdas are not supported");
expr_ref_vector conditions(m);
// is the function a macro (unconditional body)?
@ -234,6 +239,8 @@ namespace recfun {
return;
}
// analyze control flow of `rhs`, accumulating guards and
// rebuilding a `ite`-free RHS on the fly for each path in `rhs`.
// Each such `ite`-free term is converted into a case_def and added to definition.

View file

@ -9,6 +9,7 @@ z3_add_component(rewriter
bv_elim.cpp
bv_rewriter.cpp
cached_var_subst.cpp
char_rewriter.cpp
datatype_rewriter.cpp
der.cpp
distribute_forall.cpp

View file

@ -37,6 +37,7 @@ void bv_rewriter::updt_local_params(params_ref const & _p) {
m_extract_prop = p.bv_extract_prop();
m_ite2id = p.bv_ite2id();
m_le_extra = p.bv_le_extra();
m_le2extract = p.bv_le2extract();
set_sort_sums(p.bv_sort_ac());
}
@ -196,11 +197,11 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
SASSERT(num_args == 1);
return mk_bit2bool(args[0], f->get_parameter(0).get_int(), result);
case OP_BSMUL_NO_OVFL:
return mk_bvsmul_no_overflow(num_args, args, result);
return mk_bvsmul_no_overflow(num_args, args, true, result);
case OP_BSMUL_NO_UDFL:
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_NO_UDFL:
return mk_bvsmul_no_underflow(num_args, args, result);
default:
return BR_FAILED;
}
@ -577,7 +578,7 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref
result = m().mk_eq(a, m_util.mk_numeral(numeral(0), bv_sz));
return BR_REWRITE1;
}
else if (first_non_zero < bv_sz - 1) {
else if (first_non_zero < bv_sz - 1 && m_le2extract) {
result = m().mk_and(m().mk_eq(m_mk_extract(bv_sz - 1, first_non_zero + 1, a), m_util.mk_numeral(numeral(0), bv_sz - first_non_zero - 1)),
m_util.mk_ule(m_mk_extract(first_non_zero, 0, a), m_mk_extract(first_non_zero, 0, b)));
return BR_REWRITE3;
@ -2802,18 +2803,34 @@ br_status bv_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & resu
return BR_FAILED;
}
br_status bv_rewriter::mk_bvsmul_no_overflow(unsigned num, expr * const * args, expr_ref & result) {
br_status bv_rewriter::mk_distinct(unsigned num_args, expr * const * args, expr_ref & result) {
if (num_args <= 1) {
result = m().mk_true();
return BR_DONE;
}
unsigned sz = get_bv_size(args[0]);
// check if num_args > 2^sz
if (sz >= 32)
return BR_FAILED;
if (num_args <= 1u << sz)
return BR_FAILED;
result = m().mk_false();
return BR_DONE;
}
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;
rational a0_val, a1_val;
bool is_num1 = is_numeral(args[0], a0_val, bv_sz);
bool is_num2 = is_numeral(args[1], a1_val, bv_sz);
if (is_num1 && (a0_val.is_zero() || a0_val.is_one())) {
if (is_num1 && (a0_val.is_zero() || (bv_sz != 1 && a0_val.is_one()))) {
result = m().mk_true();
return BR_DONE;
}
if (is_num2 && (a1_val.is_zero() || a1_val.is_one())) {
if (is_num2 && (a1_val.is_zero() || (bv_sz != 1 && a1_val.is_one()))) {
result = m().mk_true();
return BR_DONE;
}
@ -2821,11 +2838,16 @@ br_status bv_rewriter::mk_bvsmul_no_overflow(unsigned num, expr * const * args,
if (!is_num1 || !is_num2)
return BR_FAILED;
rational lim = rational::power_of_two(bv_sz);
bool sign0 = m_util.has_sign_bit(a0_val, bv_sz);
bool sign1 = m_util.has_sign_bit(a1_val, bv_sz);
if (sign0) a0_val = rational::power_of_two(bv_sz) - a0_val;
if (sign1) a1_val = rational::power_of_two(bv_sz) - a1_val;
rational lim = rational::power_of_two(bv_sz-1);
rational r = a0_val * a1_val;
bool sign1 = m_util.has_sign_bit(a0_val, bv_sz);
bool sign2 = m_util.has_sign_bit(a1_val, bv_sz);
result = m().mk_bool_val((sign1 != sign2) || r < lim);
if (is_overflow)
result = m().mk_bool_val(sign0 != sign1 || r < lim);
else
result = m().mk_bool_val(sign0 == sign1 || r <= lim);
return BR_DONE;
}
@ -2855,36 +2877,5 @@ br_status bv_rewriter::mk_bvumul_no_overflow(unsigned num, expr * const * args,
return BR_FAILED;
}
br_status bv_rewriter::mk_bvsmul_no_underflow(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num == 2);
unsigned bv_sz;
rational a0_val, a1_val;
bool is_num1 = is_numeral(args[0], a0_val, bv_sz);
bool is_num2 = is_numeral(args[1], a1_val, bv_sz);
if (is_num1 && (a0_val.is_zero() || a0_val.is_one())) {
result = m().mk_true();
return BR_DONE;
}
if (is_num2 && (a1_val.is_zero() || a1_val.is_one())) {
result = m().mk_true();
return BR_DONE;
}
if (is_num1 && is_num2) {
rational ul = rational::power_of_two(bv_sz);
rational lim = rational::power_of_two(bv_sz-1);
if (a0_val >= lim) a0_val -= ul;
if (a1_val >= lim) a1_val -= ul;
rational mr = a0_val * a1_val;
rational neg_lim = -lim;
TRACE("bv_rewriter_bvsmul_no_underflow", tout << "a0:" << a0_val << " a1:" << a1_val << " mr:" << mr << " neg_lim:" << neg_lim << std::endl;);
result = m().mk_bool_val(mr >= neg_lim);
return BR_DONE;
}
return BR_FAILED;
}
template class poly_rewriter<bv_rewriter_core>;

View file

@ -62,6 +62,7 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
bool m_extract_prop;
bool m_bvnot_simpl;
bool m_le_extra;
bool m_le2extract;
bool is_zero_bit(expr * x, unsigned idx);
@ -134,9 +135,8 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
br_status mk_blast_eq_value(expr * lhs, expr * rhs, expr_ref & result);
br_status mk_eq_concat(expr * lhs, expr * rhs, expr_ref & result);
br_status mk_mkbv(unsigned num, expr * const * args, expr_ref & result);
br_status mk_bvsmul_no_overflow(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_no_underflow(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);
@ -180,7 +180,8 @@ public:
bool is_urem_any(expr * e, expr * & dividend, expr * & divisor);
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & resul);
br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & result);
br_status mk_distinct(unsigned num_args, expr * const * args, expr_ref & result);
bool hi_div0() const { return m_hi_div0; }

View file

@ -0,0 +1,73 @@
/*++
Copyright (c) 2015 Microsoft Corporation
Module Name:
char_rewriter.cpp
Abstract:
Basic rewriting rules for character constraints
Author:
Nikolaj Bjorner (nbjorner) 2015-12-5
--*/
#include "util/debug.h"
#include "ast/rewriter/char_rewriter.h"
#include "ast/bv_decl_plugin.h"
#include "ast/arith_decl_plugin.h"
char_rewriter::char_rewriter(ast_manager& m):
m(m) {
m_char = static_cast<char_decl_plugin*>(m.get_plugin(m.mk_family_id("char")));
}
family_id char_rewriter::get_fid() {
return m_char->get_family_id();
}
br_status char_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
SASSERT(f->get_family_id() == get_fid());
br_status st = BR_FAILED;
switch (f->get_decl_kind()) {
case OP_CHAR_CONST:
break;
case OP_CHAR_LE:
break;
case OP_CHAR_TO_INT:
st = mk_char_to_int(args[0], result);
break;
case OP_CHAR_TO_BV:
break;
case OP_CHAR_FROM_BV:
st = mk_char_from_bv(args[0], result);
break;
case OP_CHAR_IS_DIGIT:
break;
}
return st;
}
br_status char_rewriter::mk_char_from_bv(expr* e, expr_ref& result) {
bv_util bv(m);
rational n;
if (bv.is_numeral(e, n) && n.is_unsigned() && n <= m_char->max_char()) {
result = m_char->mk_char(n.get_unsigned());
return BR_DONE;
}
return BR_FAILED;
}
br_status char_rewriter::mk_char_to_int(expr* e, expr_ref& result) {
unsigned n = 0;
if (m_char->is_const_char(e, n)) {
arith_util arith(m);
result = arith.mk_int(n);
return BR_DONE;
}
return BR_FAILED;
}

View file

@ -0,0 +1,57 @@
/*++
Copyright (c) 2015 Microsoft Corporation
Module Name:
char_rewriter.h
Abstract:
Basic rewriting rules for characters constraints.
Author:
Nikolaj Bjorner (nbjorner) 2022-03-10
Notes:
--*/
#pragma once
#include "ast/char_decl_plugin.h"
#include "ast/rewriter/rewriter_types.h"
#include "util/params.h"
#include "util/lbool.h"
/**
\brief Cheap rewrite rules for character constraints
*/
class char_rewriter {
ast_manager& m;
char_decl_plugin* m_char;
br_status mk_char_from_bv(expr* e, expr_ref& result);
br_status mk_char_to_int(expr* e, expr_ref& result);
public:
char_rewriter(ast_manager& m);
family_id get_fid();
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
expr_ref mk_app(func_decl* f, expr_ref_vector const& args) { return mk_app(f, args.size(), args.data()); }
expr_ref mk_app(func_decl* f, unsigned n, expr* const* args) {
expr_ref result(m);
if (f->get_family_id() != get_fid() ||
BR_FAILED == mk_app_core(f, n, args, result))
result = m.mk_app(f, n, args);
return result;
}
};

View file

@ -23,6 +23,7 @@ Revision History:
expr_ref func_decl_replace::operator()(expr* e) {
m_todo.push_back(e);
m_refs.push_back(e);
while (!m_todo.empty()) {
expr* a = m_todo.back(), *b;

View file

@ -979,9 +979,8 @@ expr* poly_rewriter<Config>::merge_muls(expr* x, expr* y) {
template<typename Config>
bool poly_rewriter<Config>::hoist_ite(expr_ref& e) {
if (!m_hoist_ite) {
if (!m_hoist_ite)
return false;
}
obj_hashtable<expr> shared;
ptr_buffer<expr> adds;
expr_ref_vector bs(m()), pinned(m());

View file

@ -936,22 +936,13 @@ expr_ref seq_rewriter::mk_seq_last(expr* t) {
}
/*
* In general constructs substring(t,0,|t|-1) but if t = substring(s,0,k) then simplifies to substring(s,0,k-1)
* This method assumes that |t| > 0, thus, if t = substring(s,0,k) then k > 0 so substring(s,0,k-1) is correct.
* In general constructs substring(t,0,|t|-1)
* Incorrect comment: "but if t = substring(s,0,k) then simplifies to substring(s,0,k-1).
* This method assumes that |t| > 0, thus, if t = substring(s,0,k) then k > 0 so substring(s,0,k-1) is correct."
* No: if k > |s| then substring(s,0,k) = substring(s,0,k-1)
*/
expr_ref seq_rewriter::mk_seq_butlast(expr* t) {
expr_ref result(m());
expr* s, * j, * k;
rational v;
if (str().is_extract(t, s, j, k) && m_autil.is_numeral(j, v) && v.is_zero()) {
expr_ref_vector k_min_1(m());
k_min_1.push_back(k);
k_min_1.push_back(minus_one());
result = str().mk_substr(s, j, m_autil.mk_add_simplify(k_min_1));
}
else
result = str().mk_substr(t, zero(), m_autil.mk_sub(str().mk_length(t), one()));
return result;
return expr_ref(str().mk_substr(t, zero(), m_autil.mk_sub(str().mk_length(t), one())), m());
}
/*
@ -3128,8 +3119,8 @@ void seq_rewriter::mk_antimirov_deriv_rec(expr* e, expr* r, expr* path, expr_ref
expr_ref range(m());
expr_ref psi(m().mk_false(), m());
if (str().is_unit_string(r1, c1) && str().is_unit_string(r2, c2)) {
SASSERT(u().is_char(c1));
SASSERT(u().is_char(c2));
// SASSERT(u().is_char(c1));
// SASSERT(u().is_char(c2));
// case: c1 <= e <= c2
range = simplify_path(e, m().mk_and(u().mk_le(c1, e), u().mk_le(e, c2)));
psi = simplify_path(e, m().mk_and(path, range));
@ -5531,44 +5522,37 @@ lbool seq_rewriter::eq_length(expr* x, expr* y) {
maximal length (the sequence is bounded).
*/
bool seq_rewriter::min_length(expr* e, unsigned& len) {
bool seq_rewriter::min_length(unsigned sz, expr* const* ss, unsigned& len) {
ptr_buffer<expr> es;
for (unsigned i = 0; i < sz; ++i)
es.push_back(ss[i]);
zstring s;
len = 0;
if (str().is_unit(e)) {
len = 1;
return true;
bool bounded = true;
while (!es.empty()) {
expr* e = es.back();
es.pop_back();
if (str().is_unit(e))
len += 1;
else if (str().is_empty(e))
continue;
else if (str().is_string(e, s))
len += s.length();
else if (str().is_concat(e))
for (expr* arg : *to_app(e))
es.push_back(arg);
else
bounded = false;
}
else if (str().is_empty(e)) {
len = 0;
return true;
}
else if (str().is_string(e, s)) {
len = s.length();
return true;
}
else if (str().is_concat(e)) {
unsigned min_l = 0;
bool bounded = true;
for (expr* arg : *to_app(e)) {
if (!min_length(arg, min_l))
bounded = false;
len += min_l;
}
return bounded;
}
return false;
return bounded;
}
bool seq_rewriter::min_length(expr* e, unsigned& len) {
return min_length(1, &e, len);
}
bool seq_rewriter::min_length(expr_ref_vector const& es, unsigned& len) {
unsigned min_l = 0;
bool bounded = true;
len = 0;
for (expr* arg : es) {
if (!min_length(arg, min_l))
bounded = false;
len += min_l;
}
return bounded;
return min_length(es.size(), es.data(), len);
}
bool seq_rewriter::max_length(expr* e, rational& len) {

View file

@ -322,6 +322,7 @@ class seq_rewriter {
bool reduce_eq_empty(expr* l, expr* r, expr_ref& result);
bool min_length(expr_ref_vector const& es, unsigned& len);
bool min_length(expr* e, unsigned& len);
bool min_length(unsigned sz, expr* const* es, unsigned& len);
bool max_length(expr* e, rational& len);
lbool eq_length(expr* x, expr* y);
expr* concat_non_empty(expr_ref_vector& es);

View file

@ -21,6 +21,7 @@ Notes:
#include "ast/rewriter/bool_rewriter.h"
#include "ast/rewriter/arith_rewriter.h"
#include "ast/rewriter/bv_rewriter.h"
#include "ast/rewriter/char_rewriter.h"
#include "ast/rewriter/datatype_rewriter.h"
#include "ast/rewriter/array_rewriter.h"
#include "ast/rewriter/fpa_rewriter.h"
@ -48,6 +49,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
dl_rewriter m_dl_rw;
pb_rewriter m_pb_rw;
seq_rewriter m_seq_rw;
char_rewriter m_char_rw;
recfun_rewriter m_rec_rw;
arith_util m_a_util;
bv_util m_bv_util;
@ -192,9 +194,6 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
if (st != BR_FAILED)
return st;
}
if (k == OP_EQ) {
SASSERT(num == 2);
st = apply_tamagotchi(args[0], args[1], result);
if (st != BR_FAILED)
return st;
@ -218,6 +217,11 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
if (st != BR_FAILED)
return st;
}
if (k == OP_DISTINCT && num > 0 && m_bv_rw.is_bv(args[0])) {
st = m_bv_rw.mk_distinct(num, args, result);
if (st != BR_FAILED)
return st;
}
return m_b_rw.mk_app_core(f, num, args, result);
}
@ -247,6 +251,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
return m_pb_rw.mk_app_core(f, num, args, result);
if (fid == m_seq_rw.get_fid())
return m_seq_rw.mk_app_core(f, num, args, result);
if (fid == m_char_rw.get_fid())
return m_char_rw.mk_app_core(f, num, args, result);
if (fid == m_rec_rw.get_fid())
return m_rec_rw.mk_app_core(f, num, args, result);
return BR_FAILED;
@ -295,6 +301,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
bool is_ite_value_tree(expr * t) {
if (!m().is_ite(t))
return false;
if (t->get_ref_count() != 1)
return false;
ptr_buffer<app> todo;
todo.push_back(to_app(t));
while (!todo.empty()) {
@ -303,12 +311,12 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
expr * arg1 = ite->get_arg(1);
expr * arg2 = ite->get_arg(2);
if (m().is_ite(arg1) && arg1->get_ref_count() == 1) // do not apply on shared terms, since it may blowup
if (m().is_ite(arg1) && arg1->get_ref_count() == 1) // do not apply on shared terms, since it may blow up
todo.push_back(to_app(arg1));
else if (!m().is_value(arg1))
return false;
if (m().is_ite(arg2) && arg2->get_ref_count() == 1) // do not apply on shared terms, since it may blowup
if (m().is_ite(arg2) && arg2->get_ref_count() == 1) // do not apply on shared terms, since it may blow up
todo.push_back(to_app(arg2));
else if (!m().is_value(arg2))
return false;
@ -319,7 +327,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
br_status pull_ite(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
if (num == 2 && m().is_bool(f->get_range()) && !m().is_bool(args[0])) {
if (m().is_ite(args[0])) {
if (m().is_value(args[1]))
if (m().is_value(args[1]) && args[0]->get_ref_count() == 1)
return pull_ite_core<false>(f, to_app(args[0]), to_app(args[1]), result);
if (m().is_ite(args[1]) && to_app(args[0])->get_arg(0) == to_app(args[1])->get_arg(0)) {
// (p (ite C A1 B1) (ite C A2 B2)) --> (ite (p A1 A2) (p B1 B2))
@ -329,7 +337,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
return BR_REWRITE2;
}
}
if (m().is_ite(args[1]) && m().is_value(args[0]))
if (m().is_ite(args[1]) && m().is_value(args[0]) && args[1]->get_ref_count() == 1)
return pull_ite_core<true>(f, to_app(args[1]), to_app(args[0]), result);
}
family_id fid = f->get_family_id();
@ -800,6 +808,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
m_dl_rw(m),
m_pb_rw(m),
m_seq_rw(m),
m_char_rw(m),
m_rec_rw(m),
m_a_util(m),
m_bv_util(m),

View file

@ -1053,6 +1053,12 @@ sort* seq_util::rex::to_seq(sort* re) {
return to_sort(re->get_parameter(0).get_ast());
}
app* seq_util::rex::mk_power(expr* r, unsigned n) {
parameter param(n);
return m.mk_app(m_fid, OP_RE_POWER, 1, &param, 1, &r);
}
app* seq_util::rex::mk_loop(expr* r, unsigned lo) {
parameter param(lo);
return m.mk_app(m_fid, OP_RE_LOOP, 1, &param, 1, &r);

View file

@ -502,6 +502,7 @@ public:
app* mk_star(expr* r) { return m.mk_app(m_fid, OP_RE_STAR, r); }
app* mk_plus(expr* r) { return m.mk_app(m_fid, OP_RE_PLUS, r); }
app* mk_opt(expr* r) { return m.mk_app(m_fid, OP_RE_OPTION, r); }
app* mk_power(expr* r, unsigned n);
app* mk_loop(expr* r, unsigned lo);
app* mk_loop(expr* r, unsigned lo, unsigned hi);
expr* mk_loop_proper(expr* r, unsigned lo, unsigned hi);

View file

@ -61,11 +61,11 @@ func_decl * special_relations_decl_plugin::mk_func_decl(
void special_relations_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
if (logic == symbol::null) {
op_names.push_back(builtin_name(m_po.bare_str(), OP_SPECIAL_RELATION_PO));
op_names.push_back(builtin_name(m_lo.bare_str(), OP_SPECIAL_RELATION_LO));
op_names.push_back(builtin_name(m_plo.bare_str(), OP_SPECIAL_RELATION_PLO));
op_names.push_back(builtin_name(m_to.bare_str(), OP_SPECIAL_RELATION_TO));
op_names.push_back(builtin_name(m_tc.bare_str(), OP_SPECIAL_RELATION_TC));
op_names.push_back(builtin_name(m_po.str(), OP_SPECIAL_RELATION_PO));
op_names.push_back(builtin_name(m_lo.str(), OP_SPECIAL_RELATION_LO));
op_names.push_back(builtin_name(m_plo.str(), OP_SPECIAL_RELATION_PLO));
op_names.push_back(builtin_name(m_to.str(), OP_SPECIAL_RELATION_TO));
op_names.push_back(builtin_name(m_tc.str(), OP_SPECIAL_RELATION_TC));
}
}

View file

@ -58,7 +58,7 @@ public:
cmd * c = ctx.find_cmd(s);
if (c == nullptr) {
std::string err_msg("unknown command '");
err_msg = err_msg + s.bare_str() + "'";
err_msg = err_msg + s.str() + "'";
throw cmd_exception(std::move(err_msg));
}
m_cmds.push_back(s);
@ -817,9 +817,9 @@ public:
sort_ref range(ctx.m());
array_sort_args.push_back(m_f->get_range());
range = array_sort->instantiate(ctx.pm(), array_sort_args.size(), array_sort_args.data());
parameter p[1] = { parameter(m_f) };
parameter p(m_f);
func_decl_ref new_map(ctx.m());
new_map = ctx.m().mk_func_decl(get_array_fid(ctx), OP_ARRAY_MAP, 1, p, domain.size(), domain.data(), range.get());
new_map = ctx.m().mk_func_decl(get_array_fid(ctx), OP_ARRAY_MAP, 1, &p, domain.size(), domain.data(), range.get());
if (new_map == 0)
throw cmd_exception("invalid array map operator");
ctx.insert(m_name, new_map);

View file

@ -1636,6 +1636,7 @@ void cmd_context::pop(unsigned n) {
restore_aux_pdecls(s.m_aux_pdecls_lim);
restore_assertions(s.m_assertions_lim);
restore_psort_inst(s.m_psort_inst_stack_lim);
m_dt_eh.get()->reset();
m_mcs.shrink(m_mcs.size() - n);
m_scopes.shrink(new_lvl);
if (!m_global_decls)
@ -1815,6 +1816,9 @@ void cmd_context::display_model(model_ref& mdl) {
}
void cmd_context::add_declared_functions(model& mdl) {
model_params p;
if (!p.user_functions())
return;
for (auto const& kv : m_func_decls) {
func_decl* f = kv.m_value.first();
if (f->get_family_id() == null_family_id && !mdl.has_interpretation(f)) {

View file

@ -267,6 +267,7 @@ protected:
cmd_context & m_owner;
datatype_util m_dt_util;
public:
void reset() { m_dt_util.reset(); }
dt_eh(cmd_context & owner);
~dt_eh() override;
void operator()(sort * dt, pdecl* pd) override;

View file

@ -57,6 +57,8 @@ public:
void execute(cmd_context & ctx) override {
model_ref md;
if (ctx.ignore_check())
return;
if (!ctx.is_model_available(md))
throw cmd_exception("model is not available");
if (!m_target)

View file

@ -156,8 +156,8 @@ public:
return false;
return m_sort == static_cast<psort_sort const *>(other)->m_sort;
}
void display(std::ostream & out) const override {
out << m_sort->get_name();
std::ostream& display(std::ostream & out) const override {
return out << m_sort->get_name();
}
};
@ -180,8 +180,8 @@ public:
get_num_params() == other->get_num_params() &&
m_idx == static_cast<psort_var const *>(other)->m_idx;
}
void display(std::ostream & out) const override {
out << "s_" << m_idx;
std::ostream& display(std::ostream & out) const override {
return out << "s_" << m_idx;
}
unsigned idx() const { return m_idx; }
};
@ -254,7 +254,7 @@ public:
}
return true;
}
void display(std::ostream & out) const override {
std::ostream& display(std::ostream & out) const override {
if (m_args.empty()) {
out << m_decl->get_name();
}
@ -267,6 +267,7 @@ public:
}
out << ")";
}
return out;
}
};
@ -342,12 +343,12 @@ void display_sort_args(std::ostream & out, unsigned num_params) {
out << ") ";
}
void psort_user_decl::display(std::ostream & out) const {
std::ostream& psort_user_decl::display(std::ostream & out) const {
out << "(declare-sort " << m_name;
display_sort_args(out, m_num_params);
if (m_def)
m_def->display(out);
out << ")";
return out << ")";
}
// -------------------
@ -364,8 +365,8 @@ sort * psort_dt_decl::instantiate(pdecl_manager & m, unsigned n, sort * const *
return m.instantiate_datatype(this, m_name, n, s);
}
void psort_dt_decl::display(std::ostream & out) const {
out << "(datatype-sort " << m_name << ")";
std::ostream& psort_dt_decl::display(std::ostream & out) const {
return out << "(datatype-sort " << m_name << ")";
}
// -------------------
@ -410,8 +411,8 @@ sort * psort_builtin_decl::instantiate(pdecl_manager & m, unsigned n, unsigned c
}
}
void psort_builtin_decl::display(std::ostream & out) const {
out << "(declare-builtin-sort " << m_name << ")";
std::ostream& psort_builtin_decl::display(std::ostream & out) const {
return out << "(declare-builtin-sort " << m_name << ")";
}
void ptype::display(std::ostream & out, pdatatype_decl const * const * dts) const {
@ -615,7 +616,7 @@ sort * pdatatype_decl::instantiate(pdecl_manager & m, unsigned n, sort * const *
}
void pdatatype_decl::display(std::ostream & out) const {
std::ostream& pdatatype_decl::display(std::ostream & out) const {
out << "(declare-datatype " << m_name;
display_sort_args(out, m_num_params);
bool first = true;
@ -631,7 +632,7 @@ void pdatatype_decl::display(std::ostream & out) const {
}
first = false;
}
out << ")";
return out << ")";
}
bool pdatatype_decl::commit(pdecl_manager& m) {
@ -645,9 +646,11 @@ bool pdatatype_decl::commit(pdecl_manager& m) {
datatype_decl * d_ptr = dts.m_buffer[0];
sort_ref_vector sorts(m.m());
bool is_ok = m.get_dt_plugin()->mk_datatypes(1, &d_ptr, m_num_params, ps.data(), sorts);
m.notify_mk_datatype(m_name);
if (is_ok && m_num_params == 0) {
m.notify_new_dt(sorts.get(0), this);
}
return is_ok;
}
@ -722,6 +725,7 @@ void pdecl_manager::notify_datatype(sort *r, psort_decl* p, unsigned n, sort* co
void pdecl_manager::push() {
m_notified_lim.push_back(m_notified_trail.size());
m_datatypes_lim.push_back(m_datatypes_trail.size());
}
void pdecl_manager::pop(unsigned n) {
@ -732,6 +736,16 @@ void pdecl_manager::pop(unsigned n) {
}
m_notified_trail.shrink(new_sz);
m_notified_lim.shrink(m_notified_lim.size() - n);
new_sz = m_datatypes_lim[m_datatypes_lim.size() - n];
if (new_sz != m_datatypes_trail.size()) {
datatype_util util(m());
for (unsigned i = m_datatypes_trail.size(); i-- > new_sz; )
util.plugin().remove(m_datatypes_trail[i]);
}
m_datatypes_trail.shrink(new_sz);
m_datatypes_lim.shrink(m_datatypes_lim.size() - n);
}
bool pdatatypes_decl::instantiate(pdecl_manager & m, sort * const * s) {
@ -751,16 +765,24 @@ bool pdatatypes_decl::commit(pdecl_manager& m) {
sort_ref_vector sorts(m.m());
bool is_ok = m.get_dt_plugin()->mk_datatypes(m_datatypes.size(), dts.m_buffer.data(), 0, nullptr, sorts);
if (is_ok) {
for (pdatatype_decl* d : m_datatypes) {
m.notify_mk_datatype(d->get_name());
}
for (unsigned i = 0; i < m_datatypes.size(); ++i) {
pdatatype_decl* d = m_datatypes[i];
if (d->get_num_params() == 0) {
if (d->get_num_params() == 0)
m.notify_new_dt(sorts.get(i), this);
}
}
}
return is_ok;
}
void pdecl_manager::notify_mk_datatype(symbol const& name) {
m_datatypes_trail.push_back(name);
}
struct pdecl_manager::sort_info {
psort_decl * m_decl;
@ -989,12 +1011,15 @@ void pdecl_manager::del_decl(pdecl * p) {
if (p->is_psort()) {
psort * _p = static_cast<psort*>(p);
if (_p->is_sort_wrapper()) {
m_sort2psort.erase(static_cast<psort_sort*>(_p)->get_sort());
sort* s = static_cast<psort_sort*>(_p)->get_sort();
m_sort2psort.erase(s);
}
else {
m_table.erase(_p);
}
}
del_decl_core(p);
}

View file

@ -45,7 +45,7 @@ public:
unsigned get_id() const { return m_id; }
unsigned get_ref_count() const { return m_ref_count; }
unsigned hash() const { return m_id; }
virtual void display(std::ostream & out) const {}
virtual std::ostream& display(std::ostream & out) const { return out;}
virtual void reset_cache(pdecl_manager& m) {}
};
@ -123,7 +123,7 @@ protected:
~psort_user_decl() override {}
public:
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
void display(std::ostream & out) const override;
std::ostream& display(std::ostream & out) const override;
};
class psort_builtin_decl : public psort_decl {
@ -137,7 +137,7 @@ protected:
public:
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
sort * instantiate(pdecl_manager & m, unsigned n, unsigned const * s) override;
void display(std::ostream & out) const override;
std::ostream& display(std::ostream & out) const override;
};
class psort_dt_decl : public psort_decl {
@ -148,7 +148,7 @@ protected:
~psort_dt_decl() override {}
public:
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
void display(std::ostream & out) const override;
std::ostream& display(std::ostream & out) const override;
};
@ -198,7 +198,7 @@ class paccessor_decl : public pdecl {
ptype const & get_type() const { return m_type; }
~paccessor_decl() override {}
public:
void display(std::ostream & out) const override { pdecl::display(out); }
std::ostream& display(std::ostream & out) const override { pdecl::display(out); return out; }
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
};
@ -219,7 +219,7 @@ class pconstructor_decl : public pdecl {
constructor_decl * instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s);
~pconstructor_decl() override {}
public:
void display(std::ostream & out) const override { pdecl::display(out); }
std::ostream& display(std::ostream & out) const override { pdecl::display(out); return out; }
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
};
@ -237,7 +237,7 @@ class pdatatype_decl : public psort_decl {
~pdatatype_decl() override {}
public:
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
void display(std::ostream & out) const override;
std::ostream& display(std::ostream & out) const override;
bool has_missing_refs(symbol & missing) const;
bool has_duplicate_accessors(symbol & repeated) const;
bool commit(pdecl_manager& m);
@ -289,6 +289,8 @@ class pdecl_manager {
obj_hashtable<sort> m_notified;
ptr_vector<sort> m_notified_trail;
unsigned_vector m_notified_lim;
svector<symbol> m_datatypes_trail;
unsigned_vector m_datatypes_lim;
void init_list();
void del_decl_core(pdecl * p);
@ -319,6 +321,7 @@ public:
sort * instantiate_datatype(psort_decl* p, symbol const& name, unsigned n, sort * const* s);
sort * instantiate(psort * s, unsigned num, sort * const * args);
void notify_datatype(sort *r, psort_decl* p, unsigned n, sort* const* s);
void notify_mk_datatype(symbol const& name);
void push();
void pop(unsigned n);

View file

@ -223,7 +223,7 @@ class lar_solver : public column_namer {
void insert_row_with_changed_bounds(unsigned rid);
void detect_rows_with_changed_bounds_for_column(unsigned j);
void detect_rows_with_changed_bounds();
void set_value_for_nbasic_column(unsigned j, const impq & new_val);
void update_x_and_inf_costs_for_columns_with_changed_bounds();
void update_x_and_inf_costs_for_columns_with_changed_bounds_tableau();
void solve_with_core_solver();
@ -355,6 +355,9 @@ public:
bp.consume(a, witness);
}
}
void set_value_for_nbasic_column(unsigned j, const impq& new_val);
// lp_assert(implied_bound_is_correctly_explained(ib, explanation)); }
constraint_index mk_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side);
void activate_check_on_equal(constraint_index, var_index&);

View file

@ -217,14 +217,14 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_
m_can_enter_basis[j] = true;
this->set_scaled_cost(j);
this->m_lower_bounds[j] = numeric_traits<T>::zero();
this->m_upper_bounds[j] =numeric_traits<T>::one();
this->m_upper_bounds[j] = numeric_traits<T>::one();
break;
}
case column_type::free_column: {
m_can_enter_basis[j] = true;
this->set_scaled_cost(j);
this->m_upper_bounds[j] = free_bound;
this->m_lower_bounds[j] = -free_bound;
this->m_upper_bounds[j] = free_bound;
this->m_lower_bounds[j] = -free_bound;
break;
}
case column_type::boxed:

View file

@ -2013,6 +2013,11 @@ namespace algebraic_numbers {
}
else {
algebraic_cell * c = a.to_algebraic();
if (c->m_i == 0) {
// undefined
c->m_i = upm().get_root_id(c->m_p_sz, c->m_p, lower(c)) + 1;
}
SASSERT(c->m_i > 0);
return c->m_i;
}
}

View file

@ -45,8 +45,8 @@ expr * array_factory::mk_array_interp(sort * s, func_interp * & fi) {
func_decl * f = mk_aux_decl_for_array_sort(m_manager, s);
fi = alloc(func_interp, m_manager, get_array_arity(s));
m_model.register_decl(f, fi);
parameter p[1] = { parameter(f) };
expr * val = m_manager.mk_app(get_family_id(), OP_AS_ARRAY, 1, p);
parameter p(f);
expr * val = m_manager.mk_app(get_family_id(), OP_AS_ARRAY, 1, &p);
register_value(val);
return val;
}

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