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

Merge branch 'master' of https://github.com/z3prover/z3 into polysat

This commit is contained in:
Nikolaj Bjorner 2021-06-18 10:02:33 -07:00
commit 57df45dc16
162 changed files with 2885 additions and 1941 deletions

View file

@ -351,6 +351,7 @@ option(Z3_BUILD_LIBZ3_SHARED "Build libz3 as a shared library if true, otherwise
################################################################################
if (NOT MSVC)
z3_add_cxx_flag("-fvisibility=hidden" REQUIRED)
z3_add_cxx_flag("-fvisibility-inlines-hidden" REQUIRED)
endif()
################################################################################

View file

@ -14,9 +14,9 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z
## Build status
| Azure Pipelines | TravisCI |
| --------------- | -------- |
[![Build Status](https://dev.azure.com/Z3Public/Z3/_apis/build/status/Z3Prover.z3?branchName=master)](https://dev.azure.com/Z3Public/Z3/_build/latest?definitionId=1&branchName=master) | [![Build Status](https://travis-ci.org/Z3Prover/z3.svg?branch=master)](https://travis-ci.org/Z3Prover/z3)
| Azure Pipelines |
| --------------- |
[![Build Status](https://dev.azure.com/Z3Public/Z3/_apis/build/status/Z3Prover.z3?branchName=master)](https://dev.azure.com/Z3Public/Z3/_build/latest?definitionId=1&branchName=master)
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
[2]: #building-z3-using-make-and-gccclang
@ -44,6 +44,8 @@ cd build
nmake
```
Z3 uses C++17. The recommended version of Visual Studio is therefore VS2019.
## Building Z3 using make and GCC/Clang
Execute:

View file

@ -25,7 +25,7 @@ jobs:
- task: EsrpCodeSigning@1
displayName: Sign
inputs:
ConnectedServiceName: 'z3-esrp-signing'
ConnectedServiceName: 'z3-esrp-signing-2'
FolderPath: 'dist/z3-${{parameters.ReleaseVersion}}-${{parameters.BuildArchitecture}}-win/bin'
Pattern: 'Microsoft.Z3.dll,libz3.dll,libz3java.dll,z3.exe'
signConfigType: 'inlineSignParams'

View file

@ -1,136 +0,0 @@
#
# Copyright (c) 2018 Microsoft Corporation
#
# 1. download releases from github
# 2. copy over libz3.dll for the different architectures
# 3. copy over Microsoft.Z3.dll from suitable distribution
# 4. copy nuspec file from packages
# 5. call nuget pack
# 6. sign package
import json
import os
import urllib.request
import zipfile
import sys
import os.path
import shutil
import subprocess
import mk_util
import mk_project
release_data = json.loads(urllib.request.urlopen("https://api.github.com/repos/Z3Prover/z3/releases/latest").read().decode())
release_tag_name = release_data['tag_name']
release_tag_ref_data = json.loads(urllib.request.urlopen("https://api.github.com/repos/Z3Prover/z3/git/refs/tags/%s" % release_tag_name).read().decode())
release_tag_sha = release_tag_ref_data['object']['sha']
#release_tag_data = json.loads(urllib.request.urlopen("https://api.github.com/repos/Z3Prover/z3/commits/%s" % release_tag_sha).read().decode())
release_version = release_tag_name[3:]
release_commit = release_tag_sha # release_tag_data['object']['sha']
print(release_version)
def mk_dir(d):
if not os.path.exists(d):
os.makedirs(d)
def download_installs():
for asset in release_data['assets']:
url = asset['browser_download_url']
name = asset['name']
print("Downloading ", url)
sys.stdout.flush()
urllib.request.urlretrieve(url, "packages/%s" % name)
os_info = {"z64-ubuntu-14" : ('so', 'ubuntu.14.04-x64'),
'ubuntu-16' : ('so', 'ubuntu-x64'),
'x64-win' : ('dll', 'win-x64'),
# Skip x86 as I can't get dotnet build to produce AnyCPU TargetPlatform
# 'x86-win' : ('dll', 'win-x86'),
'osx' : ('dylib', 'osx-x64'),
'debian' : ('so', 'debian.8-x64') }
def classify_package(f):
for os_name in os_info:
if os_name in f:
ext, dst = os_info[os_name]
return os_name, f[:-4], ext, dst
return None
def unpack():
shutil.rmtree("out", ignore_errors=True)
# unzip files in packages
# out
# +- runtimes
# +- win-x64
# +- win-x86
# +- ubuntu.16.04-x64
# +- ubuntu.14.04-x64
# +- debian.8-x64
# +- osx-x64
# +
for f in os.listdir("packages"):
print(f)
if f.endswith(".zip") and classify_package(f):
os_name, package_dir, ext, dst = classify_package(f)
path = os.path.abspath(os.path.join("packages", f))
zip_ref = zipfile.ZipFile(path, 'r')
zip_ref.extract("%s/bin/libz3.%s" % (package_dir, ext), "tmp")
mk_dir("out/runtimes/%s/native" % dst)
shutil.move("tmp/%s/bin/libz3.%s" % (package_dir, ext), "out/runtimes/%s/native/." % dst, "/y")
if "x64-win" in f:
mk_dir("out/lib/netstandard1.4/")
for b in ["Microsoft.Z3.dll"]:
zip_ref.extract("%s/bin/%s" % (package_dir, b), "tmp")
shutil.move("tmp/%s/bin/%s" % (package_dir, b), "out/lib/netstandard1.4/%s" % b)
def mk_targets():
mk_dir("out/build")
shutil.copy("../src/api/dotnet/Microsoft.Z3.targets.in", "out/build/Microsoft.Z3.targets")
def create_nuget_spec():
contents = """<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Microsoft.Z3</id>
<version>{0}</version>
<authors>Microsoft</authors>
<description>
Z3 is a satisfiability modulo theories solver from Microsoft Research.
Linux Dependencies:
libgomp.so.1 installed
</description>
<copyright>&#169; Microsoft Corporation. All rights reserved.</copyright>
<tags>smt constraint solver theorem prover</tags>
<iconUrl>https://raw.githubusercontent.com/Z3Prover/z3/{1}/resources/icon.jpg</iconUrl>
<projectUrl>https://github.com/Z3Prover/z3</projectUrl>
<licenseUrl>https://raw.githubusercontent.com/Z3Prover/z3/{1}/LICENSE.txt</licenseUrl>
<repository
type="git"
url="https://github.com/Z3Prover/z3.git"
branch="master"
commit="{1}"
/>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<language>en</language>
</metadata>
</package>""".format(release_version, release_commit)
with open("out/Microsoft.Z3.nuspec", 'w') as f:
f.write(contents)
def create_nuget_package():
subprocess.call(["nuget", "pack"], cwd="out")
def main():
mk_dir("packages")
download_installs()
unpack()
mk_targets()
create_nuget_spec()
create_nuget_package()
main()

View file

@ -22,14 +22,14 @@ def mk_dir(d):
os.makedirs(d)
os_info = {"z64-ubuntu-14" : ('so', 'ubuntu.14.04-x64'),
'ubuntu-18' : ('so', 'ubuntu-x64'),
'ubuntu-20' : ('so', 'ubuntu-x64'),
'glibc-2.31' : ('so', 'ubuntu-x64'),
os_info = {"z64-ubuntu-14" : ('so', 'linux-x64'),
'ubuntu-18' : ('so', 'linux-x64'),
'ubuntu-20' : ('so', 'linux-x64'),
'glibc-2.31' : ('so', 'linux-x64'),
'x64-win' : ('dll', 'win-x64'),
'x86-win' : ('dll', 'win-x86'),
'osx' : ('dylib', 'osx-x64'),
'debian' : ('so', 'debian.8-x64') }
'debian' : ('so', 'linux-x64') }
def classify_package(f):
for os_name in os_info:
@ -51,7 +51,7 @@ def unpack(packages, symbols):
# +- runtimes
# +- win-x64
# +- win-x86
# +- ubuntu-x64
# +- linux-x64
# +- osx-x64
# +
tmp = "tmp" if not symbols else "tmpsym"

View file

@ -2398,6 +2398,7 @@ def mk_config():
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
if IS_WINDOWS:
CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:c++17'
config.write(
'CC=cl\n'
'CXX=cl\n'
@ -2438,7 +2439,7 @@ def mk_config():
'SLINK_FLAGS=/nologo /LDd\n' % static_opt)
if VS_X64:
config.write(
'CXXFLAGS=/c /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /GS /Gd %s %s\n' % (extra_opt, static_opt))
'CXXFLAGS=/c %s /W3 /WX- /Od /Oy- /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /Gm- /RTC1 %s %s\n' % (CXXFLAGS, extra_opt, static_opt))
config.write(
'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n'
'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt))
@ -2447,7 +2448,7 @@ def mk_config():
exit(1)
else:
config.write(
'CXXFLAGS=/c /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /GS /Gd /arch:SSE2 %s %s\n' % (extra_opt, static_opt))
'CXXFLAGS=/c %s /W3 /WX- /Od /Oy- /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /Gm- /RTC1 /arch:SSE2 %s %s\n' % (CXXFLAGS, extra_opt, static_opt))
config.write(
'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n'
'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt))
@ -2463,7 +2464,7 @@ def mk_config():
extra_opt = '%s /D _TRACE ' % extra_opt
if VS_X64:
config.write(
'CXXFLAGS=/c%s /Zi /nologo /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG /D _LIB /D _WINDOWS /D _UNICODE /D UNICODE /Gm- /EHsc /GS /Gd /GF /Gy /TP %s %s\n' % (GL, extra_opt, static_opt))
'CXXFLAGS=/c%s %s /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D NDEBUG /D _LIB /D UNICODE /Gm- /GF /Gy /TP %s %s\n' % (GL, CXXFLAGS, extra_opt, static_opt))
config.write(
'LINK_EXTRA_FLAGS=/link%s /profile /MACHINE:X64 /SUBSYSTEM:CONSOLE /STACK:8388608 %s\n'
'SLINK_EXTRA_FLAGS=/link%s /profile /MACHINE:X64 /SUBSYSTEM:WINDOWS /STACK:8388608 %s\n' % (LTCG, link_extra_opt, LTCG, link_extra_opt))
@ -2472,7 +2473,7 @@ def mk_config():
exit(1)
else:
config.write(
'CXXFLAGS=/nologo /c%s /Zi /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /GS /Gd /arch:SSE2 %s %s\n' % (GL, extra_opt, static_opt))
'CXXFLAGS=/c%s %s /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D NDEBUG /D _CONSOLE /D ASYNC_COMMANDS /Gm- /arch:SSE2 %s %s\n' % (GL, CXXFLAGS, extra_opt, static_opt))
config.write(
'LINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n'
'SLINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (LTCG, link_extra_opt, LTCG, maybe_disable_dynamic_base, link_extra_opt))
@ -2514,7 +2515,7 @@ def mk_config():
if GIT_HASH:
CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH)
CXXFLAGS = '%s -std=c++17' % CXXFLAGS
CXXFLAGS = '%s -fvisibility=hidden -c' % CXXFLAGS
CXXFLAGS = '%s -fvisibility=hidden -fvisibility-inlines-hidden -c' % CXXFLAGS
FPMATH = test_fpmath(CXX)
CXXFLAGS = '%s %s' % (CXXFLAGS, FPMATH_FLAGS)
if LOG_SYNC:

View file

@ -181,10 +181,10 @@ def exec_cmds(cmds):
def mk_z3(x64):
cmds = []
if x64:
cmds.append('call "%VCINSTALLDIR%vcvarsall.bat" amd64')
cmds.append('call "%VCINSTALLDIR%Auxiliary\\build\\vcvarsall.bat" amd64')
cmds.append('cd %s' % BUILD_X64_DIR)
else:
cmds.append('call "%VCINSTALLDIR%vcvarsall.bat" x86')
cmds.append('call "%VCINSTALLDIR%Auxiliary\\build\\vcvarsall.bat" x86')
cmds.append('cd %s' % BUILD_X86_DIR)
cmds.append('nmake')
if exec_cmds(cmds) != 0:

View file

@ -93,7 +93,7 @@ stages:
- task: CmdLine@2
inputs:
script:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x86 &&
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86 &
python scripts\mk_win_dist.py
--x86-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
@ -116,7 +116,7 @@ stages:
- task: CmdLine@2
inputs:
script:
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=amd64 &&
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 &
python scripts\mk_win_dist.py
--x64-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk

View file

@ -254,7 +254,7 @@ stages:
artifact: 'WindowsBuild-x64'
path: $(Agent.TempDirectory)
- script: cd $(Agent.TempDirectory); mkdir osx-bin; cd osx-bin; unzip ../*osx*.zip
- script: cd $(Agent.TempDirectory); mkdir linux-bin; cd linux-bin; unzip ../*centos*.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
- script: python3 -m pip install --user -U setuptools wheel

View file

@ -66,7 +66,10 @@ public:
}
void display(std::ostream & out) override {
out << "(ackr-model-converter)\n";
out << "(ackr-model-converter";
if (abstr_model)
out << *abstr_model;
out << ")\n";
}
protected:
@ -102,16 +105,13 @@ void ackr_model_converter::convert_constants(model * source, model * destination
func_decl * const c = source->get_constant(i);
app * const term = info->find_term(c);
expr * value = source->get_const_interp(c);
TRACE("ackermannize", tout << mk_ismt2_pp(c, m) << " " << term << "\n";);
if (!term) {
TRACE("ackermannize", tout << mk_ismt2_pp(c, m) << " " << mk_ismt2_pp(term, m) << "\n";);
if (!term)
destination->register_decl(c, value);
}
else if (autil.is_select(term)) {
else if (autil.is_select(term))
add_entry(evaluator, term, value, array_interpretations);
}
else {
else
add_entry(evaluator, term, value, interpretations);
}
}
for (auto & kv : interpretations) {

View file

@ -295,6 +295,8 @@ bool lackr::collect_terms() {
}
if (m_autil.is_as_array(curr, f))
m_non_funs.mark(f, true);
if (m_autil.is_map(curr))
m_non_funs.mark(m_autil.get_map_func_decl(curr), true);
break;
}
case AST_QUANTIFIER:

View file

@ -28,9 +28,7 @@ namespace api {
// TODO: add support for caching expressions -> polynomial and back
public:
pmanager(reslimit& lim) : m_pm(lim, m_nm) {}
~pmanager() {}
polynomial::manager & pm() { return m_pm; }
};
};
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
############################################
# Copyright (c) 2012 Microsoft Corporation
#
#
# Z3 Python interface for Z3 numerals
#
# Author: Leonardo de Moura (leonardo)
@ -12,18 +12,20 @@ from fractions import Fraction
from .z3 import _get_ctx
def _to_numeral(num, ctx=None):
if isinstance(num, Numeral):
return num
else:
return Numeral(num, ctx)
class Numeral:
"""
A Z3 numeral can be used to perform computations over arbitrary
precision integers, rationals and real algebraic numbers.
It also automatically converts python numeric values.
>>> Numeral(2)
2
>>> Numeral("3/2") + 1
@ -35,9 +37,9 @@ class Numeral:
>>> Numeral(Sqrt(2)) + Numeral(Sqrt(3))
3.1462643699?
Z3 numerals can be used to perform computations with
Z3 numerals can be used to perform computations with
values in a Z3 model.
>>> s = Solver()
>>> x = Real('x')
>>> s.add(x*x == 2)
@ -49,34 +51,34 @@ class Numeral:
1.4142135623?
>>> m[x] + 1
1.4142135623? + 1
The previous result is a Z3 expression.
>>> (m[x] + 1).sexpr()
'(+ (root-obj (+ (^ x 2) (- 2)) 2) 1.0)'
>>> Numeral(m[x]) + 1
2.4142135623?
>>> Numeral(m[x]).is_pos()
True
>>> Numeral(m[x])**2
2
We can also isolate the roots of polynomials.
>>> x0, x1, x2 = RealVarVector(3)
>>> r0 = isolate_roots(x0**5 - x0 - 1)
>>> r0
[1.1673039782?]
In the following example, we are isolating the roots
of a univariate polynomial (on x1) obtained after substituting
x0 -> r0[0]
>>> r1 = isolate_roots(x1**2 - x0 + 1, [ r0[0] ])
>>> r1
[-0.4090280898?, 0.4090280898?]
Similarly, in the next example we isolate the roots of
a univariate polynomial (on x2) obtained after substituting
x0 -> r0[0] and x1 -> r1[0]
@ -85,10 +87,11 @@ class Numeral:
[2.8538479564?]
"""
def __init__(self, num, ctx=None):
if isinstance(num, Ast):
self.ast = num
self.ctx = _get_ctx(ctx)
self.ast = num
self.ctx = _get_ctx(ctx)
elif isinstance(num, RatNumRef) or isinstance(num, AlgebraicNumRef):
self.ast = num.ast
self.ctx = num.ctx
@ -102,13 +105,13 @@ class Numeral:
self.ctx = v.ctx
Z3_inc_ref(self.ctx_ref(), self.as_ast())
assert Z3_algebraic_is_value(self.ctx_ref(), self.ast)
def __del__(self):
Z3_dec_ref(self.ctx_ref(), self.as_ast())
def is_integer(self):
""" Return True if the numeral is integer.
>>> Numeral(2).is_integer()
True
>>> (Numeral(Sqrt(2)) * Numeral(Sqrt(2))).is_integer()
@ -129,13 +132,13 @@ class Numeral:
True
>>> Numeral(Sqrt(2)).is_rational()
False
"""
return Z3_get_ast_kind(self.ctx_ref(), self.as_ast()) == Z3_NUMERAL_AST
def denominator(self):
""" Return the denominator if `self` is rational.
>>> Numeral("2/3").denominator()
3
"""
@ -144,14 +147,13 @@ class Numeral:
def numerator(self):
""" Return the numerator if `self` is rational.
>>> Numeral("2/3").numerator()
2
"""
assert(self.is_rational())
return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx)
def is_irrational(self):
""" Return True if the numeral is irrational.
@ -169,7 +171,7 @@ class Numeral:
"""
assert(self.is_integer())
if sys.version_info[0] >= 3:
if sys.version_info.major >= 3:
return int(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
else:
return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
@ -183,9 +185,9 @@ class Numeral:
return Fraction(self.numerator().as_long(), self.denominator().as_long())
def approx(self, precision=10):
"""Return a numeral that approximates the numeral `self`.
The result `r` is such that |r - self| <= 1/10^precision
"""Return a numeral that approximates the numeral `self`.
The result `r` is such that |r - self| <= 1/10^precision
If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2)
@ -199,9 +201,9 @@ class Numeral:
return self.upper(precision)
def upper(self, precision=10):
"""Return a upper bound that approximates the numeral `self`.
The result `r` is such that r - self <= 1/10^precision
"""Return a upper bound that approximates the numeral `self`.
The result `r` is such that r - self <= 1/10^precision
If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2)
@ -218,9 +220,9 @@ class Numeral:
return Numeral(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx)
def lower(self, precision=10):
"""Return a lower bound that approximates the numeral `self`.
The result `r` is such that self - r <= 1/10^precision
"""Return a lower bound that approximates the numeral `self`.
The result `r` is such that self - r <= 1/10^precision
If `self` is rational, then the result is `self`.
>>> x = Numeral(2).root(2)
@ -236,7 +238,7 @@ class Numeral:
def sign(self):
""" Return the sign of the numeral.
>>> Numeral(2).sign()
1
>>> Numeral(-3).sign()
@ -245,10 +247,10 @@ class Numeral:
0
"""
return Z3_algebraic_sign(self.ctx_ref(), self.ast)
def is_pos(self):
""" Return True if the numeral is positive.
>>> Numeral(2).is_pos()
True
>>> Numeral(-3).is_pos()
@ -260,7 +262,7 @@ class Numeral:
def is_neg(self):
""" Return True if the numeral is negative.
>>> Numeral(2).is_neg()
False
>>> Numeral(-3).is_neg()
@ -272,7 +274,7 @@ class Numeral:
def is_zero(self):
""" Return True if the numeral is zero.
>>> Numeral(2).is_zero()
False
>>> Numeral(-3).is_zero()
@ -353,7 +355,7 @@ class Numeral:
def __rdiv__(self, other):
""" Return the numeral `other / self`.
>>> 3 / Numeral(2)
>>> 3 / Numeral(2)
3/2
>>> 3 / Numeral(2).root(2)
2.1213203435?
@ -388,7 +390,7 @@ class Numeral:
3
"""
return Numeral(Z3_algebraic_power(self.ctx_ref(), self.ast, k), self.ctx)
def __pow__(self, k):
""" Return the numeral `self^k`.
@ -415,7 +417,7 @@ class Numeral:
def __rlt__(self, other):
""" Return True if `other < self`.
>>> 2 < Numeral(Sqrt(2))
>>> 2 < Numeral(Sqrt(2))
False
"""
return self > other
@ -440,7 +442,6 @@ class Numeral:
"""
return self < other
def __le__(self, other):
""" Return True if `self <= other`.
@ -456,7 +457,7 @@ class Numeral:
def __rle__(self, other):
""" Return True if `other <= self`.
>>> 2 <= Numeral(Sqrt(2))
>>> 2 <= Numeral(Sqrt(2))
False
"""
return self >= other
@ -523,13 +524,14 @@ class Numeral:
def ctx_ref(self):
return self.ctx.ref()
def eval_sign_at(p, vs):
"""
"""
Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3
Expression containing arithmetic operators: +, -, *, ^k where k is
an integer; and free variables x that is_var(x) is True. Moreover,
all variables must be real.
The result is 1 if the polynomial is positive at the given point,
-1 if negative, and 0 if zero.
@ -547,15 +549,16 @@ def eval_sign_at(p, vs):
_vs[i] = vs[i].ast
return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs)
def isolate_roots(p, vs=[]):
"""
Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the
Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the
roots of the univariate polynomial p(vs[0], ..., vs[len(vs)-1], x_n).
Remarks:
* p is a Z3 expression that contains only arithmetic terms and free variables.
* forall i in [0, n) vs is a numeral.
The result is a list of numerals
>>> x0 = RealVar(0)
@ -573,5 +576,4 @@ def isolate_roots(p, vs=[]):
for i in range(num):
_vs[i] = vs[i].ast
_roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx)
return [ Numeral(r) for r in _roots ]
return [Numeral(r) for r in _roots]

View file

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

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
############################################
# Copyright (c) 2013 Microsoft Corporation
#
#
# Z3 Python interface for Z3 Real Closed Fields
# that may contain
# that may contain
# - computable transcendentals
# - infinitesimals
# - algebraic extensions
@ -12,7 +12,7 @@
from .z3 import *
from .z3core import *
from .z3printer import *
from fractions import Fraction
def _to_rcfnum(num, ctx=None):
if isinstance(num, RCFNum):
@ -20,36 +20,41 @@ def _to_rcfnum(num, ctx=None):
else:
return RCFNum(num, ctx)
def Pi(ctx=None):
ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_pi(ctx.ref()), ctx)
def E(ctx=None):
ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_e(ctx.ref()), ctx)
def MkInfinitesimal(name="eps", ctx=None):
# Todo: remove parameter name.
# For now, we keep it for backward compatibility.
ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_infinitesimal(ctx.ref()), ctx)
def MkRoots(p, ctx=None):
ctx = z3.get_ctx(ctx)
num = len(p)
_tmp = []
_as = (RCFNumObj * num)()
_rs = (RCFNumObj * num)()
_tmp = []
_as = (RCFNumObj * num)()
_rs = (RCFNumObj * num)()
for i in range(num):
_a = _to_rcfnum(p[i], ctx)
_tmp.append(_a) # prevent GC
_tmp.append(_a) # prevent GC
_as[i] = _a.num
nr = Z3_rcf_mk_roots(ctx.ref(), num, _as, _rs)
r = []
r = []
for i in range(nr):
r.append(RCFNum(_rs[i], ctx))
return r
class RCFNum:
def __init__(self, num, ctx=None):
# TODO: add support for converting AST numeral values into RCFNum
@ -65,7 +70,7 @@ class RCFNum:
def ctx_ref(self):
return self.ctx.ref()
def __repr__(self):
return Z3_rcf_num_to_string(self.ctx_ref(), self.num, False, in_html_mode())
@ -112,10 +117,10 @@ class RCFNum:
def __pow__(self, k):
return self.power(k)
def decimal(self, prec=5):
return Z3_rcf_num_to_decimal_string(self.ctx_ref(), self.num, prec)
def __lt__(self, other):
v = _to_rcfnum(other, self.ctx)
return Z3_rcf_lt(self.ctx_ref(), self.num, v.num)

View file

@ -1,6 +1,6 @@
############################################
# Copyright (c) 2012 Microsoft Corporation
#
#
# Z3 Python interface
#
# Author: Leonardo de Moura (leonardo)
@ -8,123 +8,234 @@
import ctypes
class Z3Exception(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return str(self.value)
class ContextObj(ctypes.c_void_p):
def __init__(self, context): self._as_parameter_ = context
def from_param(obj): return obj
def __init__(self, context):
self._as_parameter_ = context
def from_param(obj):
return obj
class Config(ctypes.c_void_p):
def __init__(self, config): self._as_parameter_ = config
def from_param(obj): return obj
def __init__(self, config):
self._as_parameter_ = config
def from_param(obj):
return obj
class Symbol(ctypes.c_void_p):
def __init__(self, symbol): self._as_parameter_ = symbol
def from_param(obj): return obj
def __init__(self, symbol):
self._as_parameter_ = symbol
def from_param(obj):
return obj
class Sort(ctypes.c_void_p):
def __init__(self, sort): self._as_parameter_ = sort
def from_param(obj): return obj
def __init__(self, sort):
self._as_parameter_ = sort
def from_param(obj):
return obj
class FuncDecl(ctypes.c_void_p):
def __init__(self, decl): self._as_parameter_ = decl
def from_param(obj): return obj
def __init__(self, decl):
self._as_parameter_ = decl
def from_param(obj):
return obj
class Ast(ctypes.c_void_p):
def __init__(self, ast): self._as_parameter_ = ast
def from_param(obj): return obj
def __init__(self, ast):
self._as_parameter_ = ast
def from_param(obj):
return obj
class Pattern(ctypes.c_void_p):
def __init__(self, pattern): self._as_parameter_ = pattern
def from_param(obj): return obj
def __init__(self, pattern):
self._as_parameter_ = pattern
def from_param(obj):
return obj
class Model(ctypes.c_void_p):
def __init__(self, model): self._as_parameter_ = model
def from_param(obj): return obj
def __init__(self, model):
self._as_parameter_ = model
def from_param(obj):
return obj
class Literals(ctypes.c_void_p):
def __init__(self, literals): self._as_parameter_ = literals
def from_param(obj): return obj
def __init__(self, literals):
self._as_parameter_ = literals
def from_param(obj):
return obj
class Constructor(ctypes.c_void_p):
def __init__(self, constructor): self._as_parameter_ = constructor
def from_param(obj): return obj
def __init__(self, constructor):
self._as_parameter_ = constructor
def from_param(obj):
return obj
class ConstructorList(ctypes.c_void_p):
def __init__(self, constructor_list): self._as_parameter_ = constructor_list
def from_param(obj): return obj
def __init__(self, constructor_list):
self._as_parameter_ = constructor_list
def from_param(obj):
return obj
class GoalObj(ctypes.c_void_p):
def __init__(self, goal): self._as_parameter_ = goal
def from_param(obj): return obj
def __init__(self, goal):
self._as_parameter_ = goal
def from_param(obj):
return obj
class TacticObj(ctypes.c_void_p):
def __init__(self, tactic): self._as_parameter_ = tactic
def from_param(obj): return obj
def __init__(self, tactic):
self._as_parameter_ = tactic
def from_param(obj):
return obj
class ProbeObj(ctypes.c_void_p):
def __init__(self, probe): self._as_parameter_ = probe
def from_param(obj): return obj
def __init__(self, probe):
self._as_parameter_ = probe
def from_param(obj):
return obj
class ApplyResultObj(ctypes.c_void_p):
def __init__(self, obj): self._as_parameter_ = obj
def from_param(obj): return obj
def __init__(self, obj):
self._as_parameter_ = obj
def from_param(obj):
return obj
class StatsObj(ctypes.c_void_p):
def __init__(self, statistics): self._as_parameter_ = statistics
def from_param(obj): return obj
def __init__(self, statistics):
self._as_parameter_ = statistics
def from_param(obj):
return obj
class SolverObj(ctypes.c_void_p):
def __init__(self, solver): self._as_parameter_ = solver
def from_param(obj): return obj
def __init__(self, solver):
self._as_parameter_ = solver
def from_param(obj):
return obj
class SolverCallbackObj(ctypes.c_void_p):
def __init__(self, solver): self._as_parameter_ = solver
def from_param(obj): return obj
def __init__(self, solver):
self._as_parameter_ = solver
def from_param(obj):
return obj
class FixedpointObj(ctypes.c_void_p):
def __init__(self, fixedpoint): self._as_parameter_ = fixedpoint
def from_param(obj): return obj
def __init__(self, fixedpoint):
self._as_parameter_ = fixedpoint
def from_param(obj):
return obj
class OptimizeObj(ctypes.c_void_p):
def __init__(self, optimize): self._as_parameter_ = optimize
def from_param(obj): return obj
def __init__(self, optimize):
self._as_parameter_ = optimize
def from_param(obj):
return obj
class ModelObj(ctypes.c_void_p):
def __init__(self, model): self._as_parameter_ = model
def from_param(obj): return obj
def __init__(self, model):
self._as_parameter_ = model
def from_param(obj):
return obj
class AstVectorObj(ctypes.c_void_p):
def __init__(self, vector): self._as_parameter_ = vector
def from_param(obj): return obj
def __init__(self, vector):
self._as_parameter_ = vector
def from_param(obj):
return obj
class AstMapObj(ctypes.c_void_p):
def __init__(self, ast_map): self._as_parameter_ = ast_map
def from_param(obj): return obj
def __init__(self, ast_map):
self._as_parameter_ = ast_map
def from_param(obj):
return obj
class Params(ctypes.c_void_p):
def __init__(self, params): self._as_parameter_ = params
def from_param(obj): return obj
def __init__(self, params):
self._as_parameter_ = params
def from_param(obj):
return obj
class ParamDescrs(ctypes.c_void_p):
def __init__(self, paramdescrs): self._as_parameter_ = paramdescrs
def from_param(obj): return obj
def __init__(self, paramdescrs):
self._as_parameter_ = paramdescrs
def from_param(obj):
return obj
class FuncInterpObj(ctypes.c_void_p):
def __init__(self, f): self._as_parameter_ = f
def from_param(obj): return obj
def __init__(self, f):
self._as_parameter_ = f
def from_param(obj):
return obj
class FuncEntryObj(ctypes.c_void_p):
def __init__(self, e): self._as_parameter_ = e
def from_param(obj): return obj
def __init__(self, e):
self._as_parameter_ = e
def from_param(obj):
return obj
class RCFNumObj(ctypes.c_void_p):
def __init__(self, e): self._as_parameter_ = e
def from_param(obj): return obj
def __init__(self, e):
self._as_parameter_ = e
def from_param(obj):
return obj

View file

@ -1,21 +1,22 @@
############################################
# Copyright (c) 2012 Microsoft Corporation
#
#
# Z3 Python interface
#
# Authors: Leonardo de Moura (leonardo)
# ThanhVu (Vu) Nguyen <tnguyen@cs.unm.edu>
############################################
"""
Usage:
Usage:
import common_z3 as CM_Z3
"""
import ctypes
from .z3 import *
def vset(seq, idfun=None, as_list=True):
# This functions preserves the order of arguments while removing duplicates.
# This functions preserves the order of arguments while removing duplicates.
# This function is from https://code.google.com/p/common-python-vu/source/browse/vu_common.py
# (Thanhu's personal code). It has been copied here to avoid a dependency on vu_common.py.
"""
@ -24,36 +25,36 @@ def vset(seq, idfun=None, as_list=True):
>>> vset([[11,2],1, [10,['9',1]],2, 1, [11,2],[3,3],[10,99],1,[10,['9',1]]],idfun=repr)
[[11, 2], 1, [10, ['9', 1]], 2, [3, 3], [10, 99]]
"""
def _uniq_normal(seq):
d_ = {}
for s in seq:
if s not in d_:
d_[s] = None
yield s
def _uniq_idfun(seq,idfun):
def _uniq_idfun(seq, idfun):
d_ = {}
for s in seq:
h_ = idfun(s)
if h_ not in d_:
d_[h_] = None
yield s
if idfun is None:
res = _uniq_normal(seq)
else:
res = _uniq_idfun(seq,idfun)
return list(res) if as_list else res
else:
res = _uniq_idfun(seq, idfun)
return list(res) if as_list else res
def get_z3_version(as_str=False):
major = ctypes.c_uint(0)
minor = ctypes.c_uint(0)
build = ctypes.c_uint(0)
rev = ctypes.c_uint(0)
Z3_get_version(major,minor, build, rev)
rev = ctypes.c_uint(0)
Z3_get_version(major, minor, build, rev)
rs = map(int, (major.value, minor.value, build.value, rev.value))
if as_str:
return "{}.{}.{}.{}".format(*rs)
@ -64,9 +65,9 @@ def get_z3_version(as_str=False):
def ehash(v):
"""
Returns a 'stronger' hash value than the default hash() method.
The result from hash() is not enough to distinguish between 2
The result from hash() is not enough to distinguish between 2
z3 expressions in some cases.
Note: the following doctests will fail with Python 2.x as the
default formatting doesn't match that of 3.x.
>>> x1 = Bool('x'); x2 = Bool('x'); x3 = Int('x')
@ -74,7 +75,7 @@ def ehash(v):
783810685 783810685 783810685
>>> print(ehash(x1), ehash(x2), ehash(x3))
x_783810685_1 x_783810685_1 x_783810685_2
"""
if z3_debug():
assert is_expr(v)
@ -83,10 +84,11 @@ def ehash(v):
"""
In Z3, variables are called *uninterpreted* consts and
In Z3, variables are called *uninterpreted* consts and
variables are *interpreted* consts.
"""
def is_expr_var(v):
"""
EXAMPLES:
@ -111,7 +113,8 @@ def is_expr_var(v):
True
"""
return is_const(v) and v.decl().kind()==Z3_OP_UNINTERPRETED
return is_const(v) and v.decl().kind() == Z3_OP_UNINTERPRETED
def is_expr_val(v):
"""
@ -135,13 +138,11 @@ def is_expr_val(v):
False
>>> is_expr_val(SafetyInjection)
False
"""
return is_const(v) and v.decl().kind()!=Z3_OP_UNINTERPRETED
"""
return is_const(v) and v.decl().kind() != Z3_OP_UNINTERPRETED
def get_vars(f, rs = None):
def get_vars(f, rs=None):
"""
>>> x,y = Ints('x y')
>>> a,b = Bools('a b')
@ -151,15 +152,15 @@ def get_vars(f, rs = None):
"""
if rs is None:
rs = []
if z3_debug():
assert is_expr(f)
if is_const(f):
if is_expr_val(f):
return rs
else: #variable
return vset(rs + [f],str)
else: # variable
return vset(rs + [f], str)
else:
for f_ in f.children():
@ -168,7 +169,6 @@ def get_vars(f, rs = None):
return vset(rs, str)
def mk_var(name, vsort):
if vsort.kind() == Z3_INT_SORT:
v = Int(name)
@ -179,13 +179,12 @@ def mk_var(name, vsort):
elif vsort.kind() == Z3_DATATYPE_SORT:
v = Const(name, vsort)
else:
raise TypeError('Cannot handle this sort (s: %sid: %d)' %(vsort,vsort.kind()))
raise TypeError("Cannot handle this sort (s: %sid: %d)" % (vsort, vsort.kind()))
return v
def prove(claim,assume=None,verbose=0):
def prove(claim, assume=None, verbose=0):
"""
>>> r,m = prove(BoolVal(True),verbose=0); r,model_str(m,as_str=False)
(True, None)
@ -204,11 +203,11 @@ def prove(claim,assume=None,verbose=0):
AssertionError: Assumption is always False!
>>> r,m = prove(Implies(x,x),assume=y,verbose=2); r,model_str(m,as_str=False)
assume:
assume:
y
claim:
claim:
Implies(x, x)
to_prove:
to_prove:
Implies(y, Implies(x, x))
(True, None)
@ -236,52 +235,52 @@ def prove(claim,assume=None,verbose=0):
to_prove = claim
if assume:
if z3_debug():
is_proved,_ = prove(Not(assume))
is_proved, _ = prove(Not(assume))
def _f():
emsg = "Assumption is always False!"
if verbose >= 2:
emsg = "{}\n{}".format(assume,emsg)
emsg = "{}\n{}".format(assume, emsg)
return emsg
assert is_proved==False, _f()
assert is_proved is False, _f()
to_prove = Implies(assume,to_prove)
to_prove = Implies(assume, to_prove)
if verbose >= 2:
print('assume: ')
print("assume: ")
print(assume)
print('claim: ')
print("claim: ")
print(claim)
print('to_prove: ')
print("to_prove: ")
print(to_prove)
f = Not(to_prove)
models = get_models(f,k=1)
if models is None: #unknown
print('E: cannot solve !')
models = get_models(f, k=1)
if models is None: # unknown
print("E: cannot solve !")
return None, None
elif models == False: #unsat
return True,None
else: #sat
elif models is False: # unsat
return True, None
else: # sat
if z3_debug():
assert isinstance(models,list)
assert isinstance(models, list)
if models:
return False, models[0] #the first counterexample
return False, models[0] # the first counterexample
else:
return False, [] #infinite counterexample,models
return False, [] # infinite counterexample,models
def get_models(f,k):
def get_models(f, k):
"""
Returns the first k models satisfiying f.
If f is not satisfiable, returns False.
If f cannot be solved, returns None
If f is satisfiable, returns the first k models
Note that if f is a tautology, e.g.\ True, then the result is []
Note that if f is a tautology, e.g.\\ True, then the result is []
Based on http://stackoverflow.com/questions/11867611/z3py-checking-all-solutions-for-equation
EXAMPLES:
@ -314,7 +313,7 @@ def get_models(f,k):
if z3_debug():
assert is_expr(f)
assert k >= 1
s = Solver()
s.add(f)
@ -323,16 +322,14 @@ def get_models(f,k):
while s.check() == sat and i < k:
i = i + 1
m = s.model()
if not m: #if m == []
if not m: # if m == []
break
models.append(m)
#create new constraint to block the current model
# create new constraint to block the current model
block = Not(And([v() == m[v] for v in m]))
s.add(block)
if s.check() == unknown:
return None
elif s.check() == unsat and i == 0:
@ -340,7 +337,8 @@ def get_models(f,k):
else:
return models
def is_tautology(claim,verbose=0):
def is_tautology(claim, verbose=0):
"""
>>> is_tautology(Implies(Bool('x'),Bool('x')))
True
@ -355,38 +353,38 @@ def is_tautology(claim,verbose=0):
False
"""
return prove(claim=claim,assume=None,verbose=verbose)[0]
return prove(claim=claim, assume=None, verbose=verbose)[0]
def is_contradiction(claim,verbose=0):
def is_contradiction(claim, verbose=0):
"""
>>> x,y=Bools('x y')
>>> is_contradiction(BoolVal(False))
True
>>> is_contradiction(BoolVal(True))
False
>>> is_contradiction(x)
False
>>> is_contradiction(Implies(x,y))
False
>>> is_contradiction(Implies(x,x))
False
>>> is_contradiction(And(x,Not(x)))
True
"""
return prove(claim=Not(claim),assume=None,verbose=verbose)[0]
return prove(claim=Not(claim), assume=None, verbose=verbose)[0]
def exact_one_model(f):
"""
return True if f has exactly 1 model, False otherwise.
EXAMPLES:
>>> x, y = Ints('x y')
@ -403,30 +401,29 @@ def exact_one_model(f):
False
"""
models = get_models(f,k=2)
if isinstance(models,list):
return len(models)==1
models = get_models(f, k=2)
if isinstance(models, list):
return len(models) == 1
else:
return False
def myBinOp(op,*L):
def myBinOp(op, *L):
"""
>>> myAnd(*[Bool('x'),Bool('y')])
And(x, y)
>>> myAnd(*[Bool('x'),None])
x
>>> myAnd(*[Bool('x')])
x
>>> myAnd(*[])
>>> myAnd(Bool('x'),Bool('y'))
And(x, y)
>>> myAnd(*[Bool('x'),Bool('y')])
And(x, y)
@ -435,7 +432,7 @@ def myBinOp(op,*L):
>>> myAnd((Bool('x'),Bool('y')))
And(x, y)
>>> myAnd(*[Bool('x'),Bool('y'),True])
Traceback (most recent call last):
...
@ -444,59 +441,62 @@ def myBinOp(op,*L):
if z3_debug():
assert op == Z3_OP_OR or op == Z3_OP_AND or op == Z3_OP_IMPLIES
if len(L)==1 and (isinstance(L[0],list) or isinstance(L[0],tuple)):
if len(L) == 1 and (isinstance(L[0], list) or isinstance(L[0], tuple)):
L = L[0]
if z3_debug():
assert all(not isinstance(l,bool) for l in L)
assert all(not isinstance(val, bool) for val in L)
L = [l for l in L if is_expr(l)]
L = [val for val in L if is_expr(val)]
if L:
if len(L)==1:
if len(L) == 1:
return L[0]
if op == Z3_OP_OR:
if op == Z3_OP_OR:
return Or(L)
if op == Z3_OP_AND:
return And(L)
return Implies(L[0],L[1])
return And(L)
return Implies(L[0], L[1])
else:
return None
def myAnd(*L):
return myBinOp(Z3_OP_AND,*L)
return myBinOp(Z3_OP_AND, *L)
def myOr(*L):
return myBinOp(Z3_OP_OR,*L)
return myBinOp(Z3_OP_OR, *L)
def myImplies(a,b):
return myBinOp(Z3_OP_IMPLIES,[a,b])
Iff = lambda f: And(Implies(f[0],f[1]),Implies(f[1],f[0]))
def myImplies(a, b):
return myBinOp(Z3_OP_IMPLIES, [a, b])
def model_str(m,as_str=True):
def Iff(f):
return And(Implies(f[0], f[1]), Implies(f[1], f[0]))
def model_str(m, as_str=True):
"""
Returned a 'sorted' model (so that it's easier to see)
The model is sorted by its key,
e.g. if the model is y = 3 , x = 10, then the result is
The model is sorted by its key,
e.g. if the model is y = 3 , x = 10, then the result is
x = 10, y = 3
EXAMPLES:
see doctest exampels from function prove()
see doctest exampels from function prove()
"""
if z3_debug():
assert m is None or m == [] or isinstance(m,ModelRef)
assert m is None or m == [] or isinstance(m, ModelRef)
if m :
vs = [(v,m[v]) for v in m]
vs = sorted(vs,key=lambda a,_: str(a))
if m:
vs = [(v, m[v]) for v in m]
vs = sorted(vs, key=lambda a, _: str(a))
if as_str:
return '\n'.join(['{} = {}'.format(k,v) for (k,v) in vs])
return "\n".join(["{} = {}".format(k, v) for (k, v) in vs])
else:
return vs
else:
return str(m) if as_str else m

View file

@ -433,6 +433,7 @@ public:
app * mk_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(arith_family_id, OP_ADD, arg1, arg2); }
app * mk_add(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(arith_family_id, OP_ADD, arg1, arg2, arg3); }
app * mk_add(expr_ref_vector const& args) const { return mk_add(args.size(), args.data()); }
app * mk_add(expr_ref_buffer const& args) const { return mk_add(args.size(), args.data()); }
app * mk_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(arith_family_id, OP_SUB, arg1, arg2); }
app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(arith_family_id, OP_SUB, num_args, args); }

View file

@ -38,39 +38,27 @@ Revision History:
// -----------------------------------
parameter::~parameter() {
if (m_kind == PARAM_RATIONAL) {
dealloc(m_rational);
if (auto p = std::get_if<rational*>(&m_val)) {
dealloc(*p);
}
if (m_kind == PARAM_ZSTRING) {
dealloc(m_zstring);
if (auto p = std::get_if<zstring*>(&m_val)) {
dealloc(*p);
}
}
parameter::parameter(parameter const& other) {
m_kind = PARAM_INT;
m_int = 0;
*this = other;
}
parameter& parameter::operator=(parameter const& other) {
if (this == &other) {
return *this;
}
if (m_kind == PARAM_RATIONAL) {
dealloc(m_rational);
this->~parameter();
m_val = other.m_val;
if (auto p = std::get_if<rational*>(&m_val)) {
m_val = alloc(rational, **p);
}
m_kind = other.m_kind;
switch(other.m_kind) {
case PARAM_INT: m_int = other.get_int(); break;
case PARAM_AST: m_ast = other.get_ast(); break;
case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
case PARAM_RATIONAL: m_rational = alloc(rational, other.get_rational()); break;
case PARAM_DOUBLE: m_dval = other.m_dval; break;
case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
case PARAM_ZSTRING: m_zstring = alloc(zstring, other.get_zstring()); break;
default:
UNREACHABLE();
break;
if (auto p = std::get_if<zstring*>(&m_val)) {
m_val = alloc(zstring, **p);
}
return *this;
}
@ -95,45 +83,40 @@ void parameter::del_eh(ast_manager & m, family_id fid) {
}
bool parameter::operator==(parameter const & p) const {
if (m_kind != p.m_kind) return false;
switch(m_kind) {
case PARAM_INT: return m_int == p.m_int;
case PARAM_AST: return m_ast == p.m_ast;
case PARAM_SYMBOL: return get_symbol() == p.get_symbol();
if (get_kind() != p.get_kind()) return false;
switch (get_kind()) {
case PARAM_RATIONAL: return get_rational() == p.get_rational();
case PARAM_DOUBLE: return m_dval == p.m_dval;
case PARAM_EXTERNAL: return m_ext_id == p.m_ext_id;
case PARAM_ZSTRING: return get_zstring() == p.get_zstring();
default: UNREACHABLE(); return false;
default: return m_val == p.m_val;
}
}
unsigned parameter::hash() const {
unsigned b = 0;
switch(m_kind) {
case PARAM_INT: b = m_int; break;
case PARAM_AST: b = m_ast->hash(); break;
switch (get_kind()) {
case PARAM_INT: b = get_int(); break;
case PARAM_AST: b = get_ast()->hash(); break;
case PARAM_SYMBOL: b = get_symbol().hash(); break;
case PARAM_RATIONAL: b = get_rational().hash(); break;
case PARAM_DOUBLE: b = static_cast<unsigned>(m_dval); break;
case PARAM_DOUBLE: b = static_cast<unsigned>(get_double()); break;
case PARAM_ZSTRING: b = get_zstring().hash(); break;
case PARAM_EXTERNAL: b = m_ext_id; break;
case PARAM_EXTERNAL: b = get_ext_id(); break;
}
return (b << 2) | m_kind;
return b;
}
std::ostream& parameter::display(std::ostream& out) const {
switch(m_kind) {
switch (get_kind()) {
case PARAM_INT: return out << get_int();
case PARAM_SYMBOL: return out << get_symbol();
case PARAM_RATIONAL: return out << get_rational();
case PARAM_AST: return out << "#" << get_ast()->get_id();
case PARAM_DOUBLE: return out << m_dval;
case PARAM_EXTERNAL: return out << "@" << m_ext_id;
case PARAM_AST: return out << '#' << get_ast()->get_id();
case PARAM_DOUBLE: return out << get_double();
case PARAM_EXTERNAL: return out << '@' << get_ext_id();
case PARAM_ZSTRING: return out << get_zstring();
default:
UNREACHABLE();
return out << "[invalid parameter]";
return out;
}
}
@ -191,14 +174,6 @@ decl_info::decl_info(family_id family_id, decl_kind k, unsigned num_parameters,
m_private_parameters(private_params) {
}
decl_info::decl_info(decl_info const& other) :
m_family_id(other.m_family_id),
m_kind(other.m_kind),
m_parameters(other.m_parameters.size(), other.m_parameters.data()),
m_private_parameters(other.m_private_parameters) {
}
void decl_info::init_eh(ast_manager & m) {
for (parameter & p : m_parameters) {
p.init_eh(m);

View file

@ -47,6 +47,7 @@ Revision History:
#include "util/z3_exception.h"
#include "util/dependency.h"
#include "util/rlimit.h"
#include <variant>
#define RECYCLE_FREE_AST_INDICES
@ -97,6 +98,7 @@ const family_id arith_family_id = 5;
*/
class parameter {
public:
// NOTE: these must be in the same order as the entries in the variant below
enum kind_t {
PARAM_INT,
PARAM_AST,
@ -113,63 +115,50 @@ public:
PARAM_EXTERNAL
};
private:
kind_t m_kind;
// It is not possible to use tag pointers, since symbols are already tagged.
union {
int m_int; // for PARAM_INT
ast* m_ast; // for PARAM_AST
symbol m_symbol; // for PARAM_SYMBOL
rational* m_rational; // for PARAM_RATIONAL
zstring* m_zstring; // for PARAM_ZSTRING
double m_dval; // for PARAM_DOUBLE (remark: this is not used in float_decl_plugin)
unsigned m_ext_id; // for PARAM_EXTERNAL
};
std::variant<
int, // for PARAM_INT
ast*, // for PARAM_AST
symbol, // for PARAM_SYMBOL
zstring*, // for PARAM_ZSTRING
rational*, // for PARAM_RATIONAL
double, // for PARAM_DOUBLE (remark: this is not used in float_decl_plugin)
unsigned // for PARAM_EXTERNAL
> m_val;
public:
parameter(): m_kind(PARAM_INT), m_int(0) {}
explicit parameter(int val): m_kind(PARAM_INT), m_int(val) {}
explicit parameter(unsigned val): m_kind(PARAM_INT), m_int(val) {}
explicit parameter(ast * p): m_kind(PARAM_AST), m_ast(p) {}
explicit parameter(symbol const & s): m_kind(PARAM_SYMBOL), m_symbol(s) {}
explicit parameter(rational const & r): m_kind(PARAM_RATIONAL), m_rational(alloc(rational, r)) {}
explicit parameter(rational && r) : m_kind(PARAM_RATIONAL), m_rational(alloc(rational, std::move(r))) {}
explicit parameter(zstring const& s): m_kind(PARAM_ZSTRING), m_zstring(alloc(zstring, s)) {}
explicit parameter(zstring && s): m_kind(PARAM_ZSTRING), m_zstring(alloc(zstring, std::move(s))) {}
explicit parameter(double d):m_kind(PARAM_DOUBLE), m_dval(d) {}
explicit parameter(const char *s):m_kind(PARAM_SYMBOL), m_symbol(symbol(s)) {}
explicit parameter(const std::string &s):m_kind(PARAM_SYMBOL), m_symbol(symbol(s)) {}
explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}
parameter(parameter const&);
parameter() : m_val(0) {}
explicit parameter(int val): m_val(val) {}
explicit parameter(unsigned val): m_val((int)val) {}
explicit parameter(ast * p): m_val(p) {}
explicit parameter(symbol const & s): m_val(s) {}
explicit parameter(rational const & r): m_val(alloc(rational, r)) {}
explicit parameter(rational && r) : m_val(alloc(rational, std::move(r))) {}
explicit parameter(zstring const& s): m_val(alloc(zstring, s)) {}
explicit parameter(zstring && s): m_val(alloc(zstring, std::move(s))) {}
explicit parameter(double d): m_val(d) {}
explicit parameter(const char *s): m_val(symbol(s)) {}
explicit parameter(const std::string &s): m_val(symbol(s)) {}
explicit parameter(unsigned ext_id, bool): m_val(ext_id) {}
parameter(parameter const& other) { *this = other; }
parameter(parameter && other) noexcept : m_kind(other.m_kind) {
switch (other.m_kind) {
case PARAM_INT: m_int = other.get_int(); break;
case PARAM_AST: m_ast = other.get_ast(); break;
case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
case PARAM_RATIONAL: m_rational = nullptr; std::swap(m_rational, other.m_rational); break;
case PARAM_DOUBLE: m_dval = other.m_dval; break;
case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
case PARAM_ZSTRING: m_zstring = other.m_zstring; break;
default:
UNREACHABLE();
break;
}
parameter(parameter && other) noexcept : m_val(std::move(other.m_val)) {
other.m_val = 0;
}
~parameter();
parameter& operator=(parameter const& other);
kind_t get_kind() const { return m_kind; }
bool is_int() const { return m_kind == PARAM_INT; }
bool is_ast() const { return m_kind == PARAM_AST; }
bool is_symbol() const { return m_kind == PARAM_SYMBOL; }
bool is_rational() const { return m_kind == PARAM_RATIONAL; }
bool is_double() const { return m_kind == PARAM_DOUBLE; }
bool is_external() const { return m_kind == PARAM_EXTERNAL; }
bool is_zstring() const { return m_kind == PARAM_ZSTRING; }
kind_t get_kind() const { return static_cast<kind_t>(m_val.index()); }
bool is_int() const { return get_kind() == PARAM_INT; }
bool is_ast() const { return get_kind() == PARAM_AST; }
bool is_symbol() const { return get_kind() == PARAM_SYMBOL; }
bool is_rational() const { return get_kind() == PARAM_RATIONAL; }
bool is_double() const { return get_kind() == PARAM_DOUBLE; }
bool is_external() const { return get_kind() == PARAM_EXTERNAL; }
bool is_zstring() const { return get_kind() == PARAM_ZSTRING; }
bool is_int(int & i) const { return is_int() && (i = get_int(), true); }
bool is_ast(ast * & a) const { return is_ast() && (a = get_ast(), true); }
@ -191,13 +180,13 @@ public:
*/
void del_eh(ast_manager & m, family_id fid);
int get_int() const { SASSERT(is_int()); return m_int; }
ast * get_ast() const { SASSERT(is_ast()); return m_ast; }
symbol get_symbol() const { SASSERT(is_symbol()); return m_symbol; }
rational const & get_rational() const { SASSERT(is_rational()); return *m_rational; }
zstring const& get_zstring() const { SASSERT(is_zstring()); return *m_zstring; }
double get_double() const { SASSERT(is_double()); return m_dval; }
unsigned get_ext_id() const { SASSERT(is_external()); return m_ext_id; }
int get_int() const { return std::get<int>(m_val); }
ast * get_ast() const { return std::get<ast*>(m_val); }
symbol get_symbol() const { return std::get<symbol>(m_val); }
rational const & get_rational() const { return *std::get<rational*>(m_val); }
zstring const& get_zstring() const { return *std::get<zstring*>(m_val); }
double get_double() const { return std::get<double>(m_val); }
unsigned get_ext_id() const { return std::get<unsigned>(m_val); }
bool operator==(parameter const & p) const;
bool operator!=(parameter const & p) const { return !operator==(p); }
@ -225,12 +214,10 @@ void display_parameters(std::ostream & out, unsigned n, parameter const * p);
between symbols (family names) and the unique IDs.
*/
class family_manager {
family_id m_next_id;
family_id m_next_id = 0;
symbol_table<family_id> m_families;
svector<symbol> m_names;
public:
family_manager():m_next_id(0) {}
/**
\brief Return the family_id for s, a new id is created if !has_family(s)
@ -280,8 +267,6 @@ public:
decl_info(family_id family_id = null_family_id, decl_kind k = null_decl_kind,
unsigned num_parameters = 0, parameter const * parameters = nullptr, bool private_params = false);
decl_info(decl_info const& other);
void init_eh(ast_manager & m);
void del_eh(ast_manager & m);
@ -381,8 +366,7 @@ public:
unsigned num_parameters = 0, parameter const * parameters = nullptr, bool private_parameters = false):
decl_info(family_id, k, num_parameters, parameters, private_parameters), m_num_elements(num_elements) {
}
sort_info(sort_info const& other) : decl_info(other), m_num_elements(other.m_num_elements) {
}
sort_info(decl_info const& di, sort_size const& num_elements) :
decl_info(di), m_num_elements(num_elements) {}
@ -1010,8 +994,8 @@ struct builtin_name {
*/
class decl_plugin {
protected:
ast_manager * m_manager;
family_id m_family_id;
ast_manager * m_manager = nullptr;
family_id m_family_id = null_family_id;
virtual void set_manager(ast_manager * m, family_id id) {
SASSERT(m_manager == nullptr);
@ -1035,8 +1019,6 @@ protected:
friend class ast_manager;
public:
decl_plugin():m_manager(nullptr), m_family_id(null_family_id) {}
virtual ~decl_plugin() {}
virtual void finalize() {}
@ -1365,8 +1347,6 @@ class user_sort_plugin : public decl_plugin {
svector<symbol> m_sort_names;
dictionary<int> m_name2decl_kind;
public:
user_sort_plugin() {}
sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override;
func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range) override;
@ -2461,7 +2441,6 @@ typedef obj_mark<expr> expr_mark;
class expr_sparse_mark {
obj_hashtable<expr> m_marked;
public:
expr_sparse_mark() {}
bool is_marked(expr * n) const { return m_marked.contains(n); }
void mark(expr * n) { m_marked.insert(n); }
void mark(expr * n, bool flag) { if (flag) m_marked.insert(n); else m_marked.erase(n); }
@ -2472,7 +2451,6 @@ template<unsigned IDX>
class ast_fast_mark {
ptr_buffer<ast> m_to_unmark;
public:
ast_fast_mark() {}
~ast_fast_mark() {
reset();
}
@ -2614,7 +2592,6 @@ class scoped_mark : public ast_mark {
unsigned_vector m_lim;
public:
scoped_mark(ast_manager& m): m_stack(m) {}
~scoped_mark() override {}
void mark(ast * n, bool flag) override;
void reset() override;
void mark(ast * n);
@ -2655,7 +2632,3 @@ struct parameter_pp {
inline std::ostream& operator<<(std::ostream& out, parameter_pp const& pp) {
return pp.m.display(out, pp.p);
}

View file

@ -1082,6 +1082,14 @@ namespace datatype {
return r;
}
bool util::is_recursive_array(sort* a) {
array_util autil(m);
if (!autil.is_array(a))
return false;
a = autil.get_array_range_rec(a);
return is_datatype(a) && is_recursive(a);
}
bool util::is_enum_sort(sort* s) {
if (!is_datatype(s)) {
return false;
@ -1243,6 +1251,9 @@ namespace datatype {
defined together in the same mutually recursive definition.
*/
bool util::are_siblings(sort * s1, sort * s2) {
array_util autil(m);
s1 = autil.get_array_range_rec(s1);
s2 = autil.get_array_range_rec(s2);
if (!is_datatype(s1) || !is_datatype(s2)) {
return s1 == s2;
}

View file

@ -105,7 +105,6 @@ namespace datatype {
class size {
unsigned m_ref{ 0 };
public:
size() {}
virtual ~size() { }
void inc_ref() { ++m_ref; }
void dec_ref();
@ -124,7 +123,6 @@ namespace datatype {
struct offset : public size {
sort_size m_offset;
offset(sort_size const& s): m_offset(s) {}
~offset() override {}
size* subst(obj_map<sort,size*>& S) override { return this; }
sort_size eval(obj_map<sort, sort_size> const& S) override { return m_offset; }
};
@ -152,7 +150,6 @@ namespace datatype {
struct sparam : public size {
sort_ref m_param;
sparam(sort_ref& p): m_param(p) {}
~sparam() override {}
size* subst(obj_map<sort, size*>& S) override;
sort_size eval(obj_map<sort, sort_size> const& S) override { return S[m_param]; }
};
@ -333,6 +330,7 @@ namespace datatype {
bool is_datatype(sort const* s) const { return is_sort_of(s, fid(), DATATYPE_SORT); }
bool is_enum_sort(sort* s);
bool is_recursive(sort * ty);
bool is_recursive_array(sort * ty);
bool is_constructor(func_decl * f) const { return is_decl_of(f, fid(), OP_DT_CONSTRUCTOR); }
bool is_recognizer(func_decl * f) const { return is_recognizer0(f) || is_is(f); }
bool is_recognizer0(func_decl * f) const { return is_decl_of(f, fid(), OP_DT_RECOGNISER); }

View file

@ -689,7 +689,7 @@ namespace euf {
if (ra->interpreted() && rb->interpreted()) {
explain_eq(justifications, a, ra);
explain_eq(justifications, b, rb);
return UINT_MAX;
return sat::null_bool_var;
}
expr_ref eq(m.mk_eq(a->get_expr(), b->get_expr()), m);
m_tmp_eq->m_args[0] = a;

View file

@ -19,6 +19,7 @@ Author:
#include "util/id_var_list.h"
#include "util/lbool.h"
#include "util/approx_set.h"
#include "util/sat_literal.h"
#include "ast/ast.h"
#include "ast/euf/euf_justification.h"
@ -41,28 +42,28 @@ namespace euf {
const theory_id null_theory_id = -1;
class enode {
expr* m_expr{ nullptr };
bool m_mark1{ false };
bool m_mark2{ false };
bool m_commutative{ false };
bool m_update_children{ false };
bool m_interpreted{ false };
bool m_merge_enabled{ true };
bool m_is_equality{ false }; // Does the expression represent an equality
lbool m_value; // Assignment by SAT solver for Boolean node
unsigned m_bool_var { UINT_MAX }; // SAT solver variable associated with Boolean node
unsigned m_class_size{ 1 }; // Size of the equivalence class if the enode is the root.
unsigned m_table_id{ UINT_MAX };
unsigned m_generation { 0 }; // Tracks how many quantifier instantiation rounds were needed to generate this enode.
expr* m_expr = nullptr;
bool m_mark1 = false;
bool m_mark2 = false;
bool m_commutative = false;
bool m_update_children = false;
bool m_interpreted = false;
bool m_merge_enabled = true;
bool m_is_equality = false; // Does the expression represent an equality
lbool m_value = l_undef; // Assignment by SAT solver for Boolean node
sat::bool_var m_bool_var = sat::null_bool_var; // SAT solver variable associated with Boolean node
unsigned m_class_size = 1; // Size of the equivalence class if the enode is the root.
unsigned m_table_id = UINT_MAX;
unsigned m_generation = 0; // Tracks how many quantifier instantiation rounds were needed to generate this enode.
enode_vector m_parents;
enode* m_next { nullptr };
enode* m_root { nullptr };
enode* m_target { nullptr };
enode* m_cg { nullptr };
enode* m_next = nullptr;
enode* m_root = nullptr;
enode* m_target = nullptr;
enode* m_cg = nullptr;
th_var_list m_th_vars;
justification m_justification;
unsigned m_num_args{ 0 };
signed char m_lbl_hash { -1 }; // It is different from -1, if enode is used in a pattern
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;
approx_set m_plbls;
enode* m_args[0];
@ -135,7 +136,7 @@ namespace euf {
void set_merge_enabled(bool m) { m_merge_enabled = m; }
void set_value(lbool v) { m_value = v; }
void set_is_equality() { m_is_equality = true; }
void set_bool_var(unsigned v) { m_bool_var = v; }
void set_bool_var(sat::bool_var v) { m_bool_var = v; }
public:
~enode() {
@ -155,7 +156,8 @@ namespace euf {
bool interpreted() const { return m_interpreted; }
bool is_equality() const { return m_is_equality; }
lbool value() const { return m_value; }
unsigned bool_var() const { return m_bool_var; }
bool value_conflict() const { return value() != l_undef && get_root()->value() != l_undef && value() != get_root()->value(); }
sat::bool_var bool_var() const { return m_bool_var; }
bool is_cgr() const { return this == m_cg; }
enode* get_cg() const { return m_cg; }
bool commutative() const { return m_commutative; }

View file

@ -276,7 +276,7 @@ struct pull_quant::imp {
if (is_exists(old_q)) {
result = m.mk_not(new_body);
result = m.mk_not(m.update_quantifier(old_q, exists_k, result));
result = m.mk_not(m.update_quantifier(old_q, forall_k, result));
if (m.proofs_enabled())
m.mk_rewrite(old_q, result);
return true;

View file

@ -54,7 +54,9 @@ namespace recfun {
unsigned arity, sort* const * domain, sort* range, bool is_generated)
: m(m), m_name(s),
m_domain(m, arity, domain),
m_range(range, m), m_vars(m), m_cases(),
m_range(range, m),
m_vars(m),
m_cases(),
m_decl(m),
m_rhs(m),
m_fid(fid)
@ -413,6 +415,16 @@ namespace recfun {
m_defs.insert(d->get_decl(), d);
return promise_def(&u(), d);
}
void plugin::erase_def(func_decl* f) {
def* d = nullptr;
if (m_defs.find(f, d)) {
for (case_def & c : d->get_cases())
m_case_defs.erase(c.get_decl());
m_defs.erase(f);
dealloc(d);
}
}
void plugin::set_definition(replace& r, promise_def & d, unsigned n_vars, var * const * vars, expr * rhs) {
u().set_definition(r, d, n_vars, vars, rhs);

View file

@ -186,6 +186,8 @@ namespace recfun {
def* mk_def(replace& subst, symbol const& name, unsigned n, sort ** params, sort * range, unsigned n_vars, var ** vars, expr * rhs);
void erase_def(func_decl* f);
bool has_def(func_decl* f) const { return m_defs.contains(f); }
bool has_defs() const;
def const& get_def(func_decl* f) const { return *(m_defs[f]); }

View file

@ -184,6 +184,8 @@ bool arith_rewriter::is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref &
kind = inv(kind);
r = true;
}
if (a.is_zero())
return false;
if (!a.is_one())
r = true;
if (!r)

View file

@ -35,8 +35,6 @@ protected:
public:
typedef map_impl::iterator iterator;
counter() {}
void reset() { m_data.reset(); }
iterator begin() const { return m_data.begin(); }
iterator end() const { return m_data.end(); }
@ -74,7 +72,6 @@ protected:
unsigned_vector m_scopes;
unsigned get_max_var(bool & has_var);
public:
var_counter() {}
void count_vars(const app * t, int coef = 1);
unsigned get_max_var(expr* e);
unsigned get_next_var(expr* e);
@ -86,8 +83,6 @@ class ast_counter {
public:
typedef map_impl::iterator iterator;
ast_counter() {}
iterator begin() const { return m_data.begin(); }
iterator end() const { return m_data.end(); }

View file

@ -59,6 +59,7 @@ class bit_blaster : public bit_blaster_tpl<bit_blaster_cfg> {
public:
bit_blaster(ast_manager & m, bit_blaster_params const & params);
bit_blaster_params const & get_params() const { return this->m_params; }
void set_flat(bool f) { m_rw.set_flat(f); }
};

View file

@ -214,12 +214,10 @@ private:
pull_quantifier(a->get_arg(i), qt, vars, tmp, use_fresh, rewrite_ok);
args.push_back(tmp);
}
if (rewrite_ok) {
m_rewriter.mk_and(args.size(), args.data(), result);
}
else {
if (rewrite_ok)
m_rewriter.mk_and(args.size(), args.data(), result);
else
result = m.mk_and (args.size (), args.data ());
}
}
else if (m.is_or(fml)) {
num_args = to_app(fml)->get_num_args();
@ -227,12 +225,10 @@ private:
pull_quantifier(to_app(fml)->get_arg(i), qt, vars, tmp, use_fresh, rewrite_ok);
args.push_back(tmp);
}
if (rewrite_ok) {
m_rewriter.mk_or(args.size(), args.data(), result);
}
else {
if (rewrite_ok)
m_rewriter.mk_or(args.size(), args.data(), result);
else
result = m.mk_or (args.size (), args.data ());
}
}
else if (m.is_not(fml)) {
pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp, use_fresh, rewrite_ok);

View file

@ -26,7 +26,6 @@ class recfun_rewriter {
recfun::util m_rec;
public:
recfun_rewriter(ast_manager& m): m(m), m_rec(m) {}
~recfun_rewriter() {}
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);

View file

@ -432,6 +432,7 @@ br_status seq_rewriter::mk_bool_app_helper(bool is_and, unsigned n, expr* const*
obj_map<expr, expr*> in_re, not_in_re;
bool found_pair = false;
ptr_buffer<expr> new_args;
for (unsigned i = 0; i < n; ++i) {
expr* args_i = args[i];
expr* x = nullptr, *y = nullptr, *z = nullptr;
@ -455,13 +456,15 @@ br_status seq_rewriter::mk_bool_app_helper(bool is_and, unsigned n, expr* const*
found_pair |= in_re.contains(x);
}
}
else
new_args.push_back(args_i);
}
if (!found_pair) {
return BR_FAILED;
}
ptr_buffer<expr> new_args;
for (auto const & kv : in_re) {
expr* x = kv.m_key;
expr* y = kv.m_value;
@ -482,12 +485,6 @@ br_status seq_rewriter::mk_bool_app_helper(bool is_and, unsigned n, expr* const*
new_args.push_back(re().mk_in_re(x, re().mk_complement(y)));
}
}
for (unsigned i = 0; i < n; ++i) {
expr* arg = args[i], * x;
if (!str().is_in_re(arg) && !(m().is_not(arg, x) && str().is_in_re(x))) {
new_args.push_back(arg);
}
}
result = is_and ? m().mk_and(new_args) : m().mk_or(new_args);
return BR_REWRITE_FULL;
@ -2500,7 +2497,7 @@ expr_ref seq_rewriter::is_nullable(expr* r) {
m_op_cache.insert(_OP_RE_IS_NULLABLE, r, nullptr, result);
}
STRACE("seq_verbose", tout << "is_nullable result: "
<< mk_pp(result, m()) << std::endl;);
<< result << std::endl;);
return result;
}

View file

@ -17,6 +17,7 @@ Notes:
--*/
#include "ast/rewriter/var_subst.h"
#include "ast/rewriter/expr_safe_replace.h"
#include "ast/ast_ll_pp.h"
#include "ast/ast_pp.h"
#include "ast/ast_smt2_pp.h"
@ -24,8 +25,9 @@ Notes:
#include "ast/for_each_expr.h"
expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args) {
expr_ref result(m_reducer.m());
if (is_ground(n)) {
ast_manager& m = m_reducer.m();
expr_ref result(m);
if (is_ground(n) || num_args == 0) {
result = n;
//application does not have free variables or nested quantifiers.
//There is no need to print the bindings here?
@ -40,6 +42,16 @@ expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args)
return result;
}
if (has_quantifiers(n)) {
expr_safe_replace rep(m);
for (unsigned k = 0; k < num_args; ++k) {
expr* arg = args[k];
if (arg)
rep.insert(m.mk_var(m_std_order ? num_args - k - 1 : k, arg->get_sort()), arg);
}
rep(n, result);
return result;
}
SASSERT(is_well_sorted(result.m(), n));
m_reducer.reset();
if (m_std_order)
@ -47,10 +59,10 @@ expr_ref var_subst::operator()(expr * n, unsigned num_args, expr * const * args)
else
m_reducer.set_bindings(num_args, args);
m_reducer(n, result);
SASSERT(is_well_sorted(m_reducer.m(), result));
SASSERT(is_well_sorted(m, result));
TRACE("var_subst_bug",
tout << "m_std_order: " << m_std_order << "\n" << mk_ismt2_pp(n, m_reducer.m()) << "\nusing\n";
for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m_reducer.m()) << "\n";
tout << "m_std_order: " << m_std_order << "\n" << mk_ismt2_pp(n, m) << "\nusing\n";
for (unsigned i = 0; i < num_args; i++) tout << mk_ismt2_pp(args[i], m) << "\n";
tout << "\n------>\n";
tout << result << "\n";);
return result;

View file

@ -1269,7 +1269,7 @@ seq_util::rex::info seq_util::rex::mk_info_rec(app* e) const {
case OP_RE_OPTION:
i1 = get_info_rec(e->get_arg(0));
return i1.opt();
case OP_RE_RANGE:
case OP_RE_RANGE:
case OP_RE_FULL_CHAR_SET:
case OP_RE_OF_PRED:
//TBD: check if the character predicate contains uninterpreted symbols or is nonground or is unsat

View file

@ -160,7 +160,6 @@ class seq_decl_plugin : public decl_plugin {
public:
seq_decl_plugin();
~seq_decl_plugin() override {}
void finalize() override;
bool unicode() const { return get_char_plugin().unicode(); }
@ -575,8 +574,6 @@ public:
re(*this) {
}
~seq_util() {}
family_id get_family_id() const { return m_fid; }
};

View file

@ -24,8 +24,6 @@ Revision History:
class shared_occs_mark {
ptr_buffer<ast> m_to_unmark;
public:
shared_occs_mark() {}
~shared_occs_mark() {
reset();
}

View file

@ -104,7 +104,7 @@ void static_features::reset() {
m_num_aliens_per_family .reset();
m_num_theories = 0;
m_theories .reset();
m_max_stack_depth = 100;
m_max_stack_depth = 30;
flush_cache();
}

View file

@ -36,8 +36,6 @@ class matcher {
void reset();
public:
matcher() {}
/**
\brief Return true if e2 is an instance of e1.
In case of success (result is true), it will store the substitution that makes e1 equals to e2 into s.

View file

@ -352,7 +352,21 @@ void cmd_context::insert_macro(symbol const& s, unsigned arity, sort*const* doma
else {
VERIFY(decls.insert(m(), arity, domain, t));
}
model_add(s, arity, domain, t);
recfun::decl::plugin& p = get_recfun_plugin();
recfun_replace replace(m());
var_ref_vector vars(m()), rvars(m());
for (unsigned i = 0; i < arity; ++i) {
vars.push_back(m().mk_var(i, domain[i]));
rvars.push_back(m().mk_var(i, domain[arity - i - 1]));
}
recfun::promise_def d = p.ensure_def(s, arity, domain, t->get_sort());
// recursive functions have opposite calling convention from macros!
var_subst sub(m(), true);
expr_ref tt = sub(t, rvars);
p.set_definition(replace, d, vars.size(), vars.data(), tt);
register_fun(s, d.get_def()->get_decl());
}
void cmd_context::erase_macro(symbol const& s) {
@ -940,17 +954,23 @@ void cmd_context::insert(symbol const & s, object_ref * r) {
}
void cmd_context::model_add(symbol const & s, unsigned arity, sort *const* domain, expr * t) {
if (!mc0()) m_mcs.set(m_mcs.size()-1, alloc(generic_model_converter, m(), "cmd_context"));
if (m_solver.get() && !m_solver->mc0()) m_solver->set_model_converter(mc0());
func_decl_ref fn(m().mk_func_decl(s, arity, domain, t->get_sort()), m());
func_decls & fs = m_func_decls.insert_if_not_there(s, func_decls());
fs.insert(m(), fn);
VERIFY(fn->get_range() == t->get_sort());
mc0()->add(fn, t);
if (!m_global_decls)
m_func_decls_stack.push_back(sf_pair(s, fn));
VERIFY(fn->get_range() == t->get_sort());
register_fun(s, fn);
}
void cmd_context::register_fun(symbol const& s, func_decl* fn) {
func_decls & fs = m_func_decls.insert_if_not_there(s, func_decls());
fs.insert(m(), fn);
if (!m_global_decls)
m_func_decls_stack.push_back(sf_pair(s, fn));
}
void cmd_context::model_del(func_decl* f) {
if (!mc0()) m_mcs.set(m_mcs.size() - 1, alloc(generic_model_converter, m(), "cmd_context"));
@ -1230,6 +1250,8 @@ void cmd_context::erase_func_decl_core(symbol const & s, func_decl * f) {
SASSERT(m_func_decl2alias.contains(f));
m_func_decl2alias.erase(f);
}
get_recfun_plugin().erase_def(f);
fs.erase(m(), f);
if (fs.empty())
m_func_decls.erase(s);
@ -1751,7 +1773,9 @@ void cmd_context::add_declared_functions(model& mdl) {
mdl.register_decl(f, fi);
}
}
mdl.add_rec_funs();
}
}
void cmd_context::display_sat_result(lbool r) {

View file

@ -94,9 +94,8 @@ public:
\brief Generic wrapper.
*/
class object_ref {
unsigned m_ref_count;
unsigned m_ref_count = 0;
public:
object_ref():m_ref_count(0) {}
virtual ~object_ref() {}
virtual void finalize(cmd_context & ctx) = 0;
void inc_ref(cmd_context & ctx) {
@ -406,6 +405,7 @@ public:
void insert_aux_pdecl(pdecl * p);
void model_add(symbol const & s, unsigned arity, sort *const* domain, expr * t);
void model_del(func_decl* f);
void register_fun(symbol const& s, func_decl* f);
void insert_rec_fun(func_decl* f, expr_ref_vector const& binding, svector<symbol> const& ids, expr* e);
func_decl * find_func_decl(symbol const & s) const;
func_decl * find_func_decl(symbol const & s, unsigned num_indices, unsigned const * indices,

View file

@ -25,13 +25,14 @@ Notes:
void assert_exprs_from(cmd_context const & ctx, goal & t) {
if (ctx.produce_proofs() && ctx.produce_unsat_cores())
throw cmd_exception("Frontend does not support simultaneous generation of proofs and unsat cores");
if (ctx.produce_unsat_cores() && ctx.assertions().size() != ctx.assertion_names().size())
throw cmd_exception("Unsat core tracking must be set before assertions are added");
ast_manager & m = t.m();
bool proofs_enabled = t.proofs_enabled();
if (ctx.produce_unsat_cores()) {
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
ptr_vector<expr>::const_iterator end = ctx.assertions().end();
ptr_vector<expr>::const_iterator it2 = ctx.assertion_names().begin();
SASSERT(ctx.assertions().size() == ctx.assertion_names().size());
for (; it != end; ++it, ++it2) {
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, m.mk_leaf(*it2));
}

View file

@ -166,9 +166,9 @@ public:
}
};
class check_sat_using_tactict_cmd : public exec_given_tactic_cmd {
class check_sat_using_tactic_cmd : public exec_given_tactic_cmd {
public:
check_sat_using_tactict_cmd():
check_sat_using_tactic_cmd():
exec_given_tactic_cmd("check-sat-using") {
}
@ -397,7 +397,7 @@ void install_core_tactic_cmds(cmd_context & ctx) {
ctx.insert(alloc(declare_tactic_cmd));
ctx.insert(alloc(get_user_tactics_cmd));
ctx.insert(alloc(help_tactic_cmd));
ctx.insert(alloc(check_sat_using_tactict_cmd));
ctx.insert(alloc(check_sat_using_tactic_cmd));
ctx.insert(alloc(apply_tactic_cmd));
install_tactics(ctx);
}

View file

@ -26,9 +26,6 @@ class pdd_eval {
std::function<rational (unsigned)> m_var2val;
public:
pdd_eval() {}
std::function<rational (unsigned)>& var2val() { return m_var2val; } // setter
const std::function<rational (unsigned)>& var2val() const { return m_var2val; } // getter

View file

@ -27,7 +27,6 @@ class simplifier {
public:
simplifier(solver& s): s(s) {}
~simplifier() {}
void operator()();

View file

@ -32,7 +32,6 @@ namespace lp {
lia_move cut(lar_term & t, mpq & k, explanation* ex, unsigned basic_inf_int_j, const row_strip<mpq>& row);
public:
gomory(int_solver& lia);
~gomory() {}
lia_move operator()();
};
}

View file

@ -32,7 +32,6 @@ namespace lp {
public:
int_branch(int_solver& lia);
~int_branch() {}
lia_move operator()();
};
}

View file

@ -35,7 +35,6 @@ namespace lp {
impq get_cube_delta_for_term(const lar_term& t) const;
public:
int_cube(int_solver& lia);
~int_cube() {}
lia_move operator()();
};
}

View file

@ -42,6 +42,8 @@ Accumulative:
- Otherwise accumulate x = (c1 * lcm(b1,b2) / b2) + (c2 * lcm(b1,b2) / b1) mod lcm(b,b2)
and accumulate the rows from R1, R2
--*/
#include "math/lp/int_solver.h"
@ -53,10 +55,7 @@ namespace lp {
int_gcd_test::int_gcd_test(int_solver& lia): lia(lia), lra(lia.lra), m_next_gcd(0), m_delay(0) {}
bool int_gcd_test::should_apply() {
if (!lia.settings().int_run_gcd_test())
return false;
return true;
return lia.settings().int_run_gcd_test();
}
lia_move int_gcd_test::operator()() {
@ -76,18 +75,36 @@ namespace lp {
}
bool int_gcd_test::gcd_test() {
reset_test();
const auto & A = lra.A_r(); // getting the matrix
for (unsigned i = 0; i < A.row_count(); i++)
for (unsigned i = 0; i < A.row_count(); i++) {
unsigned basic_var = lra.r_basis()[i];
if (!lia.column_is_int(basic_var))
continue;
if (lia.get_value(basic_var).is_int())
continue;
if (!gcd_test_for_row(A, i))
return false;
mark_visited(i);
}
for (unsigned i = m_inserted_vars.size(); i-- > 0; ) {
unsigned j = m_inserted_vars[i];
for (const auto & c : lra.get_column(j)) {
unsigned r = c.var();
if (is_visited(r))
continue;
mark_visited(r);
if (!gcd_test_for_row(A, r))
return false;
}
}
return true;
}
static mpq get_denominators_lcm(const row_strip<mpq> & row) {
mpq r(1);
for (auto & c : row) {
for (auto & c : row)
r = lcm(r, denominator(c.coeff()));
}
return r;
}
@ -95,44 +112,50 @@ namespace lp {
auto const& row = A.m_rows[i];
unsigned basic_var = lra.r_basis()[i];
if (!lia.column_is_int(basic_var) || lia.get_value(basic_var).is_int())
if (!lia.column_is_int(basic_var))
return true;
mpq lcm_den = get_denominators_lcm(row);
mpq consts(0);
m_lcm_den = get_denominators_lcm(row);
m_consts = 0;
mpq gcds(0);
mpq least_coeff(0);
bool least_coeff_is_bounded = false;
unsigned j;
m_least_coeff = 0;
bool least_coeff_is_bounded = false;
bool least_coeff_is_unique = false;
unsigned least_coeff_index = 0;
for (auto &c : A.m_rows[i]) {
j = c.var();
unsigned j = c.var();
const mpq& a = c.coeff();
if (lra.column_is_fixed(j)) {
mpq aux = lcm_den * a;
consts += aux * lra.column_lower_bound(j).x;
mpq aux = m_lcm_den * a;
m_consts += aux * lra.column_lower_bound(j).x;
}
else if (lra.column_is_real(j)) {
return true;
}
else if (gcds.is_zero()) {
gcds = abs(lcm_den * a);
least_coeff = gcds;
gcds = abs(m_lcm_den * a);
m_least_coeff = gcds;
least_coeff_is_bounded = lra.column_is_bounded(j);
least_coeff_is_unique = true;
least_coeff_index = j;
}
else {
mpq aux = abs(lcm_den * a);
mpq aux = abs(m_lcm_den * a);
gcds = gcd(gcds, aux);
if (aux < least_coeff) {
least_coeff = aux;
if (aux < m_least_coeff) {
m_least_coeff = aux;
least_coeff_is_bounded = lra.column_is_bounded(j);
least_coeff_is_unique = true;
least_coeff_index = j;
}
else if (least_coeff_is_bounded && aux == least_coeff) {
least_coeff_is_bounded = lra.column_is_bounded(j);
else if (aux == m_least_coeff) {
least_coeff_is_bounded &= lra.column_is_bounded(j);
least_coeff_is_unique = false;
}
}
SASSERT(gcds.is_int());
SASSERT(least_coeff.is_int());
SASSERT(m_least_coeff.is_int());
TRACE("gcd_test_bug", tout << "coeff: " << a << ", gcds: " << gcds
<< " least_coeff: " << least_coeff << " consts: " << consts << "\n";);
<< " least_coeff: " << m_least_coeff << " consts: " << m_consts << "\n";);
}
@ -143,31 +166,29 @@ namespace lp {
return true;
}
if (!(consts / gcds).is_int()) {
if (!(m_consts / gcds).is_int()) {
TRACE("gcd_test", tout << "row failed the GCD test:\n"; lia.display_row_info(tout, i););
fill_explanation_from_fixed_columns(A.m_rows[i]);
return false;
}
if (least_coeff.is_one() && !least_coeff_is_bounded) {
SASSERT(gcds.is_one());
if (least_coeff_is_bounded &&
!m_least_coeff.is_one() &&
!lia.get_value(basic_var).is_int() &&
!ext_gcd_test(A.m_rows[i]))
return false;
if (!least_coeff_is_unique)
return true;
}
if (least_coeff_is_bounded) {
return ext_gcd_test(A.m_rows[i], least_coeff, lcm_den, consts);
}
return true;
return accumulate_parity(row, least_coeff_index);
}
bool int_gcd_test::ext_gcd_test(const row_strip<mpq> & row,
mpq const & least_coeff,
mpq const & lcm_den,
mpq const & consts) {
bool int_gcd_test::ext_gcd_test(const row_strip<mpq> & row) {
TRACE("ext_gcd_test", tout << "row = "; lra.print_row(row, tout););
mpq gcds(0);
mpq l(consts);
mpq u(consts);
mpq l(m_consts);
mpq u(m_consts);
mpq a;
unsigned j;
@ -178,10 +199,10 @@ namespace lp {
if (lra.column_is_fixed(j))
continue;
SASSERT(!lra.column_is_real(j));
mpq ncoeff = lcm_den * a;
mpq ncoeff = m_lcm_den * a;
SASSERT(ncoeff.is_int());
mpq abs_ncoeff = abs(ncoeff);
if (abs_ncoeff == least_coeff) {
if (abs_ncoeff == m_least_coeff) {
SASSERT(lra.column_is_bounded(j));
if (ncoeff.is_pos()) {
// l += ncoeff * lra.column_lower_bound(j).x;
@ -235,4 +256,72 @@ namespace lp {
lia.m_ex->push_back(uc);
}
bool int_gcd_test::accumulate_parity(const row_strip<mpq> & row, unsigned least_idx) {
// remove this line to enable new functionality.
// return true;
mpq modulus(0);
bool least_sign = false;
for (const auto & c : row) {
unsigned j = c.var();
const mpq& a = c.coeff();
if (j == least_idx)
least_sign = a.is_neg();
else if (!lra.column_is_fixed(j)) {
mpq aux = abs(m_lcm_den * a);
if (gcd(m_least_coeff, aux) != m_least_coeff)
return true;
modulus = modulus == 0 ? aux : gcd(modulus, aux);
if (modulus.is_one())
return true;
}
}
modulus /= m_least_coeff;
if (modulus == 0)
return true;
SASSERT(modulus.is_int());
mpq offset = m_consts / m_least_coeff;
if (!offset.is_int())
return true;
offset = mod(offset, modulus);
if (!least_sign && offset != 0)
offset = modulus - offset;
TRACE("gcd_test", tout << least_idx << " modulus: " << modulus << " consts: " << m_consts << " sign " << least_sign << " offset: " << offset << "\n";);
SASSERT(0 <= offset && offset < modulus);
return insert_parity(least_idx, row, offset, modulus);
}
void int_gcd_test::reset_test() {
for (auto j : m_inserted_vars)
m_parities[j].pop_back();
m_inserted_vars.reset();
m_visited_ts++;
if (m_visited_ts == 0) {
m_visited.reset();
m_visited_ts++;
}
}
bool int_gcd_test::insert_parity(unsigned j, row_strip<mpq> const& r, mpq const& offset, mpq const& modulo) {
m_parities.reserve(j + 1);
// incomplete parity check.
for (auto const& p : m_parities[j]) {
if (p.m_modulo != modulo)
continue;
if (p.m_offset == offset)
return true;
else {
fill_explanation_from_fixed_columns(r);
fill_explanation_from_fixed_columns(*p.m_row);
return false;
}
}
m_inserted_vars.push_back(j);
m_parities[j].push_back(parity(offset, modulo, r));
return true;
}
}

View file

@ -32,22 +32,43 @@ namespace lp {
class int_solver;
class lar_solver;
class int_gcd_test {
struct parity {
mpq m_offset;
mpq m_modulo;
const row_strip<mpq>* m_row = nullptr;
parity(mpq const& p, mpq const& m, row_strip<mpq> const& r):
m_offset(p),
m_modulo(m),
m_row(&r)
{}
};
class int_solver& lia;
class lar_solver& lra;
unsigned m_next_gcd;
unsigned m_delay;
unsigned m_next_gcd = 0;
unsigned m_delay = 0;
mpq m_consts;
mpq m_least_coeff;
mpq m_lcm_den;
unsigned_vector m_inserted_vars;
vector<vector<parity>> m_parities;
unsigned_vector m_visited;
unsigned m_visited_ts = 0;
bool is_visited(unsigned i) { return m_visited.get(i, 0) == m_visited_ts; }
void mark_visited(unsigned i) { m_visited.setx(i, m_visited_ts, 0); }
void reset_test();
bool insert_parity(unsigned j, row_strip<mpq> const& r, mpq const& parity, mpq const& modulo);
bool gcd_test();
bool gcd_test_for_row(const static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i);
bool ext_gcd_test(const row_strip<mpq> & row,
mpq const & least_coeff,
mpq const & lcm_den,
mpq const & consts);
bool ext_gcd_test(const row_strip<mpq> & row);
void fill_explanation_from_fixed_columns(const row_strip<mpq> & row);
void add_to_explanation_from_fixed_or_boxed_column(unsigned j);
bool accumulate_parity(const row_strip<mpq> & row, unsigned least_coeff_index);
public:
int_gcd_test(int_solver& lia);
~int_gcd_test() {}
lia_move operator()();
bool should_apply();
};

View file

@ -179,34 +179,33 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
default:
break; // do nothing
}
if (this->m_settings.get_cancel_flag()
||
this->iters_with_no_cost_growing() > this->m_settings.max_number_of_iterations_with_no_improvements
||
this->total_iterations() > this->m_settings.max_total_number_of_iterations
) {
this->set_status(lp_status::CANCELLED);
break; // from the loop
}
} while (this->get_status() != lp_status::FLOATING_POINT_ERROR
&&
&&
this->get_status() != lp_status::UNBOUNDED
&&
&&
this->get_status() != lp_status::OPTIMAL
&&
&&
this->get_status() != lp_status::INFEASIBLE
&&
this->iters_with_no_cost_growing() <= this->m_settings.max_number_of_iterations_with_no_improvements
&&
this->total_iterations() <= this->m_settings.max_total_number_of_iterations
&&
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)
&&
this->m_settings.get_cancel_flag() == false);
&&
!(this->current_x_is_feasible() && this->m_look_for_feasible_solution_only)
);
if (this->m_settings.get_cancel_flag()) {
this->set_status(lp_status::CANCELLED);
}
lp_assert(
this->get_status() == lp_status::FLOATING_POINT_ERROR
||
this->get_status() == lp_status::CANCELLED
||
this->current_x_is_feasible() == false
||
this->calc_current_x_is_feasible_include_non_basis());
lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR
||
this->get_status() == lp_status::CANCELLED
||
this->current_x_is_feasible() == false
||
this->calc_current_x_is_feasible_include_non_basis());
return this->total_iterations();
}

View file

@ -140,6 +140,7 @@ struct statistics {
st.update("arith-patches", m_patches);
st.update("arith-patches-success", m_patches_success);
st.update("arith-hnf-calls", m_hnf_cutter_calls);
st.update("arith-hnf-cuts", m_hnf_cuts);
st.update("arith-horner-calls", m_horner_calls);
st.update("arith-horner-conflicts", m_horner_conflicts);
st.update("arith-horner-cross-nested-forms", m_cross_nested_forms);
@ -208,7 +209,7 @@ public:
double harris_feasibility_tolerance { 1e-7 }; // page 179 of Istvan Maros
double ignore_epsilon_of_harris { 10e-5 };
unsigned max_number_of_iterations_with_no_improvements { 2000000 };
unsigned max_total_number_of_iterations { 2000000 };
unsigned max_total_number_of_iterations { 20000000 };
double time_limit; // the maximum time limit of the total run time in seconds
// dual section
double dual_feasibility_tolerance { 1e-7 }; // page 71 of the PhD thesis of Achim Koberstein

View file

@ -54,7 +54,6 @@ public:
virtual unsigned size() const { return 1; }
virtual expr_type type() const = 0;
virtual std::ostream& print(std::ostream&) const = 0;
nex() {}
bool is_elementary() const {
switch(type()) {
case expr_type::SUM:

View file

@ -92,8 +92,6 @@ public:
bool operator!=(row_iterator const& other) const { return m_index != other.m_index; }
};
bit_matrix() {}
~bit_matrix() {}
void reset(unsigned num_columns);
row_iterator begin() { return row_iterator(*this, true); }

View file

@ -166,7 +166,7 @@ namespace opt {
return true;
}
#define PASSERT(_e_) if (!(_e_)) { TRACE("opt1", display(tout, r); display(tout);); SASSERT(_e_); }
#define PASSERT(_e_) { CTRACE("qe", !(_e_), display(tout, r); display(tout);); SASSERT(_e_); }
bool model_based_opt::invariant(unsigned index, row const& r) {
vector<var> const& vars = r.m_vars;
@ -378,7 +378,8 @@ namespace opt {
}
else if ((value == lub_val && r.m_type == opt::t_lt) ||
(is_pos && value < lub_val) ||
(!is_pos && value > lub_val)) {
(!is_pos && value > lub_val)) {
m_above.push_back(bound_row_index);
lub_val = value;
bound_row_index = row_id;
@ -423,6 +424,13 @@ namespace opt {
}
return val;
}
rational model_based_opt::eval(vector<var> const& coeffs) const {
rational val(0);
for (var const& v : coeffs)
val += v.m_coeff * eval(v.m_id);
return val;
}
rational model_based_opt::get_coefficient(unsigned row_id, unsigned var_id) const {
return m_rows[row_id].get_coefficient(var_id);
@ -787,7 +795,7 @@ namespace opt {
}
std::ostream& model_based_opt::display(std::ostream& out, row const& r) {
out << (r.m_alive?"+":"-") << " ";
out << (r.m_alive?"a":"d") << " ";
display(out, r.m_vars, r.m_coeff);
if (r.m_type == opt::t_mod) {
out << r.m_type << " " << r.m_mod << " = 0; value: " << r.m_value << "\n";
@ -1002,8 +1010,7 @@ namespace opt {
result = solve_for(glb_index, x, true);
}
else {
result = def();
m_var2value[x] = rational::zero();
result = def() + m_var2value[x];
}
SASSERT(eval(result) == eval(x));
}
@ -1123,9 +1130,8 @@ namespace opt {
}
TRACE("opt1", display(tout << "tableau after replace x by y := v" << y << "\n"););
def result = project(y, compute_def);
if (compute_def) {
if (compute_def)
result = (result * D) + u;
}
SASSERT(!compute_def || eval(result) == eval(x));
return result;
}
@ -1187,13 +1193,15 @@ namespace opt {
SASSERT(a.is_pos());
if (ty == t_lt) {
SASSERT(compute_def);
m_rows[row_id1].m_coeff += a;
m_rows[row_id1].m_coeff += a;
m_rows[row_id1].m_type = t_le;
m_rows[row_id1].m_value += a;
}
if (m_var2is_int[x] && !a.is_one()) {
row& r1 = m_rows[row_id1];
vector<var> coeffs;
mk_coeffs_without(coeffs, r1.m_vars, x);
rational c = r1.m_coeff;
rational c = mod(-eval(coeffs), a);
add_divides(coeffs, c, a);
}
unsigned_vector const& row_ids = m_var2row_ids[x];
@ -1203,19 +1211,19 @@ namespace opt {
if (!visited.contains(row_id2)) {
visited.insert(row_id2);
b = get_coefficient(row_id2, x);
if (!b.is_zero()) {
row& dst = m_rows[row_id2];
switch (dst.m_type) {
case t_eq:
case t_lt:
case t_le:
solve(row_id1, a, row_id2, x);
break;
case t_mod:
// mod reduction already done.
UNREACHABLE();
break;
}
if (b.is_zero())
continue;
row& dst = m_rows[row_id2];
switch (dst.m_type) {
case t_eq:
case t_lt:
case t_le:
solve(row_id1, a, row_id2, x);
break;
case t_mod:
// mod reduction already done.
UNREACHABLE();
break;
}
}
}

View file

@ -104,6 +104,8 @@ namespace opt {
rational eval(unsigned x) const;
rational eval(def const& d) const;
rational eval(vector<var> const& coeffs) const;
void resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);

View file

@ -31,7 +31,7 @@ class exception {
class power : public std::pair<var, unsigned> {
public:
power():std::pair<var, unsigned>() {}
power() = default;
power(var v, unsigned d):std::pair<var, unsigned>(v, d) {}
var x() const { return first; }
var get_var() const { return first; }

View file

@ -132,13 +132,19 @@ expr * array_factory::get_fresh_value(sort * s) {
return get_some_value(s);
}
sort * range = get_array_range(s);
expr * range_val = m_model.get_fresh_value(range);
if (range_val != nullptr) {
// easy case
func_interp * fi;
expr * val = mk_array_interp(s, fi);
fi->set_else(range_val);
return val;
expr* range_val = nullptr;
if (!m_ranges.contains(range)) {
ptr_vector<sort>::scoped_stack _s(m_ranges);
m_ranges.push_back(range);
range_val = m_model.get_fresh_value(range);
if (range_val != nullptr) {
// easy case
func_interp* fi;
expr* val = mk_array_interp(s, fi);
fi->set_else(range_val);
return val;
}
}
TRACE("array_factory_bug", tout << "array fresh value: using fresh index, range: " << mk_pp(range, m_manager) << "\n";);

View file

@ -28,6 +28,7 @@ class array_factory : public struct_factory {
expr * mk_array_interp(sort * s, func_interp * & fi);
void get_some_args_for(sort * s, ptr_buffer<expr> & args);
bool mk_two_diff_values_for(sort * s);
ptr_vector<sort> m_ranges;
public:
array_factory(ast_manager & m, model_core & md);

View file

@ -27,6 +27,8 @@ datatype_factory::datatype_factory(ast_manager & m, model_core & md):
}
expr * datatype_factory::get_some_value(sort * s) {
if (!m_util.is_datatype(s))
return m_model.get_some_value(s);
value_set * set = nullptr;
if (m_sort2value_set.find(s, set) && !set->empty())
return *(set->begin());
@ -77,6 +79,8 @@ bool datatype_factory::is_subterm_of_last_value(app* e) {
It also updates m_last_fresh_value
*/
expr * datatype_factory::get_almost_fresh_value(sort * s) {
if (!m_util.is_datatype(s))
return m_model.get_some_value(s);
value_set * set = get_value_set(s);
if (set->empty()) {
expr * val = get_some_value(s);
@ -136,6 +140,8 @@ expr * datatype_factory::get_almost_fresh_value(sort * s) {
expr * datatype_factory::get_fresh_value(sort * s) {
if (!m_util.is_datatype(s))
return m_model.get_fresh_value(s);
TRACE("datatype", tout << "generating fresh value for: " << s->get_name() << "\n";);
value_set * set = get_value_set(s);
// Approach 0)
@ -162,7 +168,9 @@ expr * datatype_factory::get_fresh_value(sort * s) {
unsigned num = constructor->get_arity();
for (unsigned i = 0; i < num; i++) {
sort * s_arg = constructor->get_domain(i);
if (!found_fresh_arg && (!m_util.is_recursive(s) || !m_util.is_datatype(s_arg) || !m_util.are_siblings(s, s_arg))) {
if (!found_fresh_arg &&
!m_util.is_recursive_array(s_arg) &&
(!m_util.is_recursive(s) || !m_util.is_datatype(s_arg) || !m_util.are_siblings(s, s_arg))) {
expr * new_arg = m_model.get_fresh_value(s_arg);
if (new_arg != nullptr) {
found_fresh_arg = true;
@ -191,7 +199,7 @@ expr * datatype_factory::get_fresh_value(sort * s) {
// search for constructor...
unsigned num_iterations = 0;
if (m_util.is_recursive(s)) {
while(true) {
while (true) {
++num_iterations;
TRACE("datatype", tout << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
ptr_vector<func_decl> const & constructors = *m_util.get_datatype_constructors(s);
@ -207,15 +215,15 @@ expr * datatype_factory::get_fresh_value(sort * s) {
<< m_util.are_siblings(s, s_arg) << " is_datatype "
<< m_util.is_datatype(s_arg) << " found_sibling "
<< found_sibling << "\n";);
if (!found_sibling && m_util.is_datatype(s_arg) && m_util.are_siblings(s, s_arg)) {
if (!found_sibling && m_util.are_siblings(s, s_arg)) {
found_sibling = true;
expr * maybe_new_arg = nullptr;
if (num_iterations <= 1) {
maybe_new_arg = get_almost_fresh_value(s_arg);
}
else {
if (!m_util.is_datatype(s_arg))
maybe_new_arg = m_model.get_fresh_value(s_arg);
else if (num_iterations <= 1)
maybe_new_arg = get_almost_fresh_value(s_arg);
else
maybe_new_arg = get_fresh_value(s_arg);
}
if (!maybe_new_arg) {
TRACE("datatype",
tout << "no argument found for " << mk_pp(s_arg, m_manager) << "\n";);

View file

@ -24,6 +24,7 @@ Revision History:
#include "ast/rewriter/th_rewriter.h"
#include "ast/array_decl_plugin.h"
#include "ast/bv_decl_plugin.h"
#include "ast/recfun_decl_plugin.h"
#include "ast/well_sorted.h"
#include "ast/used_symbols.h"
#include "ast/for_each_expr.h"
@ -582,3 +583,32 @@ void model::reset_eval_cache() {
m_mev.reset();
}
void model::add_rec_funs() {
recfun::util u(m);
func_decl_ref_vector recfuns = u.get_rec_funs();
for (func_decl* f : recfuns) {
auto& def = u.get_def(f);
expr* rhs = def.get_rhs();
if (!rhs)
continue;
if (has_interpretation(f))
continue;
if (f->get_arity() == 0) {
register_decl(f, rhs);
continue;
}
func_interp* fi = alloc(func_interp, m, f->get_arity());
// reverse argument order so that variable 0 starts at the beginning.
expr_ref_vector subst(m);
for (unsigned i = 0; i < f->get_arity(); ++i) {
subst.push_back(m.mk_var(i, f->get_domain(i)));
}
var_subst sub(m, true);
expr_ref bodyr = sub(rhs, subst);
fi->set_else(bodyr);
register_decl(f, fi);
}
TRACE("model", tout << *this << "\n";);
}

View file

@ -108,6 +108,7 @@ public:
void reset_eval_cache();
bool has_solver();
void set_solver(expr_solver* solver);
void add_rec_funs();
class scoped_model_completion {
bool m_old_completion;

View file

@ -313,7 +313,6 @@ namespace datalog {
static unsigned get_obj_size(unsigned n) { return sizeof(rule) + n * sizeof(app *); }
rule() : m_ref_cnt(0), m_name(symbol::null) {}
~rule() {}
void deallocate(ast_manager & m);

View file

@ -178,7 +178,7 @@ namespace datalog {
class base_fn {
public:
base_fn() {}
base_fn() = default;
virtual ~base_fn() {}
private:
//private and undefined copy constructor and operator= to avoid copying
@ -219,8 +219,6 @@ namespace datalog {
*/
class mutator_fn : public base_fn {
public:
~mutator_fn() override {}
virtual void operator()(base_object & t) = 0;
virtual bool supports_attachment(base_object& other) { return false; }

View file

@ -94,7 +94,6 @@ namespace datalog {
struct uint_set2 {
uint_set lt;
uint_set le;
uint_set2() {}
bool operator==(const uint_set2& other) const {
return other.lt == lt && other.le == le;
}

View file

@ -235,7 +235,6 @@ class pred_transformer {
public:
frames (pred_transformer &pt) : m_pt (pt),
m_size(0), m_sorted (true) {}
~frames() {}
void simplify_formulas ();
pred_transformer& pt() const {return m_pt;}
@ -356,7 +355,6 @@ class pred_transformer {
rule2ptrule m_rules;
tag2ptrule m_tags;
public:
pt_rules() {}
~pt_rules() {for (auto &kv : m_rules) {dealloc(kv.m_value);}}
bool find_by_rule(const datalog::rule &r, pt_rule* &ptr) {
@ -439,7 +437,6 @@ class pred_transformer {
public:
pred_transformer(context& ctx, manager& pm, func_decl* head);
~pred_transformer() {}
inline bool use_native_mbp ();
bool mk_mdl_rf_consistent(const datalog::rule *r, model &mdl);
@ -825,7 +822,6 @@ class pob_queue {
public:
pob_queue(): m_root(nullptr), m_max_level(0), m_min_depth(0) {}
~pob_queue() {}
void reset();
pob* top();

View file

@ -681,6 +681,8 @@ namespace opt {
void context::update_solver() {
sat_params p(m_params);
if (p.euf())
return;
if (!p.euf()) {
if (!m_enable_sat || !probe_fd()) {
return;

View file

@ -75,9 +75,7 @@ namespace smt2 {
EOF_TOKEN
};
scanner(cmd_context & ctx, std::istream& stream, bool interactive = false);
~scanner() {}
scanner(cmd_context & ctx, std::istream& stream, bool interactive = false);
int get_line() const { return m_line; }
int get_pos() const { return m_pos; }

View file

@ -39,8 +39,6 @@ public:
scanner(std::istream& stream, std::ostream& err, bool smt2, bool bv_token=false);
~scanner() {}
int get_line() const { return m_line; }
int get_pos() const { return m_pos; }
@ -86,5 +84,3 @@ private:
token read_bv_literal();
bool state_ok();
};

View file

@ -281,9 +281,9 @@ namespace mbp {
obj_map<expr, unsigned> tids;
expr_ref_vector pinned(m);
unsigned j = 0;
TRACE("qe", tout << "vars: " << vars << "\nfmls: " << fmls << "\n";);
for (unsigned i = 0; i < fmls.size(); ++i) {
expr * fml = fmls.get(i);
TRACE("qe", tout << "vars: " << vars << "\nfmls: " << fmls << "\n";
for (expr* f : fmls) tout << mk_pp(f, m) << " := " << model(f) << "\n";);
for (expr* fml : fmls) {
if (!linearize(mbo, eval, fml, fmls, tids)) {
TRACE("qe", tout << "could not linearize: " << mk_pp(fml, m) << "\n";);
fmls[j++] = fml;

View file

@ -102,6 +102,8 @@ namespace mbp {
model_evaluator eval(model);
eval.set_expand_array_equalities(true);
TRACE("qe", tout << fmls << "\n";);
DEBUG_CODE(for (expr* fml : fmls) { CTRACE("qe", m.is_false(eval(fml)), tout << mk_pp(fml, m) << " is false\n";); SASSERT(!m.is_false(eval(fml))); });
for (unsigned i = 0; i < fmls.size(); ++i) {
expr* fml = fmls.get(i), * nfml, * f1, * f2, * f3;
SASSERT(m.is_bool(fml));

View file

@ -63,7 +63,6 @@ namespace dimacs {
unsigned m_node_id{ 0 };
std::string m_name;
unsigned_vector m_args;
drat_record() {}
};
struct drat_pp {
@ -111,6 +110,3 @@ namespace dimacs {
};
};

View file

@ -52,7 +52,6 @@ namespace sat {
public:
aig_finder(solver& s);
~aig_finder() {}
void set(std::function<void (literal head, literal_vector const& ands)> const& f) { m_on_aig = f; }
void set(std::function<void (literal head, literal cond, literal th, literal el)> const& f) { m_on_if = f; }
void operator()(clause_vector& clauses);

View file

@ -111,7 +111,6 @@ namespace sat {
public:
anf_simplifier(solver& s) : s(s), m_eval_ts(0) {}
~anf_simplifier() {}
void operator()();
void set(config const& cfg) { m_config = cfg; }

View file

@ -97,8 +97,6 @@ namespace sat {
memset(m_false, 0, sizeof(unsigned) * max_lits);
}
~binspr() {}
void operator()();
void updt_params(params_ref const& p) {}

View file

@ -128,6 +128,7 @@ namespace sat {
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) {
return false;
}
virtual bool is_pb() { return false; }
};
};

View file

@ -380,16 +380,14 @@ namespace sat {
if (m_config.phase_sticky()) {
unsigned v = 0;
for (var_info& vi : m_vars) {
for (var_info& vi : m_vars)
vi.m_bias = s.m_phase[v++] ? 98 : 2;
}
}
// copy units
unsigned trail_sz = s.init_trail_size();
for (unsigned i = 0; i < trail_sz; ++i) {
for (unsigned i = 0; i < trail_sz; ++i)
add_clause(1, s.m_trail.data() + i);
}
// copy binary clauses
{
@ -410,9 +408,8 @@ namespace sat {
}
// copy clauses
for (clause* c : s.m_clauses) {
for (clause* c : s.m_clauses)
add_clause(c->size(), c->begin());
}
m_num_non_binary_clauses = s.m_clauses.size();
@ -422,7 +419,7 @@ namespace sat {
[&](unsigned sz, literal const* c, unsigned k) { add_cardinality(sz, c, k); };
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)> pb =
[&](unsigned sz, literal const* c, unsigned const* coeffs, unsigned k) { add_pb(sz, c, coeffs, k); };
if (ext && !ext->extract_pb(card, pb))
if (ext && (!ext->is_pb() || !ext->extract_pb(card, pb)))
throw default_exception("local search is incomplete with extensions beyond PB");
if (_init) {

View file

@ -69,7 +69,6 @@ namespace sat {
lut_finder(solver& s) : s(s), m_max_lut_size(5) {
memset(m_masks, 0, sizeof(uint64_t)*7);
}
~lut_finder() {}
void set(std::function<void (uint64_t, bool_var_vector const&, bool_var)>& f) { m_on_lut = f; }

View file

@ -115,7 +115,6 @@ namespace sat {
public:
npn3_finder(solver& s);
~npn3_finder() {}
void set_on_mux(std::function<void(literal head, literal cond, literal th, literal el)> const& f) { m_on_mux = f; }
void set_on_maj(std::function<void(literal head, literal a, literal b, literal c)> const& f) { m_on_maj = f; }
void set_on_orand(std::function<void(literal head, literal a, literal b, literal c)> const& f) { m_on_orand = f; }

View file

@ -41,7 +41,6 @@ namespace sat {
unsigned get_length(unsigned index) const { return m_vectors[index+1]; }
unsigned const* get_ptr(unsigned index) const { return m_vectors.data() + index + 2; }
public:
vector_pool() {}
void reserve(unsigned num_owners, unsigned sz);
void begin_add_vector(unsigned owner, unsigned n);
void end_add_vector();

View file

@ -31,9 +31,8 @@ namespace sat {
class prob : public i_local_search {
struct clause_info {
clause_info(): m_trues(0), m_num_trues(0) {}
unsigned m_trues; // set of literals that are true
unsigned m_num_trues; // size of true set
unsigned m_trues = 0; // set of literals that are true
unsigned m_num_trues = 0; // size of true set
bool is_true() const { return m_num_trues > 0; }
void add(literal lit) { ++m_num_trues; m_trues += lit.index(); }
void del(literal lit) { SASSERT(m_num_trues > 0); --m_num_trues; m_trues -= lit.index(); }
@ -129,8 +128,6 @@ namespace sat {
void add(unsigned sz, literal const* c);
public:
prob() {}
~prob() override;
lbool check(unsigned sz, literal const* assumptions, parallel* p) override;

View file

@ -141,6 +141,7 @@ namespace sat {
m_participated.reset();
m_canceled.reset();
m_reasoned.reset();
m_case_split_queue.reset();
m_simplifier.reset_todos();
m_qhead = 0;
m_trail.reset();
@ -1029,7 +1030,7 @@ namespace sat {
return false;
} while (m_qhead < m_trail.size());
if (m_ext && !is_probing())
if (m_ext && (!is_probing() || at_base_lvl()))
m_ext->unit_propagate();
}
if (m_inconsistent)
@ -1396,7 +1397,8 @@ namespace sat {
}
};
scoped_ls _ls(*this);
if (inconsistent()) return l_false;
if (inconsistent())
return l_false;
scoped_limits scoped_rl(rlimit());
SASSERT(m_local_search);
m_local_search->add(*this);
@ -3540,7 +3542,7 @@ namespace sat {
else {
set_eliminated(v, true);
if (!is_external(v) || true) {
m_free_vars.push_back(v);
m_free_vars.push_back(v);
}
}
}
@ -3555,6 +3557,7 @@ namespace sat {
bool_var v = m_free_vars[i];
cleanup_watch(literal(v, false));
cleanup_watch(literal(v, true));
}
TRACE("sat",
tout << "clauses to reinit: " << (m_clauses_to_reinit.size() - old_sz) << "\n";
@ -3573,10 +3576,10 @@ namespace sat {
m_free_vars[j++] = w;
m_free_vars.shrink(j);
for (bool_var i = v; i < m_justification.size(); ++i) {
m_case_split_queue.del_var_eh(i);
m_probing.reset_cache(literal(i, true));
m_probing.reset_cache(literal(i, false));
for (bool_var w = m_justification.size(); w-- > v;) {
m_case_split_queue.del_var_eh(w);
m_probing.reset_cache(literal(w, true));
m_probing.reset_cache(literal(w, false));
}
m_watches.shrink(2*v);
m_assignment.shrink(2*v);
@ -3599,6 +3602,7 @@ namespace sat {
void solver::pop(unsigned num_scopes) {
if (num_scopes == 0)
return;
unsigned free_vars_head = m_free_vars.size();
if (m_ext) {
pop_vars(num_scopes);
m_ext->pop(num_scopes);
@ -3608,6 +3612,8 @@ namespace sat {
scope & s = m_scopes[new_lvl];
m_inconsistent = false; // TBD: use model seems to make this redundant: s.m_inconsistent;
unassign_vars(s.m_trail_lim, new_lvl);
for (unsigned i = m_free_vars.size(); i-- > free_vars_head; )
m_case_split_queue.del_var_eh(m_free_vars[i]);
m_scope_lvl -= num_scopes;
reinit_clauses(s.m_clauses_to_reinit_lim);
m_scopes.shrink(new_lvl);

View file

@ -1057,7 +1057,7 @@ private:
CTRACE("sat", !m.is_true(tmp),
tout << "Evaluation failed: " << mk_pp(f, m) << " to " << tmp << "\n";
model_smt2_pp(tout, m, *(mdl.get()), 0););
if (!m.is_true(tmp)) {
if (m.is_false(tmp)) {
IF_VERBOSE(0, verbose_stream() << "failed to verify: " << mk_pp(f, m) << "\n");
IF_VERBOSE(0, verbose_stream() << "evaluated to " << tmp << "\n");
all_true = false;

View file

@ -62,7 +62,6 @@ namespace sat {
public:
xor_finder(solver& s) : s(s), m_max_xor_size(5) { init_parity(); }
~xor_finder() {}
void set(std::function<void (literal_vector const& lits)>& f) { m_on_xor = f; }

View file

@ -331,6 +331,8 @@ namespace arith {
}
void solver::new_diseq_eh(euf::th_eq const& e) {
ensure_column(e.v1());
ensure_column(e.v2());
m_delayed_eqs.push_back(std::make_pair(e, false));
ctx.push(push_back_vector<svector<std::pair<euf::th_eq, bool>>>(m_delayed_eqs));
}

View file

@ -275,6 +275,9 @@ namespace arith {
else {
if (is_app(n)) {
internalize_args(to_app(n));
for (expr* arg : *to_app(n))
if (a.is_arith_expr(arg))
internalize_term(arg);
}
theory_var v = mk_evar(n);
coeffs[vars.size()] = coeffs[index];
@ -291,9 +294,8 @@ namespace arith {
st.to_ensure_enode().reset();
for (unsigned i = st.to_ensure_var().size(); i-- > 0; ) {
expr* n = st.to_ensure_var()[i];
if (is_app(n)) {
if (is_app(n))
internalize_term(to_app(n));
}
}
st.to_ensure_var().reset();
}
@ -388,7 +390,6 @@ namespace arith {
return true;
}
bool solver::internalize_term(expr* term) {
if (!has_var(term))
register_theory_var_in_lar_solver(internalize_def(term));
@ -424,7 +425,7 @@ namespace arith {
TRACE("arith", tout << mk_pp(t, m) << " " << force << " " << reflect(t) << "\n";);
if (!force && !reflect(t))
return;
for (expr* arg : *t)
for (expr* arg : *t)
e_internalize(arg);
}
@ -435,8 +436,8 @@ namespace arith {
theory_var v = mk_evar(t);
if (_has_var)
return v;
theory_var w = mk_evar(n);
internalize_term(n);
theory_var w = mk_evar(n);
if (p == 0) {
mk_power0_axioms(t, n);

View file

@ -76,8 +76,9 @@ namespace arith {
}
bool solver::unit_propagate() {
TRACE("arith", tout << "unit propagate\n";);
m_model_is_initialized = false;
if (!m_new_eq && m_new_bounds.empty() && m_asserted_qhead == m_asserted.size())
if (!m_solver->has_changed_columns() && !m_new_eq && m_new_bounds.empty() && m_asserted_qhead == m_asserted.size())
return false;
m_new_eq = false;
@ -138,26 +139,31 @@ namespace arith {
lp_api::bound_kind k = b.get_bound_kind();
theory_var v = b.get_var();
inf_rational val = b.get_value(is_true);
bool same_polarity = b.get_lit().sign() == lit1.sign();
lp_bounds const& bounds = m_bounds[v];
SASSERT(!bounds.empty());
if (bounds.size() == 1) return;
if (m_unassigned_bounds[v] == 0) return;
bool v_is_int = b.is_int();
literal lit2 = sat::null_literal;
bool find_glb = (is_true == (k == lp_api::lower_t));
bool find_glb = (same_polarity == (k == lp_api::lower_t));
TRACE("arith", tout << lit1 << " v" << v << " val " << val << " find_glb: " << find_glb << " is_true: " << is_true << " k: " << k << " is_lower: " << (k == lp_api::lower_t) << "\n";);
if (find_glb) {
rational glb;
api_bound* lb = nullptr;
for (api_bound* b2 : bounds) {
if (b2 == &b) continue;
if (b2 == &b)
continue;
rational const& val2 = b2->get_value();
if (((is_true || v_is_int) ? val2 < val : val2 <= val) && (!lb || glb < val2)) {
if (lb && glb >= val2)
continue;
if (((same_polarity || v_is_int) ? val2 < val : val2 <= val)) {
lb = b2;
glb = val2;
}
}
if (!lb) return;
if (!lb)
return;
bool sign = lb->get_bound_kind() != lp_api::lower_t;
lit2 = lb->get_lit();
if (sign)
@ -167,14 +173,18 @@ namespace arith {
rational lub;
api_bound* ub = nullptr;
for (api_bound* b2 : bounds) {
if (b2 == &b) continue;
if (b2 == &b)
continue;
rational const& val2 = b2->get_value();
if (((is_true || v_is_int) ? val < val2 : val <= val2) && (!ub || val2 < lub)) {
if (ub && val2 >= lub)
continue;
if (((same_polarity || v_is_int) ? val < val2 : val <= val2)) {
ub = b2;
lub = val2;
}
}
if (!ub) return;
if (!ub)
return;
bool sign = ub->get_bound_kind() != lp_api::upper_t;
lit2 = ub->get_lit();
if (sign)
@ -609,11 +619,11 @@ namespace arith {
}
else if (a.is_arith_expr(o)) {
expr_ref_vector args(m);
for (auto* arg : euf::enode_args(n)) {
if (m.is_value(arg->get_expr()))
args.push_back(arg->get_expr());
for (auto* arg : *to_app(o)) {
if (m.is_value(arg))
args.push_back(arg);
else
args.push_back(values.get(arg->get_root_id()));
args.push_back(values.get(ctx.get_enode(arg)->get_root_id()));
}
value = m.mk_app(to_app(o)->get_decl(), args.size(), args.data());
ctx.get_rewriter()(value);
@ -631,8 +641,11 @@ namespace arith {
return false;
expr* e = n->get_expr();
if (a.is_arith_expr(e) && to_app(e)->get_num_args() > 0) {
for (auto* arg : euf::enode_args(n))
dep.add(n, arg);
for (auto* arg : *to_app(e)) {
auto* earg = expr2enode(arg);
if (earg)
dep.add(n, earg);
}
}
else {
dep.insert(n, nullptr);

View file

@ -112,7 +112,7 @@ namespace arith {
}
};
scoped_ptr_vector<internalize_state> m_internalize_states;
unsigned m_internalize_head{ 0 };
unsigned m_internalize_head = 0;
class scoped_internalize_state {
solver& m_imp;
@ -149,10 +149,10 @@ namespace arith {
vector<rational> m_columns;
var_coeffs m_left_side; // constraint left side
lpvar m_one_var { UINT_MAX };
lpvar m_zero_var { UINT_MAX };
lpvar m_rone_var { UINT_MAX };
lpvar m_rzero_var { UINT_MAX };
lpvar m_one_var = UINT_MAX;
lpvar m_zero_var = UINT_MAX;
lpvar m_rone_var = UINT_MAX;
lpvar m_rzero_var = UINT_MAX;
enum constraint_source {
inequality_source,
@ -177,7 +177,7 @@ namespace arith {
vector<lp_bounds> m_bounds;
unsigned_vector m_unassigned_bounds;
unsigned_vector m_bounds_trail;
unsigned m_asserted_qhead{ 0 };
unsigned m_asserted_qhead = 0;
svector<std::pair<theory_var, theory_var> > m_assume_eq_candidates;
unsigned m_assume_eq_head{ 0 };

View file

@ -174,14 +174,19 @@ namespace array {
SASSERT(store->get_num_args() == 1 + select->get_num_args());
ptr_buffer<expr> sel1_args, sel2_args;
unsigned num_args = select->get_num_args();
sel1_args.push_back(store);
sel2_args.push_back(store->get_arg(0));
if (select->get_arg(0) != store && expr2enode(select->get_arg(0))->get_root() == expr2enode(store)->get_root())
return false;
bool has_diff = false;
for (unsigned i = 1; i < num_args; i++)
has_diff |= expr2enode(select->get_arg(i))->get_root() != expr2enode(store->get_arg(i))->get_root();
if (!has_diff)
return false;
sel1_args.push_back(store);
sel2_args.push_back(store->get_arg(0));
for (unsigned i = 1; i < num_args; i++) {
sel1_args.push_back(select->get_arg(i));
@ -191,20 +196,31 @@ namespace array {
expr_ref sel1(a.mk_select(sel1_args), m);
expr_ref sel2(a.mk_select(sel2_args), m);
expr_ref sel_eq_e(m.mk_eq(sel1, sel2), m);
bool new_prop = false;
if (!ctx.get_egraph().find(sel1))
new_prop = true;
if (!ctx.get_egraph().find(sel2))
new_prop = true;
euf::enode* s1 = e_internalize(sel1);
euf::enode* s2 = e_internalize(sel2);
TRACE("array",
tout << "select-store " << ctx.bpp(s1) << " " << ctx.bpp(s1->get_root()) << "\n";
tout << "select-store " << ctx.bpp(s2) << " " << ctx.bpp(s2->get_root()) << "\n";);
if (s1->get_root() == s2->get_root())
return false;
return new_prop;
sat::literal sel_eq = mk_literal(sel_eq_e);
if (s().value(sel_eq) == l_true)
return false;
sat::literal sel_eq = sat::null_literal;
auto init_sel_eq = [&]() {
if (sel_eq != sat::null_literal)
return true;
sel_eq = mk_literal(sel_eq_e);
return s().value(sel_eq) != l_true;
};
bool new_prop = false;
for (unsigned i = 1; i < num_args; i++) {
expr* idx1 = store->get_arg(i);
expr* idx2 = select->get_arg(i);
@ -213,11 +229,17 @@ namespace array {
if (r1 == r2)
continue;
if (m.are_distinct(r1->get_expr(), r2->get_expr())) {
new_prop = true;
add_clause(sel_eq);
if (init_sel_eq() && add_clause(sel_eq))
new_prop = true;
break;
}
sat::literal idx_eq = eq_internalize(idx1, idx2);
if (s().value(idx_eq) == l_true)
continue;
if (s().value(idx_eq) == l_undef)
new_prop = true;
if (!init_sel_eq())
break;
if (add_clause(idx_eq, sel_eq))
new_prop = true;
}

View file

@ -269,6 +269,6 @@ namespace array {
bool solver::can_beta_reduce(euf::enode* n) const {
expr* c = n->get_expr();
return a.is_const(c) || a.is_as_array(c) || a.is_store(c) || is_lambda(c);
return a.is_const(c) || a.is_as_array(c) || a.is_store(c) || is_lambda(c) || a.is_map(c);
}
}

View file

@ -54,7 +54,6 @@ namespace array {
euf::enode_vector m_lambdas; // equivalent nodes that have beta reduction properties
euf::enode_vector m_parent_lambdas; // parents that have beta reduction properties
euf::enode_vector m_parent_selects; // parents that use array in select position
var_data() {}
};

View file

@ -73,6 +73,8 @@ namespace bv {
SASSERT(e->get_num_args() >= 2);
expr_ref_vector args(m);
euf::enode* n = expr2enode(e);
if (!reflect())
return false;
auto r1 = eval_bv(n);
auto r2 = eval_args(n, args);
if (r1 == r2)
@ -356,6 +358,8 @@ namespace bv {
return internalize_mode::no_delay_i;
if (!get_config().m_bv_delay)
return internalize_mode::no_delay_i;
if (!reflect())
return internalize_mode::no_delay_i;
internalize_mode mode;
switch (to_app(e)->get_decl_kind()) {
case OP_BMUL:

View file

@ -137,7 +137,7 @@ namespace bv {
return true;
SASSERT(!n || !n->is_attached_to(get_id()));
bool suppress_args = !get_config().m_bv_reflect && !m.is_considered_uninterpreted(a->get_decl());
bool suppress_args = !reflect() && !m.is_considered_uninterpreted(a->get_decl());
if (!n)
n = mk_enode(e, suppress_args);
@ -661,12 +661,10 @@ namespace bv {
if (lit0 == sat::null_literal) {
m_bits[v_arg][idx] = lit;
TRACE("bv", tout << "add-bit: " << lit << " " << literal2expr(lit) << "\n";);
if (arg_sz > 1) {
atom* a = new (get_region()) atom(lit.var());
a->m_occs = new (get_region()) var_pos_occ(v_arg, idx);
insert_bv2a(lit.var(), a);
ctx.push(mk_atom_trail(lit.var(), *this));
}
atom* a = new (get_region()) atom(lit.var());
a->m_occs = new (get_region()) var_pos_occ(v_arg, idx);
insert_bv2a(lit.var(), a);
ctx.push(mk_atom_trail(lit.var(), *this));
}
else if (lit != lit0) {
add_clause(lit0, ~lit);

View file

@ -55,6 +55,7 @@ namespace bv {
m_ackerman(*this),
m_bb(m, get_config()),
m_find(*this) {
m_bb.set_flat(false);
}
void solver::fixed_var_eh(theory_var v1) {

View file

@ -259,6 +259,7 @@ namespace bv {
void assert_bv2int_axiom(app * n);
void assert_int2bv_axiom(app* n);
void assert_ackerman(theory_var v1, theory_var v2);
bool reflect() const { return get_config().m_bv_reflect; }
// delay internalize
enum class internalize_mode {

View file

@ -42,7 +42,7 @@ namespace euf {
if (n) {
if (m.is_bool(e)) {
SASSERT(!s().was_eliminated(n->bool_var()));
SASSERT(n->bool_var() != UINT_MAX);
SASSERT(n->bool_var() != sat::null_bool_var);
return literal(n->bool_var(), sign);
}
TRACE("euf", tout << "non-bool\n";);
@ -109,11 +109,13 @@ namespace euf {
if (m.is_bool(e))
attach_lit(literal(si.add_bool_var(e), false), e);
if (!m.is_bool(e) && e->get_sort()->get_family_id() != null_family_id) {
if (!m.is_bool(e) && !m.is_uninterp(e->get_sort())) {
auto* e_ext = expr2solver(e);
auto* s_ext = sort2solver(e->get_sort());
if (s_ext && s_ext != e_ext)
s_ext->apply_sort_cnstr(n, e->get_sort());
else if (!s_ext && !e_ext && is_app(e))
unhandled_function(to_app(e)->get_decl());
}
expr* a = nullptr, * b = nullptr;
if (m.is_eq(e, a, b) && a->get_sort()->get_family_id() != null_family_id) {
@ -151,7 +153,7 @@ namespace euf {
enode* n = m_egraph.find(e);
if (!n)
n = m_egraph.mk(e, m_generation, 0, nullptr);
SASSERT(n->bool_var() == UINT_MAX || n->bool_var() == v);
SASSERT(n->bool_var() == sat::null_bool_var || n->bool_var() == v);
m_egraph.set_bool_var(n, v);
if (m.is_eq(e) || m.is_or(e) || m.is_and(e) || m.is_not(e))
m_egraph.set_merge_enabled(n, false);
@ -177,10 +179,13 @@ namespace euf {
void solver::add_not_distinct_axiom(app* e, enode* const* args) {
SASSERT(m.is_distinct(e));
unsigned sz = e->get_num_args();
if (sz <= 1)
return;
sat::status st = sat::status::th(m_is_redundant, m.get_basic_family_id());
if (sz <= 1) {
s().mk_clause(0, nullptr, st);
return;
}
static const unsigned distinct_max_args = 32;
if (sz <= distinct_max_args) {
sat::literal_vector lits;
@ -193,8 +198,8 @@ namespace euf {
}
s().mk_clause(lits, st);
if (relevancy_enabled())
add_root(lits.size(), lits.data());
}
add_root(lits);
}
else {
// g(f(x_i)) = x_i
// f(x_1) = a + .... + f(x_n) = a >= 2
@ -228,10 +233,8 @@ namespace euf {
static const unsigned distinct_max_args = 32;
unsigned sz = e->get_num_args();
sat::status st = sat::status::th(m_is_redundant, m.get_basic_family_id());
if (sz <= 1) {
s().mk_clause(0, nullptr, st);
if (sz <= 1)
return;
}
if (sz <= distinct_max_args) {
for (unsigned i = 0; i < sz; ++i) {
for (unsigned j = i + 1; j < sz; ++j) {

View file

@ -73,16 +73,17 @@ namespace euf {
values2model(deps, mdl);
for (auto* mb : m_solvers)
mb->finalize_model(*mdl);
TRACE("model", tout << "created model " << *mdl << "\n";);
validate_model(*mdl);
}
bool solver::include_func_interp(func_decl* f) {
if (f->is_skolem())
return false;
if (f->get_family_id() == null_family_id)
return true;
if (f->get_family_id() == m.get_basic_family_id())
return false;
if (f->is_skolem())
return false;
euf::th_model_builder* mb = func_decl2solver(f);
return mb && mb->include_func_interp(f);
}
@ -190,7 +191,7 @@ namespace euf {
if (!is_app(e))
continue;
app* a = to_app(e);
func_decl* f = a->get_decl();
func_decl* f = a->get_decl();
if (!include_func_interp(f))
continue;
if (m.is_bool(e) && is_uninterp_const(e) && mdl->get_const_interp(f))
@ -209,9 +210,12 @@ namespace euf {
mdl->register_decl(f, fi);
}
args.reset();
for (enode* arg : enode_args(n))
args.push_back(m_values.get(arg->get_root_id()));
DEBUG_CODE(for (expr* arg : args) VERIFY(arg););
for (expr* arg : *a) {
enode* earg = get_enode(arg);
args.push_back(m_values.get(earg->get_root_id()));
CTRACE("euf", !args.back(), tout << "no value for " << bpp(earg) << "\n";);
SASSERT(args.back());
}
SASSERT(args.size() == arity);
if (!fi->get_entry(args.data()))
fi->insert_new_entry(args.data(), v);
@ -227,17 +231,23 @@ namespace euf {
// TODO
}
void solver::model_updated(model_ref& mdl) {
m_values2root.reset();
for (enode* n : m_egraph.nodes())
if (n->is_root() && m_values.get(n->get_expr_id()))
m_values[n->get_expr_id()] = (*mdl)(n->get_expr());
}
obj_map<expr,enode*> const& solver::values2root() {
if (!m_values2root.empty())
return m_values2root;
for (enode* n : m_egraph.nodes())
if (n->is_root() && m_values.get(n->get_expr_id()))
m_values2root.insert(m_values.get(n->get_expr_id()), n);
#if 0
for (auto kv : m_values2root) {
std::cout << mk_pp(kv.m_key, m) << " -> " << bpp(kv.m_value) << "\n";
}
#endif
TRACE("model",
for (auto kv : m_values2root)
tout << mk_pp(kv.m_key, m) << " -> " << bpp(kv.m_value) << "\n";);
return m_values2root;
}
@ -246,20 +256,29 @@ namespace euf {
}
void solver::validate_model(model& mdl) {
bool first = true;
for (enode* n : m_egraph.nodes()) {
expr* e = n->get_expr();
if (!m.is_bool(e))
continue;
if (has_quantifiers(e))
continue;
if (!is_relevant(n))
continue;
bool tt = l_true == s().value(n->bool_var());
if (tt && mdl.is_false(e)) {
IF_VERBOSE(0, verbose_stream() << "Failed to validate " << bpp(n) << " " << mdl(e) << "\n");
for (auto* arg : euf::enode_args(n))
IF_VERBOSE(0, verbose_stream() << bpp(arg) << "\n" << mdl(arg->get_expr()) << "\n");
}
if (!tt && mdl.is_true(e))
IF_VERBOSE(0, verbose_stream() << "Failed to validate " << bpp(n) << " " << mdl(e) << "\n");
if (tt && !mdl.is_false(e))
continue;
if (!tt && !mdl.is_true(e))
continue;
IF_VERBOSE(0,
verbose_stream() << "Failed to validate " << n->bool_var() << " " << bpp(n) << " " << mdl(e) << "\n";
for (auto* arg : euf::enode_args(n))
verbose_stream() << bpp(arg) << "\n" << mdl(arg->get_expr()) << "\n";);
CTRACE("euf", first,
tout << "Failed to validate " << n->bool_var() << " " << bpp(n) << " " << mdl(e) << "\n";
s().display(tout);
tout << mdl << "\n";);
first = false;
}
}

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