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:
commit
57df45dc16
162 changed files with 2885 additions and 1941 deletions
|
@ -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()
|
||||
|
||||
################################################################################
|
||||
|
|
|
@ -14,9 +14,9 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z
|
|||
|
||||
## Build status
|
||||
|
||||
| Azure Pipelines | TravisCI |
|
||||
| --------------- | -------- |
|
||||
[](https://dev.azure.com/Z3Public/Z3/_build/latest?definitionId=1&branchName=master) | [](https://travis-ci.org/Z3Prover/z3)
|
||||
| Azure Pipelines |
|
||||
| --------------- |
|
||||
[](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:
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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>© 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()
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
@ -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]
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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);
|
||||
|
|
119
src/ast/ast.h
119
src/ast/ast.h
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]); }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(); }
|
||||
|
||||
|
|
|
@ -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); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ Revision History:
|
|||
class shared_occs_mark {
|
||||
ptr_buffer<ast> m_to_unmark;
|
||||
public:
|
||||
shared_occs_mark() {}
|
||||
|
||||
~shared_occs_mark() {
|
||||
reset();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ class simplifier {
|
|||
public:
|
||||
|
||||
simplifier(solver& s): s(s) {}
|
||||
~simplifier() {}
|
||||
|
||||
void operator()();
|
||||
|
||||
|
|
|
@ -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()();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ namespace lp {
|
|||
|
||||
public:
|
||||
int_branch(int_solver& lia);
|
||||
~int_branch() {}
|
||||
lia_move operator()();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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()();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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";);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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";);
|
||||
|
|
|
@ -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";);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
|||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -97,8 +97,6 @@ namespace sat {
|
|||
memset(m_false, 0, sizeof(unsigned) * max_lits);
|
||||
}
|
||||
|
||||
~binspr() {}
|
||||
|
||||
void operator()();
|
||||
|
||||
void updt_params(params_ref const& p) {}
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue