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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2398,6 +2398,7 @@ def mk_config():
config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w') config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w')
global CXX, CC, GMP, GUARD_CF, STATIC_BIN, GIT_HASH, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, LOG_SYNC, SINGLE_THREADED global CXX, CC, GMP, GUARD_CF, STATIC_BIN, GIT_HASH, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG, FPMATH_FLAGS, LOG_SYNC, SINGLE_THREADED
if IS_WINDOWS: if IS_WINDOWS:
CXXFLAGS = '/nologo /Zi /D WIN32 /D _WINDOWS /EHsc /GS /Gd /std:c++17'
config.write( config.write(
'CC=cl\n' 'CC=cl\n'
'CXX=cl\n' 'CXX=cl\n'
@ -2438,7 +2439,7 @@ def mk_config():
'SLINK_FLAGS=/nologo /LDd\n' % static_opt) 'SLINK_FLAGS=/nologo /LDd\n' % static_opt)
if VS_X64: if VS_X64:
config.write( 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( 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' '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)) '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) exit(1)
else: else:
config.write( 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( 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' '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)) '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 extra_opt = '%s /D _TRACE ' % extra_opt
if VS_X64: if VS_X64:
config.write( 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( config.write(
'LINK_EXTRA_FLAGS=/link%s /profile /MACHINE:X64 /SUBSYSTEM:CONSOLE /STACK:8388608 %s\n' '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)) '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) exit(1)
else: else:
config.write( 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( 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' '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)) '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: if GIT_HASH:
CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH) CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH)
CXXFLAGS = '%s -std=c++17' % CXXFLAGS 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) FPMATH = test_fpmath(CXX)
CXXFLAGS = '%s %s' % (CXXFLAGS, FPMATH_FLAGS) CXXFLAGS = '%s %s' % (CXXFLAGS, FPMATH_FLAGS)
if LOG_SYNC: if LOG_SYNC:

View file

@ -181,10 +181,10 @@ def exec_cmds(cmds):
def mk_z3(x64): def mk_z3(x64):
cmds = [] cmds = []
if x64: 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) cmds.append('cd %s' % BUILD_X64_DIR)
else: 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('cd %s' % BUILD_X86_DIR)
cmds.append('nmake') cmds.append('nmake')
if exec_cmds(cmds) != 0: if exec_cmds(cmds) != 0:

View file

@ -93,7 +93,7 @@ stages:
- task: CmdLine@2 - task: CmdLine@2
inputs: inputs:
script: 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 python scripts\mk_win_dist.py
--x86-only --x86-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
@ -116,7 +116,7 @@ stages:
- task: CmdLine@2 - task: CmdLine@2
inputs: inputs:
script: 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 python scripts\mk_win_dist.py
--x64-only --x64-only
--dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk

View file

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

View file

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

View file

@ -295,6 +295,8 @@ bool lackr::collect_terms() {
} }
if (m_autil.is_as_array(curr, f)) if (m_autil.is_as_array(curr, f))
m_non_funs.mark(f, true); 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; break;
} }
case AST_QUANTIFIER: case AST_QUANTIFIER:

View file

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

File diff suppressed because it is too large Load diff

View file

@ -12,12 +12,14 @@ from fractions import Fraction
from .z3 import _get_ctx from .z3 import _get_ctx
def _to_numeral(num, ctx=None): def _to_numeral(num, ctx=None):
if isinstance(num, Numeral): if isinstance(num, Numeral):
return num return num
else: else:
return Numeral(num, ctx) return Numeral(num, ctx)
class Numeral: class Numeral:
""" """
A Z3 numeral can be used to perform computations over arbitrary A Z3 numeral can be used to perform computations over arbitrary
@ -85,6 +87,7 @@ class Numeral:
[2.8538479564?] [2.8538479564?]
""" """
def __init__(self, num, ctx=None): def __init__(self, num, ctx=None):
if isinstance(num, Ast): if isinstance(num, Ast):
self.ast = num self.ast = num
@ -151,7 +154,6 @@ class Numeral:
assert(self.is_rational()) assert(self.is_rational())
return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx) return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx)
def is_irrational(self): def is_irrational(self):
""" Return True if the numeral is irrational. """ Return True if the numeral is irrational.
@ -169,7 +171,7 @@ class Numeral:
""" """
assert(self.is_integer()) 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())) return int(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
else: else:
return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast())) return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast()))
@ -440,7 +442,6 @@ class Numeral:
""" """
return self < other return self < other
def __le__(self, other): def __le__(self, other):
""" Return True if `self <= other`. """ Return True if `self <= other`.
@ -523,6 +524,7 @@ class Numeral:
def ctx_ref(self): def ctx_ref(self):
return self.ctx.ref() return self.ctx.ref()
def eval_sign_at(p, vs): def eval_sign_at(p, vs):
""" """
Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3 Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3
@ -547,6 +549,7 @@ def eval_sign_at(p, vs):
_vs[i] = vs[i].ast _vs[i] = vs[i].ast
return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs) return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs)
def isolate_roots(p, 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
@ -573,5 +576,4 @@ def isolate_roots(p, vs=[]):
for i in range(num): for i in range(num):
_vs[i] = vs[i].ast _vs[i] = vs[i].ast
_roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx) _roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx)
return [ Numeral(r) for r in _roots ] return [Numeral(r) for r in _roots]

View file

@ -8,6 +8,7 @@
from .z3 import * from .z3 import *
def subresultants(p, q, x): def subresultants(p, q, x):
""" """
Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'. Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'.
@ -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) return AstVector(Z3_polynomial_subresultants(p.ctx_ref(), p.as_ast(), q.as_ast(), x.as_ast()), p.ctx)
if __name__ == "__main__": if __name__ == "__main__":
import doctest import doctest
if doctest.testmod().failed: if doctest.testmod().failed:

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@
from .z3 import * from .z3 import *
from .z3core import * from .z3core import *
from .z3printer import * from .z3printer import *
from fractions import Fraction
def _to_rcfnum(num, ctx=None): def _to_rcfnum(num, ctx=None):
if isinstance(num, RCFNum): if isinstance(num, RCFNum):
@ -20,20 +20,24 @@ def _to_rcfnum(num, ctx=None):
else: else:
return RCFNum(num, ctx) return RCFNum(num, ctx)
def Pi(ctx=None): def Pi(ctx=None):
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_pi(ctx.ref()), ctx) return RCFNum(Z3_rcf_mk_pi(ctx.ref()), ctx)
def E(ctx=None): def E(ctx=None):
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_e(ctx.ref()), ctx) return RCFNum(Z3_rcf_mk_e(ctx.ref()), ctx)
def MkInfinitesimal(name="eps", ctx=None): def MkInfinitesimal(name="eps", ctx=None):
# Todo: remove parameter name. # Todo: remove parameter name.
# For now, we keep it for backward compatibility. # For now, we keep it for backward compatibility.
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
return RCFNum(Z3_rcf_mk_infinitesimal(ctx.ref()), ctx) return RCFNum(Z3_rcf_mk_infinitesimal(ctx.ref()), ctx)
def MkRoots(p, ctx=None): def MkRoots(p, ctx=None):
ctx = z3.get_ctx(ctx) ctx = z3.get_ctx(ctx)
num = len(p) num = len(p)
@ -50,6 +54,7 @@ def MkRoots(p, ctx=None):
r.append(RCFNum(_rs[i], ctx)) r.append(RCFNum(_rs[i], ctx))
return r return r
class RCFNum: class RCFNum:
def __init__(self, num, ctx=None): def __init__(self, num, ctx=None):
# TODO: add support for converting AST numeral values into RCFNum # TODO: add support for converting AST numeral values into RCFNum

View file

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

View file

@ -14,6 +14,7 @@ import common_z3 as CM_Z3
import ctypes import ctypes
from .z3 import * from .z3 import *
def vset(seq, idfun=None, as_list=True): 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 # This function is from https://code.google.com/p/common-python-vu/source/browse/vu_common.py
@ -32,7 +33,7 @@ def vset(seq, idfun=None, as_list=True):
d_[s] = None d_[s] = None
yield s yield s
def _uniq_idfun(seq,idfun): def _uniq_idfun(seq, idfun):
d_ = {} d_ = {}
for s in seq: for s in seq:
h_ = idfun(s) h_ = idfun(s)
@ -43,7 +44,7 @@ def vset(seq, idfun=None, as_list=True):
if idfun is None: if idfun is None:
res = _uniq_normal(seq) res = _uniq_normal(seq)
else: else:
res = _uniq_idfun(seq,idfun) res = _uniq_idfun(seq, idfun)
return list(res) if as_list else res return list(res) if as_list else res
@ -53,7 +54,7 @@ def get_z3_version(as_str=False):
minor = ctypes.c_uint(0) minor = ctypes.c_uint(0)
build = ctypes.c_uint(0) build = ctypes.c_uint(0)
rev = ctypes.c_uint(0) rev = ctypes.c_uint(0)
Z3_get_version(major,minor, build, rev) Z3_get_version(major, minor, build, rev)
rs = map(int, (major.value, minor.value, build.value, rev.value)) rs = map(int, (major.value, minor.value, build.value, rev.value))
if as_str: if as_str:
return "{}.{}.{}.{}".format(*rs) return "{}.{}.{}.{}".format(*rs)
@ -87,6 +88,7 @@ In Z3, variables are called *uninterpreted* consts and
variables are *interpreted* consts. variables are *interpreted* consts.
""" """
def is_expr_var(v): def is_expr_var(v):
""" """
EXAMPLES: EXAMPLES:
@ -111,7 +113,8 @@ def is_expr_var(v):
True 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): def is_expr_val(v):
""" """
@ -136,12 +139,10 @@ def is_expr_val(v):
>>> is_expr_val(SafetyInjection) >>> is_expr_val(SafetyInjection)
False 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') >>> x,y = Ints('x y')
>>> a,b = Bools('a b') >>> a,b = Bools('a b')
@ -158,8 +159,8 @@ def get_vars(f, rs = None):
if is_const(f): if is_const(f):
if is_expr_val(f): if is_expr_val(f):
return rs return rs
else: #variable else: # variable
return vset(rs + [f],str) return vset(rs + [f], str)
else: else:
for f_ in f.children(): for f_ in f.children():
@ -168,7 +169,6 @@ def get_vars(f, rs = None):
return vset(rs, str) return vset(rs, str)
def mk_var(name, vsort): def mk_var(name, vsort):
if vsort.kind() == Z3_INT_SORT: if vsort.kind() == Z3_INT_SORT:
v = Int(name) v = Int(name)
@ -179,13 +179,12 @@ def mk_var(name, vsort):
elif vsort.kind() == Z3_DATATYPE_SORT: elif vsort.kind() == Z3_DATATYPE_SORT:
v = Const(name, vsort) v = Const(name, vsort)
else: 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 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) >>> r,m = prove(BoolVal(True),verbose=0); r,model_str(m,as_str=False)
(True, None) (True, None)
@ -236,51 +235,51 @@ def prove(claim,assume=None,verbose=0):
to_prove = claim to_prove = claim
if assume: if assume:
if z3_debug(): if z3_debug():
is_proved,_ = prove(Not(assume)) is_proved, _ = prove(Not(assume))
def _f(): def _f():
emsg = "Assumption is always False!" emsg = "Assumption is always False!"
if verbose >= 2: if verbose >= 2:
emsg = "{}\n{}".format(assume,emsg) emsg = "{}\n{}".format(assume, emsg)
return 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: if verbose >= 2:
print('assume: ') print("assume: ")
print(assume) print(assume)
print('claim: ') print("claim: ")
print(claim) print(claim)
print('to_prove: ') print("to_prove: ")
print(to_prove) print(to_prove)
f = Not(to_prove) f = Not(to_prove)
models = get_models(f,k=1) models = get_models(f, k=1)
if models is None: #unknown if models is None: # unknown
print('E: cannot solve !') print("E: cannot solve !")
return None, None return None, None
elif models == False: #unsat elif models is False: # unsat
return True,None return True, None
else: #sat else: # sat
if z3_debug(): if z3_debug():
assert isinstance(models,list) assert isinstance(models, list)
if models: if models:
return False, models[0] #the first counterexample return False, models[0] # the first counterexample
else: 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. Returns the first k models satisfiying f.
If f is not satisfiable, returns False. If f is not satisfiable, returns False.
If f cannot be solved, returns None If f cannot be solved, returns None
If f is satisfiable, returns the first k models 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 Based on http://stackoverflow.com/questions/11867611/z3py-checking-all-solutions-for-equation
@ -323,16 +322,14 @@ def get_models(f,k):
while s.check() == sat and i < k: while s.check() == sat and i < k:
i = i + 1 i = i + 1
m = s.model() m = s.model()
if not m: #if m == [] if not m: # if m == []
break break
models.append(m) 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])) block = Not(And([v() == m[v] for v in m]))
s.add(block) s.add(block)
if s.check() == unknown: if s.check() == unknown:
return None return None
elif s.check() == unsat and i == 0: elif s.check() == unsat and i == 0:
@ -340,7 +337,8 @@ def get_models(f,k):
else: else:
return models return models
def is_tautology(claim,verbose=0):
def is_tautology(claim, verbose=0):
""" """
>>> is_tautology(Implies(Bool('x'),Bool('x'))) >>> is_tautology(Implies(Bool('x'),Bool('x')))
True True
@ -355,10 +353,10 @@ def is_tautology(claim,verbose=0):
False 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') >>> x,y=Bools('x y')
>>> is_contradiction(BoolVal(False)) >>> is_contradiction(BoolVal(False))
@ -380,7 +378,7 @@ def is_contradiction(claim,verbose=0):
True 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): def exact_one_model(f):
@ -403,15 +401,14 @@ def exact_one_model(f):
False False
""" """
models = get_models(f,k=2) models = get_models(f, k=2)
if isinstance(models,list): if isinstance(models, list):
return len(models)==1 return len(models) == 1
else: else:
return False return False
def myBinOp(op, *L):
def myBinOp(op,*L):
""" """
>>> myAnd(*[Bool('x'),Bool('y')]) >>> myAnd(*[Bool('x'),Bool('y')])
And(x, y) And(x, y)
@ -445,38 +442,42 @@ def myBinOp(op,*L):
if z3_debug(): if z3_debug():
assert op == Z3_OP_OR or op == Z3_OP_AND or op == Z3_OP_IMPLIES 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] L = L[0]
if z3_debug(): 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 L:
if len(L)==1: if len(L) == 1:
return L[0] return L[0]
if op == Z3_OP_OR: if op == Z3_OP_OR:
return Or(L) return Or(L)
if op == Z3_OP_AND: if op == Z3_OP_AND:
return And(L) return And(L)
return Implies(L[0],L[1]) return Implies(L[0], L[1])
else: else:
return None return None
def myAnd(*L): def myAnd(*L):
return myBinOp(Z3_OP_AND,*L) return myBinOp(Z3_OP_AND, *L)
def myOr(*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) Returned a 'sorted' model (so that it's easier to see)
The model is sorted by its key, The model is sorted by its key,
@ -488,15 +489,14 @@ def model_str(m,as_str=True):
""" """
if z3_debug(): 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 : if m:
vs = [(v,m[v]) for v in m] vs = [(v, m[v]) for v in m]
vs = sorted(vs,key=lambda a,_: str(a)) vs = sorted(vs, key=lambda a, _: str(a))
if as_str: 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: else:
return vs return vs
else: else:
return str(m) if as_str else m return str(m) if as_str else m

View file

@ -433,6 +433,7 @@ public:
app * mk_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(arith_family_id, OP_ADD, arg1, arg2); } app * mk_add(expr * arg1, expr * arg2) 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 * 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_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(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); } app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(arith_family_id, OP_SUB, num_args, args); }

View file

@ -38,39 +38,27 @@ Revision History:
// ----------------------------------- // -----------------------------------
parameter::~parameter() { parameter::~parameter() {
if (m_kind == PARAM_RATIONAL) { if (auto p = std::get_if<rational*>(&m_val)) {
dealloc(m_rational); dealloc(*p);
} }
if (m_kind == PARAM_ZSTRING) { if (auto p = std::get_if<zstring*>(&m_val)) {
dealloc(m_zstring); dealloc(*p);
} }
} }
parameter::parameter(parameter const& other) {
m_kind = PARAM_INT;
m_int = 0;
*this = other;
}
parameter& parameter::operator=(parameter const& other) { parameter& parameter::operator=(parameter const& other) {
if (this == &other) { if (this == &other) {
return *this; 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; if (auto p = std::get_if<zstring*>(&m_val)) {
switch(other.m_kind) { m_val = alloc(zstring, **p);
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;
} }
return *this; return *this;
} }
@ -95,45 +83,40 @@ void parameter::del_eh(ast_manager & m, family_id fid) {
} }
bool parameter::operator==(parameter const & p) const { bool parameter::operator==(parameter const & p) const {
if (m_kind != p.m_kind) return false; if (get_kind() != p.get_kind()) return false;
switch(m_kind) { switch (get_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();
case PARAM_RATIONAL: return get_rational() == p.get_rational(); 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(); 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 parameter::hash() const {
unsigned b = 0; unsigned b = 0;
switch(m_kind) { switch (get_kind()) {
case PARAM_INT: b = m_int; break; case PARAM_INT: b = get_int(); break;
case PARAM_AST: b = m_ast->hash(); break; case PARAM_AST: b = get_ast()->hash(); break;
case PARAM_SYMBOL: b = get_symbol().hash(); break; case PARAM_SYMBOL: b = get_symbol().hash(); break;
case PARAM_RATIONAL: b = get_rational().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_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 { std::ostream& parameter::display(std::ostream& out) const {
switch(m_kind) { switch (get_kind()) {
case PARAM_INT: return out << get_int(); case PARAM_INT: return out << get_int();
case PARAM_SYMBOL: return out << get_symbol(); case PARAM_SYMBOL: return out << get_symbol();
case PARAM_RATIONAL: return out << get_rational(); case PARAM_RATIONAL: return out << get_rational();
case PARAM_AST: return out << "#" << get_ast()->get_id(); case PARAM_AST: return out << '#' << get_ast()->get_id();
case PARAM_DOUBLE: return out << m_dval; case PARAM_DOUBLE: return out << get_double();
case PARAM_EXTERNAL: return out << "@" << m_ext_id; case PARAM_EXTERNAL: return out << '@' << get_ext_id();
case PARAM_ZSTRING: return out << get_zstring(); case PARAM_ZSTRING: return out << get_zstring();
default: default:
UNREACHABLE(); 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) { 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) { void decl_info::init_eh(ast_manager & m) {
for (parameter & p : m_parameters) { for (parameter & p : m_parameters) {
p.init_eh(m); p.init_eh(m);

View file

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

View file

@ -1082,6 +1082,14 @@ namespace datatype {
return r; 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) { bool util::is_enum_sort(sort* s) {
if (!is_datatype(s)) { if (!is_datatype(s)) {
return false; return false;
@ -1243,6 +1251,9 @@ namespace datatype {
defined together in the same mutually recursive definition. defined together in the same mutually recursive definition.
*/ */
bool util::are_siblings(sort * s1, sort * s2) { 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)) { if (!is_datatype(s1) || !is_datatype(s2)) {
return s1 == s2; return s1 == s2;
} }

View file

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

View file

@ -689,7 +689,7 @@ namespace euf {
if (ra->interpreted() && rb->interpreted()) { if (ra->interpreted() && rb->interpreted()) {
explain_eq(justifications, a, ra); explain_eq(justifications, a, ra);
explain_eq(justifications, b, rb); 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); expr_ref eq(m.mk_eq(a->get_expr(), b->get_expr()), m);
m_tmp_eq->m_args[0] = a; m_tmp_eq->m_args[0] = a;

View file

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

View file

@ -276,7 +276,7 @@ struct pull_quant::imp {
if (is_exists(old_q)) { if (is_exists(old_q)) {
result = m.mk_not(new_body); 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()) if (m.proofs_enabled())
m.mk_rewrite(old_q, result); m.mk_rewrite(old_q, result);
return true; return true;

View file

@ -54,7 +54,9 @@ namespace recfun {
unsigned arity, sort* const * domain, sort* range, bool is_generated) unsigned arity, sort* const * domain, sort* range, bool is_generated)
: m(m), m_name(s), : m(m), m_name(s),
m_domain(m, arity, domain), 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_decl(m),
m_rhs(m), m_rhs(m),
m_fid(fid) m_fid(fid)
@ -414,6 +416,16 @@ namespace recfun {
return promise_def(&u(), 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) { 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); u().set_definition(r, d, n_vars, vars, rhs);
for (case_def & c : d.get_def()->get_cases()) { for (case_def & c : d.get_def()->get_cases()) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -432,6 +432,7 @@ br_status seq_rewriter::mk_bool_app_helper(bool is_and, unsigned n, expr* const*
obj_map<expr, expr*> in_re, not_in_re; obj_map<expr, expr*> in_re, not_in_re;
bool found_pair = false; bool found_pair = false;
ptr_buffer<expr> new_args;
for (unsigned i = 0; i < n; ++i) { for (unsigned i = 0; i < n; ++i) {
expr* args_i = args[i]; expr* args_i = args[i];
expr* x = nullptr, *y = nullptr, *z = nullptr; 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); found_pair |= in_re.contains(x);
} }
} }
else
new_args.push_back(args_i);
} }
if (!found_pair) { if (!found_pair) {
return BR_FAILED; return BR_FAILED;
} }
ptr_buffer<expr> new_args;
for (auto const & kv : in_re) { for (auto const & kv : in_re) {
expr* x = kv.m_key; expr* x = kv.m_key;
expr* y = kv.m_value; 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))); 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); result = is_and ? m().mk_and(new_args) : m().mk_or(new_args);
return BR_REWRITE_FULL; 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); m_op_cache.insert(_OP_RE_IS_NULLABLE, r, nullptr, result);
} }
STRACE("seq_verbose", tout << "is_nullable result: " STRACE("seq_verbose", tout << "is_nullable result: "
<< mk_pp(result, m()) << std::endl;); << result << std::endl;);
return result; return result;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -352,7 +352,21 @@ void cmd_context::insert_macro(symbol const& s, unsigned arity, sort*const* doma
else { else {
VERIFY(decls.insert(m(), arity, domain, t)); 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) { 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) { 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 (!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()); 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_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); mc0()->add(fn, t);
if (!m_global_decls) VERIFY(fn->get_range() == t->get_sort());
m_func_decls_stack.push_back(sf_pair(s, fn)); 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) { void cmd_context::model_del(func_decl* f) {
if (!mc0()) m_mcs.set(m_mcs.size() - 1, alloc(generic_model_converter, m(), "cmd_context")); 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)); SASSERT(m_func_decl2alias.contains(f));
m_func_decl2alias.erase(f); m_func_decl2alias.erase(f);
} }
get_recfun_plugin().erase_def(f);
fs.erase(m(), f); fs.erase(m(), f);
if (fs.empty()) if (fs.empty())
m_func_decls.erase(s); m_func_decls.erase(s);
@ -1751,7 +1773,9 @@ void cmd_context::add_declared_functions(model& mdl) {
mdl.register_decl(f, fi); mdl.register_decl(f, fi);
} }
} }
mdl.add_rec_funs();
} }
} }
void cmd_context::display_sat_result(lbool r) { void cmd_context::display_sat_result(lbool r) {

View file

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

View file

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

View file

@ -166,9 +166,9 @@ public:
} }
}; };
class check_sat_using_tactict_cmd : public exec_given_tactic_cmd { class check_sat_using_tactic_cmd : public exec_given_tactic_cmd {
public: public:
check_sat_using_tactict_cmd(): check_sat_using_tactic_cmd():
exec_given_tactic_cmd("check-sat-using") { 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(declare_tactic_cmd));
ctx.insert(alloc(get_user_tactics_cmd)); ctx.insert(alloc(get_user_tactics_cmd));
ctx.insert(alloc(help_tactic_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)); ctx.insert(alloc(apply_tactic_cmd));
install_tactics(ctx); install_tactics(ctx);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -32,22 +32,43 @@ namespace lp {
class int_solver; class int_solver;
class lar_solver; class lar_solver;
class int_gcd_test { 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 int_solver& lia;
class lar_solver& lra; class lar_solver& lra;
unsigned m_next_gcd; unsigned m_next_gcd = 0;
unsigned m_delay; 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();
bool gcd_test_for_row(const static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i); bool gcd_test_for_row(const static_matrix<mpq, numeric_pair<mpq>> & A, unsigned i);
bool ext_gcd_test(const row_strip<mpq> & row, bool ext_gcd_test(const row_strip<mpq> & row);
mpq const & least_coeff,
mpq const & lcm_den,
mpq const & consts);
void fill_explanation_from_fixed_columns(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); void add_to_explanation_from_fixed_or_boxed_column(unsigned j);
bool accumulate_parity(const row_strip<mpq> & row, unsigned least_coeff_index);
public: public:
int_gcd_test(int_solver& lia); int_gcd_test(int_solver& lia);
~int_gcd_test() {}
lia_move operator()(); lia_move operator()();
bool should_apply(); bool should_apply();
}; };

View file

@ -179,6 +179,15 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
default: default:
break; // do nothing 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 } while (this->get_status() != lp_status::FLOATING_POINT_ERROR
&& &&
this->get_status() != lp_status::UNBOUNDED this->get_status() != lp_status::UNBOUNDED
@ -186,21 +195,11 @@ unsigned lp_primal_core_solver<T, X>::solve_with_tableau() {
this->get_status() != lp_status::OPTIMAL this->get_status() != lp_status::OPTIMAL
&& &&
this->get_status() != lp_status::INFEASIBLE 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->current_x_is_feasible() && this->m_look_for_feasible_solution_only)
&& );
this->m_settings.get_cancel_flag() == false);
if (this->m_settings.get_cancel_flag()) { lp_assert(this->get_status() == lp_status::FLOATING_POINT_ERROR
this->set_status(lp_status::CANCELLED);
}
lp_assert(
this->get_status() == lp_status::FLOATING_POINT_ERROR
|| ||
this->get_status() == lp_status::CANCELLED this->get_status() == lp_status::CANCELLED
|| ||

View file

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

View file

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

View file

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

View file

@ -166,7 +166,7 @@ namespace opt {
return true; 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) { bool model_based_opt::invariant(unsigned index, row const& r) {
vector<var> const& vars = r.m_vars; vector<var> const& vars = r.m_vars;
@ -378,6 +378,7 @@ namespace opt {
} }
else if ((value == lub_val && r.m_type == opt::t_lt) || 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)) { (!is_pos && value > lub_val)) {
m_above.push_back(bound_row_index); m_above.push_back(bound_row_index);
lub_val = value; lub_val = value;
@ -424,6 +425,13 @@ namespace opt {
return val; 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 { rational model_based_opt::get_coefficient(unsigned row_id, unsigned var_id) const {
return m_rows[row_id].get_coefficient(var_id); 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) { 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); display(out, r.m_vars, r.m_coeff);
if (r.m_type == opt::t_mod) { if (r.m_type == opt::t_mod) {
out << r.m_type << " " << r.m_mod << " = 0; value: " << r.m_value << "\n"; 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); result = solve_for(glb_index, x, true);
} }
else { else {
result = def(); result = def() + m_var2value[x];
m_var2value[x] = rational::zero();
} }
SASSERT(eval(result) == eval(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");); TRACE("opt1", display(tout << "tableau after replace x by y := v" << y << "\n"););
def result = project(y, compute_def); def result = project(y, compute_def);
if (compute_def) { if (compute_def)
result = (result * D) + u; result = (result * D) + u;
}
SASSERT(!compute_def || eval(result) == eval(x)); SASSERT(!compute_def || eval(result) == eval(x));
return result; return result;
} }
@ -1188,12 +1194,14 @@ namespace opt {
if (ty == t_lt) { if (ty == t_lt) {
SASSERT(compute_def); 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()) { if (m_var2is_int[x] && !a.is_one()) {
row& r1 = m_rows[row_id1]; row& r1 = m_rows[row_id1];
vector<var> coeffs; vector<var> coeffs;
mk_coeffs_without(coeffs, r1.m_vars, x); mk_coeffs_without(coeffs, r1.m_vars, x);
rational c = r1.m_coeff; rational c = mod(-eval(coeffs), a);
add_divides(coeffs, c, a); add_divides(coeffs, c, a);
} }
unsigned_vector const& row_ids = m_var2row_ids[x]; unsigned_vector const& row_ids = m_var2row_ids[x];
@ -1203,7 +1211,8 @@ namespace opt {
if (!visited.contains(row_id2)) { if (!visited.contains(row_id2)) {
visited.insert(row_id2); visited.insert(row_id2);
b = get_coefficient(row_id2, x); b = get_coefficient(row_id2, x);
if (!b.is_zero()) { if (b.is_zero())
continue;
row& dst = m_rows[row_id2]; row& dst = m_rows[row_id2];
switch (dst.m_type) { switch (dst.m_type) {
case t_eq: case t_eq:
@ -1218,7 +1227,6 @@ namespace opt {
} }
} }
} }
}
def result; def result;
if (compute_def) { if (compute_def) {
result = def(m_rows[row_id1], x); result = def(m_rows[row_id1], x);

View file

@ -105,6 +105,8 @@ namespace opt {
rational eval(def const& d) 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); void resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);
void solve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x); void solve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);

View file

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

View file

@ -132,14 +132,20 @@ expr * array_factory::get_fresh_value(sort * s) {
return get_some_value(s); return get_some_value(s);
} }
sort * range = get_array_range(s); sort * range = get_array_range(s);
expr * range_val = m_model.get_fresh_value(range); 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) { if (range_val != nullptr) {
// easy case // easy case
func_interp * fi; func_interp* fi;
expr * val = mk_array_interp(s, fi); expr* val = mk_array_interp(s, fi);
fi->set_else(range_val); fi->set_else(range_val);
return val; return val;
} }
}
TRACE("array_factory_bug", tout << "array fresh value: using fresh index, range: " << mk_pp(range, m_manager) << "\n";); TRACE("array_factory_bug", tout << "array fresh value: using fresh index, range: " << mk_pp(range, m_manager) << "\n";);
expr_ref v1(m_manager), v2(m_manager), w1(m_manager), w2(m_manager); expr_ref v1(m_manager), v2(m_manager), w1(m_manager), w2(m_manager);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -77,8 +77,6 @@ namespace smt2 {
scanner(cmd_context & ctx, std::istream& stream, bool interactive = false); scanner(cmd_context & ctx, std::istream& stream, bool interactive = false);
~scanner() {}
int get_line() const { return m_line; } int get_line() const { return m_line; }
int get_pos() const { return m_pos; } int get_pos() const { return m_pos; }
symbol const & get_id() const { return m_id; } symbol const & get_id() const { return m_id; }

View file

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

View file

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

View file

@ -102,6 +102,8 @@ namespace mbp {
model_evaluator eval(model); model_evaluator eval(model);
eval.set_expand_array_equalities(true); eval.set_expand_array_equalities(true);
TRACE("qe", tout << fmls << "\n";); 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) { for (unsigned i = 0; i < fmls.size(); ++i) {
expr* fml = fmls.get(i), * nfml, * f1, * f2, * f3; expr* fml = fmls.get(i), * nfml, * f1, * f2, * f3;
SASSERT(m.is_bool(fml)); SASSERT(m.is_bool(fml));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -380,16 +380,14 @@ namespace sat {
if (m_config.phase_sticky()) { if (m_config.phase_sticky()) {
unsigned v = 0; unsigned v = 0;
for (var_info& vi : m_vars) { for (var_info& vi : m_vars)
vi.m_bias = s.m_phase[v++] ? 98 : 2; vi.m_bias = s.m_phase[v++] ? 98 : 2;
} }
}
// copy units // copy units
unsigned trail_sz = s.init_trail_size(); 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); add_clause(1, s.m_trail.data() + i);
}
// copy binary clauses // copy binary clauses
{ {
@ -410,9 +408,8 @@ namespace sat {
} }
// copy clauses // copy clauses
for (clause* c : s.m_clauses) { for (clause* c : s.m_clauses)
add_clause(c->size(), c->begin()); add_clause(c->size(), c->begin());
}
m_num_non_binary_clauses = s.m_clauses.size(); 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); }; [&](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 = 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); }; [&](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"); throw default_exception("local search is incomplete with extensions beyond PB");
if (_init) { if (_init) {

View file

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

View file

@ -115,7 +115,6 @@ namespace sat {
public: public:
npn3_finder(solver& s); 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_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_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; } void set_on_orand(std::function<void(literal head, literal a, literal b, literal c)> const& f) { m_on_orand = f; }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -331,6 +331,8 @@ namespace arith {
} }
void solver::new_diseq_eh(euf::th_eq const& e) { 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)); 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)); ctx.push(push_back_vector<svector<std::pair<euf::th_eq, bool>>>(m_delayed_eqs));
} }

View file

@ -275,6 +275,9 @@ namespace arith {
else { else {
if (is_app(n)) { if (is_app(n)) {
internalize_args(to_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); theory_var v = mk_evar(n);
coeffs[vars.size()] = coeffs[index]; coeffs[vars.size()] = coeffs[index];
@ -291,10 +294,9 @@ namespace arith {
st.to_ensure_enode().reset(); st.to_ensure_enode().reset();
for (unsigned i = st.to_ensure_var().size(); i-- > 0; ) { for (unsigned i = st.to_ensure_var().size(); i-- > 0; ) {
expr* n = st.to_ensure_var()[i]; expr* n = st.to_ensure_var()[i];
if (is_app(n)) { if (is_app(n))
internalize_term(to_app(n)); internalize_term(to_app(n));
} }
}
st.to_ensure_var().reset(); st.to_ensure_var().reset();
} }
@ -388,7 +390,6 @@ namespace arith {
return true; return true;
} }
bool solver::internalize_term(expr* term) { bool solver::internalize_term(expr* term) {
if (!has_var(term)) if (!has_var(term))
register_theory_var_in_lar_solver(internalize_def(term)); register_theory_var_in_lar_solver(internalize_def(term));
@ -435,8 +436,8 @@ namespace arith {
theory_var v = mk_evar(t); theory_var v = mk_evar(t);
if (_has_var) if (_has_var)
return v; return v;
theory_var w = mk_evar(n);
internalize_term(n); internalize_term(n);
theory_var w = mk_evar(n);
if (p == 0) { if (p == 0) {
mk_power0_axioms(t, n); mk_power0_axioms(t, n);

View file

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

View file

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

View file

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

View file

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

View file

@ -54,7 +54,6 @@ namespace array {
euf::enode_vector m_lambdas; // equivalent nodes that have beta reduction properties euf::enode_vector m_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_lambdas; // parents that have beta reduction properties
euf::enode_vector m_parent_selects; // parents that use array in select position euf::enode_vector m_parent_selects; // parents that use array in select position
var_data() {}
}; };

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -107,7 +107,7 @@ namespace euf {
TRACE("euf", TRACE("euf",
for (enode* n : m_egraph.nodes()) for (enode* n : m_egraph.nodes())
if (is_relevant(n)) if (is_relevant(n))
tout << "relevant " << mk_bounded_pp(n->get_expr(), m) << "\n";); tout << "relevant " << n->get_expr_id() << " [r" << n->get_root_id() << "]: " << mk_bounded_pp(n->get_expr(), m) << "\n";);
return true; return true;
} }
} }

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