diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 7ac026673..2c8d93acd 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -26,6 +26,10 @@ Version 4.3.2
- Fixed crash reported at http://z3.codeplex.com/workitem/10
+- Removed auxiliary constants created by the nnf tactic from Z3 models.
+
+- Fixed problem in the pretty printer. It was not introducing quotes for attribute names such as |foo:10|.
+
Version 4.3.1
=============
diff --git a/scripts/mk_util.py b/scripts/mk_util.py
index 381f92def..3ffa7e313 100644
--- a/scripts/mk_util.py
+++ b/scripts/mk_util.py
@@ -75,6 +75,8 @@ VER_BUILD=None
VER_REVISION=None
PREFIX='/usr'
GMP=False
+VS_PAR=False
+VS_PAR_NUM=8
def is_windows():
return IS_WINDOWS
@@ -362,6 +364,8 @@ def display_help(exit_code):
if not IS_WINDOWS:
print " -p
, --prefix= installation prefix (default: %s)." % PREFIX
print " -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR
+ else:
+ print " --parallel=num use cl option /MP with 'num' parallel processes"
print " -b , --build= subdirectory where Z3 will be built (default: build)."
print " -d, --debug compile Z3 in debug mode."
print " -t, --trace enable tracing in release mode."
@@ -391,13 +395,13 @@ def display_help(exit_code):
# Parse configuration option for mk_make script
def parse_options():
- global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE
+ global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM
global DOTNET_ENABLED, JAVA_ENABLED, STATIC_LIB, PREFIX, GMP, PYTHON_PACKAGE_DIR
try:
options, remainder = getopt.gnu_getopt(sys.argv[1:],
'b:dsxhmcvtnp:gjy:',
['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj',
- 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir='])
+ 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=', 'parallel='])
except:
print "ERROR: Invalid command line option"
display_help(1)
@@ -429,8 +433,11 @@ def parse_options():
DOTNET_ENABLED = False
elif opt in ('--staticlib'):
STATIC_LIB = True
- elif opt in ('-p', '--prefix'):
+ elif not IS_WINDOWS and opt in ('-p', '--prefix'):
PREFIX = arg
+ elif IS_WINDOWS and opt == '--parallel':
+ VS_PAR = True
+ VS_PAR_NUM = int(arg)
elif opt in ('-y', '--pydir'):
PYTHON_PACKAGE_DIR = arg
mk_dir(PYTHON_PACKAGE_DIR)
@@ -656,8 +663,32 @@ class Component:
out.write(' -I%s' % get_component(dep).to_src_dir)
out.write('\n')
mk_dir(os.path.join(BUILD_DIR, self.build_dir))
- for cppfile in get_cpp_files(self.src_dir):
- self.add_cpp_rules(out, include_defs, cppfile)
+ if VS_PAR and IS_WINDOWS:
+ cppfiles = get_cpp_files(self.src_dir)
+ dependencies = set()
+ for cppfile in cppfiles:
+ dependencies.add(os.path.join(self.to_src_dir, cppfile))
+ self.add_rule_for_each_include(out, cppfile)
+ includes = extract_c_includes(os.path.join(self.src_dir, cppfile))
+ for include in includes:
+ owner = self.find_file(include, cppfile)
+ dependencies.add('%s.node' % os.path.join(owner.build_dir, include))
+ for cppfile in cppfiles:
+ out.write('%s$(OBJ_EXT) ' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0]))
+ out.write(': ')
+ for dep in dependencies:
+ out.write(dep)
+ out.write(' ')
+ out.write('\n')
+ out.write('\t@$(CXX) $(CXXFLAGS) /MP%s $(%s)' % (VS_PAR_NUM, include_defs))
+ for cppfile in cppfiles:
+ out.write(' ')
+ out.write(os.path.join(self.to_src_dir, cppfile))
+ out.write('\n')
+ out.write('\tmove *.obj %s\n' % self.build_dir)
+ else:
+ for cppfile in get_cpp_files(self.src_dir):
+ self.add_cpp_rules(out, include_defs, cppfile)
# Return true if the component should be included in the all: rule
def main_component(self):
@@ -933,10 +964,8 @@ class DLLComponent(Component):
mk_dir(os.path.join(dist_path, 'bin'))
shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name),
'%s.dll' % os.path.join(dist_path, 'bin', self.dll_name))
- if self.static:
- mk_dir(os.path.join(dist_path, 'bin'))
- shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name),
- '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name))
+ shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name),
+ '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name))
class DotNetDLLComponent(Component):
def __init__(self, name, dll_name, path, deps, assembly_info_dir):
@@ -1042,6 +1071,11 @@ class JavaDLLComponent(Component):
def main_component(self):
return is_java_enabled()
+ def mk_win_dist(self, build_path, dist_path):
+ if JAVA_ENABLED:
+ mk_dir(os.path.join(dist_path, 'bin'))
+ shutil.copy('%s.jar' % os.path.join(build_path, self.package_name),
+ '%s.jar' % os.path.join(dist_path, 'bin', self.package_name))
class ExampleComponent(Component):
def __init__(self, name, path):
@@ -1250,12 +1284,12 @@ def mk_config():
'SLINK_FLAGS=/nologo /LDd\n')
if not VS_X64:
config.write(
- 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n'
+ 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n'
'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n'
'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n')
else:
config.write(
- 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n'
+ 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n'
'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n'
'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n')
else:
diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py
index 57ae66b03..dd50a3977 100644
--- a/scripts/mk_win_dist.py
+++ b/scripts/mk_win_dist.py
@@ -16,13 +16,15 @@ import subprocess
import zipfile
from mk_exception import *
from mk_project import *
+import mk_util
BUILD_DIR='build-dist'
-BUILD_X64_DIR='build-dist/x64'
-BUILD_X86_DIR='build-dist/x86'
+BUILD_X64_DIR=os.path.join('build-dist', 'x64')
+BUILD_X86_DIR=os.path.join('build-dist', 'x86')
VERBOSE=True
DIST_DIR='dist'
FORCE_MK=False
+JAVA_ENABLED=True
def set_verbose(flag):
global VERBOSE
@@ -38,8 +40,8 @@ def mk_dir(d):
def set_build_dir(path):
global BUILD_DIR
BUILD_DIR = path
- BUILD_X86_DIR = '%s/x86' % path
- BUILD_X64_DIR = '%s/x64' % path
+ BUILD_X86_DIR = os.path.join(path, 'x86')
+ BUILD_X64_DIR = os.path.join(path, 'x64')
mk_dir(BUILD_X86_DIR)
mk_dir(BUILD_X64_DIR)
@@ -52,16 +54,18 @@ def display_help():
print " -s, --silent do not print verbose messages."
print " -b , --build= subdirectory where x86 and x64 Z3 versions will be built (default: build-dist)."
print " -f, --force force script to regenerate Makefiles."
+ print " --nojava do not include Java bindings in the binary distribution files."
exit(0)
# Parse configuration option for mk_make script
def parse_options():
- global FORCE_MK
+ global FORCE_MK, JAVA_ENABLED
path = BUILD_DIR
options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=',
'help',
'silent',
- 'force'
+ 'force',
+ 'nojava'
])
for opt, arg in options:
if opt in ('-b', '--build'):
@@ -74,18 +78,22 @@ def parse_options():
display_help()
elif opt in ('-f', '--force'):
FORCE_MK = True
+ elif opt == '--nojava':
+ JAVA_ENABLED = False
else:
raise MKException("Invalid command line option '%s'" % opt)
set_build_dir(path)
# Check whether build directory already exists or not
def check_build_dir(path):
- return os.path.exists(path) and os.path.exists('%s/Makefile' % path)
+ return os.path.exists(path) and os.path.exists(os.path.join(path, 'Makefile'))
# Create a build directory using mk_make.py
def mk_build_dir(path, x64):
if not check_build_dir(path) or FORCE_MK:
- opts = ["python", "scripts/mk_make.py", "-b", path]
+ opts = ["python", os.path.join('scripts', 'mk_make.py'), "-b", path]
+ if JAVA_ENABLED:
+ opts.append('--java')
if x64:
opts.append('-x')
if subprocess.call(opts) != 0:
@@ -147,8 +155,12 @@ def mk_dist_dir_core(x64):
else:
platform = "x86"
build_path = BUILD_X86_DIR
- dist_path = '%s/z3-%s.%s.%s-%s' % (DIST_DIR, major, minor, build, platform)
+ dist_path = os.path.join(DIST_DIR, 'z3-%s.%s.%s-%s' % (major, minor, build, platform))
mk_dir(dist_path)
+ if JAVA_ENABLED:
+ # HACK: Propagate JAVA_ENABLED flag to mk_util
+ # TODO: fix this hack
+ mk_util.JAVA_ENABLED = JAVA_ENABLED
mk_win_dist(build_path, dist_path)
if is_verbose():
print "Generated %s distribution folder at '%s'" % (platform, dist_path)
@@ -225,7 +237,7 @@ def cp_vs_runtime_core(x64):
path = '%sredist\\%s' % (vcdir, platform)
VS_RUNTIME_FILES = []
os.path.walk(path, cp_vs_runtime_visitor, '*.dll')
- bin_dist_path = '%s/%s/bin' % (DIST_DIR, get_dist_path(x64))
+ bin_dist_path = os.path.join(DIST_DIR, get_dist_path(x64), 'bin')
for f in VS_RUNTIME_FILES:
shutil.copy(f, bin_dist_path)
if is_verbose():
@@ -236,8 +248,8 @@ def cp_vs_runtime():
cp_vs_runtime_core(False)
def cp_license():
- shutil.copy("LICENSE.txt", "%s/%s" % (DIST_DIR, get_dist_path(True)))
- shutil.copy("LICENSE.txt", "%s/%s" % (DIST_DIR, get_dist_path(False)))
+ shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(True)))
+ shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(False)))
# Entry point
def main():
diff --git a/scripts/trackall.sh b/scripts/trackall.sh
new file mode 100755
index 000000000..d8351af24
--- /dev/null
+++ b/scripts/trackall.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Script for "cloning" (and tracking) all branches at codeplex.
+# On Windows, this script must be executed in the "git Bash" console.
+for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do
+ git branch --track ${branch##*/} $branch
+done
+git fetch --all
+git pull --all
diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp
index afe301ddf..1ad2b8222 100644
--- a/src/ast/ast_smt2_pp.cpp
+++ b/src/ast/ast_smt2_pp.cpp
@@ -501,7 +501,12 @@ class smt2_printer {
}
format * pp_simple_attribute(char const * attr, symbol const & s) {
- return mk_compose(m(), mk_string(m(), attr), mk_string(m(), s.str().c_str()));
+ std::string str;
+ if (is_smt2_quoted_symbol(s))
+ str = mk_smt2_quoted_symbol(s);
+ else
+ str = s.str();
+ return mk_compose(m(), mk_string(m(), attr), mk_string(m(), str.c_str()));
}
format * pp_labels(bool is_pos, buffer const & names, format * f) {
@@ -851,7 +856,7 @@ class smt2_printer {
buf.push_back(pp_simple_attribute(":weight ", q->get_weight()));
}
if (q->get_skid() != symbol::null) {
- buf.push_back(pp_simple_attribute(":skid ", q->get_skid()));
+ buf.push_back(pp_simple_attribute(":skolemid ", q->get_skid()));
}
if (q->get_qid() != symbol::null) {
#if 0
diff --git a/src/ast/normal_forms/defined_names.cpp b/src/ast/normal_forms/defined_names.cpp
index dab0ca0d8..16e9098fc 100644
--- a/src/ast/normal_forms/defined_names.cpp
+++ b/src/ast/normal_forms/defined_names.cpp
@@ -17,11 +17,67 @@ Revision History:
--*/
#include"defined_names.h"
+#include"obj_hashtable.h"
#include"used_vars.h"
#include"var_subst.h"
#include"ast_smt2_pp.h"
#include"ast_pp.h"
+struct defined_names::impl {
+ typedef obj_map expr2name;
+ typedef obj_map expr2proof;
+ ast_manager & m_manager;
+ symbol m_z3name;
+
+ /**
+ \brief Mapping from expressions to their names. A name is an application.
+ If the expression does not have free variables, then the name is just a constant.
+ */
+ expr2name m_expr2name;
+ /**
+ \brief Mapping from expressions to the apply-def proof.
+ That is, for each expression e, m_expr2proof[e] is the
+ proof e and m_expr2name[2] are observ. equivalent.
+
+ This mapping is not used if proof production is disabled.
+ */
+ expr2proof m_expr2proof;
+
+ /**
+ \brief Domain of m_expr2name. It is used to keep the expressions
+ alive and for backtracking
+ */
+ expr_ref_vector m_exprs;
+ expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive.
+ proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive.
+
+
+ unsigned_vector m_lims; //!< Backtracking support.
+
+ impl(ast_manager & m, char const * prefix);
+ virtual ~impl();
+
+ app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names);
+ void cache_new_name(expr * e, app * name);
+ void cache_new_name_intro_proof(expr * e, proof * pr);
+ void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref & result);
+ void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref_buffer & result);
+ virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def);
+ bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
+ void push_scope();
+ void pop_scope(unsigned num_scopes);
+ void reset();
+
+ unsigned get_num_names() const { return m_names.size(); }
+ func_decl * get_name_decl(unsigned i) const { return to_app(m_names.get(i))->get_decl(); }
+};
+
+struct defined_names::pos_impl : public defined_names::impl {
+ pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {}
+ virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def);
+};
+
+
defined_names::impl::impl(ast_manager & m, char const * prefix):
m_manager(m),
m_exprs(m),
@@ -222,5 +278,50 @@ void defined_names::impl::reset() {
m_lims.reset();
}
+defined_names::defined_names(ast_manager & m, char const * fresh_prefix) {
+ m_impl = alloc(impl, m, fresh_prefix);
+ m_pos_impl = alloc(pos_impl, m, fresh_prefix);
+}
+
+defined_names::~defined_names() {
+ dealloc(m_impl);
+ dealloc(m_pos_impl);
+}
+
+bool defined_names::mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) {
+ return m_impl->mk_name(e, new_def, new_def_pr, n, pr);
+}
+
+bool defined_names::mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) {
+ return m_pos_impl->mk_name(e, new_def, new_def_pr, n, pr);
+}
+
+void defined_names::push() {
+ m_impl->push_scope();
+ m_pos_impl->push_scope();
+}
+
+void defined_names::pop(unsigned num_scopes) {
+ m_impl->pop_scope(num_scopes);
+ m_pos_impl->pop_scope(num_scopes);
+}
+
+void defined_names::reset() {
+ m_impl->reset();
+ m_pos_impl->reset();
+}
+
+unsigned defined_names::get_num_names() const {
+ return m_impl->get_num_names() + m_pos_impl->get_num_names();
+}
+
+func_decl * defined_names::get_name_decl(unsigned i) const {
+ SASSERT(i < get_num_names());
+ unsigned n1 = m_impl->get_num_names();
+ return i < n1 ? m_impl->get_name_decl(i) : m_pos_impl->get_name_decl(i - n1);
+}
+
+
+
diff --git a/src/ast/normal_forms/defined_names.h b/src/ast/normal_forms/defined_names.h
index c5e4a116f..0b9f04569 100644
--- a/src/ast/normal_forms/defined_names.h
+++ b/src/ast/normal_forms/defined_names.h
@@ -21,7 +21,6 @@ Revision History:
#define _DEFINED_NAMES_H_
#include"ast.h"
-#include"obj_hashtable.h"
/**
\brief Mapping from expressions to skolem functions that are used to name them.
@@ -29,62 +28,13 @@ Revision History:
The mapping supports backtracking using the methods #push_scope and #pop_scope.
*/
class defined_names {
-
- struct impl {
- typedef obj_map expr2name;
- typedef obj_map expr2proof;
- ast_manager & m_manager;
- symbol m_z3name;
-
- /**
- \brief Mapping from expressions to their names. A name is an application.
- If the expression does not have free variables, then the name is just a constant.
- */
- expr2name m_expr2name;
- /**
- \brief Mapping from expressions to the apply-def proof.
- That is, for each expression e, m_expr2proof[e] is the
- proof e and m_expr2name[2] are observ. equivalent.
-
- This mapping is not used if proof production is disabled.
- */
- expr2proof m_expr2proof;
-
- /**
- \brief Domain of m_expr2name. It is used to keep the expressions
- alive and for backtracking
- */
- expr_ref_vector m_exprs;
- expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive.
- proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive.
-
-
- unsigned_vector m_lims; //!< Backtracking support.
-
- impl(ast_manager & m, char const * prefix);
- virtual ~impl();
-
- app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names);
- void cache_new_name(expr * e, app * name);
- void cache_new_name_intro_proof(expr * e, proof * pr);
- void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref & result);
- void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref_buffer & result);
- virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def);
- bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
- void push_scope();
- void pop_scope(unsigned num_scopes);
- void reset();
- };
-
- struct pos_impl : public impl {
- pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {}
- virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def);
- };
-
- impl m_impl;
- pos_impl m_pos_impl;
+ struct impl;
+ struct pos_impl;
+ impl * m_impl;
+ pos_impl * m_pos_impl;
public:
- defined_names(ast_manager & m, char const * fresh_prefix = "z3name"):m_impl(m, fresh_prefix), m_pos_impl(m, fresh_prefix) {}
+ defined_names(ast_manager & m, char const * fresh_prefix = "z3name");
+ ~defined_names();
// -----------------------------------
//
@@ -113,9 +63,7 @@ public:
Remark: the definitions are closed with an universal quantifier if e contains free variables.
*/
- bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) {
- return m_impl.mk_name(e, new_def, new_def_pr, n, pr);
- }
+ bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
/**
\brief Create a name for a positive occurrence of the expression \c e.
@@ -127,24 +75,14 @@ public:
Remark: the definitions are closed with an universal quantifier if e contains free variables.
*/
- bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) {
- return m_pos_impl.mk_name(e, new_def, new_def_pr, n, pr);
- }
+ bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr);
- void push_scope() {
- m_impl.push_scope();
- m_pos_impl.push_scope();
- }
+ void push();
+ void pop(unsigned num_scopes);
+ void reset();
- void pop_scope(unsigned num_scopes) {
- m_impl.pop_scope(num_scopes);
- m_pos_impl.pop_scope(num_scopes);
- }
-
- void reset() {
- m_impl.reset();
- m_pos_impl.reset();
- }
+ unsigned get_num_names() const;
+ func_decl * get_name_decl(unsigned i) const;
};
#endif /* _DEFINED_NAMES_H_ */
diff --git a/src/muz_qe/dl_mk_extract_quantifiers2.cpp b/src/muz_qe/dl_mk_extract_quantifiers2.cpp
index 33b33f0aa..cd13bb44b 100644
--- a/src/muz_qe/dl_mk_extract_quantifiers2.cpp
+++ b/src/muz_qe/dl_mk_extract_quantifiers2.cpp
@@ -333,7 +333,7 @@ namespace datalog {
smt::quantifier_manager* qm = ctx.get_quantifier_manager();
qm->get_plugin()->set_instance_plugin(alloc(instance_plugin, *this));
#endif
- lbool res = solver.check();
+ solver.check();
for (unsigned i = 0; i < m_bindings.size(); ++i) {
expr_ref_vector& binding = m_bindings[i];
diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp
index ca58b15af..460e07f58 100644
--- a/src/nlsat/nlsat_explain.cpp
+++ b/src/nlsat/nlsat_explain.cpp
@@ -981,6 +981,14 @@ namespace nlsat {
bool atom_val = a->get_kind() == atom::EQ;
bool lit_val = l.sign() ? !atom_val : atom_val;
new_lit = lit_val ? true_literal : false_literal;
+ if (!info.m_lc_const) {
+ // We have essentially shown the current factor must be zero If the leading coefficient is not zero.
+ // Note that, if the current factor is zero, then the whole polynomial is zero.
+ // The atom is true if it is an equality, and false otherwise.
+ // The sign of the leading coefficient (info.m_lc) of info.m_eq doesn't matter.
+ // However, we have to store the fact it is not zero.
+ info.add_lc_diseq();
+ }
return;
}
else if (s == -1 && !is_even) {
@@ -1341,3 +1349,32 @@ namespace nlsat {
}
};
+
+#ifdef Z3DEBUG
+void pp(nlsat::explain::imp & ex, unsigned num, nlsat::literal const * ls) {
+ ex.display(std::cout, num, ls);
+}
+void pp(nlsat::explain::imp & ex, nlsat::scoped_literal_vector & ls) {
+ ex.display(std::cout, ls);
+}
+void pp(nlsat::explain::imp & ex, polynomial_ref const & p) {
+ ex.display(std::cout, p);
+ std::cout << std::endl;
+}
+void pp(nlsat::explain::imp & ex, polynomial::polynomial * p) {
+ polynomial_ref _p(p, ex.m_pm);
+ ex.display(std::cout, _p);
+ std::cout << std::endl;
+}
+void pp(nlsat::explain::imp & ex, polynomial_ref_vector const & ps) {
+ ex.display(std::cout, ps);
+}
+void pp_var(nlsat::explain::imp & ex, nlsat::var x) {
+ ex.display(std::cout, x);
+ std::cout << std::endl;
+}
+void pp_lit(nlsat::explain::imp & ex, nlsat::literal l) {
+ ex.display(std::cout, l);
+ std::cout << std::endl;
+}
+#endif
diff --git a/src/nlsat/nlsat_explain.h b/src/nlsat/nlsat_explain.h
index 08f6201be..5ecb9d385 100644
--- a/src/nlsat/nlsat_explain.h
+++ b/src/nlsat/nlsat_explain.h
@@ -27,7 +27,9 @@ namespace nlsat {
class evaluator;
class explain {
+ public:
struct imp;
+ private:
imp * m_imp;
public:
explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq,
diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp
index 6da2c15f5..5552050db 100644
--- a/src/smt/asserted_formulas.cpp
+++ b/src/smt/asserted_formulas.cpp
@@ -189,7 +189,7 @@ void asserted_formulas::push_scope() {
s.m_asserted_formulas_lim = m_asserted_formulas.size();
SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead);
s.m_inconsistent_old = m_inconsistent;
- m_defined_names.push_scope();
+ m_defined_names.push();
m_bv_sharing.push_scope();
commit();
}
@@ -201,7 +201,7 @@ void asserted_formulas::pop_scope(unsigned num_scopes) {
unsigned new_lvl = m_scopes.size() - num_scopes;
scope & s = m_scopes[new_lvl];
m_inconsistent = s.m_inconsistent_old;
- m_defined_names.pop_scope(num_scopes);
+ m_defined_names.pop(num_scopes);
m_asserted_formulas.shrink(s.m_asserted_formulas_lim);
if (m_manager.proofs_enabled())
m_asserted_formula_prs.shrink(s.m_asserted_formulas_lim);
diff --git a/src/smt/params/qi_params.h b/src/smt/params/qi_params.h
index b0a21e75b..0cd817f22 100644
--- a/src/smt/params/qi_params.h
+++ b/src/smt/params/qi_params.h
@@ -52,8 +52,6 @@ struct qi_params {
bool m_mbqi_trace;
unsigned m_mbqi_force_template;
- bool m_instgen;
-
qi_params(params_ref const & p = params_ref()):
/*
The "weight 0" performance bug
@@ -99,8 +97,7 @@ struct qi_params {
m_mbqi_max_cexs_incr(1),
m_mbqi_max_iterations(1000),
m_mbqi_trace(false),
- m_mbqi_force_template(10),
- m_instgen(false) {
+ m_mbqi_force_template(10) {
updt_params(p);
}
diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp
index e62a3de21..519302c19 100644
--- a/src/smt/params/smt_params.cpp
+++ b/src/smt/params/smt_params.cpp
@@ -18,6 +18,7 @@ Revision History:
--*/
#include"smt_params.h"
#include"smt_params_helper.hpp"
+#include"model_params.hpp"
void smt_params::updt_local_params(params_ref const & _p) {
smt_params_helper p(_p);
@@ -33,6 +34,8 @@ void smt_params::updt_local_params(params_ref const & _p) {
m_delay_units_threshold = p.delay_units_threshold();
m_preprocess = _p.get_bool("preprocess", true); // hidden parameter
m_soft_timeout = p.soft_timeout();
+ model_params mp(_p);
+ m_model_compact = mp.compact();
if (_p.get_bool("arith.greatest_error_pivot", false))
m_arith_pivot_strategy = ARITH_PIVOT_GREATEST_ERROR;
else if (_p.get_bool("arith.least_error_pivot", false))
@@ -50,5 +53,4 @@ void smt_params::updt_params(params_ref const & p) {
void smt_params::updt_params(context_params const & p) {
m_auto_config = p.m_auto_config;
m_model = p.m_model;
- m_model_validate = p.m_model_validate;
}
diff --git a/src/smt/params/smt_params.h b/src/smt/params/smt_params.h
index 3d823cb51..256c5a646 100644
--- a/src/smt/params/smt_params.h
+++ b/src/smt/params/smt_params.h
@@ -177,7 +177,6 @@ struct smt_params : public preprocessor_params,
// -----------------------------------
bool m_model;
bool m_model_compact;
- bool m_model_validate;
bool m_model_on_timeout;
bool m_model_on_final_check;
@@ -264,7 +263,6 @@ struct smt_params : public preprocessor_params,
m_abort_after_preproc(false),
m_model(true),
m_model_compact(false),
- m_model_validate(false),
m_model_on_timeout(false),
m_model_on_final_check(false),
m_progress_sampling_freq(0),
diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp
index b3f16a3ce..42e761b61 100644
--- a/src/smt/smt_internalizer.cpp
+++ b/src/smt/smt_internalizer.cpp
@@ -23,7 +23,6 @@ Revision History:
#include"ast_smt2_pp.h"
#include"smt_model_finder.h"
#include"for_each_expr.h"
-#include"theory_instgen.h"
namespace smt {
@@ -530,11 +529,6 @@ namespace smt {
SASSERT(!b_internalized(q));
SASSERT(q->is_forall());
SASSERT(check_patterns(q));
- if (m_fparams.m_instgen) {
- theory* th = m_theories.get_plugin(m_manager.get_family_id("inst_gen"));
- static_cast(th)->internalize_quantifier(q);
- return;
- }
bool_var v = mk_bool_var(q);
unsigned generation = m_generation;
unsigned _generation;
diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp
index ac31eb1a9..f0dc1f5a6 100644
--- a/src/smt/smt_setup.cpp
+++ b/src/smt/smt_setup.cpp
@@ -28,7 +28,6 @@ Revision History:
#include"theory_datatype.h"
#include"theory_dummy.h"
#include"theory_dl.h"
-#include"theory_instgen.h"
#include"theory_seq_empty.h"
namespace smt {
@@ -772,11 +771,6 @@ namespace smt {
void setup::setup_seq() {
m_context.register_plugin(alloc(theory_seq_empty, m_manager));
}
- void setup::setup_instgen() {
- if (m_params.m_instgen) {
- m_context.register_plugin(mk_theory_instgen(m_manager, m_params));
- }
- }
void setup::setup_unknown() {
setup_arith();
@@ -784,7 +778,6 @@ namespace smt {
setup_bv();
setup_datatypes();
setup_dl();
- setup_instgen();
setup_seq();
}
diff --git a/src/smt/theory_instgen.cpp b/src/smt/theory_instgen.cpp
deleted file mode 100644
index 68e04aab0..000000000
--- a/src/smt/theory_instgen.cpp
+++ /dev/null
@@ -1,1494 +0,0 @@
-/*++
-Copyright (c) 2011 Microsoft Corporation
-
-Module Name:
-
- theory_instgen.cpp
-
-Abstract:
-
- iProver style theory solver.
- It provides an instantiation based engine
- based on InstGen methods together with
- unit propagation.
-
-Author:
-
- Krystof Hoder (t-khoder)
- Nikolaj Bjorner (nbjorner) 2011-10-6
-
-Revision History:
-
-Main data-structures:
-
-- Instantiation = Var -> Expr
-- MatchingSet = Instantiation-set
- operations:
- - has_instance : Instantiation -> Bool
- has_instance(i) = exists j in MatchingSet . j <= i
-- UnificationIndex
- operations:
- - insert : Expr
- - remove : Expr
- - unify : Expr -> Expr-set
- - set of inserted expressions that unify
-- RootClauseMap : Expr -> Quantifier
- where RootClauseMap(clause) = The quantifier that originated clause
-- Occurs : Expr -> Quantifier-set
- the set of quantifiers where non-ground literal occurs.
-- LiteralMeanings : Literal -> Expr-set
- - set of non-ground literals that were grounded to Literal
-- InternalizedFoLits : Expr-set
- - forall e in InternalizedFoLits . e \in LiteralMeanings(ground(e))
-- MatchingSets : Quantifier -> MatchingSet
-
-
-Main operation:
-
- - insert all assigned literals into UnificationIndex
- - for l' in LiteralMeanings(l) do:
- for m',theta in UnificationIndex.unify(not l') do:
- for q in Occurs(l') do:
- for q' in Occurs(m') do:
- instantiate q with theta
- instantiate q' with theta
-
- instantiate q with theta:
-
-Discussion of plans:
-
-- Efficient unit propagation using the tables from dl_
- See addittional notes under unit propagation.
- The idea is to perfrm unit propagation using the tables
- provided in the dl_ module. This is similar to unit
- propagation from the EPR solver and retains succinctness
- features, but does not carry over the splitting component.
- The efficient propagator is aimed at solving ground problems more efficiently,
- for example
-
-- Reduce set of selected literals when clause already has on selected literal.
-
-- Subsumption module:
- - simplify clause using already asserted clauses.
- - check for variants.
-
-- Completeness for EPR with equality:
- The relevant equality clause for EPR are C \/ x = y and C \/ a = x
- Destructive E-resolution (DER) removes disequalities.
- Two approaches:
- 1. Rely on super-position/hyper-resolution of ordinary literals
- in the clause.
- 2. Instantiate based on congruence closure.
- The instantiation based approach takes a clause of the form C \/ x = y,
- where all other non-equality literals in C are assigned false by the
- current assignment, and (the grounded version U = U' of) x = y is
- assigned true. Take the equivalence classes of the type of x and
- instantiate x, y using representatives for different equivalence
- classes. The number of instantiations is potentially quadratic
- in the number of terms. One reduction considers symmetries:
- instantiate x by a smaller representative than y.
-- Unit propagation:
- - Why should unit-propagation matter: hunch: similar role as
- theory propagation where conflicts are created close to root
- of search tree.
- - Add theory identifiers to literals so that assign_eh is invoked.
- - Produce explanation objects for unit propagation.
- - Unit propagation index.
- - Idea only propagate known literals
-- Exchange unit literals with super position engine for equalities.
- iProver approach: perform unit super-position proof, get instances
- by labeling equalities by clauses + substitution (set-labeling)
- portfolio approach: exchange unit literals to super-position
- (or hypotheses as suggested in more general setting).
-
---*/
-
-#include "theory_instgen.h"
-#include "value_factory.h"
-#include "smt_model_generator.h"
-#include "smt_context.h"
-#include "ast_smt2_pp.h"
-#include "substitution.h"
-#include "substitution_tree.h"
-#include "uint_set.h"
-#include "unifier.h"
-#include "matcher.h"
-#include "rewriter.h"
-#include "rewriter_def.h"
-#include "var_subst.h"
-
-#define PP mk_pp
-
-namespace smt {
-
-
- //
- // expression grounding for passing to the SMT solver
- //
- class grounder {
- ast_manager& m;
- vector > m_defaults;
- expr_ref_vector m_ref_holder;
-
- class grounding_rewriter_cfg;
-
- void reserve(unsigned idx) {
- if (m_defaults.size() <= idx) {
- m_defaults.resize(idx+1);
- }
- }
-
- expr* mk_default(sort* s) {
- return mk_default(0, s);
- }
-
- expr* mk_default(unsigned i, sort* s) {
- expr* d;
- reserve(i);
- if (!m_defaults[i].find(s, d)) {
- d = m.mk_fresh_const("U",s);
- m_defaults[i].insert(s, d);
- m_ref_holder.push_back(d);
- }
- return d;
- }
-
- class grounding_rewriter_cfg : public default_rewriter_cfg {
- grounder& m_parent;
- bool m_collapse;
- public:
- grounding_rewriter_cfg(grounder& parent, bool collapse)
- : m_parent(parent), m_collapse(collapse) {}
-
- bool get_subst(expr * s, expr * & t, proof * & t_pr) {
- SASSERT(is_app(s) || is_var(s));
- if (is_var(s)) {
- var* v = to_var(s);
- if (m_collapse) {
- t = m_parent.mk_default(v->get_sort());
- }
- else {
- t = m_parent.mk_default(v->get_idx(), v->get_sort());
- }
- }
- return is_var(s);
- }
- };
-
- void mk(expr * e, app_ref& res, bool collapse) {
- if(is_ground(e)) {
- res = to_app(e);
- }
- else {
- while (is_quantifier(e)) {
- e = to_quantifier(e)->get_expr();
- }
- SASSERT(is_app(e));
- grounding_rewriter_cfg r_cfg(*this, collapse);
- rewriter_tpl rwr(m, false, r_cfg);
- expr_ref res_e(m);
- rwr(e, res_e);
- res = to_app(res_e);
- }
- SASSERT(is_ground(res.get()));
- }
-
- public:
- grounder(ast_manager& m): m(m), m_ref_holder(m) {
- reserve(0);
- }
-
- /**
- create a grounding that recycles the same constant for
- different variables of the same sort.
-
- This function can be called either with whole clauses (incl. quantifier),
- or with literals one by one (without a quantifier)
- */
- void operator()(expr * e, app_ref& res) {
- mk(e, res, true);
- }
-
- //
- // create a grounding where different variables have different names
- //
- void mk_diff(expr * e, app_ref& res) {
- mk(e, res, false);
- }
- };
-
- //
- // Class for first-order subsumption checking.
- // if clause[renaming] is a superset of existing clause in context, then clause is subsumed.
- // if context => clause then clause is subsumed.
- // if context & clause => ~ lit then lit is subsumed from clause
- //
- // TBD:
- // - check unit propagation
- // - use internalizer functions directly. The assertions have already been pre-processed.
- //
- class clause_subsumption {
- ast_manager& m;
- grounder m_grounder;
- smt_params m_params;
- context m_ctx;
- quantifier_ref_vector m_assumptions;
- unsigned_vector m_limit;
- public:
- clause_subsumption(ast_manager& m, smt_params& p):
- m(m), m_grounder(m), m_params(p), m_ctx(m,m_params), m_assumptions(m) {
- m_params.m_instgen = false;
- }
-
- void simplify(quantifier* new_clause, expr_ref& result, ptr_vector& assumptions) {
-#if 1
- result = new_clause;
- return;
-#endif
-
- SASSERT(new_clause->is_forall());
- expr* body = new_clause->get_expr();
- app_ref ground_clause(m);
- m_grounder.mk_diff(new_clause, ground_clause);
- if (is_subsumed(ground_clause)) {
- TRACE("theory_instgen", tout << "subsumed: " << PP(new_clause,m) << "\n";);
- result = m.mk_true();
- return;
- }
- if (is_homomorphic_image(body)) {
- result = m.mk_true();
- return;
- }
- // Assert the current clause.
- m_ctx.internalize(ground_clause, true);
- m_ctx.assign(m_ctx.get_literal(ground_clause), b_justification());
- TRACE("theory_instgen", tout << "Asserting: " << PP(ground_clause,m) << "\n";);
- m_assumptions.push_back(new_clause);
- SASSERT(m.is_or(body) == m.is_or(ground_clause));
- if (!m.is_or(body)) {
- result = new_clause;
- return;
- }
- SASSERT(to_app(body)->get_num_args() == ground_clause->get_num_args());
- ptr_vector lits;
- for (unsigned i = 0; i < to_app(body)->get_num_args(); ++i) {
- m_ctx.push();
- m_ctx.assign(m_ctx.get_literal(ground_clause->get_arg(i)), b_justification());
- lbool is_sat = m_ctx.check();
- m_ctx.pop(1);
- if (is_sat != l_false) {
- lits.push_back(to_app(body)->get_arg(i));
- }
- else {
- TRACE("theory_instgen", tout << "subsumed literal: " << PP(to_app(body)->get_arg(i),m) << "\n";);
- }
- }
- if (lits.size() == ground_clause->get_num_args()) {
- result = new_clause;
- }
- else {
- SASSERT(!lits.empty());
- result = lits.size()==1?lits[0]:m.mk_or(lits.size(), lits.c_ptr());
- result = m.update_quantifier(new_clause, result);
- TRACE("theory_instgen", tout << "simplified: " << PP(new_clause,m) << "\n";
- tout << PP(result.get(), m) << "\n";
- );
- //overapproximation of required assumptions
- //( m_assumptions.size()-1 ... the -1 is not to make ourselves as an assumption)
- assumptions.append(m_assumptions.size()-1, m_assumptions.c_ptr());
- }
- }
-
- void push() {
- m_ctx.push();
- m_limit.push_back(m_assumptions.size());
- }
-
- void pop(unsigned num_scopes) {
- m_ctx.pop(num_scopes);
-
- unsigned last_idx = m_limit.size()-num_scopes;
- unsigned restored_assumptions_size = m_limit[last_idx];
- m_limit.resize(last_idx);
- m_assumptions.resize(restored_assumptions_size);
- }
-
- private:
-
- bool is_subsumed(expr* ground_clause) {
- m_ctx.push();
- m_ctx.internalize(ground_clause, true);
- m_ctx.assign(~m_ctx.get_literal(ground_clause), b_justification());
- lbool is_sat = m_ctx.check();
- m_ctx.pop(1);
- TRACE("theory_instgen",
- tout << PP(ground_clause, m) << " " <<
- ((is_sat==l_false)?"unsat":"sat") << "\n";);
- return (is_sat == l_false);
- }
-
- bool is_homomorphic_image(expr* body) {
- // TBD
- return false;
- }
-
- };
-
- class fo_clause_internalizer;
- class instantiator;
- class theory_instgen_impl;
- typedef expr_ref_vector inst;
-
- class instantiation_result {
- quantifier_ref m_clause;
- inst m_subst;
- public:
- instantiation_result(ast_manager& m) : m_clause(m), m_subst(m) {}
-
- void init(quantifier * q, const inst& subst) {
- SASSERT(!m_clause); //we init each object at most once
- SASSERT(m_subst.empty());
- SASSERT(q);
- m_clause = q;
- m_subst.append(subst);
- }
- quantifier * clause() const { return m_clause; }
- const inst& subst() const { return m_subst; }
- };
-
- typedef vector instantiation_result_vector;
-
- // TBD: replace this by the substitution tree index.
- // It should do the trick of identifying instances and generalizers.
- // see matching_set2..
- //
- class matching_set {
- ast_manager& m;
- vector m_inst;
-
- //used in the has_instance function
- mutable substitution m_subst;
-
- public:
- matching_set(ast_manager& m) : m(m), m_subst(m) {}
- unsigned size() const { return m_inst.size(); }
- inst const& operator[](unsigned i) const { return m_inst[i]; }
-
- void insert(inst const& inst) {
- SASSERT(m_inst.empty() || m_inst.back().size() == inst.size());
- TRACE("theory_instgen_verbose",
- for (unsigned i = 0; i < inst.size(); ++i) {
- tout << PP(inst[i], m) << " ";
- }
- tout << "\n";
- );
- m_inst.push_back(inst);
- }
- void insert(unsigned sz, expr* const* exprs) {
- insert(inst(m, sz, exprs));
- }
- void pop_insert() { m_inst.pop_back(); }
-
- bool has_instance(inst const& inst) {
- unsigned dont_care;
- return has_instance(inst, dont_care);
- }
-
- bool has_instance(inst const& new_inst, unsigned& index) {
- for (unsigned i = 0; i < size(); ++i) {
- if (has_instance(new_inst, m_inst[i])) {
- index = i;
- return true;
- }
- }
- return false;
- }
-
- class insert_inst : public trail {
- matching_set& m_ms;
- public:
- insert_inst(matching_set& m): m_ms(m) {}
- virtual void undo(smt::context& ctx) { m_ms.pop_insert(); }
- };
-
- static bool is_identity(const inst& subst) {
- uint_set vars;
- vars.reset();
- unsigned sz = subst.size();
- for(unsigned i=0; iget_idx();
- if(vars.contains(var_idx)) {
- return false;
- }
- vars.insert(var_idx);
- }
- return true;
- }
-
- private:
- // check if old_instance is an instance of new_instance.
- bool has_instance(inst const& new_instance, inst const& old_instance) const {
- SASSERT(new_instance.size() == old_instance.size());
- unsigned sz = new_instance.size();
- m_subst.reset();
- m_subst.reserve_vars(sz);
- m_subst.reserve_offsets(2);
- matcher mtchr(m);
- for(unsigned i = 0; i < sz; i++) {
- TRACE("theory_instgen_verbose", tout << PP(new_instance[i], m) << " " << PP(old_instance[i], m) << "\n";);
- if(!mtchr(new_instance[i], old_instance[i], m_subst)) {
- return false;
- }
- }
- return true;
- }
- };
-
-
- class matching_set2 {
- class inst_visitor : public st_visitor {
- bool m_found;
- public:
- inst_visitor(substitution& s): st_visitor(s), m_found(false) {}
- virtual bool operator()(expr * e) {
- m_found = true;
- return false;
- }
- void reset() { m_found = false; }
- bool found() const { return m_found; }
- };
-
- ast_manager& m;
- substitution_tree m_st;
- func_decl_ref m_f;
- app_ref_vector m_trail;
- substitution m_dummy;
- inst_visitor m_visitor;
-
- public:
- matching_set2(ast_manager& m) : m(m), m_st(m), m_f(m), m_trail(m), m_dummy(m), m_visitor(m_dummy) {}
-
- void insert(inst const& inst) {
- if (!m_f.get()) {
- ptr_buffer domain;
- for (unsigned i = 0; i < inst.size(); ++i) {
- domain.push_back(m.get_sort(inst[i]));
- }
- m_f = m.mk_func_decl(symbol("tuple"),inst.size(), domain.c_ptr(), m.mk_bool_sort());
- m_trail.push_back(m.mk_app(m_f, inst.size(), inst.c_ptr()));
- m_st.insert(m_trail.back());
- }
- }
- void insert(unsigned sz, expr* const* exprs) {
- insert(inst(m, sz, exprs));
- }
- void pop_insert() {
- m_st.erase(m_trail.back());
- m_trail.pop_back();
- }
-
- bool has_instance(inst const& inst) {
- app_ref f(m);
- f = m.mk_app(m_f, inst.size(), inst.c_ptr());
- m_visitor.reset();
- m_st.inst(f, m_visitor);
- return m_visitor.found();
- }
-
- class insert_inst : public trail {
- matching_set& m_ms;
- public:
- insert_inst(matching_set& m): m_ms(m) {}
- virtual void undo(smt::context& ctx) { m_ms.pop_insert(); }
- };
-
- static bool is_identity(const inst& subst) {
- uint_set vars;
- vars.reset();
- unsigned sz = subst.size();
- for(unsigned i=0; iget_idx();
- if(vars.contains(var_idx)) {
- return false;
- }
- vars.insert(var_idx);
- }
- return true;
- }
- };
-
-
- /////////////////////////
- // inst_gen_unif_index
- //
-
- class inst_gen_unif_index {
- ast_manager & m;
- substitution_tree m_st;
- unsigned m_num_vars;
- app_ref_vector m_ref_holder;
- unsigned_vector m_lim;
-
- class collecting_visitor : public st_visitor {
- app_ref_vector& m_acc;
- public:
- collecting_visitor(app_ref_vector& acc, substitution& subst)
- : st_visitor(subst), m_acc(acc) {}
- virtual bool operator()(expr * e) {
- SASSERT(is_app(e));
- m_acc.push_back(to_app(e));
- return true;
- }
- };
-
-
- class st_contains_visitor : public st_visitor {
- expr* m_e;
- bool m_found;
- public:
- st_contains_visitor(substitution& s, expr* e): st_visitor(s), m_e(e), m_found(false) {}
- virtual bool operator()(expr* e) {
- if (e == m_e) {
- m_found = true;
- return false;
- }
- return true;
- }
- bool found() const { return m_found; }
- };
-
- void debug_st(char const* cmd, app* l) {
- expr_ref e(m);
- ptr_vector sorts;
- svector names;
- get_free_vars(l, sorts);
- for (unsigned i = 0; i < sorts.size(); ++i) {
- if (!sorts[i]) {
- sorts[i] = m.mk_bool_sort();
- }
- names.push_back(symbol(i));
- }
- sorts.reverse();
- if (!sorts.empty()) {
- e = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), l);
- }
- else {
- e = l;
- }
- std::cout << ":" << cmd << " " << PP(e.get(),m) << "\n";
- }
-
- public:
- inst_gen_unif_index(ast_manager & m) :
- m(m), m_st(m), m_num_vars(0), m_ref_holder(m) {}
-
- void insert_literal(app * lit) {
- // debug_st("st_insert", lit);
- m_ref_holder.push_back(lit);
- m_st.insert(lit);
- }
-
- void get_unifications(app * lit, app_ref_vector& res) {
- substitution subst(m);
- subst.reserve_vars(m_num_vars);
- subst.reserve_offsets(m_st.get_approx_num_regs());
- collecting_visitor visitor(res, subst);
- // TRACE("theory_instgen", m_st.display(tout); );
- m_st.unify(lit, visitor);
- }
- void reserve_num_vars(unsigned num_vars) {
- if (num_vars > m_num_vars) m_num_vars = num_vars;
- }
-
- void push() {
- m_lim.push_back(m_ref_holder.size());
- }
-
- void pop() {
- unsigned sz = m_lim.back();
- m_ref_holder.resize(sz);
- m_lim.pop_back();
- m_st.reset();
- }
-
- void pop_orig() {
- unsigned sz = m_lim.back();
- while (m_ref_holder.size() > sz) {
- debug_st("st_erase", m_ref_holder.back());
- m_st.erase(m_ref_holder.back());
-
- substitution subst(m);
- subst.reserve_vars(m_num_vars);
- subst.reserve_offsets(m_st.get_approx_num_regs());
- st_contains_visitor cv(subst, m_ref_holder.back());
- m_st.unify(m_ref_holder.back(), cv);
- if (cv.found()) {
- m_st.display(std::cout);
- m_st.erase(m_ref_holder.back());
- }
- SASSERT(!cv.found());
- m_ref_holder.pop_back();
- }
- m_lim.pop_back();
- }
-
- void display(std::ostream& out) {
- m_st.display(out);
- }
-
- bool empty() const{
- return m_st.empty();
- }
- };
-
-
- ///////////////////////////
- // fo_clause_internalizer
- //
-
- class fo_clause_internalizer {
- private:
- typedef map, default_eq > literal_meaning_map;
- typedef obj_map occurs;
- typedef obj_map root_clause_map; //for any clause instance it gives us the clause from the original problem
-
- theory_instgen_impl& m_parent;
- expr_ref_vector m_vars;
- var_subst m_subst;
- occurs m_occurs;
- grounder m_grounder;
- /**
- For each clause which is a result of instantiation contains the
- original problem clause from which it derives.
- */
- root_clause_map m_root_clause_map;
-
-
- /**
- For each SMT literal contains a vector of first-order literals
- that are represented by this literal.
- */
- literal_meaning_map m_literal_meanings;
-
- /**
- fo literals that have been internalized by this object.
- Invariant: any app* fol in this set has a literal l such that
- m_literal_meanings[l].contains(fol).
- Particularly, l==get_context().get_literal(gnd_fol) where gnd_fol
- is a grounded version of this literal
- */
- obj_hashtable m_internalized_fo_lits;
-
-
- ast_manager& m() const;
- smt::context& get_context() const;
-
- class insert_occurs_trail : public trail {
- occurs& m_occ;
- quantifier_ref_vector* m_qs;
- expr_ref m_lit;
- public:
- insert_occurs_trail(occurs& o, expr_ref& lit, quantifier* q): m_occ(o), m_qs(0), m_lit(lit) {
- occurs::obj_map_entry* e = m_occ.insert_if_not_there2(lit,0);
- m_qs = e->get_data().m_value;
- if (!m_qs) {
- m_qs = alloc(quantifier_ref_vector, lit.get_manager());
- e->get_data().m_value = m_qs;
- }
- m_qs->push_back(q);
- }
-
- virtual void undo(smt::context& ctx) {
- SASSERT(m_qs && !m_qs->empty());
- SASSERT(m_qs == m_occ.find_core(m_lit)->get_data().m_value);
- m_qs->pop_back();
- if (m_qs->empty()) {
- m_occ.remove(m_lit);
- dealloc(m_qs);
- }
- }
- };
-
- class lit_meaning_trail : public trail {
- literal_meaning_map& m_map;
- app_ref_vector* m_apps;
- smt::literal m_smtlit;
- public:
-
- lit_meaning_trail(literal_meaning_map& map, ast_manager& m, smt::literal l, app* lit):
- m_map(map), m_smtlit(l) {
- literal_meaning_map::entry* e = map.insert_if_not_there2(l, 0);
- m_apps = e->get_data().m_value;
- if (!m_apps) {
- m_apps = alloc(app_ref_vector, m);
- e->get_data().m_value = m_apps;
- }
- m_apps->push_back(lit);
- }
-
- virtual void undo(smt::context& ctx) {
- SASSERT(m_apps && !m_apps->empty());
- SASSERT(m_apps == m_map.find_core(m_smtlit)->get_data().m_value);
- m_apps->pop_back();
- if (m_apps->empty()) {
- m_map.remove(m_smtlit);
- dealloc(m_apps);
- }
- }
- };
-
- quantifier * get_root_clause(expr* clause) const {
- quantifier * root;
- if(!m_root_clause_map.find(clause, root)) {
- SASSERT(is_forall(clause));
- root = to_quantifier(clause);
- }
- return root;
- }
-
- void replace_by_root_clauses(ptr_vector& vect) const {
- unsigned sz = vect.size();
- for(unsigned i=0; i(t));
- get_context().push_trail(insert_obj_trail(m_internalized_fo_lits, lit));
- get_context().push_trail(lit_meaning_trail(m_literal_meanings, m(), smt_lit, lit));
- TRACE("theory_instgen", tout << smt_lit << " "<< PP(grounded_lit, m()) << " |-> " << PP(lit, m()) << "\n";);
- }
- get_context().mark_as_relevant(smt_lit);
- return smt_lit;
- }
-
- void add_clause_to_smt(expr * clause, quantifier* root_clause, ptr_vector const& assumptions=ptr_vector());
-
- void get_instance_clause(instantiation_result const& ir, expr_ref& res);
-
- /**
- return false if nothing was done
-
- assumptions are instantiated clauses (to get a correct assumption for the SMT solver, we need
- to convert the vector to root clauses).
- */
- bool simplify_clause(quantifier * clause, expr_ref& result, ptr_vector& assumptions);
-
- public:
-
- fo_clause_internalizer(theory_instgen_impl& parent):
- m_parent(parent),
- m_vars(m()),
- m_subst(m()),
- m_grounder(m()) {
- }
-
- ~fo_clause_internalizer() {
- reset_dealloc_values(m_occurs);
- }
-
- void get_literal_meanings(literal l, ptr_vector& fo_lits) {
- app_ref_vector* lits = 0;
- m_literal_meanings.find(l, lits);
- if (lits) {
- fo_lits.append(lits->size(), lits->c_ptr());
- }
- }
-
- void add_initial_clause(quantifier* q) {
- add_clause_to_smt(q, 0);
- }
-
- quantifier_ref_vector* find_occurs(app * l) {
- quantifier_ref_vector* result = 0;
- m_occurs.find(l, result);
- return result;
- }
-
- void add_new_instance(instantiation_result const& ir) {
- quantifier * root_clause = get_root_clause(ir.clause());
- expr_ref inst_clause(m());
- get_instance_clause(ir, inst_clause);
-
- ptr_vector assumptions;
- if(is_quantifier(inst_clause.get())) {
- quantifier * q_clause = to_quantifier(inst_clause.get());
- bool simplified = simplify_clause(q_clause, inst_clause, assumptions);
- SASSERT(simplified || assumptions.empty());
- }
- replace_by_root_clauses(assumptions);
-
- if(!m_root_clause_map.contains(inst_clause)) {
- m_root_clause_map.insert(inst_clause, root_clause);
- get_context().push_trail(insert_obj_map(m_root_clause_map, inst_clause));
- }
- add_clause_to_smt(inst_clause, root_clause, assumptions);
- }
- };
-
-
- /////////////////
- // instantiator
- //
-
- class instantiator {
- private:
- typedef quantifier clause_type;
- typedef ptr_vector clause_vector;
- typedef obj_map matching_sets;
-
- ast_manager& m;
- theory_instgen_impl& m_parent;
- fo_clause_internalizer& m_internalizer;
- inst_gen_unif_index m_unif_index;
- matching_sets m_matching;
- unifier m_unifier; //used in the unify method, but we don't want to recreate over and over
-
- class var_rename_rewriter_cfg : public default_rewriter_cfg {
- ast_manager& m;
- u_map m_index_rename;
- public:
- var_rename_rewriter_cfg(ast_manager& m) : m(m) {}
-
- bool get_subst(expr * s, expr * & t, proof * & t_pr) {
- if (is_var(s)) {
- unsigned idx = to_var(s)->get_idx();
- unsigned new_idx = 0;
- if (!m_index_rename.find(idx, new_idx)) {
- new_idx = m_index_rename.size();
- m_index_rename.insert(idx, new_idx);
- }
- t = m.mk_var(new_idx, to_var(s)->get_sort());
- return true;
- }
- else {
- return false;
- }
- }
- };
-
- static void extract_substitution(substitution& s, quantifier * q, unsigned subst_var_cnt, bool is_first_bank, expr_ref_vector& tgt) {
- // unsigned var_increment = is_first_bank ? 0 : subst_var_cnt;
- unsigned var_offset = is_first_bank ? 0 : 1;
-
- unsigned deltas[2] = {0, subst_var_cnt};
- ast_manager& m = s.get_manager();
- unsigned var_cnt = q->get_num_decls();
- var_rename_rewriter_cfg r_cfg(m);
- rewriter_tpl rwr(m, false, r_cfg);
- for(unsigned i=0; iget_decl_sort(i);
- unsigned var_idx = var_cnt-1-i;
- var_ref v(m.mk_var(var_idx, var_sort), m);
- expr_ref tmp(m), subst_result(m);
- s.apply(2, deltas, expr_offset(v.get(), var_offset), tmp);
- rwr(tmp, subst_result);
- tgt.push_back(subst_result);
- }
- }
-
-
- // just to be sure there's not misunderstanding with the caller, we require the res to be empty:)
- void get_literal_occurrences(app * lit, clause_vector& res) {
- SASSERT(res.empty());
- quantifier_ref_vector * occurrences = m_internalizer.find_occurs(lit);
- if(occurrences) {
- res.append(occurrences->size(), occurrences->c_ptr());
- }
- }
-
- /**
- check substitution wrt dismatching constraints of clause
- (variable offset is to deal with how variable banks are shifted on each
- other in the substitution)
- */
- bool is_allowed_instantiation(clause_type * clause, const inst& subst) {
- matching_set * ms;
- return !m_matching.find(clause, ms) || !ms->has_instance(subst);
- }
-
- class new_ms : public trail {
- matching_sets& m_ms;
- matching_set* m_s;
- quantifier* m_q;
- public:
- new_ms(matching_sets& m, matching_set* s, quantifier* q): m_ms(m), m_s(s), m_q(q) {}
- virtual void undo(smt::context& ctx) { dealloc(m_s); m_ms.remove(m_q); }
- };
-
- // add instantiating substitution among the dismatching constraints
- void record_instantiation(instantiation_result const& inst) {
- quantifier * cl = inst.clause();
- matching_set * ms;
- if(!m_matching.find(cl, ms)) {
- ms = alloc(matching_set, m);
- m_matching.insert(cl, ms);
- get_context().push_trail(new_ms(m_matching, ms, cl));
- }
- ms->insert(inst.subst());
- get_context().push_trail(matching_set::insert_inst(*ms));
- }
-
- void get_result_from_subst(clause_type * clause, const inst& subst, instantiation_result& res) {
- res.init(clause, subst);
- record_instantiation(res);
- }
-
- void display_vector(expr_ref_vector const& v, std::ostream& out) {
- for (unsigned i = 0; i < v.size(); ++i) {
- out << PP(v[i], m) << " ";
- }
- out << "\n";
- }
-
-
- void add_lit(literal lit) {
- ptr_vector fo_lits;
- m_internalizer.get_literal_meanings(lit, fo_lits);
- expr_ref e(m);
- get_context().literal2expr(lit, e);
- if (is_ground(e.get())) {
- fo_lits.push_back(to_app(e));
- }
- for (unsigned i = 0; i < fo_lits.size(); ++i) {
- app * fol = fo_lits[i];
- m_unif_index.insert_literal(fol);
- }
- }
-
- void mk_folit_neg(app * lit, app_ref& res) {
- expr * arg;
- if(m.is_not(lit, arg)) {
- SASSERT(is_app(arg));
- res = to_app(arg);
- }
- else {
- res = m.mk_not(lit);
- }
- }
-
- ast_manager& get_manager() const;
- context& get_context() const;
-
- public:
- instantiator(fo_clause_internalizer& internalizer, theory_instgen_impl& parent, ast_manager& m) :
- m(m),
- m_parent(parent),
- m_internalizer(internalizer),
- m_unif_index(m),
- m_unifier(m) {}
-
- ~instantiator() {
- reset_dealloc_values(m_matching);
- }
-
- bool unif_is_empty() const {
- return m_unif_index.empty();
- }
-
- void display(std::ostream& out) {
- m_unif_index.display(out);
- }
-
- void add_true_lit(literal lit) {
- add_lit(lit);
- }
-
- void push() {
- m_unif_index.push();
- }
-
- void pop() {
- m_unif_index.pop();
- }
-
- void reserve_num_vars(unsigned num_vars) {
- m_unif_index.reserve_num_vars(num_vars);
- }
-
- bool instantiate_clauses(
- app * lit1, clause_type * clause1,
- app * lit2, clause_type * clause2,
- instantiation_result_vector& result);
-
- bool instantiate_clause(
- app * lit1, clause_type * clause1, app * lit2,
- instantiation_result_vector& result);
-
- void do_instantiating(literal lit, instantiation_result_vector& res) {
- ptr_vector folits;
- clause_vector folit_clauses; // clauses in which the first-order literal appears
- app_ref_vector unifs(m); // unifying complementary literals
- clause_vector comp_clauses; // clauses in which the unifying complementary literal appears
-
- m_internalizer.get_literal_meanings(lit, folits);
-
- while(!folits.empty()) {
- app * folit = folits.back();
-
- folits.pop_back();
- folit_clauses.reset();
- get_literal_occurrences(folit, folit_clauses);
- SASSERT(!folit_clauses.empty()); //if we have a literal it should be in some clause (or not?)
-
- SASSERT(folit->get_ref_count() > 0);
- app_ref complementary(m);
- mk_folit_neg(folit, complementary);
- m_unif_index.get_unifications(complementary, unifs);
-
- while(!unifs.empty()) {
- app * comp_lit = unifs.back();
- unifs.pop_back();
- SASSERT(comp_lit->get_ref_count() > 0);
- comp_clauses.reset();
- get_literal_occurrences(comp_lit, comp_clauses);
- TRACE("theory_instgen", tout << "Literal " << lit << " meaning: " << PP(folit, m) << "\n";
- tout << "Unifies with: " << PP(comp_lit, m) << "\n";);
- //
- //if a literal is in the unification index (i.e. was assigned true sometime before),
- //it should be in some clause or it is a ground literal.
-
- //iterate through all clauses that contain the query literal
- //
- clause_vector::const_iterator fc_end = folit_clauses.end();
- for(clause_vector::const_iterator fc_it = folit_clauses.begin(); fc_it!=fc_end; ++fc_it) {
-
- //iterate through all clauses that contain the complementary unifying literal
- clause_vector::const_iterator end = comp_clauses.end();
- for(clause_vector::const_iterator it = comp_clauses.begin(); it!=end; ++it) {
-
- instantiate_clauses(folit, *fc_it, comp_lit, *it, res);
- }
- if (comp_clauses.empty()) {
- instantiate_clause(folit, *fc_it, comp_lit, res);
- }
- }
- }
- complementary.reset();
- }
- }
- };
-
-
- ///////////////////////////
- // theory_instgen_impl
- //
-
- class theory_instgen_impl : public theory_instgen {
-
- friend class instantiator;
- friend class fo_clause_internalizer;
-
- struct stats {
- unsigned m_num_axioms;
- unsigned m_num_subsumptions;
- unsigned m_num_pruned;
- stats() { memset(this, 0, sizeof(*this)); }
- };
-
- ast_manager& m_manager;
- smt_params& m_params;
- fo_clause_internalizer m_internalizer;
- instantiator m_instantiator;
- clause_subsumption m_subsumer;
- stats m_stats;
-
- final_check_status instantiate_all_possible() {
- // traverse instantiation queue and create initial instances.
-
- ast_manager& m = get_manager();
- context& ctx = get_context();
- instantiation_result_vector generated_clauses;
- unsigned bv_cnt = ctx.get_num_bool_vars();
-
- m_instantiator.push();
-
- TRACE("theory_instgen",
- tout << "Literals:\n";
- for (unsigned v = 0; v < bv_cnt; ++v) {
- if (l_undef == ctx.get_assignment(v)) continue;
- literal lit(v, ctx.get_assignment(v) == l_false);
- expr_ref e(m);
- ctx.literal2expr(lit, e);
- tout << PP(e.get(),m) << "\n";
- }
- );
-
- SASSERT(m_instantiator.unif_is_empty());
-
- for(unsigned bvi=0; bvi < bv_cnt; ++bvi) {
- lbool asgn_val = ctx.get_assignment(bvi);
- if(asgn_val==l_undef) {
- continue;
- }
- literal lit(bvi, asgn_val==l_false);
- m_instantiator.add_true_lit(lit);
- m_instantiator.do_instantiating(lit, generated_clauses);
- }
-
- bool change = !generated_clauses.empty();
-
- while(!generated_clauses.empty()) {
- m_internalizer.add_new_instance(generated_clauses.back());
- generated_clauses.pop_back();
- }
-
- m_instantiator.pop();
-
- return change?FC_CONTINUE:FC_DONE;
- }
-
-
- public:
- theory_instgen_impl(ast_manager& m, smt_params& p):
- theory_instgen(m.get_family_id("inst_gen")),
- m_manager(m),
- m_params(p),
- m_internalizer(*this),
- m_instantiator(m_internalizer, *this, m),
- m_subsumer(m, p)
- {}
-
- ast_manager& m() { return m_manager; }
-
- virtual void internalize_quantifier(quantifier* q) {
- TRACE("theory_instgen", tout << PP(q, m()) << "\n";);
- context& ctx = get_context();
- if (!ctx.b_internalized(q)) {
- bool_var v = ctx.mk_bool_var(q);
- ctx.set_var_theory(v, get_id());
- m_instantiator.reserve_num_vars(q->get_num_decls());
- }
- }
-
- virtual bool internalize_atom(app * atom, bool gate_ctx) {
- UNREACHABLE();
- return false;
- }
-
- virtual bool internalize_term(app * term) {
- UNREACHABLE();
- return false;
- }
-
- virtual void new_eq_eh(theory_var v1, theory_var v2) {}
-
- virtual void new_diseq_eh(theory_var v1, theory_var v2) {}
-
- virtual theory * mk_fresh(context * new_ctx) {
- return alloc(theory_instgen_impl, get_manager(), m_params);
- }
-
- virtual void assign_eh(bool_var v, bool is_true) {
- context& ctx = get_context();
- expr* e = ctx.bool_var2expr(v);
- if (is_quantifier(e)) {
- if (is_true) {
- m_internalizer.add_initial_clause(to_quantifier(e));
- }
- else {
- // TBD: handle existential force later.
- }
- }
- }
-
- virtual final_check_status final_check_eh() {
- TRACE("theory_instgen", tout << "Final check\n";);
- return instantiate_all_possible();
- }
-
- virtual void init_model(smt::model_generator & m) { }
-
- virtual smt::model_value_proc * mk_value(smt::enode * n, smt::model_generator & m) {
- UNREACHABLE();
- return 0;
- }
-
- virtual void relevant_eh(app * n) { }
-
- virtual void push_scope_eh() {
- m_subsumer.push();
- }
-
- virtual void pop_scope_eh(unsigned num_scopes) {
- m_subsumer.pop(num_scopes);
- }
-
- virtual void collect_statistics(::statistics & st) const {
- st.update("inst axiom", m_stats.m_num_axioms);
- st.update("inst subsump", m_stats.m_num_subsumptions);
- }
-
- void inc_subsumptions() {
- ++m_stats.m_num_subsumptions;
- }
-
- void inc_axioms() {
- ++m_stats.m_num_axioms;
- }
-
- void inc_pruned() {
- ++m_stats.m_num_pruned;
- }
-
- };
-
- theory_instgen* mk_theory_instgen(ast_manager& m, smt_params& p) {
- return alloc(theory_instgen_impl, m, p);
- }
-
- ast_manager& instantiator::get_manager() const {
- return m_parent.m();
- }
-
- smt::context& instantiator::get_context() const {
- return m_parent.get_context();
- }
-
- bool instantiator::instantiate_clauses(
- app * lit1, clause_type * clause1,
- app * lit2, clause_type * clause2,
- instantiation_result_vector& result) {
- TRACE("theory_instgen", tout << PP(lit1, m) << " " << PP(clause1, m) << "\n";
- tout << PP(lit2, m) << " " << PP(clause2, m) << "\n";);
- substitution subst(m);
- unsigned var_cnt = std::max(clause1->get_num_decls(), clause2->get_num_decls());
- subst.reserve(2, var_cnt);
- //don't trust there offset values too much, it's just what i expect the substitution does:)
- app_ref complementary(m);
- mk_folit_neg(lit1, complementary);
- TRUSTME(m_unifier(complementary, lit2, subst));
-
- inst subst1(m);
- extract_substitution(subst, clause1, var_cnt, true, subst1);
- inst subst2(m);
- extract_substitution(subst, clause2, var_cnt, false, subst2);
-
- bool s1_identity = matching_set::is_identity(subst1);
- bool s2_identity = matching_set::is_identity(subst2);
-
- if((!s1_identity && !is_allowed_instantiation(clause1, subst1)) ||
- (!s2_identity && !is_allowed_instantiation(clause2, subst2))) {
- TRACE("theory_instgen",
- tout << "Pruned instantiation\n";
- tout << PP(clause1, m) << "\n";
- display_vector(subst1, tout);
- tout << PP(clause2, m) << "\n";
- display_vector(subst2, tout);
- );
- m_parent.inc_pruned();
- return false;
- }
-
- //
- // both substitutions cannot be identity as then the two complementary
- // literals would correspond to the same SAT solver variable
- //
- SASSERT(!s1_identity || !s2_identity);
-
- if(!s1_identity) {
- instantiation_result res1(m);
- get_result_from_subst(clause1, subst1, res1);
- result.push_back(res1);
- }
-
- if(!s2_identity) {
- instantiation_result res2(m);
- get_result_from_subst(clause2, subst2, res2);
- result.push_back(res2);
- }
- return true;
- }
-
- // literal lit2 is ground. It is not associated with a clause.
- // literal lit1 is associatd with a non-ground clause.
- bool instantiator::instantiate_clause(
- app * lit1, clause_type * clause1, app * lit2,
- instantiation_result_vector& result) {
- TRACE("theory_instgen", tout << PP(lit1, m) << " " << PP(clause1, m) << "\n";
- tout << PP(lit2, m) << "\n";);
- if (!is_ground(lit2)) {
- // TBD: remove. Debug code.
- std::cout << PP(lit1, m) << " " << PP(clause1, m) << "\n";
- std::cout << PP(lit2, m) << "\n";
- m_unif_index.display(std::cout);
- }
- SASSERT(is_ground(lit2));
- substitution subst(m);
- unsigned var_cnt = clause1->get_num_decls();
- subst.reserve(2, var_cnt);
- app_ref complementary(m);
- mk_folit_neg(lit1, complementary);
-
- TRUSTME(m_unifier(complementary, lit2, subst));
-
- inst subst1(m);
- extract_substitution(subst, clause1, var_cnt, true, subst1);
-
- if(matching_set::is_identity(subst1) ||
- !is_allowed_instantiation(clause1, subst1)) {
- TRACE("theory_instgen",
- tout << "Pruned instantiation\n";
- tout << PP(clause1, m) << "\n";
- display_vector(subst1, tout);
- );
- m_parent.inc_pruned();
- return false;
- }
-
- instantiation_result res1(m);
- get_result_from_subst(clause1, subst1, res1);
- result.push_back(res1);
- return true;
- }
-
-
- //--------------------------
- //
- // fo_clause_internalizer
- //
- //--------------------------
-
- smt::context& fo_clause_internalizer::get_context() const {
- return m_parent.get_context();
- }
-
- ast_manager& fo_clause_internalizer::m() const {
- return m_parent.m();
- }
-
- bool fo_clause_internalizer::simplify_clause(quantifier * clause, expr_ref& result, ptr_vector& assumptions) {
- m_parent.m_subsumer.simplify(clause, result, assumptions);
- bool change = clause!=result.get();
- if (change) {
- m_parent.inc_subsumptions();
- }
- return change;
- }
-
- void fo_clause_internalizer::get_instance_clause(instantiation_result const& ir, expr_ref& res) {
- expr * orig_cl = ir.clause()->get_expr();
- SASSERT(is_app(orig_cl));
-
- expr_ref res_inner(m()); //the clause after substitution, we might still need to quantify it
- m_subst(orig_cl, ir.subst().size(), ir.subst().c_ptr(), res_inner);
- SASSERT(is_app(res_inner.get()));
-
- if(is_ground(res_inner.get())) {
- res = res_inner;
- return; //we made it ground!
- }
-
- ptr_vector free_var_sorts;
- svector quant_names;
- get_free_vars(res_inner.get(), free_var_sorts);
- unsigned free_var_cnt = free_var_sorts.size();
- for(unsigned i=0; i const& assumptions) {
- SASSERT(!root_clause || root_clause->is_forall());
- SASSERT(is_quantifier(clause) || root_clause);
- context& ctx = get_context();
- buffer lits;
- ptr_buffer todo;
-
- bool is_q_clause = is_quantifier(clause);
- quantifier * q_clause = is_q_clause ? to_quantifier(clause) : 0;
- if (!root_clause) root_clause = q_clause;
-
- lits.push_back(~get_root_clause_control_literal(root_clause));
-
- for(unsigned i=0; iget_expr()):clause);
-
- while (!todo.empty()) {
- expr* e = todo.back();
- todo.pop_back();
- if (m().is_or(e)) {
- todo.append(to_app(e)->get_num_args(), to_app(e)->get_args());
- }
- else if (is_app(e)) {
- lits.push_back(ground_fo_literal(to_app(e), q_clause));
- }
- else {
- SASSERT(is_var(e) || is_quantifier(e));
- UNREACHABLE();
- //by skipping part of the disjunction we may get unsound
- }
- }
- TRACE("theory_instgen",
- tout << "Axiom: \n";
- for (unsigned i = 0; i < lits.size(); ++i) {
- expr_ref e(m());
- get_context().literal2expr(lits[i], e);
- tout << PP(e.get(), m()) << "\n";
- }
- );
- m_parent.inc_axioms();
- ctx.mk_th_axiom(m_parent.get_id(), lits.size(), lits.c_ptr());
- }
-
-
-};
diff --git a/src/smt/theory_instgen.h b/src/smt/theory_instgen.h
deleted file mode 100644
index c32636e9b..000000000
--- a/src/smt/theory_instgen.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*++
-Copyright (c) 2011 Microsoft Corporation
-
-Module Name:
-
- theory_instgen.h
-
-Abstract:
-
- InstGen (iProver) style theory solver.
- It provides an instantiation based engine
- based on InstGen methods together with
- unit propagation.
-
-
-Author:
-
- Krystof Hoder (t-khoder)
- Nikolaj Bjorner (nbjorner) 2011-10-6
-
-Revision History:
-
---*/
-#ifndef _THEORY_INST_GEN_H_
-#define _THEORY_INST_GEN_H_
-
-#include "smt_theory.h"
-#include "smt_params.h"
-
-namespace smt {
-
- class theory_instgen : public theory {
- public:
- theory_instgen(family_id fid) : theory(fid) {}
- virtual ~theory_instgen() {}
- virtual void internalize_quantifier(quantifier* q) = 0;
- virtual char const * get_name() const { return "instgen"; }
- };
-
- theory_instgen* mk_theory_instgen(ast_manager& m, smt_params& p);
-
-};
-
-#endif /* _THEORY_INST_GEN_H_ */
-
diff --git a/src/tactic/core/ctx_simplify_tactic.cpp b/src/tactic/core/ctx_simplify_tactic.cpp
index cca21b90e..831efa087 100644
--- a/src/tactic/core/ctx_simplify_tactic.cpp
+++ b/src/tactic/core/ctx_simplify_tactic.cpp
@@ -18,7 +18,7 @@ Notes:
--*/
#include"ctx_simplify_tactic.h"
#include"mk_simplified_app.h"
-#include"num_occurs_goal.h"
+#include"goal_num_occurs.h"
#include"cooperate.h"
#include"ast_ll_pp.h"
#include"ast_smt2_pp.h"
@@ -51,7 +51,7 @@ struct ctx_simplify_tactic::imp {
unsigned m_scope_lvl;
unsigned m_depth;
unsigned m_num_steps;
- num_occurs_goal m_occs;
+ goal_num_occurs m_occs;
mk_simplified_app m_mk_app;
unsigned long long m_max_memory;
unsigned m_max_depth;
diff --git a/src/tactic/core/nnf_tactic.cpp b/src/tactic/core/nnf_tactic.cpp
index a79a4ed06..19190c299 100644
--- a/src/tactic/core/nnf_tactic.cpp
+++ b/src/tactic/core/nnf_tactic.cpp
@@ -18,6 +18,7 @@ Revision History:
--*/
#include"nnf.h"
#include"tactical.h"
+#include"filter_model_converter.h"
class nnf_tactic : public tactic {
params_ref m_params;
@@ -100,6 +101,13 @@ public:
}
g->inc_depth();
result.push_back(g.get());
+ unsigned num_extra_names = dnames.get_num_names();
+ if (num_extra_names > 0) {
+ filter_model_converter * fmc = alloc(filter_model_converter, m);
+ mc = fmc;
+ for (unsigned i = 0; i < num_extra_names; i++)
+ fmc->insert(dnames.get_name_decl(i));
+ }
TRACE("nnf", g->display(tout););
SASSERT(g->is_well_sorted());
}
diff --git a/src/tactic/num_occurs_goal.cpp b/src/tactic/goal_num_occurs.cpp
similarity index 75%
rename from src/tactic/num_occurs_goal.cpp
rename to src/tactic/goal_num_occurs.cpp
index adc412434..6c94e307c 100644
--- a/src/tactic/num_occurs_goal.cpp
+++ b/src/tactic/goal_num_occurs.cpp
@@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation
Module Name:
- num_occurs_goal.cpp
+ goal_num_occurs.cpp
Abstract:
@@ -15,10 +15,10 @@ Author:
Revision History:
--*/
-#include"num_occurs_goal.h"
+#include"goal_num_occurs.h"
#include"goal.h"
-void num_occurs_goal::operator()(goal const & g) {
+void goal_num_occurs::operator()(goal const & g) {
expr_fast_mark1 visited;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
diff --git a/src/tactic/num_occurs_goal.h b/src/tactic/goal_num_occurs.h
similarity index 64%
rename from src/tactic/num_occurs_goal.h
rename to src/tactic/goal_num_occurs.h
index 5e6e0cc94..33a25e03f 100644
--- a/src/tactic/num_occurs_goal.h
+++ b/src/tactic/goal_num_occurs.h
@@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation
Module Name:
- num_occurs_goal.h
+ goal_num_occurs.h
Abstract:
@@ -15,16 +15,16 @@ Author:
Revision History:
--*/
-#ifndef _NUM_OCCURS_GOAL_H_
-#define _NUM_OCCURS_GOAL_H_
+#ifndef _GOAL_NUM_OCCURS_H_
+#define _GOAL_NUM_OCCURS_H_
#include"num_occurs.h"
class goal;
-class num_occurs_goal : public num_occurs {
+class goal_num_occurs : public num_occurs {
public:
- num_occurs_goal(bool ignore_ref_count1 = false, bool ignore_quantifiers = false):
+ goal_num_occurs(bool ignore_ref_count1 = false, bool ignore_quantifiers = false):
num_occurs(ignore_ref_count1, ignore_quantifiers) {
}