mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 01:24:08 +00:00
merged with unstable
This commit is contained in:
commit
3a0947b3ba
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf
|
|
@ -63,6 +63,8 @@ Version 4.3.2
|
|||
|
||||
- Fixed bug reported at http://z3.codeplex.com/workitem/23 (Thanks to Paul Jackson).
|
||||
|
||||
- Fixed bug reported at http://stackoverflow.com/questions/15226944/segmentation-fault-in-z3 (Thanks to Tianhai Liu).
|
||||
|
||||
Version 4.3.1
|
||||
=============
|
||||
|
||||
|
|
|
@ -906,6 +906,72 @@ void enum_sort_example() {
|
|||
std::cout << "2: " << result_goal.as_expr() << std::endl;
|
||||
}
|
||||
|
||||
void expr_vector_example() {
|
||||
std::cout << "expr_vector example\n";
|
||||
context c;
|
||||
const unsigned N = 10;
|
||||
|
||||
expr_vector x(c);
|
||||
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
std::stringstream x_name;
|
||||
x_name << "x_" << i;
|
||||
x.push_back(c.int_const(x_name.str().c_str()));
|
||||
}
|
||||
|
||||
solver s(c);
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
s.add(x[i] >= 1);
|
||||
}
|
||||
|
||||
std::cout << s << "\n" << "solving...\n" << s.check() << "\n";
|
||||
model m = s.get_model();
|
||||
std::cout << "solution\n" << m;
|
||||
}
|
||||
|
||||
void exists_expr_vector_example() {
|
||||
std::cout << "exists expr_vector example\n";
|
||||
context c;
|
||||
const unsigned N = 10;
|
||||
|
||||
expr_vector xs(c);
|
||||
expr x(c);
|
||||
expr b(c);
|
||||
b = c.bool_val(true);
|
||||
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
std::stringstream x_name;
|
||||
x_name << "x_" << i;
|
||||
x = c.int_const(x_name.str().c_str());
|
||||
xs.push_back(x);
|
||||
b = b && x >= 0;
|
||||
}
|
||||
|
||||
expr ex(c);
|
||||
ex = exists(xs, b);
|
||||
std::cout << ex << std::endl;
|
||||
}
|
||||
|
||||
void substitute_example() {
|
||||
std::cout << "substitute example\n";
|
||||
context c;
|
||||
expr x(c);
|
||||
x = c.int_const("x");
|
||||
expr f(c);
|
||||
f = (x == 2) || (x == 1);
|
||||
std::cout << f << std::endl;
|
||||
|
||||
expr two(c), three(c);
|
||||
two = c.int_val(2);
|
||||
three = c.int_val(3);
|
||||
Z3_ast from[] = { two };
|
||||
Z3_ast to[] = { three };
|
||||
expr new_f(c);
|
||||
new_f = to_expr(c, Z3_substitute(c, f, 1, from, to));
|
||||
|
||||
std::cout << new_f << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
demorgan(); std::cout << "\n";
|
||||
|
@ -937,10 +1003,13 @@ int main() {
|
|||
tactic_example9(); std::cout << "\n";
|
||||
tactic_qe(); std::cout << "\n";
|
||||
tst_visit(); std::cout << "\n";
|
||||
incremental_example1(); std::cout << "\n";
|
||||
incremental_example2(); std::cout << "\n";
|
||||
incremental_example3(); std::cout << "\n";
|
||||
incremental_example1(); std::cout << "\n";
|
||||
incremental_example2(); std::cout << "\n";
|
||||
incremental_example3(); std::cout << "\n";
|
||||
enum_sort_example(); std::cout << "\n";
|
||||
expr_vector_example(); std::cout << "\n";
|
||||
exists_expr_vector_example(); std::cout << "\n";
|
||||
substitute_example(); std::cout << "\n";
|
||||
std::cout << "done\n";
|
||||
}
|
||||
catch (exception & ex) {
|
||||
|
|
|
@ -474,7 +474,7 @@ namespace test_mapi
|
|||
cells_c[i] = new BoolExpr[9];
|
||||
for (uint j = 0; j < 9; j++)
|
||||
cells_c[i][j] = ctx.MkAnd(ctx.MkLe(ctx.MkInt(1), X[i][j]),
|
||||
ctx.MkLe(X[i][j], ctx.MkInt(9)));
|
||||
ctx.MkLe(X[i][j], ctx.MkInt(9)));
|
||||
}
|
||||
|
||||
// each row contains a digit at most once
|
||||
|
@ -485,7 +485,13 @@ namespace test_mapi
|
|||
// each column contains a digit at most once
|
||||
BoolExpr[] cols_c = new BoolExpr[9];
|
||||
for (uint j = 0; j < 9; j++)
|
||||
cols_c[j] = ctx.MkDistinct(X[j]);
|
||||
{
|
||||
IntExpr[] column = new IntExpr[9];
|
||||
for (uint i = 0; i < 9; i++)
|
||||
column[i] = X[i][j];
|
||||
|
||||
cols_c[j] = ctx.MkDistinct(column);
|
||||
}
|
||||
|
||||
// each 3x3 square contains a digit at most once
|
||||
BoolExpr[][] sq_c = new BoolExpr[3][];
|
||||
|
@ -2087,7 +2093,7 @@ namespace test_mapi
|
|||
{
|
||||
QuantifierExample3(ctx);
|
||||
QuantifierExample4(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Close();
|
||||
if (Log.isOpen())
|
||||
|
|
18
examples/tptp/README
Normal file
18
examples/tptp/README
Normal file
|
@ -0,0 +1,18 @@
|
|||
TPTP front-end and utilities as a sample using the C++ bindings.
|
||||
To build the example execute
|
||||
make examples
|
||||
in the build directory.
|
||||
|
||||
This command will create the executable tptp.
|
||||
On Windows, you can just execute it.
|
||||
On OSX and Linux, you must install z3 first using
|
||||
sudo make install
|
||||
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX)
|
||||
with the build directory. You need that to be able to
|
||||
find the Z3 shared library.
|
||||
|
||||
The sample illustrates using Z3 from the TPTP language.
|
||||
The TPTP language is documented on http://tptp.org
|
||||
It also exposes utilities for converting between SMT-LIB
|
||||
and TPTP format.
|
||||
|
2480
examples/tptp/tptp5.cpp
Normal file
2480
examples/tptp/tptp5.cpp
Normal file
File diff suppressed because it is too large
Load diff
38
examples/tptp/tptp5.h
Normal file
38
examples/tptp/tptp5.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef TPTP5_H_
|
||||
#define TPTP5_H_
|
||||
|
||||
|
||||
class TreeNode;
|
||||
|
||||
#if 0
|
||||
class named_formulas {
|
||||
expr_ref_vector m_fmls;
|
||||
svector<symbol> m_names;
|
||||
bool m_has_conjecture;
|
||||
unsigned m_conjecture_index;
|
||||
public:
|
||||
named_formulas(ast_manager& m) :
|
||||
m_fmls(m),
|
||||
m_has_conjecture(false),
|
||||
m_conjecture_index(0)
|
||||
{}
|
||||
void push_back(expr* fml, char const* name) {
|
||||
m_fmls.push_back(fml);
|
||||
m_names.push_back(symbol(name));
|
||||
}
|
||||
unsigned size() const { return m_fmls.size(); }
|
||||
expr*const* c_ptr() const { return m_fmls.c_ptr(); }
|
||||
expr* operator[](unsigned i) { return m_fmls[i].get(); }
|
||||
symbol const& name(unsigned i) { return m_names[i]; }
|
||||
void set_has_conjecture() {
|
||||
m_has_conjecture = true;
|
||||
m_conjecture_index = m_fmls.size();
|
||||
}
|
||||
bool has_conjecture() const { return m_has_conjecture; }
|
||||
unsigned conjecture_index() const { return m_conjecture_index; }
|
||||
};
|
||||
|
||||
bool tptp5_parse(ast_manager& m, char const* filename, named_formulas& fmls);
|
||||
#endif
|
||||
|
||||
#endif
|
2672
examples/tptp/tptp5.lex.cpp
Normal file
2672
examples/tptp/tptp5.lex.cpp
Normal file
File diff suppressed because it is too large
Load diff
4475
examples/tptp/tptp5.tab.c
Normal file
4475
examples/tptp/tptp5.tab.c
Normal file
File diff suppressed because it is too large
Load diff
138
examples/tptp/tptp5.tab.h
Normal file
138
examples/tptp/tptp5.tab.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* A Bison parser, made by GNU Bison 2.4.2. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
AMPERSAND = 258,
|
||||
AT_SIGN = 259,
|
||||
AT_SIGN_MINUS = 260,
|
||||
AT_SIGN_PLUS = 261,
|
||||
CARET = 262,
|
||||
COLON = 263,
|
||||
COLON_EQUALS = 264,
|
||||
COMMA = 265,
|
||||
EQUALS = 266,
|
||||
EQUALS_GREATER = 267,
|
||||
EXCLAMATION = 268,
|
||||
EXCLAMATION_EQUALS = 269,
|
||||
EXCLAMATION_EXCLAMATION = 270,
|
||||
EXCLAMATION_GREATER = 271,
|
||||
LBRKT = 272,
|
||||
LESS_EQUALS = 273,
|
||||
LESS_EQUALS_GREATER = 274,
|
||||
LESS_TILDE_GREATER = 275,
|
||||
LPAREN = 276,
|
||||
MINUS = 277,
|
||||
MINUS_MINUS_GREATER = 278,
|
||||
PERIOD = 279,
|
||||
QUESTION = 280,
|
||||
QUESTION_QUESTION = 281,
|
||||
QUESTION_STAR = 282,
|
||||
RBRKT = 283,
|
||||
RPAREN = 284,
|
||||
STAR = 285,
|
||||
TILDE = 286,
|
||||
TILDE_AMPERSAND = 287,
|
||||
TILDE_VLINE = 288,
|
||||
VLINE = 289,
|
||||
_DLR_cnf = 290,
|
||||
_DLR_fof = 291,
|
||||
_DLR_fot = 292,
|
||||
_DLR_itef = 293,
|
||||
_DLR_itetf = 294,
|
||||
_DLR_itett = 295,
|
||||
_DLR_tff = 296,
|
||||
_DLR_thf = 297,
|
||||
_LIT_cnf = 298,
|
||||
_LIT_fof = 299,
|
||||
_LIT_include = 300,
|
||||
_LIT_tff = 301,
|
||||
_LIT_thf = 302,
|
||||
arrow = 303,
|
||||
comment = 304,
|
||||
comment_line = 305,
|
||||
decimal = 306,
|
||||
decimal_exponent = 307,
|
||||
decimal_fraction = 308,
|
||||
distinct_object = 309,
|
||||
dollar_dollar_word = 310,
|
||||
dollar_word = 311,
|
||||
dot_decimal = 312,
|
||||
integer = 313,
|
||||
less_sign = 314,
|
||||
lower_word = 315,
|
||||
plus = 316,
|
||||
positive_decimal = 317,
|
||||
rational = 318,
|
||||
real = 319,
|
||||
signed_integer = 320,
|
||||
signed_rational = 321,
|
||||
signed_real = 322,
|
||||
single_quoted = 323,
|
||||
star = 324,
|
||||
unrecognized = 325,
|
||||
unsigned_integer = 326,
|
||||
unsigned_rational = 327,
|
||||
unsigned_real = 328,
|
||||
upper_word = 329,
|
||||
vline = 330
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
|
||||
/* Line 1685 of yacc.c */
|
||||
#line 148 "tptp5.y"
|
||||
int ival; double dval; char* sval; TreeNode* pval;
|
||||
|
||||
|
||||
/* Line 1685 of yacc.c */
|
||||
#line 130 "tptp5.tab.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
|
|
@ -14,6 +14,7 @@ def init_project_def():
|
|||
add_lib('polynomial', ['util'], 'math/polynomial')
|
||||
add_lib('sat', ['util'])
|
||||
add_lib('nlsat', ['polynomial', 'sat'])
|
||||
add_lib('hilbert', ['util'], 'math/hilbert')
|
||||
add_lib('interval', ['util'], 'math/interval')
|
||||
add_lib('realclosure', ['interval'], 'math/realclosure')
|
||||
add_lib('subpaving', ['interval'], 'math/subpaving')
|
||||
|
@ -55,11 +56,19 @@ def init_project_def():
|
|||
add_lib('smt_tactic', ['smt'], 'smt/tactic')
|
||||
add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls')
|
||||
add_lib('duality', ['smt', 'interp'])
|
||||
# TODO: split muz_qe inbto muz, qe. Perhaps, we should also consider breaking muz into muz and pdr.
|
||||
add_lib('muz_qe', ['smt', 'sat', 'smt2parser', 'duality'])
|
||||
add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'muz_qe'], 'tactic/smtlogics')
|
||||
add_lib('qe', ['smt','sat'], 'qe')
|
||||
add_lib('muz', ['smt', 'sat', 'smt2parser', 'aig_tactic', 'qe'], 'muz/base')
|
||||
add_lib('transforms', ['muz', 'hilbert'], 'muz/transforms')
|
||||
add_lib('rel', ['muz', 'transforms'], 'muz/rel')
|
||||
add_lib('pdr', ['muz', 'transforms', 'arith_tactics', 'smt_tactic'], 'muz/pdr')
|
||||
add_lib('clp', ['muz', 'transforms'], 'muz/clp')
|
||||
add_lib('tab', ['muz', 'transforms'], 'muz/tab')
|
||||
add_lib('bmc', ['muz', 'transforms'], 'muz/bmc')
|
||||
add_lib('duality_intf', ['muz', 'transforms', 'duality'], 'muz/duality')
|
||||
add_lib('fp', ['muz', 'pdr', 'clp', 'tab', 'rel', 'bmc', 'duality_intf'], 'muz/fp')
|
||||
add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'fp', 'muz','qe'], 'tactic/smtlogics')
|
||||
add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv')
|
||||
add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
|
||||
add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'fp', 'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
|
||||
add_lib('smtparser', ['portfolio'], 'parsers/smt')
|
||||
# add_dll('foci2', ['util'], 'interp/foci2stub',
|
||||
# dll_name='foci2',
|
||||
|
@ -82,6 +91,7 @@ def init_project_def():
|
|||
# Examples
|
||||
add_cpp_example('cpp_example', 'c++')
|
||||
add_cpp_example('iz3', 'interp')
|
||||
add_cpp_example('z3_tptp', 'tptp')
|
||||
add_c_example('c_example', 'c')
|
||||
add_c_example('maxsat')
|
||||
add_dotnet_example('dotnet_example', 'dotnet')
|
||||
|
|
|
@ -292,7 +292,7 @@ def check_java():
|
|||
print("Finding jni.h...")
|
||||
|
||||
if JNI_HOME != None:
|
||||
if not os.path.exists(path.join(JNI_HOME, 'jni.h')):
|
||||
if not os.path.exists(os.path.join(JNI_HOME, 'jni.h')):
|
||||
raise MKException("Failed to detect jni.h '%s'; the environment variable JNI_HOME is probably set to the wrong path." % os.path.join(JNI_HOME))
|
||||
else:
|
||||
# Search for jni.h in the library directories...
|
||||
|
@ -952,6 +952,9 @@ class ExtraExeComponent(ExeComponent):
|
|||
def main_component(self):
|
||||
return False
|
||||
|
||||
def require_mem_initializer(self):
|
||||
return False
|
||||
|
||||
def get_so_ext():
|
||||
sysname = os.uname()[0]
|
||||
if sysname == 'Darwin':
|
||||
|
@ -1117,20 +1120,19 @@ class DotNetDLLComponent(Component):
|
|||
cs_fp_files.append(os.path.join(self.to_src_dir, self.assembly_info_dir, cs_file))
|
||||
cs_files.append(os.path.join(self.assembly_info_dir, cs_file))
|
||||
dllfile = '%s.dll' % self.dll_name
|
||||
out.write('%s:' % dllfile)
|
||||
out.write('%s: %s$(SO_EXT)' % (dllfile, get_component(Z3_DLL_COMPONENT).dll_name))
|
||||
for cs_file in cs_fp_files:
|
||||
out.write(' ')
|
||||
out.write(cs_file)
|
||||
out.write('\n')
|
||||
out.write(' cd %s && csc /noconfig /unsafe+ /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:mscorlib.dll /reference:System.Core.dll /reference:System.dll /reference:System.Numerics.dll /debug+ /debug:full /filealign:512 /optimize- /out:%s.dll /target:library' % (self.to_src_dir, self.dll_name))
|
||||
out.write(' csc /noconfig /unsafe+ /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:mscorlib.dll /reference:System.Core.dll /reference:System.dll /reference:System.Numerics.dll /debug+ /debug:full /filealign:512 /optimize- /linkresource:%s.dll /out:%s.dll /target:library' % (get_component(Z3_DLL_COMPONENT).dll_name, self.dll_name))
|
||||
if VS_X64:
|
||||
out.write(' /platform:x64')
|
||||
else:
|
||||
out.write(' /platform:x86')
|
||||
for cs_file in cs_files:
|
||||
out.write(' ')
|
||||
out.write(cs_file)
|
||||
out.write(' %s' % os.path.join(self.to_src_dir, cs_file))
|
||||
out.write('\n')
|
||||
# HACK
|
||||
win_to_src_dir = self.to_src_dir.replace('/', '\\')
|
||||
out.write(' move %s\n' % os.path.join(win_to_src_dir, dllfile))
|
||||
out.write(' move %s.pdb\n' % os.path.join(win_to_src_dir, self.dll_name))
|
||||
out.write('%s: %s\n\n' % (self.name, dllfile))
|
||||
return
|
||||
|
||||
|
@ -1256,7 +1258,7 @@ class CppExampleComponent(ExampleComponent):
|
|||
out.write(' ')
|
||||
out.write(os.path.join(self.to_ex_dir, cppfile))
|
||||
out.write('\n')
|
||||
out.write('\t%s $(EXAMP_DEBUG_FLAG) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % (self.compiler(), exefile))
|
||||
out.write('\t%s $(OS_DEFINES) $(EXAMP_DEBUG_FLAG) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % (self.compiler(), exefile))
|
||||
# Add include dir components
|
||||
out.write(' -I%s' % get_component(API_COMPONENT).to_src_dir)
|
||||
out.write(' -I%s' % get_component(CPP_COMPONENT).to_src_dir)
|
||||
|
@ -1428,7 +1430,8 @@ def mk_config():
|
|||
'LINK_OUT_FLAG=/Fe\n'
|
||||
'SO_EXT=.dll\n'
|
||||
'SLINK=cl\n'
|
||||
'SLINK_OUT_FLAG=/Fe\n')
|
||||
'SLINK_OUT_FLAG=/Fe\n'
|
||||
'OS_DEFINES=/D _WINDOWS\n')
|
||||
extra_opt = ''
|
||||
if GIT_HASH:
|
||||
extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH)
|
||||
|
@ -1476,6 +1479,7 @@ def mk_config():
|
|||
print('Java Compiler: %s' % JAVAC)
|
||||
else:
|
||||
global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG
|
||||
OS_DEFINES = ""
|
||||
ARITH = "internal"
|
||||
check_ar()
|
||||
CXX = find_cxx_compiler()
|
||||
|
@ -1526,18 +1530,21 @@ def mk_config():
|
|||
SLIBFLAGS = '-dynamiclib'
|
||||
elif sysname == 'Linux':
|
||||
CXXFLAGS = '%s -fno-strict-aliasing -D_LINUX_' % CXXFLAGS
|
||||
OS_DEFINES = '-D_LINUX'
|
||||
SO_EXT = '.so'
|
||||
LDFLAGS = '%s -lrt' % LDFLAGS
|
||||
SLIBFLAGS = '-shared'
|
||||
SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
|
||||
elif sysname == 'FreeBSD':
|
||||
CXXFLAGS = '%s -fno-strict-aliasing -D_FREEBSD_' % CXXFLAGS
|
||||
OS_DEFINES = '-D_FREEBSD_'
|
||||
SO_EXT = '.so'
|
||||
LDFLAGS = '%s -lrt' % LDFLAGS
|
||||
SLIBFLAGS = '-shared'
|
||||
SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
|
||||
elif sysname[:6] == 'CYGWIN':
|
||||
CXXFLAGS = '%s -D_CYGWIN -fno-strict-aliasing' % CXXFLAGS
|
||||
OS_DEFINES = '-D_CYGWIN'
|
||||
SO_EXT = '.dll'
|
||||
SLIBFLAGS = '-shared'
|
||||
else:
|
||||
|
@ -1573,6 +1580,7 @@ def mk_config():
|
|||
config.write('SLINK_FLAGS=%s\n' % SLIBFLAGS)
|
||||
config.write('SLINK_EXTRA_FLAGS=%s\n' % SLIBEXTRAFLAGS)
|
||||
config.write('SLINK_OUT_FLAG=-o \n')
|
||||
config.write('OS_DEFINES=%s\n' % OS_DEFINES)
|
||||
if is_verbose():
|
||||
print('Host platform: %s' % sysname)
|
||||
print('C++ Compiler: %s' % CXX)
|
||||
|
|
|
@ -373,7 +373,7 @@ extern "C" {
|
|||
scoped_anum_vector roots(_am);
|
||||
{
|
||||
cancel_eh<algebraic_numbers::manager> eh(_am);
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
|
||||
vector_var2anum v2a(as);
|
||||
_am.isolate_roots(_p, v2a, roots);
|
||||
|
@ -408,7 +408,7 @@ extern "C" {
|
|||
}
|
||||
{
|
||||
cancel_eh<algebraic_numbers::manager> eh(_am);
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
|
||||
vector_var2anum v2a(as);
|
||||
int r = _am.eval_sign_at(_p, v2a);
|
||||
|
|
|
@ -46,7 +46,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_mk_int_symbol(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i < 0 || (unsigned)i >= (SIZE_MAX >> PTR_ALIGNMENT)) {
|
||||
if (i < 0 || (size_t)i >= (SIZE_MAX >> PTR_ALIGNMENT)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
|
@ -682,7 +682,7 @@ extern "C" {
|
|||
th_rewriter m_rw(m, p);
|
||||
expr_ref result(m);
|
||||
cancel_eh<th_rewriter> eh(m_rw);
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
|
@ -1072,6 +1072,16 @@ extern "C" {
|
|||
case OP_BV2INT: return Z3_OP_BV2INT;
|
||||
case OP_CARRY: return Z3_OP_CARRY;
|
||||
case OP_XOR3: return Z3_OP_XOR3;
|
||||
case OP_BSMUL_NO_OVFL:
|
||||
case OP_BUMUL_NO_OVFL:
|
||||
case OP_BSMUL_NO_UDFL:
|
||||
case OP_BSDIV_I:
|
||||
case OP_BUDIV_I:
|
||||
case OP_BSREM_I:
|
||||
case OP_BUREM_I:
|
||||
case OP_BSMOD_I:
|
||||
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
|
|
|
@ -121,10 +121,20 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
unsigned sz = Z3_get_bv_sort_size(c, s);
|
||||
rational max_bound = power(rational(2), sz);
|
||||
Z3_ast bound = Z3_mk_numeral(c, max_bound.to_string().c_str(), int_s);
|
||||
Z3_ast pred = Z3_mk_bvslt(c, n, Z3_mk_int(c, 0, s));
|
||||
Z3_inc_ref(c, bound);
|
||||
Z3_ast zero = Z3_mk_int(c, 0, s);
|
||||
Z3_inc_ref(c, zero);
|
||||
Z3_ast pred = Z3_mk_bvslt(c, n, zero);
|
||||
Z3_inc_ref(c, pred);
|
||||
// if n <_sigend 0 then r - s^sz else r
|
||||
Z3_ast args[2] = { r, bound };
|
||||
Z3_ast res = Z3_mk_ite(c, pred, Z3_mk_sub(c, 2, args), r);
|
||||
Z3_ast sub = Z3_mk_sub(c, 2, args);
|
||||
Z3_inc_ref(c, sub);
|
||||
Z3_ast res = Z3_mk_ite(c, pred, sub, r);
|
||||
Z3_dec_ref(c, bound);
|
||||
Z3_dec_ref(c, pred);
|
||||
Z3_dec_ref(c, sub);
|
||||
Z3_dec_ref(c, zero);
|
||||
RETURN_Z3(res);
|
||||
}
|
||||
else {
|
||||
|
@ -156,7 +166,14 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return Z3_mk_bvshl(c, Z3_mk_int64(c, 1, s), Z3_mk_int64(c, sz - 1, s));
|
||||
Z3_ast x = Z3_mk_int64(c, 1, s);
|
||||
Z3_inc_ref(c, x);
|
||||
Z3_ast y = Z3_mk_int64(c, sz - 1, s);
|
||||
Z3_inc_ref(c, y);
|
||||
Z3_ast result = Z3_mk_bvshl(c, x, y);
|
||||
Z3_dec_ref(c, x);
|
||||
Z3_dec_ref(c, y);
|
||||
return result;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -177,17 +194,40 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
Z3_inc_ref(c, zero);
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
Z3_ast args[2] = { Z3_mk_bvslt(c, zero, t1), Z3_mk_bvslt(c, zero, t2) };
|
||||
Z3_inc_ref(c, r);
|
||||
Z3_ast l1 = Z3_mk_bvslt(c, zero, t1);
|
||||
Z3_inc_ref(c, l1);
|
||||
Z3_ast l2 = Z3_mk_bvslt(c, zero, t2);
|
||||
Z3_inc_ref(c, l2);
|
||||
Z3_ast args[2] = { l1, l2 };
|
||||
Z3_ast args_pos = Z3_mk_and(c, 2, args);
|
||||
return Z3_mk_implies(c, args_pos, Z3_mk_bvslt(c, zero, r));
|
||||
Z3_inc_ref(c, args_pos);
|
||||
Z3_ast result = Z3_mk_implies(c, args_pos, Z3_mk_bvslt(c, zero, r));
|
||||
Z3_dec_ref(c, r);
|
||||
Z3_dec_ref(c, l1);
|
||||
Z3_dec_ref(c, l2);
|
||||
Z3_dec_ref(c, args_pos);
|
||||
Z3_dec_ref(c, zero);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
unsigned sz = Z3_get_bv_sort_size(c, Z3_get_sort(c, t1));
|
||||
t1 = Z3_mk_zero_ext(c, 1, t1);
|
||||
Z3_inc_ref(c, t1);
|
||||
t2 = Z3_mk_zero_ext(c, 1, t2);
|
||||
Z3_inc_ref(c, t2);
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
return Z3_mk_eq(c, Z3_mk_extract(c, sz, sz, r), Z3_mk_int(c, 0, Z3_mk_bv_sort(c, 1)));
|
||||
Z3_inc_ref(c, r);
|
||||
Z3_ast ex = Z3_mk_extract(c, sz, sz, r);
|
||||
Z3_inc_ref(c, ex);
|
||||
Z3_ast result = Z3_mk_eq(c, ex, Z3_mk_int(c, 0, Z3_mk_bv_sort(c, 1)));
|
||||
Z3_dec_ref(c, t1);
|
||||
Z3_dec_ref(c, t2);
|
||||
Z3_dec_ref(c, ex);
|
||||
Z3_dec_ref(c, r);
|
||||
return result;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
@ -197,10 +237,26 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
Z3_inc_ref(c, zero);
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
Z3_ast args[2] = { Z3_mk_bvslt(c, t1, zero), Z3_mk_bvslt(c, t2, zero) };
|
||||
Z3_inc_ref(c, r);
|
||||
Z3_ast l1 = Z3_mk_bvslt(c, t1, zero);
|
||||
Z3_inc_ref(c, l1);
|
||||
Z3_ast l2 = Z3_mk_bvslt(c, t2, zero);
|
||||
Z3_inc_ref(c, l2);
|
||||
Z3_ast args[2] = { l1, l2 };
|
||||
Z3_ast args_neg = Z3_mk_and(c, 2, args);
|
||||
return Z3_mk_implies(c, args_neg, Z3_mk_bvslt(c, r, zero));
|
||||
Z3_inc_ref(c, args_neg);
|
||||
Z3_ast lt = Z3_mk_bvslt(c, r, zero);
|
||||
Z3_inc_ref(c, lt);
|
||||
Z3_ast result = Z3_mk_implies(c, args_neg, lt);
|
||||
Z3_dec_ref(c, lt);
|
||||
Z3_dec_ref(c, l1);
|
||||
Z3_dec_ref(c, l2);
|
||||
Z3_dec_ref(c, r);
|
||||
Z3_dec_ref(c, args_neg);
|
||||
Z3_dec_ref(c, zero);
|
||||
return result;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -208,12 +264,28 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
Z3_ast Z3_API Z3_mk_bvsub_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort s = Z3_get_sort(c, t2);
|
||||
Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
|
||||
Z3_inc_ref(c, minus_t2);
|
||||
Z3_sort s = Z3_get_sort(c, t2);
|
||||
Z3_ast min = Z3_mk_bvsmin(c, s);
|
||||
return Z3_mk_ite(c, Z3_mk_eq(c, t2, min),
|
||||
Z3_mk_bvslt(c, t1, Z3_mk_int(c, 0, s)),
|
||||
Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true));
|
||||
Z3_inc_ref(c, min);
|
||||
Z3_ast x = Z3_mk_eq(c, t2, min);
|
||||
Z3_inc_ref(c, x);
|
||||
Z3_ast zero = Z3_mk_int(c, 0, s);
|
||||
Z3_inc_ref(c, zero);
|
||||
Z3_ast y = Z3_mk_bvslt(c, t1, zero);
|
||||
Z3_inc_ref(c, y);
|
||||
Z3_ast z = Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true);
|
||||
Z3_inc_ref(c, z);
|
||||
Z3_ast result = Z3_mk_ite(c, x, y, z);
|
||||
mk_c(c)->save_ast_trail(to_app(result));
|
||||
Z3_dec_ref(c, minus_t2);
|
||||
Z3_dec_ref(c, min);
|
||||
Z3_dec_ref(c, x);
|
||||
Z3_dec_ref(c, y);
|
||||
Z3_dec_ref(c, z);
|
||||
Z3_dec_ref(c, zero);
|
||||
return result;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -222,10 +294,19 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_inc_ref(c, zero);
|
||||
Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
return Z3_mk_implies(c, Z3_mk_bvslt(c, zero, t2), Z3_mk_bvadd_no_underflow(c, t1, minus_t2));
|
||||
Z3_inc_ref(c, minus_t2);
|
||||
Z3_ast x = Z3_mk_bvslt(c, zero, t2);
|
||||
Z3_inc_ref(c, x);
|
||||
Z3_ast y = Z3_mk_bvadd_no_underflow(c, t1, minus_t2);
|
||||
Z3_inc_ref(c, y);
|
||||
Z3_ast result = Z3_mk_implies(c, x, y);
|
||||
Z3_dec_ref(c, zero);
|
||||
Z3_dec_ref(c, minus_t2);
|
||||
Z3_dec_ref(c, x);
|
||||
Z3_dec_ref(c, y);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return Z3_mk_bvule(c, t2, t1);
|
||||
|
@ -267,12 +348,24 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
|||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort s = Z3_get_sort(c, t1);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast min = Z3_mk_bvmsb(c, s);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast args[2] = { Z3_mk_eq(c, t1, min),
|
||||
Z3_mk_eq(c, t2, Z3_mk_int(c, -1, s)) };
|
||||
return Z3_mk_not(c, Z3_mk_and(c, 2, args));
|
||||
Z3_inc_ref(c, min);
|
||||
Z3_ast x = Z3_mk_eq(c, t1, min);
|
||||
Z3_inc_ref(c, x);
|
||||
Z3_ast y = Z3_mk_int(c, -1, s);
|
||||
Z3_inc_ref(c, y);
|
||||
Z3_ast z = Z3_mk_eq(c, t2, y);
|
||||
Z3_inc_ref(c, z);
|
||||
Z3_ast args[2] = { x, z };
|
||||
Z3_ast u = Z3_mk_and(c, 2, args);
|
||||
Z3_inc_ref(c, u);
|
||||
Z3_ast result = Z3_mk_not(c, u);
|
||||
Z3_dec_ref(c, min);
|
||||
Z3_dec_ref(c, x);
|
||||
Z3_dec_ref(c, y);
|
||||
Z3_dec_ref(c, z);
|
||||
Z3_dec_ref(c, u);
|
||||
return result;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace api {
|
|||
if (m_interruptable)
|
||||
(*m_interruptable)();
|
||||
m().set_cancel(true);
|
||||
if (m_rcf_manager.get() == 0)
|
||||
if (m_rcf_manager.get() != 0)
|
||||
m_rcf_manager->set_cancel(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ Revision History:
|
|||
#include"api_datalog.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"dl_context.h"
|
||||
#include"ast_pp.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"api_log_macros.h"
|
||||
|
@ -29,104 +28,126 @@ Revision History:
|
|||
#include"dl_cmds.h"
|
||||
#include"cmd_context.h"
|
||||
#include"smt2parser.h"
|
||||
#include"dl_context.h"
|
||||
#include"dl_register_engine.h"
|
||||
#include"dl_external_relation.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"rel_context.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
fixedpoint_context::fixedpoint_context(ast_manager& m, smt_params& p) :
|
||||
m_state(0),
|
||||
m_reduce_app(0),
|
||||
m_reduce_assign(0),
|
||||
m_context(m, p),
|
||||
m_trail(m) {}
|
||||
|
||||
|
||||
void fixedpoint_context::set_state(void* state) {
|
||||
SASSERT(!m_state);
|
||||
m_state = state;
|
||||
symbol name("datalog_relation");
|
||||
ast_manager& m = m_context.get_manager();
|
||||
if (!m.has_plugin(name)) {
|
||||
m.register_plugin(name, alloc(datalog::dl_decl_plugin));
|
||||
}
|
||||
datalog::relation_manager& r = m_context.get_rel_context().get_rmanager();
|
||||
r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
|
||||
}
|
||||
|
||||
void fixedpoint_context::reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) {
|
||||
expr* r = 0;
|
||||
if (m_reduce_app) {
|
||||
m_reduce_app(m_state, f, num_args, args, &r);
|
||||
result = r;
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_trail.push_back(r);
|
||||
}
|
||||
// allow fallthrough.
|
||||
if (r == 0) {
|
||||
|
||||
class fixedpoint_context : public datalog::external_relation_context {
|
||||
void * m_state;
|
||||
reduce_app_callback_fptr m_reduce_app;
|
||||
reduce_assign_callback_fptr m_reduce_assign;
|
||||
datalog::register_engine m_register_engine;
|
||||
datalog::context m_context;
|
||||
ast_ref_vector m_trail;
|
||||
public:
|
||||
fixedpoint_context(ast_manager& m, smt_params& p):
|
||||
m_state(0),
|
||||
m_reduce_app(0),
|
||||
m_reduce_assign(0),
|
||||
m_context(m, m_register_engine, p),
|
||||
m_trail(m) {}
|
||||
|
||||
virtual ~fixedpoint_context() {}
|
||||
family_id get_family_id() const { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
|
||||
void set_state(void* state) {
|
||||
SASSERT(!m_state);
|
||||
m_state = state;
|
||||
symbol name("datalog_relation");
|
||||
ast_manager& m = m_context.get_manager();
|
||||
result = m.mk_app(f, num_args, args);
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite terms passed in outs vector with values computed by function.
|
||||
void fixedpoint_context::reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) {
|
||||
if (m_reduce_assign) {
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
if (!m.has_plugin(name)) {
|
||||
m.register_plugin(name, alloc(datalog::dl_decl_plugin));
|
||||
}
|
||||
datalog::rel_context_base* rel = m_context.get_rel_context();
|
||||
if (rel) {
|
||||
datalog::relation_manager& r = rel->get_rmanager();
|
||||
r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
|
||||
}
|
||||
m_reduce_assign(m_state, f, num_args, args, num_out, outs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fixedpoint_context::add_rule(expr* rule, symbol const& name) {
|
||||
m_context.add_rule(rule, name);
|
||||
}
|
||||
|
||||
void fixedpoint_context::update_rule(expr* rule, symbol const& name) {
|
||||
m_context.update_rule(rule, name);
|
||||
}
|
||||
|
||||
void fixedpoint_context::add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
|
||||
m_context.add_table_fact(r, num_args, args);
|
||||
}
|
||||
|
||||
unsigned fixedpoint_context::get_num_levels(func_decl* pred) {
|
||||
return m_context.get_num_levels(pred);
|
||||
}
|
||||
|
||||
expr_ref fixedpoint_context::get_cover_delta(int level, func_decl* pred) {
|
||||
return m_context.get_cover_delta(level, pred);
|
||||
}
|
||||
|
||||
void fixedpoint_context::add_cover(int level, func_decl* pred, expr* predicate) {
|
||||
m_context.add_cover(level, pred, predicate);
|
||||
}
|
||||
|
||||
std::string fixedpoint_context::get_last_status() {
|
||||
datalog::execution_result status = m_context.get_status();
|
||||
switch(status) {
|
||||
case datalog::INPUT_ERROR:
|
||||
return "input error";
|
||||
case datalog::OK:
|
||||
return "ok";
|
||||
case datalog::TIMEOUT:
|
||||
return "timeout";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "unknown";
|
||||
void set_reduce_app(reduce_app_callback_fptr f) {
|
||||
m_reduce_app = f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string fixedpoint_context::to_string(unsigned num_queries, expr*const* queries) {
|
||||
std::stringstream str;
|
||||
m_context.display_smt2(num_queries, queries, str);
|
||||
return str.str();
|
||||
}
|
||||
|
||||
void set_reduce_assign(reduce_assign_callback_fptr f) {
|
||||
m_reduce_assign = f;
|
||||
}
|
||||
virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) {
|
||||
expr* r = 0;
|
||||
if (m_reduce_app) {
|
||||
m_reduce_app(m_state, f, num_args, args, &r);
|
||||
result = r;
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_trail.push_back(r);
|
||||
}
|
||||
// allow fallthrough.
|
||||
if (r == 0) {
|
||||
ast_manager& m = m_context.get_manager();
|
||||
result = m.mk_app(f, num_args, args);
|
||||
}
|
||||
}
|
||||
virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) {
|
||||
if (m_reduce_assign) {
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_reduce_assign(m_state, f, num_args, args, num_out, outs);
|
||||
}
|
||||
}
|
||||
datalog::context& ctx() { return m_context; }
|
||||
void add_rule(expr* rule, symbol const& name) {
|
||||
m_context.add_rule(rule, name);
|
||||
}
|
||||
void update_rule(expr* rule, symbol const& name) {
|
||||
m_context.update_rule(rule, name);
|
||||
}
|
||||
void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
|
||||
m_context.add_table_fact(r, num_args, args);
|
||||
}
|
||||
std::string get_last_status() {
|
||||
datalog::execution_result status = m_context.get_status();
|
||||
switch(status) {
|
||||
case datalog::INPUT_ERROR:
|
||||
return "input error";
|
||||
case datalog::OK:
|
||||
return "ok";
|
||||
case datalog::TIMEOUT:
|
||||
return "timeout";
|
||||
case datalog::APPROX:
|
||||
return "approximated";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
std::string to_string(unsigned num_queries, expr*const* queries) {
|
||||
std::stringstream str;
|
||||
m_context.display_smt2(num_queries, queries, str);
|
||||
return str.str();
|
||||
}
|
||||
void cancel() {
|
||||
m_context.cancel();
|
||||
}
|
||||
void reset_cancel() {
|
||||
m_context.reset_cancel();
|
||||
}
|
||||
unsigned get_num_levels(func_decl* pred) {
|
||||
return m_context.get_num_levels(pred);
|
||||
}
|
||||
expr_ref get_cover_delta(int level, func_decl* pred) {
|
||||
return m_context.get_cover_delta(level, pred);
|
||||
}
|
||||
void add_cover(int level, func_decl* pred, expr* predicate) {
|
||||
m_context.add_cover(level, pred, predicate);
|
||||
}
|
||||
void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
|
||||
void updt_params(params_ref const& p) { m_context.updt_params(p); }
|
||||
};
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
@ -266,7 +287,7 @@ extern "C" {
|
|||
lbool r = l_undef;
|
||||
cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
|
@ -291,7 +312,7 @@ extern "C" {
|
|||
lbool r = l_undef;
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
|
@ -358,7 +379,7 @@ extern "C" {
|
|||
v->m_ast_vector.push_back(coll.m_queries[i].get());
|
||||
}
|
||||
for (unsigned i = 0; i < coll.m_rels.size(); ++i) {
|
||||
to_fixedpoint_ref(d)->ctx().register_predicate(coll.m_rels[i].get());
|
||||
to_fixedpoint_ref(d)->ctx().register_predicate(coll.m_rels[i].get(), true);
|
||||
}
|
||||
for (unsigned i = 0; i < coll.m_rules.size(); ++i) {
|
||||
to_fixedpoint_ref(d)->add_rule(coll.m_rules[i].get(), coll.m_names[i]);
|
||||
|
@ -415,7 +436,7 @@ extern "C" {
|
|||
void Z3_API Z3_fixedpoint_register_relation(Z3_context c,Z3_fixedpoint d, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_register_relation(c, d, f);
|
||||
to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f));
|
||||
to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f), true);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,48 +22,14 @@ Revision History:
|
|||
#include"z3.h"
|
||||
#include"ast.h"
|
||||
#include"smt_params.h"
|
||||
#include"dl_external_relation.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"smt_kernel.h"
|
||||
#include"api_util.h"
|
||||
#include"dl_context.h"
|
||||
|
||||
typedef void (*reduce_app_callback_fptr)(void*, func_decl*, unsigned, expr*const*, expr**);
|
||||
typedef void (*reduce_assign_callback_fptr)(void*, func_decl*, unsigned, expr*const*, unsigned, expr*const*);
|
||||
|
||||
namespace api {
|
||||
|
||||
class fixedpoint_context : public datalog::external_relation_context {
|
||||
void * m_state;
|
||||
reduce_app_callback_fptr m_reduce_app;
|
||||
reduce_assign_callback_fptr m_reduce_assign;
|
||||
datalog::context m_context;
|
||||
ast_ref_vector m_trail;
|
||||
public:
|
||||
fixedpoint_context(ast_manager& m, smt_params& p);
|
||||
virtual ~fixedpoint_context() {}
|
||||
family_id get_family_id() const { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
|
||||
void set_state(void* state);
|
||||
void set_reduce_app(reduce_app_callback_fptr f) { m_reduce_app = f; }
|
||||
void set_reduce_assign(reduce_assign_callback_fptr f) { m_reduce_assign = f; }
|
||||
virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result);
|
||||
virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs);
|
||||
datalog::context& ctx() { return m_context; }
|
||||
void add_rule(expr* rule, symbol const& name);
|
||||
void update_rule(expr* rule, symbol const& name);
|
||||
void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]);
|
||||
std::string get_last_status();
|
||||
std::string to_string(unsigned num_queries, expr*const* queries);
|
||||
void cancel() { m_context.cancel(); }
|
||||
void reset_cancel() { m_context.reset_cancel(); }
|
||||
|
||||
unsigned get_num_levels(func_decl* pred);
|
||||
expr_ref get_cover_delta(int level, func_decl* pred);
|
||||
void add_cover(int level, func_decl* pred, expr* predicate);
|
||||
void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
|
||||
void updt_params(params_ref const& p) { m_context.updt_params(p); }
|
||||
|
||||
};
|
||||
class fixedpoint_context;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ extern "C" {
|
|||
expr_ref _r(mk_c(c)->m());
|
||||
{
|
||||
cancel_eh<polynomial::manager> eh(pm);
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
|
||||
pm.psc_chain(_p, _q, v_x, rs);
|
||||
}
|
||||
|
|
|
@ -165,7 +165,10 @@ extern "C" {
|
|||
}
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
app* a = to_app(bound[i]);
|
||||
SASSERT(a->get_kind() == AST_APP);
|
||||
if (a->get_kind() != AST_APP) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
symbol s(to_app(a)->get_decl()->get_name());
|
||||
names.push_back(of_symbol(s));
|
||||
types.push_back(of_sort(mk_c(c)->m().get_sort(a)));
|
||||
|
|
|
@ -243,7 +243,7 @@ extern "C" {
|
|||
unsigned timeout = to_solver(s)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", false);
|
||||
cancel_eh<solver> eh(*to_solver_ref(s));
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
|
|
|
@ -73,7 +73,7 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
cancel_eh<smt::kernel> eh(mk_c(c)->get_smt_kernel());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
lbool result;
|
||||
try {
|
||||
|
@ -123,7 +123,7 @@ extern "C" {
|
|||
expr * const* _assumptions = to_exprs(assumptions);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
cancel_eh<smt::kernel> eh(mk_c(c)->get_smt_kernel());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
result = mk_c(c)->get_smt_kernel().check(num_assumptions, _assumptions);
|
||||
if (result != l_false && m) {
|
||||
|
|
|
@ -410,7 +410,7 @@ extern "C" {
|
|||
|
||||
to_tactic_ref(t)->updt_params(p);
|
||||
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
|
|
|
@ -29,7 +29,6 @@ Revision History:
|
|||
#define Z3_CATCH_RETURN_NO_HANDLE(VAL) } catch (z3_exception &) { return VAL; }
|
||||
|
||||
#define CHECK_REF_COUNT(a) (reinterpret_cast<ast const*>(a)->get_ref_count() > 0)
|
||||
#define VALIDATE(a) SASSERT(!a || CHECK_REF_COUNT(a))
|
||||
|
||||
namespace api {
|
||||
// Generic wrapper for ref-count objects exposed by the API
|
||||
|
@ -44,30 +43,30 @@ namespace api {
|
|||
};
|
||||
};
|
||||
|
||||
inline ast * to_ast(Z3_ast a) { VALIDATE(a); return reinterpret_cast<ast *>(a); }
|
||||
inline ast * to_ast(Z3_ast a) { return reinterpret_cast<ast *>(a); }
|
||||
inline Z3_ast of_ast(ast* a) { return reinterpret_cast<Z3_ast>(a); }
|
||||
|
||||
inline expr * to_expr(Z3_ast a) { VALIDATE(a); return reinterpret_cast<expr*>(a); }
|
||||
inline expr * to_expr(Z3_ast a) { return reinterpret_cast<expr*>(a); }
|
||||
inline Z3_ast of_expr(expr* e) { return reinterpret_cast<Z3_ast>(e); }
|
||||
|
||||
inline expr * const * to_exprs(Z3_ast const* a) { return reinterpret_cast<expr* const*>(a); }
|
||||
inline Z3_ast * const * of_exprs(expr* const* e) { return reinterpret_cast<Z3_ast* const*>(e); }
|
||||
|
||||
inline app * to_app(Z3_app a) { VALIDATE(a); return reinterpret_cast<app*>(a); }
|
||||
inline app * to_app(Z3_ast a) { VALIDATE(a); return reinterpret_cast<app*>(a); }
|
||||
inline app * to_app(Z3_app a) { return reinterpret_cast<app*>(a); }
|
||||
inline app * to_app(Z3_ast a) { return reinterpret_cast<app*>(a); }
|
||||
inline Z3_app of_app(app* a) { return reinterpret_cast<Z3_app>(a); }
|
||||
|
||||
inline app * const* to_apps(Z3_ast const* a) { VALIDATE(a); return reinterpret_cast<app * const*>(a); }
|
||||
inline app * const* to_apps(Z3_ast const* a) { return reinterpret_cast<app * const*>(a); }
|
||||
|
||||
inline ast * const * to_asts(Z3_ast const* a) { return reinterpret_cast<ast* const*>(a); }
|
||||
|
||||
inline sort * to_sort(Z3_sort a) { VALIDATE(a); return reinterpret_cast<sort*>(a); }
|
||||
inline sort * to_sort(Z3_sort a) { return reinterpret_cast<sort*>(a); }
|
||||
inline Z3_sort of_sort(sort* s) { return reinterpret_cast<Z3_sort>(s); }
|
||||
|
||||
inline sort * const * to_sorts(Z3_sort const* a) { return reinterpret_cast<sort* const*>(a); }
|
||||
inline Z3_sort const * of_sorts(sort* const* s) { return reinterpret_cast<Z3_sort const*>(s); }
|
||||
|
||||
inline func_decl * to_func_decl(Z3_func_decl a) { VALIDATE(a); return reinterpret_cast<func_decl*>(a); }
|
||||
inline func_decl * to_func_decl(Z3_func_decl a) { return reinterpret_cast<func_decl*>(a); }
|
||||
inline Z3_func_decl of_func_decl(func_decl* f) { return reinterpret_cast<Z3_func_decl>(f); }
|
||||
|
||||
inline func_decl * const * to_func_decls(Z3_func_decl const* f) { return reinterpret_cast<func_decl*const*>(f); }
|
||||
|
@ -75,7 +74,7 @@ inline func_decl * const * to_func_decls(Z3_func_decl const* f) { return reinter
|
|||
inline symbol to_symbol(Z3_symbol s) { return symbol::mk_symbol_from_c_ptr(reinterpret_cast<void*>(s)); }
|
||||
inline Z3_symbol of_symbol(symbol s) { return reinterpret_cast<Z3_symbol>(const_cast<void*>(s.c_ptr())); }
|
||||
|
||||
inline Z3_pattern of_pattern(ast* a) { VALIDATE(a); return reinterpret_cast<Z3_pattern>(a); }
|
||||
inline Z3_pattern of_pattern(ast* a) { return reinterpret_cast<Z3_pattern>(a); }
|
||||
inline app* to_pattern(Z3_pattern p) { return reinterpret_cast<app*>(p); }
|
||||
|
||||
inline Z3_lbool of_lbool(lbool b) { return static_cast<Z3_lbool>(b); }
|
||||
|
|
|
@ -204,6 +204,8 @@ namespace z3 {
|
|||
|
||||
func_decl function(symbol const & name, unsigned arity, sort const * domain, sort const & range);
|
||||
func_decl function(char const * name, unsigned arity, sort const * domain, sort const & range);
|
||||
func_decl function(symbol const& name, sort_vector const& domain, sort const& range);
|
||||
func_decl function(char const * name, sort_vector const& domain, sort const& range);
|
||||
func_decl function(char const * name, sort const & domain, sort const & range);
|
||||
func_decl function(char const * name, sort const & d1, sort const & d2, sort const & range);
|
||||
func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & range);
|
||||
|
@ -249,6 +251,8 @@ namespace z3 {
|
|||
array & operator=(array const & s);
|
||||
public:
|
||||
array(unsigned sz):m_size(sz) { m_array = new T[sz]; }
|
||||
template<typename T2>
|
||||
array(ast_vector_tpl<T2> const & v);
|
||||
~array() { delete[] m_array; }
|
||||
unsigned size() const { return m_size; }
|
||||
T & operator[](int i) { assert(0 <= i); assert(static_cast<unsigned>(i) < m_size); return m_array[i]; }
|
||||
|
@ -427,6 +431,7 @@ namespace z3 {
|
|||
|
||||
expr operator()() const;
|
||||
expr operator()(unsigned n, expr const * args) const;
|
||||
expr operator()(expr_vector const& v) const;
|
||||
expr operator()(expr const & a) const;
|
||||
expr operator()(int a) const;
|
||||
expr operator()(expr const & a1, expr const & a2) const;
|
||||
|
@ -872,7 +877,18 @@ namespace z3 {
|
|||
\brief Return a simplified version of this expression. The parameter \c p is a set of parameters for the Z3 simplifier.
|
||||
*/
|
||||
expr simplify(params const & p) const { Z3_ast r = Z3_simplify_ex(ctx(), m_ast, p); check_error(); return expr(ctx(), r); }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Apply substitution. Replace src expressions by dst.
|
||||
*/
|
||||
expr substitute(expr_vector const& src, expr_vector const& dst);
|
||||
|
||||
/**
|
||||
\brief Apply substitution. Replace bound variables by expressions.
|
||||
*/
|
||||
expr substitute(expr_vector const& dst);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Wraps a Z3_ast as an expr object. It also checks for errors.
|
||||
|
@ -928,49 +944,6 @@ namespace z3 {
|
|||
inline expr udiv(expr const & a, int b) { return udiv(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr udiv(int a, expr const & b) { return udiv(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
// Basic functions for creating quantified formulas.
|
||||
// The C API should be used for creating quantifiers with patterns, weights, many variables, etc.
|
||||
inline expr forall(expr const & x, expr const & b) {
|
||||
check_context(x, b);
|
||||
Z3_app vars[] = {(Z3_app) x};
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr const & x1, expr const & x2, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2};
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 };
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 };
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x, expr const & b) {
|
||||
check_context(x, b);
|
||||
Z3_app vars[] = {(Z3_app) x};
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x1, expr const & x2, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2};
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 };
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 };
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
|
||||
template<typename T> class cast_ast;
|
||||
|
||||
template<> class cast_ast<ast> {
|
||||
|
@ -1032,6 +1005,67 @@ namespace z3 {
|
|||
friend std::ostream & operator<<(std::ostream & out, ast_vector_tpl const & v) { out << Z3_ast_vector_to_string(v.ctx(), v); return out; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename T2>
|
||||
array<T>::array(ast_vector_tpl<T2> const & v) {
|
||||
m_array = new T[v.size()];
|
||||
m_size = v.size();
|
||||
for (unsigned i = 0; i < m_size; i++) {
|
||||
m_array[i] = v[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Basic functions for creating quantified formulas.
|
||||
// The C API should be used for creating quantifiers with patterns, weights, many variables, etc.
|
||||
inline expr forall(expr const & x, expr const & b) {
|
||||
check_context(x, b);
|
||||
Z3_app vars[] = {(Z3_app) x};
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr const & x1, expr const & x2, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2};
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 };
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 };
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr forall(expr_vector const & xs, expr const & b) {
|
||||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x, expr const & b) {
|
||||
check_context(x, b);
|
||||
Z3_app vars[] = {(Z3_app) x};
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x1, expr const & x2, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2};
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 };
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 };
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr exists(expr_vector const & xs, expr const & b) {
|
||||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
|
||||
class func_entry : public object {
|
||||
Z3_func_entry m_entry;
|
||||
void init(Z3_func_entry e) {
|
||||
|
@ -1274,7 +1308,7 @@ namespace z3 {
|
|||
expr as_expr() const {
|
||||
unsigned n = size();
|
||||
if (n == 0)
|
||||
return ctx().bool_val(false);
|
||||
return ctx().bool_val(true);
|
||||
else if (n == 1)
|
||||
return operator[](0);
|
||||
else {
|
||||
|
@ -1485,6 +1519,22 @@ namespace z3 {
|
|||
inline func_decl context::function(char const * name, unsigned arity, sort const * domain, sort const & range) {
|
||||
return function(range.ctx().str_symbol(name), arity, domain, range);
|
||||
}
|
||||
|
||||
inline func_decl context::function(symbol const& name, sort_vector const& domain, sort const& range) {
|
||||
array<Z3_sort> args(domain.size());
|
||||
for (unsigned i = 0; i < domain.size(); i++) {
|
||||
check_context(domain[i], range);
|
||||
args[i] = domain[i];
|
||||
}
|
||||
Z3_func_decl f = Z3_mk_func_decl(m_ctx, name, domain.size(), args.ptr(), range);
|
||||
check_error();
|
||||
return func_decl(*this, f);
|
||||
}
|
||||
|
||||
inline func_decl context::function(char const * name, sort_vector const& domain, sort const& range) {
|
||||
return function(range.ctx().str_symbol(name), domain, range);
|
||||
}
|
||||
|
||||
|
||||
inline func_decl context::function(char const * name, sort const & domain, sort const & range) {
|
||||
check_context(domain, range);
|
||||
|
@ -1571,6 +1621,16 @@ namespace z3 {
|
|||
return expr(ctx(), r);
|
||||
|
||||
}
|
||||
inline expr func_decl::operator()(expr_vector const& args) const {
|
||||
array<Z3_ast> _args(args.size());
|
||||
for (unsigned i = 0; i < args.size(); i++) {
|
||||
check_context(*this, args[i]);
|
||||
_args[i] = args[i];
|
||||
}
|
||||
Z3_ast r = Z3_mk_app(ctx(), *this, args.size(), _args.ptr());
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
inline expr func_decl::operator()() const {
|
||||
Z3_ast r = Z3_mk_app(ctx(), *this, 0, 0);
|
||||
ctx().check_error();
|
||||
|
@ -1680,6 +1740,30 @@ namespace z3 {
|
|||
d.check_error();
|
||||
return expr(d.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr expr::substitute(expr_vector const& src, expr_vector const& dst) {
|
||||
assert(src.size() == dst.size());
|
||||
array<Z3_ast> _src(src.size());
|
||||
array<Z3_ast> _dst(dst.size());
|
||||
for (unsigned i = 0; i < src.size(); ++i) {
|
||||
_src[i] = src[i];
|
||||
_dst[i] = dst[i];
|
||||
}
|
||||
Z3_ast r = Z3_substitute(ctx(), m_ast, src.size(), _src.ptr(), _dst.ptr());
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
inline expr expr::substitute(expr_vector const& dst) {
|
||||
array<Z3_ast> _dst(dst.size());
|
||||
for (unsigned i = 0; i < dst.size(); ++i) {
|
||||
_dst[i] = dst[i];
|
||||
}
|
||||
Z3_ast r = Z3_substitute_vars(ctx(), m_ast, dst.size(), _dst.ptr());
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -44,6 +44,21 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The following parameters can be set:
|
||||
/// - proof (Boolean) Enable proof generation
|
||||
/// - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting
|
||||
/// - trace (Boolean) Tracing support for VCC
|
||||
/// - trace_file_name (String) Trace out file for VCC traces
|
||||
/// - timeout (unsigned) default timeout (in milliseconds) used for solvers
|
||||
/// - well_sorted_check type checker
|
||||
/// - auto_config use heuristics to automatically select solver and configure it
|
||||
/// - model model generation for solvers, this parameter can be overwritten when creating a solver
|
||||
/// - model_validate validate models produced by solvers
|
||||
/// - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver
|
||||
/// Note that in previous versions of Z3, this constructor was also used to set global and module parameters.
|
||||
/// For this purpose we should now use <see cref="Global.SetParameter"/>
|
||||
/// </remarks>
|
||||
public Context(Dictionary<string, string> settings)
|
||||
: base()
|
||||
{
|
||||
|
@ -288,6 +303,9 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Create a new finite domain sort.
|
||||
/// <param name="name">The name used to identify the sort</param>
|
||||
/// <param size="size">The size of the sort</param>
|
||||
/// <returns>The result is a sort</returns>
|
||||
/// </summary>
|
||||
public FiniteDomainSort MkFiniteDomainSort(Symbol name, ulong size)
|
||||
{
|
||||
|
@ -300,6 +318,11 @@ namespace Microsoft.Z3
|
|||
|
||||
/// <summary>
|
||||
/// Create a new finite domain sort.
|
||||
/// <param name="name">The name used to identify the sort</param>
|
||||
/// <param size="size">The size of the sort</param>
|
||||
/// <returns>The result is a sort</returns>
|
||||
/// Elements of the sort are created using <seealso cref="MkNumeral"/>,
|
||||
/// and the elements range from 0 to <tt>size-1</tt>.
|
||||
/// </summary>
|
||||
public FiniteDomainSort MkFiniteDomainSort(string name, ulong size)
|
||||
{
|
||||
|
|
|
@ -399,4 +399,4 @@
|
|||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -210,7 +210,7 @@ namespace Microsoft.Z3
|
|||
public Status Check(params Expr[] assumptions)
|
||||
{
|
||||
Z3_lbool r;
|
||||
if (assumptions == null)
|
||||
if (assumptions == null || assumptions.Length == 0)
|
||||
r = (Z3_lbool)Native.Z3_solver_check(Context.nCtx, NativeObject);
|
||||
else
|
||||
r = (Z3_lbool)Native.Z3_solver_check_assumptions(Context.nCtx, NativeObject, (uint)assumptions.Length, AST.ArrayToNative(assumptions));
|
||||
|
|
|
@ -27,6 +27,21 @@ public class Context extends IDisposable
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
* <remarks>
|
||||
* The following parameters can be set:
|
||||
* - proof (Boolean) Enable proof generation
|
||||
* - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting
|
||||
* - trace (Boolean) Tracing support for VCC
|
||||
* - trace_file_name (String) Trace out file for VCC traces
|
||||
* - timeout (unsigned) default timeout (in milliseconds) used for solvers
|
||||
* - well_sorted_check type checker
|
||||
* - auto_config use heuristics to automatically select solver and configure it
|
||||
* - model model generation for solvers, this parameter can be overwritten when creating a solver
|
||||
* - model_validate validate models produced by solvers
|
||||
* - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver
|
||||
* Note that in previous versions of Z3, this constructor was also used to set global and
|
||||
* module parameters. For this purpose we should now use <see cref="Global.setParameter"/>
|
||||
* </remarks>
|
||||
**/
|
||||
public Context(Map<String, String> settings) throws Z3Exception
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ package com.microsoft.z3;
|
|||
public enum Status
|
||||
{
|
||||
// / Used to signify an unsatisfiable status.
|
||||
UNSATISFIABLE(1),
|
||||
UNSATISFIABLE(-1),
|
||||
|
||||
// / Used to signify an unknown status.
|
||||
UNKNOWN(0),
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
This directory contains scripts to build the test application using
|
||||
OCaml. You also need CamlIDL to be able to generate the OCaml API.
|
||||
|
||||
- To download OCaml:
|
||||
http://caml.inria.fr/ocaml/
|
||||
|
||||
- To download CamlIDL:
|
||||
http://forge.ocamlcore.org/projects/camlidl/
|
||||
|
||||
- One must build the OCaml library before compiling the example.
|
||||
Go to directory ../ocaml
|
||||
|
||||
- Use 'build-test.cmd' to build the test application using the OCaml compiler.
|
||||
|
||||
Remark: The OCaml and C compiler tool chains must be configured in your environment.
|
||||
Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
|
||||
|
||||
- The script 'exec.cmd' adds the bin directory to the path. So,
|
||||
test_mlapi.exe can find z3.dll.
|
||||
|
||||
|
||||
|
||||
|
||||
This directory contains scripts to build the test application using
|
||||
OCaml. You also need CamlIDL to be able to generate the OCaml API.
|
||||
|
||||
- To download OCaml:
|
||||
http://caml.inria.fr/ocaml/
|
||||
|
||||
- To download CamlIDL:
|
||||
http://forge.ocamlcore.org/projects/camlidl/
|
||||
|
||||
- One must build the OCaml library before compiling the example.
|
||||
Go to directory ../ocaml
|
||||
|
||||
- Use 'build-test.cmd' to build the test application using the OCaml compiler.
|
||||
|
||||
Remark: The OCaml and C compiler tool chains must be configured in your environment.
|
||||
Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
|
||||
|
||||
- The script 'exec.cmd' adds the bin directory to the path. So,
|
||||
test_mlapi.exe can find z3.dll.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
The OCaml API for Z3 was tested using OCaml 3.12.1.
|
||||
You also need CamlIDL to be able to generate the OCaml API.
|
||||
|
||||
- To download OCaml:
|
||||
http://caml.inria.fr/ocaml/
|
||||
|
||||
- To download CamlIDL:
|
||||
http://forge.ocamlcore.org/projects/camlidl/
|
||||
|
||||
- To build the OCaml API for Z3:
|
||||
.\build-lib.cmd
|
||||
|
||||
Remark: The OCaml and C compiler tool chains must be configured in your environment.
|
||||
Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
|
||||
|
||||
Remark: Building the OCaml API copies some pathnames into files,
|
||||
so the OCaml API must be recompiled if the Z3 library files are moved.
|
||||
|
||||
See ..\examples\ocaml\build-test.cmd for an example of how to compile and link with Z3.
|
||||
|
||||
Acknowledgements:
|
||||
The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg.
|
||||
Many thanks to them!
|
||||
The OCaml API for Z3 was tested using OCaml 3.12.1.
|
||||
You also need CamlIDL to be able to generate the OCaml API.
|
||||
|
||||
- To download OCaml:
|
||||
http://caml.inria.fr/ocaml/
|
||||
|
||||
- To download CamlIDL:
|
||||
http://forge.ocamlcore.org/projects/camlidl/
|
||||
|
||||
- To build the OCaml API for Z3:
|
||||
.\build-lib.cmd
|
||||
|
||||
Remark: The OCaml and C compiler tool chains must be configured in your environment.
|
||||
Running from the Visual Studio Command Prompt configures the Microsoft C compiler.
|
||||
|
||||
Remark: Building the OCaml API copies some pathnames into files,
|
||||
so the OCaml API must be recompiled if the Z3 library files are moved.
|
||||
|
||||
See ..\examples\ocaml\build-test.cmd for an example of how to compile and link with Z3.
|
||||
|
||||
Acknowledgements:
|
||||
The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg.
|
||||
Many thanks to them!
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
@echo off
|
||||
|
||||
call .\compile_mlapi.cmd ..\include ..\bin ..\bin
|
||||
@echo off
|
||||
|
||||
call .\compile_mlapi.cmd ..\include ..\bin ..\bin
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
@echo off
|
||||
|
||||
if not exist ..\..\ocaml\z3.cmxa (
|
||||
echo "YOU MUST BUILD OCAML API! Go to directory ..\ocaml"
|
||||
goto :EOF
|
||||
)
|
||||
|
||||
REM ocaml (>= 3.11) calls the linker through flexlink
|
||||
ocamlc -version >> ocaml_version
|
||||
set /p OCAML_VERSION= <ocaml_version
|
||||
if %OCAML_VERSION% GEQ 3.11 (
|
||||
set XCFLAGS=
|
||||
) else (
|
||||
set XCFLAGS=/nologo /MT /DWIN32
|
||||
)
|
||||
|
||||
ocamlc -w A -ccopt "%XCFLAGS%" -o test_mlapi_byte.exe -I ..\..\ocaml z3.cma test_mlapi.ml
|
||||
|
||||
ocamlopt -w A -ccopt "%XCFLAGS%" -o test_mlapi.exe -I ..\..\ocaml z3.cmxa test_mlapi.ml
|
||||
@echo off
|
||||
|
||||
if not exist ..\..\ocaml\z3.cmxa (
|
||||
echo "YOU MUST BUILD OCAML API! Go to directory ..\ocaml"
|
||||
goto :EOF
|
||||
)
|
||||
|
||||
REM ocaml (>= 3.11) calls the linker through flexlink
|
||||
ocamlc -version >> ocaml_version
|
||||
set /p OCAML_VERSION= <ocaml_version
|
||||
if %OCAML_VERSION% GEQ 3.11 (
|
||||
set XCFLAGS=
|
||||
) else (
|
||||
set XCFLAGS=/nologo /MT /DWIN32
|
||||
)
|
||||
|
||||
ocamlc -w A -ccopt "%XCFLAGS%" -o test_mlapi_byte.exe -I ..\..\ocaml z3.cma test_mlapi.ml
|
||||
|
||||
ocamlopt -w A -ccopt "%XCFLAGS%" -o test_mlapi.exe -I ..\..\ocaml z3.cmxa test_mlapi.ml
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@echo off
|
||||
SETLOCAL
|
||||
set PATH=..\..\bin;%PATH%
|
||||
test_mlapi.exe
|
||||
ENDLOCAL
|
||||
@echo off
|
||||
SETLOCAL
|
||||
set PATH=..\..\bin;%PATH%
|
||||
test_mlapi.exe
|
||||
ENDLOCAL
|
||||
|
|
|
@ -585,6 +585,9 @@ class FuncDeclRef(AstRef):
|
|||
def as_ast(self):
|
||||
return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
|
||||
|
||||
def as_func_decl(self):
|
||||
return self.ast
|
||||
|
||||
def name(self):
|
||||
"""Return the name of the function declaration `self`.
|
||||
|
||||
|
@ -3853,32 +3856,6 @@ def is_array(a):
|
|||
"""
|
||||
return isinstance(a, ArrayRef)
|
||||
|
||||
def is_select(a):
|
||||
"""Return `True` if `a` is a Z3 array select.
|
||||
|
||||
>>> a = Array('a', IntSort(), IntSort())
|
||||
>>> is_select(a)
|
||||
False
|
||||
>>> i = Int('i')
|
||||
>>> is_select(a[i])
|
||||
True
|
||||
"""
|
||||
return is_app_of(a, Z3_OP_SELECT)
|
||||
|
||||
def is_store(a):
|
||||
"""Return `True` if `a` is a Z3 array store.
|
||||
|
||||
>>> a = Array('a', IntSort(), IntSort())
|
||||
>>> is_store(a)
|
||||
False
|
||||
>>> i = Int('i')
|
||||
>>> is_store(a[i])
|
||||
False
|
||||
>>> is_store(Store(a, i, i + 1))
|
||||
True
|
||||
"""
|
||||
return is_app_of(a, Z3_OP_STORE)
|
||||
|
||||
def is_const_array(a):
|
||||
"""Return `True` if `a` is a Z3 constant array.
|
||||
|
||||
|
@ -4069,7 +4046,8 @@ def is_select(a):
|
|||
>>> a = Array('a', IntSort(), IntSort())
|
||||
>>> is_select(a)
|
||||
False
|
||||
>>> is_select(a[0])
|
||||
>>> i = Int('i')
|
||||
>>> is_select(a[i])
|
||||
True
|
||||
"""
|
||||
return is_app_of(a, Z3_OP_SELECT)
|
||||
|
|
|
@ -703,7 +703,7 @@ typedef enum
|
|||
over Boolean connectives 'and' and 'or'.
|
||||
|
||||
|
||||
- Z3_OP_PR_NFF_NEG: Proof for a (negative) NNF step. Examples:
|
||||
- Z3_OP_PR_NNF_NEG: Proof for a (negative) NNF step. Examples:
|
||||
\nicebox{
|
||||
T1: (not s_1) ~ r_1
|
||||
...
|
||||
|
@ -780,11 +780,11 @@ typedef enum
|
|||
}
|
||||
or
|
||||
\nicebox{
|
||||
(=> (and ln+1 ln+2 .. ln+m) l0)
|
||||
(=> (and l1 l2 .. ln) l0)
|
||||
}
|
||||
or in the most general (ground) form:
|
||||
\nicebox{
|
||||
(=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1))
|
||||
(=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln))
|
||||
}
|
||||
In other words we use the following (Prolog style) convention for Horn
|
||||
implications:
|
||||
|
@ -800,7 +800,7 @@ typedef enum
|
|||
general non-ground form is:
|
||||
|
||||
\nicebox{
|
||||
(forall (vars) (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1)))
|
||||
(forall (vars) (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln)))
|
||||
}
|
||||
|
||||
The hyper-resolution rule takes a sequence of parameters.
|
||||
|
@ -1724,6 +1724,8 @@ extern "C" {
|
|||
To create constants that belong to the finite domain,
|
||||
use the APIs for creating numerals and pass a numeric
|
||||
constant together with the sort returned by this call.
|
||||
The numeric constant should be between 0 and the less
|
||||
than the size of the domain.
|
||||
|
||||
\sa Z3_get_finite_domain_sort_size
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ Notes:
|
|||
void register_z3_replayer_cmds(z3_replayer & in);
|
||||
|
||||
void throw_invalid_reference() {
|
||||
TRACE("z3_replayer", tout << "invalid argument reference\n";);
|
||||
throw z3_replayer_exception("invalid argument reference");
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,8 @@ public:
|
|||
bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); }
|
||||
|
||||
MATCH_UNARY(is_uminus);
|
||||
MATCH_UNARY(is_to_real);
|
||||
MATCH_UNARY(is_to_int);
|
||||
MATCH_BINARY(is_sub);
|
||||
MATCH_BINARY(is_add);
|
||||
MATCH_BINARY(is_mul);
|
||||
|
|
|
@ -300,7 +300,7 @@ std::ostream & operator<<(std::ostream & out, func_decl_info const & info) {
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
char const * g_ast_kind_names[] = {"application", "variable", "quantifier", "sort", "function declaration" };
|
||||
static char const * g_ast_kind_names[] = {"application", "variable", "quantifier", "sort", "function declaration" };
|
||||
|
||||
char const * get_ast_kind_name(ast_kind k) {
|
||||
return g_ast_kind_names[k];
|
||||
|
@ -2765,7 +2765,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
app const * cls = to_app(f1);
|
||||
unsigned num_args = cls->get_num_args();
|
||||
#ifdef Z3DEBUG
|
||||
vector<bool> found;
|
||||
svector<bool> found;
|
||||
#endif
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * lit = cls->get_arg(i);
|
||||
|
|
|
@ -1194,7 +1194,6 @@ enum pattern_op_kind {
|
|||
heurisitic quantifier instantiation.
|
||||
*/
|
||||
class pattern_decl_plugin : public decl_plugin {
|
||||
sort * m_list;
|
||||
public:
|
||||
virtual decl_plugin * mk_fresh() { return alloc(pattern_decl_plugin); }
|
||||
|
||||
|
|
|
@ -134,6 +134,16 @@ bool lt(ast * n1, ast * n2) {
|
|||
}
|
||||
}
|
||||
|
||||
bool is_sorted(unsigned num, expr * const * ns) {
|
||||
for (unsigned i = 1; i < num; i++) {
|
||||
ast * prev = ns[i-1];
|
||||
ast * curr = ns[i];
|
||||
if (lt(curr, prev))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lex_lt(unsigned num, ast * const * n1, ast * const * n2) {
|
||||
for (unsigned i = 0; i < num; i ++) {
|
||||
if (n1[i] == n2[i])
|
||||
|
|
|
@ -22,6 +22,7 @@ Revision History:
|
|||
class ast;
|
||||
|
||||
bool lt(ast * n1, ast * n2);
|
||||
bool is_sorted(unsigned num, expr * const * ns);
|
||||
|
||||
struct ast_to_lt {
|
||||
bool operator()(ast * n1, ast * n2) const { return lt(n1, n2); }
|
||||
|
|
|
@ -260,6 +260,7 @@ class smt_printer {
|
|||
else {
|
||||
m_out << sym << "[";
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < num_params; ++i) {
|
||||
parameter const& p = params[i];
|
||||
if (p.is_ast()) {
|
||||
|
@ -642,9 +643,7 @@ class smt_printer {
|
|||
m_out << m_var_names[m_num_var_names - idx - 1];
|
||||
}
|
||||
else {
|
||||
if (!m_is_smt2) {
|
||||
m_out << "?" << idx;
|
||||
}
|
||||
m_out << "?" << idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_util.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Helper functions
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2007-06-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "ast_util.h"
|
||||
|
||||
app * mk_list_assoc_app(ast_manager & m, func_decl * f, unsigned num_args, expr * const * args) {
|
||||
|
@ -138,3 +156,38 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx) {
|
|||
SASSERT(m.is_or(cls));
|
||||
return to_app(cls)->get_arg(idx);
|
||||
}
|
||||
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_true();
|
||||
else if (num_args == 1)
|
||||
return args[0];
|
||||
else
|
||||
return m.mk_and(num_args, args);
|
||||
}
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_false();
|
||||
else if (num_args == 1)
|
||||
return args[0];
|
||||
else
|
||||
return m.mk_or(num_args, args);
|
||||
}
|
||||
|
||||
expr * mk_not(ast_manager & m, expr * arg) {
|
||||
expr * atom;
|
||||
if (m.is_not(arg, atom))
|
||||
return atom;
|
||||
else
|
||||
return m.mk_not(arg);
|
||||
}
|
||||
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
expr_ref_buffer new_diseqs(m);
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
for (unsigned j = i + 1; j < num_args; j++)
|
||||
new_diseqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
|
||||
}
|
||||
return mk_and(m, new_diseqs.size(), new_diseqs.c_ptr());
|
||||
}
|
||||
|
|
|
@ -95,5 +95,36 @@ bool is_clause(ast_manager & m, expr * n);
|
|||
unsigned get_clause_num_literals(ast_manager & m, expr * cls);
|
||||
expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Goodies for creating Boolean expressions
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
/**
|
||||
Return (and args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
Return true if num_args == 0
|
||||
*/
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Return (or args[0] ... args[num_args-1]) if num_args >= 2
|
||||
Return args[0] if num_args == 1
|
||||
Return false if num_args == 0
|
||||
*/
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Return a if arg = (not a)
|
||||
Retur (not arg) otherwise
|
||||
*/
|
||||
expr * mk_not(ast_manager & m, expr * arg);
|
||||
|
||||
/**
|
||||
Return the expression (and (not (= args[0] args[1])) (not (= args[0] args[2])) ... (not (= args[num_args-2] args[num_args-1])))
|
||||
*/
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
#endif /* _AST_UTIL_H_ */
|
||||
|
||||
|
|
|
@ -210,6 +210,10 @@ func_decl * bv_decl_plugin::mk_unary(ptr_vector<func_decl> & decls, decl_kind k,
|
|||
|
||||
func_decl * bv_decl_plugin::mk_int2bv(unsigned bv_size, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain) {
|
||||
if (bv_size == 0) {
|
||||
m_manager->raise_exception("bit-vector size must be greater than zero");
|
||||
}
|
||||
|
||||
force_ptr_array_size(m_int2bv, bv_size + 1);
|
||||
|
||||
if (arity != 1) {
|
||||
|
@ -415,6 +419,9 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const
|
|||
return 0;
|
||||
}
|
||||
unsigned bv_size = parameters[1].get_int();
|
||||
if (bv_size == 0) {
|
||||
m_manager->raise_exception("bit-vector size must be greater than zero");
|
||||
}
|
||||
// TODO: sign an error if the parameters[0] is out of range, that is, it is a value not in [0, 2^{bv_size})
|
||||
// This cannot be enforced now, since some Z3 modules try to generate these invalid numerals.
|
||||
// After SMT-COMP, I should find all offending modules.
|
||||
|
@ -766,7 +773,7 @@ bool bv_recognizers::is_zero(expr const * n) const {
|
|||
return decl->get_parameter(0).get_rational().is_zero();
|
||||
}
|
||||
|
||||
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) {
|
||||
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) const {
|
||||
if (!is_extract(e)) return false;
|
||||
low = get_extract_low(e);
|
||||
high = get_extract_high(e);
|
||||
|
@ -774,7 +781,7 @@ bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, ex
|
|||
return true;
|
||||
}
|
||||
|
||||
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) {
|
||||
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) const {
|
||||
if (!is_bv2int(e)) return false;
|
||||
r = to_app(e)->get_arg(0);
|
||||
return true;
|
||||
|
|
|
@ -288,10 +288,10 @@ public:
|
|||
bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); }
|
||||
unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); }
|
||||
unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); }
|
||||
unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
|
||||
unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
|
||||
bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b);
|
||||
bool is_bv2int(expr const * e, expr * & r);
|
||||
unsigned get_extract_high(expr const * n) const { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
|
||||
unsigned get_extract_low(expr const * n) const { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
|
||||
bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b) const;
|
||||
bool is_bv2int(expr const * e, expr * & r) const;
|
||||
bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); }
|
||||
bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); }
|
||||
bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); }
|
||||
|
|
|
@ -84,7 +84,8 @@ class datatype_decl {
|
|||
ptr_vector<constructor_decl> m_constructors;
|
||||
public:
|
||||
datatype_decl(const symbol & n, unsigned num_constructors, constructor_decl * const * constructors):
|
||||
m_name(n), m_constructors(num_constructors, constructors) {}
|
||||
m_name(n), m_constructors(num_constructors, constructors) {
|
||||
}
|
||||
~datatype_decl() {
|
||||
std::for_each(m_constructors.begin(), m_constructors.end(), delete_proc<constructor_decl>());
|
||||
}
|
||||
|
|
|
@ -326,6 +326,7 @@ namespace datalog {
|
|||
}
|
||||
unsigned index0;
|
||||
sort* last_sort = 0;
|
||||
SASSERT(num_params > 0);
|
||||
for (unsigned i = 0; i < num_params; ++i) {
|
||||
parameter const& p = params[i];
|
||||
if (!p.is_int()) {
|
||||
|
@ -636,9 +637,13 @@ namespace datalog {
|
|||
|
||||
app* dl_decl_util::mk_numeral(uint64 value, sort* s) {
|
||||
if (is_finite_sort(s)) {
|
||||
uint64 sz = 0;
|
||||
if (try_get_size(s, sz) && sz <= value) {
|
||||
m.raise_exception("value is out of bounds");
|
||||
}
|
||||
parameter params[2] = { parameter(rational(value, rational::ui64())), parameter(s) };
|
||||
return m.mk_const(m.mk_func_decl(m_fid, OP_DL_CONSTANT, 2, params, 0, (sort*const*)0));
|
||||
}
|
||||
}
|
||||
if (m_arith.is_int(s) || m_arith.is_real(s)) {
|
||||
return m_arith.mk_numeral(rational(value, rational::ui64()), s);
|
||||
}
|
||||
|
@ -652,13 +657,15 @@ namespace datalog {
|
|||
SASSERT(value == 1);
|
||||
return m.mk_true();
|
||||
}
|
||||
m.raise_exception("unrecognized sort");
|
||||
std::stringstream strm;
|
||||
strm << "sort '" << mk_pp(s, m) << "' is not recognized as a sort that contains numeric values.\nUse Bool, BitVec, Int, Real, or a Finite domain sort";
|
||||
m.raise_exception(strm.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool dl_decl_util::is_numeral(expr* e, uint64& v) const {
|
||||
bool dl_decl_util::is_numeral(const expr* e, uint64& v) const {
|
||||
if (is_numeral(e)) {
|
||||
app* c = to_app(e);
|
||||
const app* c = to_app(e);
|
||||
SASSERT(c->get_decl()->get_num_parameters() == 2);
|
||||
parameter const& p = c->get_decl()->get_parameter(0);
|
||||
SASSERT(p.is_rational());
|
||||
|
|
|
@ -169,11 +169,11 @@ namespace datalog {
|
|||
|
||||
app* mk_le(expr* a, expr* b);
|
||||
|
||||
bool is_lt(expr* a) { return is_app_of(a, m_fid, OP_DL_LT); }
|
||||
bool is_lt(const expr* a) const { return is_app_of(a, m_fid, OP_DL_LT); }
|
||||
|
||||
bool is_numeral(expr* c) const { return is_app_of(c, m_fid, OP_DL_CONSTANT); }
|
||||
bool is_numeral(const expr* c) const { return is_app_of(c, m_fid, OP_DL_CONSTANT); }
|
||||
|
||||
bool is_numeral(expr* e, uint64& v) const;
|
||||
bool is_numeral(const expr* e, uint64& v) const;
|
||||
|
||||
//
|
||||
// Utilities for extracting constants
|
||||
|
|
|
@ -20,52 +20,50 @@ Notes:
|
|||
#include "expr_abstract.h"
|
||||
#include "map.h"
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
ast_ref_vector pinned(m);
|
||||
ptr_vector<expr> stack;
|
||||
obj_map<expr, expr*> map;
|
||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
|
||||
expr * curr = 0, *b = 0;
|
||||
SASSERT(n->get_ref_count() > 0);
|
||||
|
||||
stack.push_back(n);
|
||||
m_stack.push_back(n);
|
||||
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
b = bound[i];
|
||||
expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b));
|
||||
pinned.push_back(v);
|
||||
map.insert(b, v);
|
||||
m_pinned.push_back(v);
|
||||
m_map.insert(b, v);
|
||||
}
|
||||
|
||||
while(!stack.empty()) {
|
||||
curr = stack.back();
|
||||
if (map.contains(curr)) {
|
||||
stack.pop_back();
|
||||
while(!m_stack.empty()) {
|
||||
curr = m_stack.back();
|
||||
if (m_map.contains(curr)) {
|
||||
m_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
switch(curr->get_kind()) {
|
||||
case AST_VAR: {
|
||||
map.insert(curr, curr);
|
||||
stack.pop_back();
|
||||
m_map.insert(curr, curr);
|
||||
m_stack.pop_back();
|
||||
break;
|
||||
}
|
||||
case AST_APP: {
|
||||
app* a = to_app(curr);
|
||||
bool all_visited = true;
|
||||
ptr_vector<expr> args;
|
||||
m_args.reset();
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
if (!map.find(a->get_arg(i), b)) {
|
||||
stack.push_back(a->get_arg(i));
|
||||
if (!m_map.find(a->get_arg(i), b)) {
|
||||
m_stack.push_back(a->get_arg(i));
|
||||
all_visited = false;
|
||||
}
|
||||
else {
|
||||
args.push_back(b);
|
||||
m_args.push_back(b);
|
||||
}
|
||||
}
|
||||
if (all_visited) {
|
||||
b = m.mk_app(a->get_decl(), args.size(), args.c_ptr());
|
||||
pinned.push_back(b);
|
||||
map.insert(curr, b);
|
||||
stack.pop_back();
|
||||
b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
|
||||
m_pinned.push_back(b);
|
||||
m_map.insert(curr, b);
|
||||
m_stack.pop_back();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -81,17 +79,24 @@ void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* cons
|
|||
}
|
||||
expr_abstract(m, new_base, num_bound, bound, q->get_expr(), result1);
|
||||
b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get());
|
||||
pinned.push_back(b);
|
||||
map.insert(curr, b);
|
||||
stack.pop_back();
|
||||
m_pinned.push_back(b);
|
||||
m_map.insert(curr, b);
|
||||
m_stack.pop_back();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (!map.find(n, b)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
VERIFY (m_map.find(n, b));
|
||||
result = b;
|
||||
m_pinned.reset();
|
||||
m_map.reset();
|
||||
m_stack.reset();
|
||||
m_args.reset();
|
||||
}
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
expr_abstractor abs(m);
|
||||
abs(base, num_bound, bound, n, result);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,17 @@ Notes:
|
|||
|
||||
#include"ast.h"
|
||||
|
||||
class expr_abstractor {
|
||||
ast_manager& m;
|
||||
expr_ref_vector m_pinned;
|
||||
ptr_vector<expr> m_stack, m_args;
|
||||
obj_map<expr, expr*> m_map;
|
||||
|
||||
public:
|
||||
expr_abstractor(ast_manager& m): m(m), m_pinned(m) {}
|
||||
void operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
|
||||
};
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -200,6 +200,7 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par
|
|||
}
|
||||
else {
|
||||
m_manager->raise_exception("sort of floating point constant was not specified");
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT));
|
||||
|
@ -254,7 +255,11 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param
|
|||
case OP_FLOAT_IS_ZERO: name = "isZero"; break;
|
||||
case OP_FLOAT_IS_NZERO: name = "isNZero"; break;
|
||||
case OP_FLOAT_IS_PZERO: name = "isPZero"; break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break;
|
||||
case OP_FLOAT_IS_NAN: name = "isNaN"; break;
|
||||
case OP_FLOAT_IS_INF: name = "isInfinite"; break;
|
||||
case OP_FLOAT_IS_NORMAL: name = "isNormal"; break;
|
||||
case OP_FLOAT_IS_SUBNORMAL: name = "isSubnormal"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -353,27 +358,22 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters,
|
|||
sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1);
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// .. Otherwise we only know how to convert rationals/reals.
|
||||
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int()))
|
||||
m_manager->raise_exception("expecting two integer parameters to asFloat");
|
||||
if (arity != 2 && arity != 3)
|
||||
m_manager->raise_exception("invalid number of arguments to asFloat operator");
|
||||
if (!is_rm_sort(domain[0]) || domain[1] != m_real_sort)
|
||||
if (arity == 3 && domain[2] != m_int_sort)
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (!is_rm_sort(domain[0]) ||
|
||||
!(domain[1] == m_real_sort || is_sort_of(domain[1], m_family_id, FLOAT_SORT)))
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
if (arity == 2) {
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
else {
|
||||
if (domain[2] != m_int_sort)
|
||||
m_manager->raise_exception("sort mismatch");
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
symbol name("asFloat");
|
||||
return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,10 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_FLOAT_IS_NZERO:
|
||||
case OP_FLOAT_IS_PZERO:
|
||||
case OP_FLOAT_IS_SIGN_MINUS:
|
||||
case OP_FLOAT_IS_NAN:
|
||||
case OP_FLOAT_IS_INF:
|
||||
case OP_FLOAT_IS_NORMAL:
|
||||
case OP_FLOAT_IS_SUBNORMAL:
|
||||
return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FLOAT_ABS:
|
||||
case OP_FLOAT_UMINUS:
|
||||
|
@ -477,9 +481,13 @@ void float_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol co
|
|||
op_names.push_back(builtin_name("<=", OP_FLOAT_LE));
|
||||
op_names.push_back(builtin_name(">=", OP_FLOAT_GE));
|
||||
|
||||
op_names.push_back(builtin_name("isNaN", OP_FLOAT_IS_NAN));
|
||||
op_names.push_back(builtin_name("isInfinite", OP_FLOAT_IS_INF));
|
||||
op_names.push_back(builtin_name("isZero", OP_FLOAT_IS_ZERO));
|
||||
op_names.push_back(builtin_name("isNZero", OP_FLOAT_IS_NZERO));
|
||||
op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO));
|
||||
op_names.push_back(builtin_name("isNormal", OP_FLOAT_IS_NORMAL));
|
||||
op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL));
|
||||
op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS));
|
||||
|
||||
op_names.push_back(builtin_name("min", OP_FLOAT_MIN));
|
||||
|
@ -496,6 +504,15 @@ void float_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbo
|
|||
sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT));
|
||||
}
|
||||
|
||||
expr * float_decl_plugin::get_some_value(sort * s) {
|
||||
SASSERT(s->is_sort_of(m_family_id, FLOAT_SORT));
|
||||
mpf tmp;
|
||||
m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp);
|
||||
expr * res = this->mk_value(tmp);
|
||||
m_fm.del(tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool float_decl_plugin::is_value(app * e) const {
|
||||
if (e->get_family_id() != m_family_id)
|
||||
return false;
|
||||
|
|
|
@ -61,9 +61,13 @@ enum float_op_kind {
|
|||
OP_FLOAT_GT,
|
||||
OP_FLOAT_LE,
|
||||
OP_FLOAT_GE,
|
||||
OP_FLOAT_IS_NAN,
|
||||
OP_FLOAT_IS_INF,
|
||||
OP_FLOAT_IS_ZERO,
|
||||
OP_FLOAT_IS_NZERO,
|
||||
OP_FLOAT_IS_NORMAL,
|
||||
OP_FLOAT_IS_SUBNORMAL,
|
||||
OP_FLOAT_IS_PZERO,
|
||||
OP_FLOAT_IS_NZERO,
|
||||
OP_FLOAT_IS_SIGN_MINUS,
|
||||
|
||||
OP_TO_FLOAT,
|
||||
|
@ -140,6 +144,7 @@ public:
|
|||
unsigned arity, sort * const * domain, sort * range);
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
|
||||
virtual expr * get_some_value(sort * s);
|
||||
virtual bool is_value(app* e) const;
|
||||
virtual bool is_unique_value(app* e) const { return is_value(e); }
|
||||
|
||||
|
@ -222,7 +227,7 @@ public:
|
|||
app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); }
|
||||
app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); }
|
||||
app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); }
|
||||
app * mk_abs(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1, arg2); }
|
||||
app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); }
|
||||
app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); }
|
||||
app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); }
|
||||
app * mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
|
||||
|
@ -236,7 +241,11 @@ public:
|
|||
app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LE, arg1, arg2); }
|
||||
app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GE, arg1, arg2); }
|
||||
|
||||
app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NAN, arg1); }
|
||||
app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_INF, arg1); }
|
||||
app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_ZERO, arg1); }
|
||||
app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NORMAL, arg1); }
|
||||
app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); }
|
||||
app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); }
|
||||
app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); }
|
||||
app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SIGN_MINUS, arg1); }
|
||||
|
|
|
@ -79,7 +79,6 @@ void func_decl_dependencies::collect_ng_func_decls(expr * n, func_decl_set * s)
|
|||
*/
|
||||
class func_decl_dependencies::top_sort {
|
||||
enum color { OPEN, IN_PROGRESS, CLOSED };
|
||||
ast_manager & m_manager;
|
||||
dependency_graph & m_deps;
|
||||
|
||||
typedef obj_map<func_decl, color> color_map;
|
||||
|
@ -177,7 +176,7 @@ class func_decl_dependencies::top_sort {
|
|||
}
|
||||
|
||||
public:
|
||||
top_sort(ast_manager & m, dependency_graph & deps):m_manager(m), m_deps(deps) {}
|
||||
top_sort(dependency_graph & deps) : m_deps(deps) {}
|
||||
|
||||
bool operator()(func_decl * new_decl) {
|
||||
|
||||
|
@ -198,7 +197,7 @@ bool func_decl_dependencies::insert(func_decl * f, func_decl_set * s) {
|
|||
|
||||
m_deps.insert(f, s);
|
||||
|
||||
top_sort cycle_detector(m_manager, m_deps);
|
||||
top_sort cycle_detector(m_deps);
|
||||
if (cycle_detector(f)) {
|
||||
m_deps.erase(f);
|
||||
dealloc(s);
|
||||
|
|
|
@ -597,8 +597,9 @@ void hint_to_macro_head(ast_manager & m, app * head, unsigned num_decls, app_ref
|
|||
is_hint_head(head, vars) must also return true
|
||||
*/
|
||||
bool macro_util::is_poly_hint(expr * n, app * head, expr * exception) {
|
||||
TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n"
|
||||
<< mk_pp(exception, m_manager) << "\n";);
|
||||
TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n";
|
||||
if (exception) tout << mk_pp(exception, m_manager); else tout << "<null>";
|
||||
tout << "\n";);
|
||||
ptr_buffer<var> vars;
|
||||
if (!is_hint_head(head, vars)) {
|
||||
TRACE("macro_util_hint", tout << "failed because head is not hint head\n";);
|
||||
|
@ -792,7 +793,10 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a
|
|||
mk_add(args.size(), args.c_ptr(), m_manager.get_sort(arg), rest);
|
||||
expr_ref def(m_manager);
|
||||
mk_sub(rhs, rest, def);
|
||||
add_arith_macro_candidate(to_app(arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
// If is_poly_hint, rhs may contain variables that do not occur in to_app(arg).
|
||||
// So, we should re-check.
|
||||
if (!_is_poly_hint || is_poly_hint(def, to_app(arg), 0))
|
||||
add_arith_macro_candidate(to_app(arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
}
|
||||
else if (is_times_minus_one(arg, neg_arg) && is_app(neg_arg)) {
|
||||
f = to_app(neg_arg)->get_decl();
|
||||
|
@ -810,7 +814,10 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a
|
|||
mk_add(args.size(), args.c_ptr(), m_manager.get_sort(arg), rest);
|
||||
expr_ref def(m_manager);
|
||||
mk_sub(rest, rhs, def);
|
||||
add_arith_macro_candidate(to_app(neg_arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
// If is_poly_hint, rhs may contain variables that do not occur in to_app(neg_arg).
|
||||
// So, we should re-check.
|
||||
if (!_is_poly_hint || is_poly_hint(def, to_app(neg_arg), 0))
|
||||
add_arith_macro_candidate(to_app(neg_arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,9 @@ Revision History:
|
|||
#include"uint_set.h"
|
||||
#include"var_subst.h"
|
||||
|
||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, basic_simplifier_plugin & p, simplifier & s) :
|
||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s) :
|
||||
m_manager(m),
|
||||
m_macro_manager(mm),
|
||||
m_bsimp(p),
|
||||
m_simplifier(s),
|
||||
m_new_vars(m),
|
||||
m_new_eqs(m),
|
||||
|
|
|
@ -32,7 +32,6 @@ class quasi_macros {
|
|||
|
||||
ast_manager & m_manager;
|
||||
macro_manager & m_macro_manager;
|
||||
basic_simplifier_plugin & m_bsimp;
|
||||
simplifier & m_simplifier;
|
||||
occurrences_map m_occurrences;
|
||||
ptr_vector<expr> m_todo;
|
||||
|
@ -57,7 +56,7 @@ class quasi_macros {
|
|||
void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
|
||||
public:
|
||||
quasi_macros(ast_manager & m, macro_manager & mm, basic_simplifier_plugin & p, simplifier & s);
|
||||
quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
|
||||
~quasi_macros();
|
||||
|
||||
/**
|
||||
|
|
|
@ -119,13 +119,13 @@
|
|||
:pattern (?select (?select (?asElems e) a) i))))
|
||||
(assert (forall ((x Int) (f Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
|
||||
(not (= (?isAllocated x a0) 1))
|
||||
(= (?isAllocated (?select f x) a0) 1))
|
||||
:pattern (?isAllocated (?select f x) a0))))
|
||||
(assert (forall ((a Int) (e Int) (i Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?eClosedTime e))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?eClosedTime e))) 0)
|
||||
(not (= (?isAllocated a a0) 1))
|
||||
(= (?isAllocated (?select (?select e a) i) a0) 1))
|
||||
:pattern (?isAllocated (?select (?select e a) i) a0))))
|
||||
|
@ -281,13 +281,13 @@
|
|||
:pattern (IntsAllocated h (?StructGet_ s f)))))
|
||||
(assert (forall ((x Int) (f Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
|
||||
(not (?isAllocated_ x a0))
|
||||
(?isAllocated_ (?select f x) a0))
|
||||
:pattern (?isAllocated_ (?select f x) a0))))
|
||||
(assert (forall ((a Int) (e Int) (i Int) (a0 Int))
|
||||
(!
|
||||
(or (<= (+ a0 (* -1 (?eClosedTime e))) 0)
|
||||
(or (<= (+ a0 (* (- 1) (?eClosedTime e))) 0)
|
||||
(not (?isAllocated_ a a0))
|
||||
(?isAllocated_ (?select (?select e a) i) a0))
|
||||
:pattern (?isAllocated_ (?select (?select e a) i) a0))))
|
||||
|
|
|
@ -30,7 +30,7 @@ class recurse_expr : public Visitor {
|
|||
vector<T, CallDestructors> m_results2;
|
||||
|
||||
bool is_cached(expr * n) const { T c; return m_cache.find(n, c); }
|
||||
T get_cached(expr * n) const { T c; m_cache.find(n, c); return c; }
|
||||
T get_cached(expr * n) const { return m_cache.find(n); }
|
||||
void cache_result(expr * n, T c) { m_cache.insert(n, c); }
|
||||
|
||||
void visit(expr * n, bool & visited);
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
|
||||
void mk_eq(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_eq_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m_util.mk_le(arg1, arg2);
|
||||
result = m_util.mk_eq(arg1, arg2);
|
||||
}
|
||||
void mk_le(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_le_core(arg1, arg2, result) == BR_FAILED)
|
||||
|
|
|
@ -25,6 +25,7 @@ void array_rewriter::updt_params(params_ref const & _p) {
|
|||
array_rewriter_params p(_p);
|
||||
m_sort_store = p.sort_store();
|
||||
m_expand_select_store = p.expand_select_store();
|
||||
m_expand_store_eq = p.expand_store_eq();
|
||||
}
|
||||
|
||||
void array_rewriter::get_param_descrs(param_descrs & r) {
|
||||
|
@ -365,3 +366,40 @@ br_status array_rewriter::mk_set_subset(expr * arg1, expr * arg2, expr_ref & res
|
|||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
if (!m_expand_store_eq) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
expr* lhs1 = lhs;
|
||||
while (m_util.is_store(lhs1)) {
|
||||
lhs1 = to_app(lhs1)->get_arg(0);
|
||||
}
|
||||
expr* rhs1 = rhs;
|
||||
while (m_util.is_store(rhs1)) {
|
||||
rhs1 = to_app(rhs1)->get_arg(0);
|
||||
}
|
||||
if (lhs1 != rhs1) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
ptr_buffer<expr> fmls, args;
|
||||
expr* e;
|
||||
expr_ref tmp1(m()), tmp2(m());
|
||||
#define MK_EQ() \
|
||||
while (m_util.is_store(e)) { \
|
||||
args.push_back(lhs); \
|
||||
args.append(to_app(e)->get_num_args()-2,to_app(e)->get_args()+1); \
|
||||
mk_select(args.size(), args.c_ptr(), tmp1); \
|
||||
args[0] = rhs; \
|
||||
mk_select(args.size(), args.c_ptr(), tmp2); \
|
||||
fmls.push_back(m().mk_eq(tmp1, tmp2)); \
|
||||
e = to_app(e)->get_arg(0); \
|
||||
args.reset(); \
|
||||
} \
|
||||
|
||||
e = lhs;
|
||||
MK_EQ();
|
||||
e = rhs;
|
||||
MK_EQ();
|
||||
result = m().mk_and(fmls.size(), fmls.c_ptr());
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
|
|
@ -31,12 +31,14 @@ class array_rewriter {
|
|||
array_util m_util;
|
||||
bool m_sort_store;
|
||||
bool m_expand_select_store;
|
||||
bool m_expand_store_eq;
|
||||
template<bool CHECK_DISEQ>
|
||||
lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
|
||||
public:
|
||||
array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m) {
|
||||
updt_params(p);
|
||||
|
||||
}
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
|
@ -60,6 +62,7 @@ public:
|
|||
br_status mk_set_complement(expr * arg, expr_ref & result);
|
||||
br_status mk_set_difference(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_set_subset(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,4 +2,5 @@ def_module_params(module_name='rewriter',
|
|||
class_name='array_rewriter_params',
|
||||
export=True,
|
||||
params=(("expand_select_store", BOOL, False, "replace a (select (store ...) ...) term by an if-then-else term"),
|
||||
("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
|
||||
("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
|
||||
|
|
175
src/ast/rewriter/ast_counter.cpp
Normal file
175
src/ast/rewriter/ast_counter.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_counter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines for counting features of terms, such as free variables.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast_counter.h"
|
||||
#include "var_subst.h"
|
||||
|
||||
void counter::update(unsigned el, int delta) {
|
||||
int & counter = get(el);
|
||||
SASSERT(!m_stay_non_negative || counter>=0);
|
||||
SASSERT(!m_stay_non_negative || static_cast<int>(counter)>=-delta);
|
||||
counter += delta;
|
||||
}
|
||||
|
||||
int & counter::get(unsigned el) {
|
||||
return m_data.insert_if_not_there2(el, 0)->get_data().m_value;
|
||||
}
|
||||
|
||||
counter & counter::count(unsigned sz, const unsigned * els, int delta) {
|
||||
for(unsigned i=0; i<sz; i++) {
|
||||
update(els[i], delta);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned counter::get_positive_count() const {
|
||||
unsigned cnt = 0;
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for(; eit!=eend; ++eit) {
|
||||
if( eit->m_value>0 ) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void counter::collect_positive(uint_set & acc) const {
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for(; eit!=eend; ++eit) {
|
||||
if(eit->m_value>0) { acc.insert(eit->m_key); }
|
||||
}
|
||||
}
|
||||
|
||||
bool counter::get_max_positive(unsigned & res) const {
|
||||
bool found = false;
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for(; eit!=eend; ++eit) {
|
||||
if( eit->m_value>0 && (!found || eit->m_key>res) ) {
|
||||
found = true;
|
||||
res = eit->m_key;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
unsigned counter::get_max_positive() const {
|
||||
unsigned max_pos;
|
||||
VERIFY(get_max_positive(max_pos));
|
||||
return max_pos;
|
||||
}
|
||||
|
||||
int counter::get_max_counter_value() const {
|
||||
int res = 0;
|
||||
iterator eit = begin();
|
||||
iterator eend = end();
|
||||
for (; eit!=eend; ++eit) {
|
||||
if( eit->m_value>res ) {
|
||||
res = eit->m_value;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void var_counter::count_vars(ast_manager & m, const app * pred, int coef) {
|
||||
unsigned n = pred->get_num_args();
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
m_sorts.reset();
|
||||
m_todo.reset();
|
||||
m_mark.reset();
|
||||
::get_free_vars(m_mark, m_todo, pred->get_arg(i), m_sorts);
|
||||
for (unsigned j = 0; j < m_sorts.size(); ++j) {
|
||||
if (m_sorts[j]) {
|
||||
update(j, coef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned var_counter::get_max_var(bool& has_var) {
|
||||
has_var = false;
|
||||
unsigned max_var = 0;
|
||||
ptr_vector<quantifier> qs;
|
||||
while (!m_todo.empty()) {
|
||||
expr* e = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
if (m_visited.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
m_visited.mark(e, true);
|
||||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
qs.push_back(to_quantifier(e));
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
if (to_var(e)->get_idx() >= max_var) {
|
||||
has_var = true;
|
||||
max_var = to_var(e)->get_idx();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AST_APP: {
|
||||
app* a = to_app(e);
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
m_todo.push_back(a->get_arg(i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_visited.reset();
|
||||
|
||||
while (!qs.empty()) {
|
||||
var_counter aux_counter;
|
||||
quantifier* q = qs.back();
|
||||
qs.pop_back();
|
||||
aux_counter.m_todo.push_back(q->get_expr());
|
||||
bool has_var1 = false;
|
||||
unsigned max_v = aux_counter.get_max_var(has_var1);
|
||||
if (max_v >= max_var + q->get_num_decls()) {
|
||||
max_var = max_v - q->get_num_decls();
|
||||
has_var = has_var || has_var1;
|
||||
}
|
||||
}
|
||||
|
||||
return max_var;
|
||||
}
|
||||
|
||||
|
||||
unsigned var_counter::get_max_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
return get_max_var(has_var);
|
||||
}
|
||||
|
||||
unsigned var_counter::get_next_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
unsigned mv = get_max_var(has_var);
|
||||
if (has_var) mv++;
|
||||
return mv;
|
||||
}
|
||||
|
109
src/ast/rewriter/ast_counter.h
Normal file
109
src/ast/rewriter/ast_counter.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_counter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines for counting features of terms, such as free variables.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-18.
|
||||
Krystof Hoder (t-khoder) 2010-10-10.
|
||||
|
||||
Revision History:
|
||||
|
||||
Hoisted from dl_util.h 2013-03-18.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#ifndef _AST_COUNTER_H_
|
||||
#define _AST_COUNTER_H_
|
||||
|
||||
#include "ast.h"
|
||||
#include "map.h"
|
||||
#include "uint_set.h"
|
||||
|
||||
class counter {
|
||||
protected:
|
||||
typedef u_map<int> map_impl;
|
||||
map_impl m_data;
|
||||
const bool m_stay_non_negative;
|
||||
public:
|
||||
typedef map_impl::iterator iterator;
|
||||
|
||||
counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
|
||||
|
||||
void reset() { m_data.reset(); }
|
||||
iterator begin() const { return m_data.begin(); }
|
||||
iterator end() const { return m_data.end(); }
|
||||
void update(unsigned el, int delta);
|
||||
int & get(unsigned el);
|
||||
|
||||
/**
|
||||
\brief Increase values of elements in \c els by \c delta.
|
||||
|
||||
The function returns a reference to \c *this to allow for expressions like
|
||||
counter().count(sz, arr).get_positive_count()
|
||||
*/
|
||||
counter & count(unsigned sz, const unsigned * els, int delta = 1);
|
||||
counter & count(const unsigned_vector & els, int delta = 1) {
|
||||
return count(els.size(), els.c_ptr(), delta);
|
||||
}
|
||||
|
||||
void collect_positive(uint_set & acc) const;
|
||||
unsigned get_positive_count() const;
|
||||
|
||||
bool get_max_positive(unsigned & res) const;
|
||||
unsigned get_max_positive() const;
|
||||
|
||||
/**
|
||||
Since the default counter value of a counter is zero, the result is never negative.
|
||||
*/
|
||||
int get_max_counter_value() const;
|
||||
};
|
||||
|
||||
class var_counter : public counter {
|
||||
protected:
|
||||
ptr_vector<sort> m_sorts;
|
||||
expr_fast_mark1 m_visited;
|
||||
ptr_vector<expr> m_todo;
|
||||
ast_mark m_mark;
|
||||
unsigned_vector m_scopes;
|
||||
unsigned get_max_var(bool & has_var);
|
||||
public:
|
||||
var_counter(bool stay_non_negative = true): counter(stay_non_negative) {}
|
||||
void count_vars(ast_manager & m, const app * t, int coef = 1);
|
||||
unsigned get_max_var(expr* e);
|
||||
unsigned get_next_var(expr* e);
|
||||
};
|
||||
|
||||
class ast_counter {
|
||||
typedef obj_map<ast, int> map_impl;
|
||||
map_impl m_data;
|
||||
bool m_stay_non_negative;
|
||||
public:
|
||||
typedef map_impl::iterator iterator;
|
||||
|
||||
ast_counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
|
||||
|
||||
iterator begin() const { return m_data.begin(); }
|
||||
iterator end() const { return m_data.end(); }
|
||||
|
||||
int & get(ast * el) {
|
||||
return m_data.insert_if_not_there2(el, 0)->get_data().m_value;
|
||||
}
|
||||
void update(ast * el, int delta){
|
||||
get(el) += delta;
|
||||
SASSERT(!m_stay_non_negative || get(el) >= 0);
|
||||
}
|
||||
|
||||
void inc(ast * el) { update(el, 1); }
|
||||
void dec(ast * el) { update(el, -1); }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -64,6 +64,7 @@ void bv_rewriter::updt_local_params(params_ref const & _p) {
|
|||
m_split_concat_eq = p.split_concat_eq();
|
||||
m_udiv2mul = p.udiv2mul();
|
||||
m_bvnot2arith = p.bvnot2arith();
|
||||
m_bv_sort_ac = p.bv_sort_ac();
|
||||
m_mkbv2num = _p.get_bool("mkbv2num", false);
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1316,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
|
|||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
if (!flattened && !merged && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero()))) {
|
||||
if (!flattened && !merged && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero())) && (!m_bv_sort_ac || is_sorted(num, args))) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
@ -1331,6 +1332,8 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
|
|||
result = new_args[0];
|
||||
return BR_DONE;
|
||||
default:
|
||||
if (m_bv_sort_ac)
|
||||
std::sort(new_args.begin(), new_args.end(), ast_to_lt());
|
||||
result = m_util.mk_bv_or(new_args.size(), new_args.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -1456,7 +1459,8 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
|
|||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1)))))
|
||||
if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1)))) &&
|
||||
(!m_bv_sort_ac || is_sorted(num, args)))
|
||||
return BR_FAILED;
|
||||
|
||||
ptr_buffer<expr> new_args;
|
||||
|
@ -1497,6 +1501,8 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
|
|||
}
|
||||
__fallthrough;
|
||||
default:
|
||||
if (m_bv_sort_ac)
|
||||
std::sort(new_args.begin(), new_args.end(), ast_to_lt());
|
||||
result = m_util.mk_bv_xor(new_args.size(), new_args.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
|
|||
bool m_split_concat_eq;
|
||||
bool m_udiv2mul;
|
||||
bool m_bvnot2arith;
|
||||
bool m_bv_sort_ac;
|
||||
|
||||
bool is_zero_bit(expr * x, unsigned idx);
|
||||
|
||||
|
|
|
@ -8,5 +8,6 @@ def_module_params(module_name='rewriter',
|
|||
("elim_sign_ext", BOOL, True, "expand sign-ext operator using concat and extract"),
|
||||
("hi_div0", BOOL, True, "use the 'hardware interpretation' for division by zero (for bit-vector terms)"),
|
||||
("mul2concat", BOOL, False, "replace multiplication by a power of two into a concatenation"),
|
||||
("bvnot2arith", BOOL, False, "replace (bvnot x) with (bvsub -1 x)")
|
||||
("bvnot2arith", BOOL, False, "replace (bvnot x) with (bvsub -1 x)"),
|
||||
("bv_sort_ac", BOOL, False, "sort the arguments of all AC operators")
|
||||
))
|
||||
|
|
|
@ -100,3 +100,16 @@ void expr_safe_replace::operator()(expr* e, expr_ref& res) {
|
|||
}
|
||||
res = cache.find(e);
|
||||
}
|
||||
|
||||
void expr_safe_replace::reset() {
|
||||
m_src.reset();
|
||||
m_dst.reset();
|
||||
m_subst.reset();
|
||||
}
|
||||
|
||||
void expr_safe_replace::apply_substitution(expr* s, expr* def, expr_ref& t) {
|
||||
reset();
|
||||
insert(s, def);
|
||||
(*this)(t, t);
|
||||
reset();
|
||||
}
|
|
@ -38,6 +38,10 @@ public:
|
|||
void operator()(expr_ref& e) { (*this)(e.get(), e); }
|
||||
|
||||
void operator()(expr* src, expr_ref& e);
|
||||
|
||||
void apply_substitution(expr* s, expr* def, expr_ref& t);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif /* __EXPR_SAFE_REPLACE_H__ */
|
|
@ -58,6 +58,10 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
|
|||
case OP_FLOAT_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break;
|
||||
case OP_FLOAT_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break;
|
||||
case OP_FLOAT_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break;
|
||||
case OP_FLOAT_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break;
|
||||
case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break;
|
||||
case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break;
|
||||
case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break;
|
||||
case OP_FLOAT_IS_SIGN_MINUS: SASSERT(num_args == 1); st = mk_is_sign_minus(args[0], result); break;
|
||||
case OP_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
|
||||
}
|
||||
|
@ -77,14 +81,27 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
return BR_FAILED;
|
||||
|
||||
rational q;
|
||||
if (!m_util.au().is_numeral(args[1], q))
|
||||
mpf q_mpf;
|
||||
if (m_util.au().is_numeral(args[1], q)) {
|
||||
TRACE("fp_rewriter", tout << "q: " << q << std::endl; );
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (m_util.is_value(args[1], q_mpf)) {
|
||||
TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; );
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else
|
||||
return BR_FAILED;
|
||||
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (num_args == 3 &&
|
||||
m_util.is_rm(m().get_sort(args[0])) &&
|
||||
|
@ -104,11 +121,11 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
|
|||
return BR_FAILED;
|
||||
|
||||
TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";);
|
||||
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator());
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
m_util.fm().del(v);
|
||||
// TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
|
@ -217,8 +234,7 @@ br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) {
|
|||
result = arg1;
|
||||
return BR_DONE;
|
||||
}
|
||||
sort * s = m().get_sort(arg1);
|
||||
result = m().mk_ite(m_util.mk_lt(arg1, m_util.mk_pzero(s)),
|
||||
result = m().mk_ite(m_util.mk_is_sign_minus(arg1),
|
||||
m_util.mk_uminus(arg1),
|
||||
arg1);
|
||||
return BR_REWRITE2;
|
||||
|
@ -234,13 +250,13 @@ br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_DONE;
|
||||
}
|
||||
// expand as using ite's
|
||||
result = m().mk_ite(mk_eq_nan(arg1),
|
||||
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
|
||||
arg2,
|
||||
m().mk_ite(mk_eq_nan(arg2),
|
||||
arg1,
|
||||
m().mk_ite(m_util.mk_lt(arg1, arg2),
|
||||
arg1,
|
||||
arg2)));
|
||||
arg1,
|
||||
arg2)));
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
|
@ -254,7 +270,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
return BR_DONE;
|
||||
}
|
||||
// expand as using ite's
|
||||
result = m().mk_ite(mk_eq_nan(arg1),
|
||||
result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
|
||||
arg2,
|
||||
m().mk_ite(mk_eq_nan(arg2),
|
||||
arg1,
|
||||
|
@ -420,6 +436,46 @@ br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) {
|
||||
scoped_mpf v(m_util.fm());
|
||||
if (m_util.is_value(arg1, v)) {
|
||||
|
|
|
@ -66,6 +66,10 @@ public:
|
|||
br_status mk_is_zero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_nzero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_pzero(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_nan(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_inf(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_normal(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_subnormal(expr * arg1, expr_ref & result);
|
||||
br_status mk_is_sign_minus(expr * arg1, expr_ref & result);
|
||||
|
||||
br_status mk_to_ieee_bv(expr * arg1, expr_ref & result);
|
||||
|
|
|
@ -62,6 +62,8 @@ struct mk_simplified_app::imp {
|
|||
st = m_dt_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_f_rw.get_fid())
|
||||
st = m_f_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_ar_rw.get_fid())
|
||||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,7 +25,8 @@ Revision History:
|
|||
#include "bool_rewriter.h"
|
||||
#include "var_subst.h"
|
||||
#include "ast_pp.h"
|
||||
|
||||
#include "ast_counter.h"
|
||||
#include "expr_safe_replace.h"
|
||||
|
||||
//
|
||||
// Bring quantifiers of common type into prenex form.
|
||||
|
@ -42,7 +43,7 @@ public:
|
|||
|
||||
void operator()(expr* fml, app_ref_vector& vars, bool& is_fa, expr_ref& result) {
|
||||
quantifier_type qt = Q_none_pos;
|
||||
pull_quantifiers(fml, qt, vars, result);
|
||||
pull_quantifier(fml, qt, vars, result);
|
||||
TRACE("qe_verbose",
|
||||
tout << mk_pp(fml, m) << "\n";
|
||||
tout << mk_pp(result, m) << "\n";);
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
|
||||
void pull_exists(expr* fml, app_ref_vector& vars, expr_ref& result) {
|
||||
quantifier_type qt = Q_exists_pos;
|
||||
pull_quantifiers(fml, qt, vars, result);
|
||||
pull_quantifier(fml, qt, vars, result);
|
||||
TRACE("qe_verbose",
|
||||
tout << mk_pp(fml, m) << "\n";
|
||||
tout << mk_pp(result, m) << "\n";);
|
||||
|
@ -61,7 +62,7 @@ public:
|
|||
void pull_quantifier(bool is_forall, expr_ref& fml, app_ref_vector& vars) {
|
||||
quantifier_type qt = is_forall?Q_forall_pos:Q_exists_pos;
|
||||
expr_ref result(m);
|
||||
pull_quantifiers(fml, qt, vars, result);
|
||||
pull_quantifier(fml, qt, vars, result);
|
||||
TRACE("qe_verbose",
|
||||
tout << mk_pp(fml, m) << "\n";
|
||||
tout << mk_pp(result, m) << "\n";);
|
||||
|
@ -78,7 +79,57 @@ public:
|
|||
expr * const * exprs = (expr* const*) (vars.c_ptr() + vars.size()- nd);
|
||||
instantiate(m, q, exprs, result);
|
||||
}
|
||||
|
||||
|
||||
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names) {
|
||||
unsigned index = var_counter().get_next_var(fml);
|
||||
while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) {
|
||||
quantifier* q = to_quantifier(fml);
|
||||
index += q->get_num_decls();
|
||||
if (names) {
|
||||
names->append(q->get_num_decls(), q->get_decl_names());
|
||||
}
|
||||
if (sorts) {
|
||||
sorts->append(q->get_num_decls(), q->get_decl_sorts());
|
||||
}
|
||||
fml = q->get_expr();
|
||||
}
|
||||
if (!has_quantifiers(fml)) {
|
||||
return index;
|
||||
}
|
||||
app_ref_vector vars(m);
|
||||
pull_quantifier(is_forall, fml, vars);
|
||||
if (vars.empty()) {
|
||||
return index;
|
||||
}
|
||||
// replace vars by de-bruijn indices
|
||||
expr_safe_replace rep(m);
|
||||
svector<symbol> bound_names;
|
||||
ptr_vector<sort> bound_sorts;
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
app* v = vars[i].get();
|
||||
if (names) {
|
||||
bound_names.push_back(v->get_decl()->get_name());
|
||||
}
|
||||
if (sorts) {
|
||||
bound_sorts.push_back(m.get_sort(v));
|
||||
}
|
||||
rep.insert(v, m.mk_var(index++, m.get_sort(v)));
|
||||
}
|
||||
if (names && !bound_names.empty()) {
|
||||
bound_names.reverse();
|
||||
bound_names.append(*names);
|
||||
names->reset();
|
||||
names->append(bound_names);
|
||||
}
|
||||
if (sorts && !bound_sorts.empty()) {
|
||||
bound_sorts.reverse();
|
||||
bound_sorts.append(*sorts);
|
||||
sorts->reset();
|
||||
sorts->append(bound_sorts);
|
||||
}
|
||||
rep(fml);
|
||||
return index;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
@ -143,7 +194,7 @@ private:
|
|||
}
|
||||
|
||||
|
||||
void pull_quantifiers(expr* fml, quantifier_type& qt, app_ref_vector& vars, expr_ref& result) {
|
||||
void pull_quantifier(expr* fml, quantifier_type& qt, app_ref_vector& vars, expr_ref& result) {
|
||||
|
||||
if (!has_quantifiers(fml)) {
|
||||
result = fml;
|
||||
|
@ -159,7 +210,7 @@ private:
|
|||
if (m.is_and(fml)) {
|
||||
num_args = a->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
pull_quantifiers(a->get_arg(i), qt, vars, tmp);
|
||||
pull_quantifier(a->get_arg(i), qt, vars, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
m_rewriter.mk_and(args.size(), args.c_ptr(), result);
|
||||
|
@ -167,25 +218,25 @@ private:
|
|||
else if (m.is_or(fml)) {
|
||||
num_args = to_app(fml)->get_num_args();
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(i), qt, vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(i), qt, vars, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
m_rewriter.mk_or(args.size(), args.c_ptr(), result);
|
||||
}
|
||||
else if (m.is_not(fml)) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
negate(qt);
|
||||
result = m.mk_not(tmp);
|
||||
}
|
||||
else if (m.is_implies(fml)) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
negate(qt);
|
||||
pull_quantifiers(to_app(fml)->get_arg(1), qt, vars, result);
|
||||
pull_quantifier(to_app(fml)->get_arg(1), qt, vars, result);
|
||||
result = m.mk_implies(tmp, result);
|
||||
}
|
||||
else if (m.is_ite(fml)) {
|
||||
pull_quantifiers(to_app(fml)->get_arg(1), qt, vars, tmp);
|
||||
pull_quantifiers(to_app(fml)->get_arg(2), qt, vars, result);
|
||||
pull_quantifier(to_app(fml)->get_arg(1), qt, vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(2), qt, vars, result);
|
||||
result = m.mk_ite(to_app(fml)->get_arg(0), tmp, result);
|
||||
}
|
||||
else {
|
||||
|
@ -203,7 +254,7 @@ private:
|
|||
}
|
||||
set_quantifier_type(qt, q->is_forall());
|
||||
extract_quantifier(q, vars, tmp);
|
||||
pull_quantifiers(tmp, qt, vars, result);
|
||||
pull_quantifier(tmp, qt, vars, result);
|
||||
break;
|
||||
}
|
||||
case AST_VAR:
|
||||
|
@ -215,6 +266,7 @@ private:
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
quantifier_hoister::quantifier_hoister(ast_manager& m) {
|
||||
|
@ -237,3 +289,6 @@ void quantifier_hoister::pull_quantifier(bool is_forall, expr_ref& fml, app_ref_
|
|||
m_impl->pull_quantifier(is_forall, fml, vars);
|
||||
}
|
||||
|
||||
unsigned quantifier_hoister::pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names) {
|
||||
return m_impl->pull_quantifier(is_forall, fml, sorts, names);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,15 @@ public:
|
|||
The list of variables is empty if there are no top-level universal/existential quantifier.
|
||||
*/
|
||||
void pull_quantifier(bool is_forall, expr_ref& fml, app_ref_vector& vars);
|
||||
|
||||
/**
|
||||
\brief Pull top-most universal (is_forall true) or existential (is_forall=false) quantifier up.
|
||||
Return an expression with de-Bruijn indices and the list of names that were used.
|
||||
Return index of maximal variable.
|
||||
*/
|
||||
|
||||
unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -169,7 +169,9 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
st = m_dt_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_f_rw.get_fid())
|
||||
st = m_f_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
else if (s_fid == m_ar_rw.get_fid())
|
||||
st = m_ar_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ Notes:
|
|||
|
||||
--*/
|
||||
#include"var_subst.h"
|
||||
#include"used_vars.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
@ -40,7 +39,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
|
|||
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
||||
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
if (is_ground(q->get_expr())) {
|
||||
// ignore patterns if the body is a ground formula.
|
||||
|
@ -51,17 +50,17 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
result = q;
|
||||
return;
|
||||
}
|
||||
used_vars used;
|
||||
used.process(q->get_expr());
|
||||
m_used.reset();
|
||||
m_used.process(q->get_expr());
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
for (unsigned i = 0; i < num_patterns; i++)
|
||||
used.process(q->get_pattern(i));
|
||||
m_used.process(q->get_pattern(i));
|
||||
unsigned num_no_patterns = q->get_num_no_patterns();
|
||||
for (unsigned i = 0; i < num_no_patterns; i++)
|
||||
used.process(q->get_no_pattern(i));
|
||||
m_used.process(q->get_no_pattern(i));
|
||||
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
if (used.uses_all_vars(num_decls)) {
|
||||
if (m_used.uses_all_vars(num_decls)) {
|
||||
q->set_no_unused_vars();
|
||||
result = q;
|
||||
return;
|
||||
|
@ -70,7 +69,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
ptr_buffer<sort> used_decl_sorts;
|
||||
buffer<symbol> used_decl_names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
if (used.contains(num_decls - i - 1)) {
|
||||
if (m_used.contains(num_decls - i - 1)) {
|
||||
used_decl_sorts.push_back(q->get_decl_sort(i));
|
||||
used_decl_names.push_back(q->get_decl_name(i));
|
||||
}
|
||||
|
@ -79,10 +78,10 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
unsigned num_removed = 0;
|
||||
expr_ref_buffer var_mapping(m);
|
||||
int next_idx = 0;
|
||||
unsigned sz = used.get_max_found_var_idx_plus_1();
|
||||
unsigned sz = m_used.get_max_found_var_idx_plus_1();
|
||||
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
sort * s = used.contains(i);
|
||||
sort * s = m_used.contains(i);
|
||||
if (s) {
|
||||
var_mapping.push_back(m.mk_var(next_idx, s));
|
||||
next_idx++;
|
||||
|
@ -95,7 +94,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
// (VAR 0) is in the first position of var_mapping.
|
||||
|
||||
for (unsigned i = num_decls; i < sz; i++) {
|
||||
sort * s = used.contains(i);
|
||||
sort * s = m_used.contains(i);
|
||||
if (s)
|
||||
var_mapping.push_back(m.mk_var(i - num_removed, s));
|
||||
else
|
||||
|
@ -110,9 +109,8 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
std::reverse(var_mapping.c_ptr(), var_mapping.c_ptr() + var_mapping.size());
|
||||
|
||||
expr_ref new_expr(m);
|
||||
var_subst subst(m);
|
||||
|
||||
subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
|
||||
if (num_removed == num_decls) {
|
||||
result = new_expr;
|
||||
|
@ -124,11 +122,11 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
expr_ref_buffer new_no_patterns(m);
|
||||
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
new_patterns.push_back(tmp);
|
||||
}
|
||||
for (unsigned i = 0; i < num_no_patterns; i++) {
|
||||
subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
new_no_patterns.push_back(tmp);
|
||||
}
|
||||
|
||||
|
@ -145,7 +143,12 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
|||
num_no_patterns,
|
||||
new_no_patterns.c_ptr());
|
||||
to_quantifier(result)->set_no_unused_vars();
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
||||
unused_vars_eliminator el(m);
|
||||
el(q, result);
|
||||
}
|
||||
|
||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
|
||||
|
@ -161,9 +164,7 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
|
|||
tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
|
||||
}
|
||||
|
||||
static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sorts) {
|
||||
ast_mark mark;
|
||||
ptr_vector<expr> todo;
|
||||
static void get_free_vars_offset(ast_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
|
||||
todo.push_back(e);
|
||||
while (!todo.empty()) {
|
||||
e = todo.back();
|
||||
|
@ -175,7 +176,9 @@ static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sor
|
|||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(e);
|
||||
get_free_vars_offset(q->get_expr(), offset+q->get_num_decls(), sorts);
|
||||
ast_mark mark1;
|
||||
ptr_vector<expr> todo1;
|
||||
get_free_vars_offset(mark1, todo1, offset+q->get_num_decls(), q->get_expr(), sorts);
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
|
@ -207,5 +210,11 @@ static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sor
|
|||
|
||||
|
||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts) {
|
||||
get_free_vars_offset(e, 0, sorts);
|
||||
ast_mark mark;
|
||||
ptr_vector<expr> todo;
|
||||
get_free_vars_offset(mark, todo, 0, e, sorts);
|
||||
}
|
||||
|
||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts) {
|
||||
get_free_vars_offset(mark, todo, 0, e, sorts);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#define _VAR_SUBST_H_
|
||||
|
||||
#include"rewriter.h"
|
||||
#include"used_vars.h"
|
||||
|
||||
/**
|
||||
\brief Alias for var_shifter class.
|
||||
|
@ -53,6 +54,15 @@ public:
|
|||
/**
|
||||
\brief Eliminate the unused variables from \c q. Store the result in \c r.
|
||||
*/
|
||||
class unused_vars_eliminator {
|
||||
ast_manager& m;
|
||||
var_subst m_subst;
|
||||
used_vars m_used;
|
||||
public:
|
||||
unused_vars_eliminator(ast_manager& m): m(m), m_subst(m) {}
|
||||
void operator()(quantifier* q, expr_ref& r);
|
||||
};
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & r);
|
||||
|
||||
/**
|
||||
|
@ -73,6 +83,8 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
|
|||
*/
|
||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts);
|
||||
|
||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
55
src/ast/scoped_proof.h
Normal file
55
src/ast/scoped_proof.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
scoped_proof.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Scoped proof environments. Toggles enabling proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-08-28
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _SCOPED_PROOF__H_
|
||||
#define _SCOPED_PROOF_H_
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
class scoped_proof_mode {
|
||||
ast_manager& m;
|
||||
proof_gen_mode m_mode;
|
||||
public:
|
||||
scoped_proof_mode(ast_manager& m, proof_gen_mode mode): m(m) {
|
||||
m_mode = m.proof_mode();
|
||||
m.toggle_proof_mode(mode);
|
||||
}
|
||||
~scoped_proof_mode() {
|
||||
m.toggle_proof_mode(m_mode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class scoped_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
|
||||
};
|
||||
|
||||
class scoped_no_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
|
||||
};
|
||||
|
||||
class scoped_restore_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -179,7 +179,7 @@ bool bv_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const
|
|||
}
|
||||
SASSERT(result.get());
|
||||
|
||||
TRACE("bv_simplifier",
|
||||
TRACE("bv_simplifier",
|
||||
tout << mk_pp(f, m_manager) << "\n";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m_manager) << " ";
|
||||
|
@ -636,7 +636,31 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar
|
|||
if (!all_found) {
|
||||
return false;
|
||||
}
|
||||
result = m_manager.mk_app(m_fid, a->get_decl_kind(), new_args.size(), new_args.c_ptr());
|
||||
// We should not use mk_app because it does not guarantee that the result would be in simplified form.
|
||||
// result = m_manager.mk_app(m_fid, a->get_decl_kind(), new_args.size(), new_args.c_ptr());
|
||||
if (is_app_of(a, m_fid, OP_BAND))
|
||||
mk_bv_and(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BOR))
|
||||
mk_bv_or(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BXOR))
|
||||
mk_bv_xor(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BNOR))
|
||||
mk_bv_nor(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BNAND))
|
||||
mk_bv_nand(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BNOT)) {
|
||||
SASSERT(new_args.size() == 1);
|
||||
mk_bv_not(new_args[0], result);
|
||||
}
|
||||
else if (is_app_of(a, m_fid, OP_BADD))
|
||||
mk_add(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BMUL))
|
||||
mk_mul(new_args.size(), new_args.c_ptr(), result);
|
||||
else if (is_app_of(a, m_fid, OP_BSUB))
|
||||
mk_sub(new_args.size(), new_args.c_ptr(), result);
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (m_manager.is_ite(a)) {
|
||||
|
@ -747,16 +771,16 @@ void bv_simplifier_plugin::mk_bv_eq(expr* a1, expr* a2, expr_ref& result) {
|
|||
expr * arg1 = *it1;
|
||||
expr * arg2 = *it2;
|
||||
TRACE("expr_bv_util", tout << "low1: " << low1 << " low2: " << low2 << "\n";
|
||||
ast_ll_pp(tout, m_manager, arg1);
|
||||
ast_ll_pp(tout, m_manager, arg2););
|
||||
tout << mk_pp(arg1, m_manager) << "\n";
|
||||
tout << mk_pp(arg2, m_manager) << "\n";);
|
||||
unsigned sz1 = get_bv_size(arg1);
|
||||
unsigned sz2 = get_bv_size(arg2);
|
||||
SASSERT(low1 < sz1 && low2 < sz2);
|
||||
unsigned rsz1 = sz1 - low1;
|
||||
unsigned rsz2 = sz2 - low2;
|
||||
TRACE("expr_bv_util", tout << "rsz1: " << rsz1 << " rsz2: " << rsz2 << "\n";
|
||||
ast_ll_pp(tout, m_manager, arg1); ast_ll_pp(tout, m_manager, arg2););
|
||||
|
||||
tout << mk_pp(arg1, m_manager) << "\n";
|
||||
tout << mk_pp(arg2, m_manager) << "\n";);
|
||||
|
||||
if (rsz1 == rsz2) {
|
||||
mk_extract(sz1 - 1, low1, arg1, lhs);
|
||||
|
@ -826,9 +850,9 @@ void bv_simplifier_plugin::mk_eq_core(expr * arg1, expr * arg2, expr_ref & resul
|
|||
}
|
||||
m_bsimp.mk_and(tmps.size(), tmps.c_ptr(), result);
|
||||
TRACE("mk_eq_bb",
|
||||
ast_ll_pp(tout, m_manager, arg1);
|
||||
ast_ll_pp(tout, m_manager, arg2);
|
||||
ast_ll_pp(tout, m_manager, result););
|
||||
tout << mk_pp(arg1, m_manager) << "\n";
|
||||
tout << mk_pp(arg2, m_manager) << "\n";
|
||||
tout << mk_pp(result, m_manager) << "\n";);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@ Author:
|
|||
#include"ast_pp.h"
|
||||
#include"ast_util.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
|
||||
poly_simplifier_plugin::poly_simplifier_plugin(symbol const & fname, ast_manager & m, decl_kind add, decl_kind mul, decl_kind uminus, decl_kind sub,
|
||||
decl_kind num):
|
||||
|
@ -173,7 +174,7 @@ void poly_simplifier_plugin::mk_monomial(unsigned num_args, expr * * args, expr_
|
|||
result = args[0];
|
||||
break;
|
||||
default:
|
||||
std::sort(args, args + num_args, monomial_element_lt_proc(*this));
|
||||
std::stable_sort(args, args + num_args, monomial_element_lt_proc(*this));
|
||||
result = mk_mul(num_args, args);
|
||||
SASSERT(wf_monomial(result));
|
||||
break;
|
||||
|
@ -284,6 +285,7 @@ bool poly_simplifier_plugin::merge_monomials(bool inv, expr * n1, expr * n2, exp
|
|||
else
|
||||
result = m_manager.mk_app(m_fid, m_MUL, mk_numeral(k1), b);
|
||||
}
|
||||
TRACE("merge_monomials", tout << mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n" << mk_pp(result, m_manager) << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -465,7 +467,9 @@ void poly_simplifier_plugin::mk_sum_of_monomials(expr_ref_vector & monomials, ex
|
|||
result = monomials.get(0);
|
||||
break;
|
||||
default: {
|
||||
std::sort(monomials.c_ptr(), monomials.c_ptr() + monomials.size(), monomial_lt_proc(*this));
|
||||
TRACE("mk_sum_sort", tout << "before\n"; for (unsigned i = 0; i < monomials.size(); i++) tout << mk_ll_pp(monomials.get(i), m_manager) << "\n";);
|
||||
std::stable_sort(monomials.c_ptr(), monomials.c_ptr() + monomials.size(), monomial_lt_proc(*this));
|
||||
TRACE("mk_sum_sort", tout << "after\n"; for (unsigned i = 0; i < monomials.size(); i++) tout << mk_ll_pp(monomials.get(i), m_manager) << "\n";);
|
||||
if (is_simple_sum_of_monomials(monomials)) {
|
||||
mk_sum_of_monomials_core(monomials.size(), monomials.c_ptr(), result);
|
||||
return;
|
||||
|
|
|
@ -18,10 +18,6 @@ Revision History:
|
|||
--*/
|
||||
#include"matcher.h"
|
||||
|
||||
matcher::matcher(ast_manager & m):
|
||||
m_manager(m) {
|
||||
}
|
||||
|
||||
bool matcher::operator()(expr * e1, expr * e2, substitution & s) {
|
||||
reset();
|
||||
m_subst = &s;
|
||||
|
|
|
@ -30,7 +30,6 @@ class matcher {
|
|||
typedef pair_hash<obj_ptr_hash<expr>, obj_ptr_hash<expr> > expr_pair_hash;
|
||||
typedef hashtable<expr_pair, expr_pair_hash, default_eq<expr_pair> > cache;
|
||||
|
||||
ast_manager & m_manager;
|
||||
substitution * m_subst;
|
||||
// cache m_cache;
|
||||
svector<expr_pair> m_todo;
|
||||
|
@ -38,7 +37,7 @@ class matcher {
|
|||
void reset();
|
||||
|
||||
public:
|
||||
matcher(ast_manager & m);
|
||||
matcher() {}
|
||||
|
||||
/**
|
||||
\brief Return true if e2 is an instance of e1.
|
||||
|
|
|
@ -148,7 +148,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e
|
|||
expr * arg = to_app(e)->get_arg(i);
|
||||
expr * new_arg;
|
||||
|
||||
m_apply_cache.find(expr_offset(arg, off), new_arg);
|
||||
VERIFY(m_apply_cache.find(expr_offset(arg, off), new_arg));
|
||||
new_args.push_back(new_arg);
|
||||
if (arg != new_arg)
|
||||
has_new_args = true;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Command context provides the infrastructure for executing commands in front-ends such as SMT-LIB 2.0.
|
||||
It is also provides the solver abstraction to plugin solvers in this kind of front-end.
|
||||
It is also provides the solver abstraction to plugin solvers in this kind of front-end.
|
||||
|
|
|
@ -584,7 +584,7 @@ public:
|
|||
ctx.regular_stream() << "(:authors \"Leonardo de Moura and Nikolaj Bjorner\")" << std::endl;
|
||||
}
|
||||
else if (opt == m_version) {
|
||||
ctx.regular_stream() << "(:version \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "\")" << std::endl;
|
||||
ctx.regular_stream() << "(:version \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "\")" << std::endl;
|
||||
}
|
||||
else if (opt == m_status) {
|
||||
ctx.regular_stream() << "(:status " << ctx.get_status() << ")" << std::endl;
|
||||
|
|
|
@ -517,6 +517,9 @@ void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector<rational>& r
|
|||
int numps = s->get_num_parameters();
|
||||
rats.resize(numps-1);
|
||||
rats[0] = rational(1);
|
||||
ast conseq = arg(conc(proof),0);
|
||||
opr conseq_o = is_not(conseq) ? op(arg(conseq,0)) : op(conseq);
|
||||
bool conseq_neg = is_not(conseq) ? (conseq_o == Leq || conseq_o == Lt) : (conseq_o == Geq || conseq_o == Gt);
|
||||
for(int i = 2; i < numps; i++){
|
||||
rational r;
|
||||
bool ok = s->get_parameter(i).is_rational(r);
|
||||
|
@ -528,7 +531,8 @@ void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector<rational>& r
|
|||
opr o = is_not(con) ? op(arg(con,0)) : op(con);
|
||||
if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt))
|
||||
r = -r;
|
||||
r = -r;
|
||||
if(conseq_neg)
|
||||
r = -r;
|
||||
}
|
||||
rats[i-1] = r;
|
||||
}
|
||||
|
|
|
@ -364,7 +364,7 @@ class iz3mgr {
|
|||
return cook(to_func_decl(s)->get_parameters()[idx].get_ast());
|
||||
}
|
||||
|
||||
enum lemma_theory {ArithTheory,UnknownTheory};
|
||||
enum lemma_theory {ArithTheory,ArrayTheory,UnknownTheory};
|
||||
|
||||
lemma_theory get_theory_lemma_theory(const ast &proof){
|
||||
symb s = sym(proof);
|
||||
|
@ -374,6 +374,8 @@ class iz3mgr {
|
|||
std::string foo(p0.bare_str());
|
||||
if(foo == "arith")
|
||||
return ArithTheory;
|
||||
if(foo == "array")
|
||||
return ArrayTheory;
|
||||
return UnknownTheory;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,10 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
and yields a proof of false. */
|
||||
symb leq2eq;
|
||||
|
||||
/* Equality to inequality. eq2leq(p, q) takes a proof p of x=y, and
|
||||
a proof q ~(x <= y) and and yields a proof of false. */
|
||||
symb eq2leq;
|
||||
|
||||
/* Proof term cong(p,q) takes a proof p of x=y and a proof
|
||||
q of t != t<y/x> and returns a proof of false. */
|
||||
symb cong;
|
||||
|
@ -85,6 +89,9 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
and q of ~Q and returns a proof of false. */
|
||||
symb modpon;
|
||||
|
||||
/* This represents a lack of a proof */
|
||||
ast no_proof;
|
||||
|
||||
// This is used to represent an infinitessimal value
|
||||
ast epsilon;
|
||||
|
||||
|
@ -102,13 +109,15 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
return res;
|
||||
}
|
||||
|
||||
ast make_contra_node(const ast &pf, const std::vector<ast> &lits){
|
||||
ast make_contra_node(const ast &pf, const std::vector<ast> &lits, int pfok = -1){
|
||||
if(lits.size() == 0)
|
||||
return pf;
|
||||
std::vector<ast> reslits;
|
||||
reslits.push_back(make(contra,pf,mk_false()));
|
||||
for(unsigned i = 0; i < lits.size(); i++){
|
||||
ast bar = make(rotate_sum,lits[i],pf);
|
||||
ast bar;
|
||||
if(pfok & (1 << i)) bar = make(rotate_sum,lits[i],pf);
|
||||
else bar = no_proof;
|
||||
ast foo = make(contra,bar,lits[i]);
|
||||
reslits.push_back(foo);
|
||||
}
|
||||
|
@ -129,6 +138,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
return pv->range_contained(r,rng) ? LitA : LitB;
|
||||
}
|
||||
|
||||
bool term_common(const ast &t){
|
||||
prover::range r = pv->ast_scope(t);
|
||||
return pv->ranges_intersect(r,rng) && !pv->range_contained(r,rng);
|
||||
}
|
||||
|
||||
/** Make a resolution node with given pivot literal and premises.
|
||||
The conclusion of premise1 should contain the negation of the
|
||||
pivot literal, while the conclusion of premise2 should contain the
|
||||
|
@ -267,24 +281,59 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
if(!(f == pivot)){
|
||||
ast ph = get_placeholder(mk_not(arg(pivot1,1)));
|
||||
ast pf = arg(pivot1,0);
|
||||
ast thing = subst_term_and_simp(ph,pf,arg(f,0));
|
||||
ast thing = pf == no_proof ? no_proof : subst_term_and_simp(ph,pf,arg(f,0));
|
||||
ast newf = make(contra,thing,arg(f,1));
|
||||
res.push_back(newf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_negative_equality(const ast &e){
|
||||
if(op(e) == Not){
|
||||
opr o = op(arg(e,0));
|
||||
return o == Equal || o == Iff;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ast resolve_contra(const ast &pivot1, const ast &conj1,
|
||||
int count_negative_equalities(const std::vector<ast> &resolvent){
|
||||
int res = 0;
|
||||
for(unsigned i = 0; i < resolvent.size(); i++)
|
||||
if(is_negative_equality(arg(resolvent[i],1)))
|
||||
res++;
|
||||
return res;
|
||||
}
|
||||
|
||||
ast resolve_contra_nf(const ast &pivot1, const ast &conj1,
|
||||
const ast &pivot2, const ast &conj2){
|
||||
std::vector<ast> resolvent;
|
||||
collect_contra_resolvents(0,pivot1,pivot2,conj2,resolvent);
|
||||
collect_contra_resolvents(1,pivot2,pivot1,conj1,resolvent);
|
||||
if(count_negative_equalities(resolvent) > 1)
|
||||
throw proof_error();
|
||||
if(resolvent.size() == 1) // we have proved a contradiction
|
||||
return simplify(arg(resolvent[0],0)); // this is the proof -- get interpolant
|
||||
return make(And,resolvent);
|
||||
}
|
||||
|
||||
|
||||
ast resolve_contra(const ast &pivot1, const ast &conj1,
|
||||
const ast &pivot2, const ast &conj2){
|
||||
#if 0
|
||||
int nargs = num_args(conj1);
|
||||
for(int i = 0; i < nargs; i++){
|
||||
ast foo = arg(conj1,i);
|
||||
if(!(foo == pivot1) && is_negative_equality(arg(foo,1)))
|
||||
return resolve_contra_nf(pivot2, conj2, pivot1, conj1);
|
||||
}
|
||||
#endif
|
||||
if(arg(pivot1,0) != no_proof)
|
||||
return resolve_contra_nf(pivot1, conj1, pivot2, conj2);
|
||||
if(arg(pivot2,0) != no_proof)
|
||||
return resolve_contra_nf(pivot2, conj2, pivot1, conj1);
|
||||
return resolve_with_quantifier(pivot1, conj1, pivot2, conj2);
|
||||
}
|
||||
|
||||
|
||||
bool is_contra_itp(const ast &pivot1, ast itp2, ast &pivot2){
|
||||
if(op(itp2) == And){
|
||||
int nargs = num_args(itp2);
|
||||
|
@ -408,7 +457,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
}
|
||||
|
||||
/* This is where the real work happens. Here, we simplify the
|
||||
proof obtained by cut elimination, obtaining a interpolant. */
|
||||
proof obtained by cut elimination, obtaining an interpolant. */
|
||||
|
||||
struct cannot_simplify {};
|
||||
hash_map<ast,ast> simplify_memo;
|
||||
|
@ -424,19 +473,23 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
if(bar.second){
|
||||
int nargs = num_args(e);
|
||||
std::vector<ast> args(nargs);
|
||||
for(int i = 0; i < nargs; i++)
|
||||
bool placeholder_arg = false;
|
||||
for(int i = 0; i < nargs; i++){
|
||||
args[i] = simplify_rec(arg(e,i));
|
||||
placeholder_arg |= is_placeholder(args[i]);
|
||||
}
|
||||
try {
|
||||
opr f = op(e);
|
||||
if(f == Equal && args[0] == args[1]) res = mk_true();
|
||||
else if(f == And) res = my_and(args);
|
||||
else if(f == Or) res = my_or(args);
|
||||
else if(f == Idiv) res = mk_idiv(args[0],args[1]);
|
||||
else if(f == Uninterpreted){
|
||||
else if(f == Uninterpreted && !placeholder_arg){
|
||||
symb g = sym(e);
|
||||
if(g == rotate_sum) res = simplify_rotate(args);
|
||||
else if(g == symm) res = simplify_symm(args);
|
||||
else if(g == modpon) res = simplify_modpon(args);
|
||||
else if(g == sum) res = simplify_sum(args);
|
||||
#if 0
|
||||
else if(g == cong) res = simplify_cong(args);
|
||||
else if(g == modpon) res = simplify_modpon(args);
|
||||
|
@ -462,17 +515,26 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
symb g = sym(pf);
|
||||
if(g == sum) return simplify_rotate_sum(pl,pf);
|
||||
if(g == leq2eq) return simplify_rotate_leq2eq(pl,args[0],pf);
|
||||
if(g == eq2leq) return simplify_rotate_eq2leq(pl,args[0],pf);
|
||||
if(g == cong) return simplify_rotate_cong(pl,args[0],pf);
|
||||
if(g == modpon) return simplify_rotate_modpon(pl,args[0],pf);
|
||||
// if(g == symm) return simplify_rotate_symm(pl,args[0],pf);
|
||||
}
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
ast simplify_sum(std::vector<ast> &args){
|
||||
ast cond = mk_true();
|
||||
ast ineq = args[0];
|
||||
if(!is_ineq(ineq)) throw cannot_simplify();
|
||||
sum_cond_ineq(ineq,cond,args[1],args[2]);
|
||||
return my_implies(cond,ineq);
|
||||
}
|
||||
|
||||
ast simplify_rotate_sum(const ast &pl, const ast &pf){
|
||||
ast cond = mk_true();
|
||||
ast ineq = make(Leq,make_int("0"),make_int("0"));
|
||||
rotate_sum_rec(pl,pf,cond,ineq);
|
||||
return ineq;
|
||||
return rotate_sum_rec(pl,pf,cond,ineq);
|
||||
}
|
||||
|
||||
void sum_cond_ineq(ast &ineq, ast &cond, const ast &coeff2, const ast &ineq2){
|
||||
|
@ -481,18 +543,26 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
sum_cond_ineq(ineq,cond,coeff2,arg(ineq2,1));
|
||||
cond = my_and(cond,arg(ineq2,0));
|
||||
}
|
||||
else if(o == Leq || o == Lt)
|
||||
ineq = sum_ineq(make_int("1"),ineq,coeff2,ineq2);
|
||||
else if(is_ineq(ineq2))
|
||||
linear_comb(ineq,coeff2,ineq2);
|
||||
else
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
bool is_ineq(const ast &ineq){
|
||||
opr o = op(ineq);
|
||||
if(o == Not) o = op(arg(ineq,0));
|
||||
return o == Leq || o == Lt || o == Geq || o == Gt;
|
||||
}
|
||||
|
||||
// divide both sides of inequality by a non-negative integer divisor
|
||||
ast idiv_ineq(const ast &ineq, const ast &divisor){
|
||||
return make(op(ineq),mk_idiv(arg(ineq,0),divisor),mk_idiv(arg(ineq,1),divisor));
|
||||
}
|
||||
|
||||
ast rotate_sum_rec(const ast &pl, const ast &pf, ast &cond, ast &ineq){
|
||||
if(pf == pl)
|
||||
return my_implies(cond,simplify_ineq(ineq));
|
||||
if(op(pf) == Uninterpreted && sym(pf) == sum){
|
||||
if(arg(pf,2) == pl){
|
||||
sum_cond_ineq(ineq,cond,make_int("1"),arg(pf,0));
|
||||
|
@ -510,25 +580,57 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
ast equality = arg(neg_equality,0);
|
||||
ast x = arg(equality,0);
|
||||
ast y = arg(equality,1);
|
||||
ast xleqy = arg(pf,1);
|
||||
ast yleqx = arg(pf,2);
|
||||
ast xleqy = round_ineq(arg(pf,1));
|
||||
ast yleqx = round_ineq(arg(pf,2));
|
||||
ast itpeq;
|
||||
if(get_term_type(x) == LitA)
|
||||
itpeq = make(Equal,x,make(Plus,x,get_ineq_rhs(xleqy)));
|
||||
itpeq = make(Equal,x,z3_simplify(make(Plus,x,get_ineq_rhs(xleqy))));
|
||||
else if(get_term_type(y) == LitA)
|
||||
itpeq = make(Equal,make(Plus,y,get_ineq_rhs(yleqx)),y);
|
||||
itpeq = make(Equal,z3_simplify(make(Plus,y,get_ineq_rhs(yleqx))),y);
|
||||
else
|
||||
throw cannot_simplify();
|
||||
ast cond = mk_true();
|
||||
ast ineq = make(Leq,make_int("0"),make_int("0"));
|
||||
sum_cond_ineq(ineq,cond,make_int("-1"),xleqy);
|
||||
sum_cond_ineq(ineq,cond,make_int("-1"),yleqx);
|
||||
cond = my_and(cond,ineq);
|
||||
cond = z3_simplify(my_and(cond,ineq));
|
||||
return my_implies(cond,itpeq);
|
||||
}
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
ast round_ineq(const ast &ineq){
|
||||
if(!is_ineq(ineq))
|
||||
throw cannot_simplify();
|
||||
ast res = simplify_ineq(ineq);
|
||||
if(op(res) == Lt)
|
||||
res = make(Leq,arg(res,0),make(Sub,arg(res,1),make_int("1")));
|
||||
return res;
|
||||
}
|
||||
|
||||
ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){
|
||||
if(pl == arg(pf,1)){
|
||||
ast cond = mk_true();
|
||||
ast equa = sep_cond(arg(pf,0),cond);
|
||||
if(op(equa) == Equal)
|
||||
return my_implies(cond,z3_simplify(make(Leq,make_int("0"),make(Sub,arg(equa,1),arg(equa,0)))));
|
||||
if(op(equa) == True)
|
||||
return my_implies(cond,z3_simplify(make(Leq,make_int("0"),make_int("0"))));
|
||||
}
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
ast simplify_rotate_modpon(const ast &pl, const ast &neg_equality, const ast &pf){
|
||||
if(pl == arg(pf,2)){
|
||||
std::vector<ast> args; args.resize(3);
|
||||
args[0] = arg(pf,0);
|
||||
args[1] = arg(pf,1);
|
||||
args[2] = mk_true();
|
||||
return simplify_modpon(args);
|
||||
}
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
ast get_ineq_rhs(const ast &ineq2){
|
||||
opr o = op(ineq2);
|
||||
if(o == Implies)
|
||||
|
@ -564,8 +666,8 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
return mk_true();
|
||||
ast cond = mk_true();
|
||||
ast equa = sep_cond(args[0],cond);
|
||||
if(op(equa) == Equal)
|
||||
return my_implies(cond,make(Equal,arg(equa,1),arg(equa,0)));
|
||||
if(is_equivrel(equa))
|
||||
return my_implies(cond,make(op(equa),arg(equa,1),arg(equa,0)));
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
|
@ -575,12 +677,120 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
ast P = sep_cond(args[0],cond);
|
||||
ast notQ = sep_cond(args[2],cond);
|
||||
ast Q = mk_not(notQ);
|
||||
ast d = mk_not(delta(P,Q));
|
||||
ast d = op(notQ) == True ? P : op(P) == True ? notQ : mk_not(delta(P,Q));
|
||||
return my_implies(cond,d);
|
||||
}
|
||||
else {
|
||||
ast cond = mk_true();
|
||||
ast P = sep_cond(args[0],cond);
|
||||
ast PeqQ = sep_cond(args[1],cond);
|
||||
ast Q2 = sep_cond(args[2],cond);
|
||||
ast P1 = arg(PeqQ,0);
|
||||
ast Q1 = arg(PeqQ,1);
|
||||
if(op(P) == True){
|
||||
if(is_equivrel(P1) && is_equivrel(Q1)){ // special case of transitivity
|
||||
if(arg(P1,0) == arg(Q1,0))
|
||||
if(op(args[2]) == True)
|
||||
return my_implies(cond,make(op(P1),arg(P1,1),arg(Q1,1)));
|
||||
}
|
||||
if(op(args[2]) == True)
|
||||
throw cannot_simplify(); // return my_implies(cond,make(rewrite(P1,Q1)));
|
||||
ast A_rewrites = mk_true();
|
||||
ast foo = commute_rewrites(P1,Q1,mk_not(Q2),A_rewrites);
|
||||
return my_implies(cond,my_implies(my_implies(A_rewrites,foo),mk_false()));
|
||||
}
|
||||
else if(op(args[2]) == True){
|
||||
ast P2 = apply_common_rewrites(P,P,P1,cond);
|
||||
ast A_rewrites = mk_true();
|
||||
if(is_equivrel(P2)){
|
||||
try {
|
||||
ast foo = commute_rewrites(arg(P2,0),arg(P2,1),arg(Q1,1),A_rewrites);
|
||||
ast P3 = make(op(P1),arg(P1,0),foo);
|
||||
if(P3 == P2)
|
||||
return my_implies(cond,Q1);
|
||||
// return my_implies(cond,make(rewrite,my_implies(A_rewrites,P3),Q1));
|
||||
}
|
||||
catch(const rewrites_failed &){
|
||||
std::cout << "foo!\n";
|
||||
}
|
||||
}
|
||||
ast Q2 = apply_all_rewrites(P2,P1,Q1);
|
||||
return my_implies(cond,Q2);
|
||||
}
|
||||
}
|
||||
throw cannot_simplify();
|
||||
}
|
||||
|
||||
bool is_equivrel(const ast &p){
|
||||
opr o = op(p);
|
||||
return o == Equal || o == Iff;
|
||||
}
|
||||
|
||||
struct rewrites_failed{};
|
||||
|
||||
/* Suppose p in Lang(B) and A |- p -> q and B |- q -> r. Return a z in Lang(B) such that
|
||||
B |- p -> z and A |- z -> q. Collect any side conditions in "rules". */
|
||||
|
||||
ast commute_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){
|
||||
if(q == r)
|
||||
return p;
|
||||
if(p == q)
|
||||
return r;
|
||||
else {
|
||||
ast rew = make(Equal,q,r);
|
||||
if(get_term_type(rew) == LitB){
|
||||
apply_common_rewrites(p,p,q,rules); // A rewrites must be over comon vocab
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if(sym(p) != sym(q) || sym(q) != sym(r))
|
||||
throw rewrites_failed();
|
||||
int nargs = num_args(p);
|
||||
if(nargs != num_args(q) || nargs != num_args(r))
|
||||
throw rewrites_failed();
|
||||
std::vector<ast> args; args.resize(nargs);
|
||||
for(int i = 0; i < nargs; i++)
|
||||
args[i] = commute_rewrites(arg(p,i),arg(q,i),arg(r,i),rules);
|
||||
return clone(p,args);
|
||||
}
|
||||
|
||||
ast apply_common_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){
|
||||
if(q == r)
|
||||
return p;
|
||||
ast rew = make(Equal,q,r);
|
||||
if(term_common(rew)){
|
||||
if(p != q)
|
||||
throw rewrites_failed();
|
||||
rules = my_and(rules,rew);
|
||||
return r;
|
||||
}
|
||||
if(sym(p) != sym(q) || sym(q) != sym(r))
|
||||
return p;
|
||||
int nargs = num_args(p);
|
||||
if(nargs != num_args(q) || nargs != num_args(r))
|
||||
return p;
|
||||
std::vector<ast> args; args.resize(nargs);
|
||||
for(int i = 0; i < nargs; i++)
|
||||
args[i] = apply_common_rewrites(arg(p,i),arg(q,i),arg(r,i),rules);
|
||||
return clone(p,args);
|
||||
}
|
||||
|
||||
ast apply_all_rewrites(const ast &p, const ast &q, const ast &r){
|
||||
if(q == r)
|
||||
return p;
|
||||
if(p == q)
|
||||
return r;
|
||||
if(sym(p) != sym(q) || sym(q) != sym(r))
|
||||
throw rewrites_failed();
|
||||
int nargs = num_args(p);
|
||||
if(nargs != num_args(q) || nargs != num_args(r))
|
||||
throw rewrites_failed();
|
||||
std::vector<ast> args; args.resize(nargs);
|
||||
for(int i = 0; i < nargs; i++)
|
||||
args[i] = apply_all_rewrites(arg(p,i),arg(q,i),arg(r,i));
|
||||
return clone(p,args);
|
||||
}
|
||||
|
||||
ast delta(const ast &x, const ast &y){
|
||||
if(op(x) != op(y) || (op(x) == Uninterpreted && sym(x) != sym(y)) || num_args(x) != num_args(y))
|
||||
return make(Equal,x,y);
|
||||
|
@ -617,6 +827,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
ast triv_interp(const symb &rule, const std::vector<ast> &premises){
|
||||
std::vector<ast> ps; ps.resize(premises.size());
|
||||
std::vector<ast> conjs;
|
||||
int mask = 0;
|
||||
for(unsigned i = 0; i < ps.size(); i++){
|
||||
ast p = premises[i];
|
||||
switch(get_term_type(p)){
|
||||
|
@ -627,12 +838,14 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
ps[i] = mk_true();
|
||||
break;
|
||||
default:
|
||||
ps[i] = get_placeholder(p);
|
||||
ps[i] = get_placeholder(p); // can only prove consequent!
|
||||
if(i == ps.size()-1)
|
||||
mask |= (1 << conjs.size());
|
||||
conjs.push_back(p);
|
||||
}
|
||||
}
|
||||
ast ref = make(rule,ps);
|
||||
ast res = make_contra_node(ref,conjs);
|
||||
ast res = make_contra_node(ref,conjs,mask);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -689,8 +902,30 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
|
||||
/** Make an axiom node. The conclusion must be an instance of an axiom. */
|
||||
virtual node make_axiom(const std::vector<ast> &conclusion){
|
||||
throw proof_error();
|
||||
}
|
||||
prover::range frng = pv->range_full();
|
||||
int nargs = conclusion.size();
|
||||
std::vector<ast> largs(nargs);
|
||||
std::vector<ast> eqs;
|
||||
std::vector<ast> pfs;
|
||||
|
||||
for(int i = 0; i < nargs; i++){
|
||||
ast argpf;
|
||||
ast lit = conclusion[i];
|
||||
largs[i] = localize_term(lit,frng,argpf);
|
||||
frng = pv->range_glb(frng,pv->ast_scope(largs[i]));
|
||||
if(largs[i] != lit){
|
||||
eqs.push_back(make_equiv(largs[i],lit));
|
||||
pfs.push_back(argpf);
|
||||
}
|
||||
}
|
||||
|
||||
int frame = pv->range_max(frng);
|
||||
ast itp = make_assumption(frame,largs);
|
||||
|
||||
for(unsigned i = 0; i < eqs.size(); i++)
|
||||
itp = make_mp(eqs[i],itp,pfs[i]);
|
||||
return itp;
|
||||
}
|
||||
|
||||
/** Make a Contra node. This rule takes a derivation of the form
|
||||
Gamma |- False and produces |- \/~Gamma. */
|
||||
|
@ -880,6 +1115,45 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
return itp;
|
||||
}
|
||||
|
||||
int find_congruence_position(const ast &p, const ast &con){
|
||||
// find the argument position of x and y
|
||||
const ast &x = arg(p,0);
|
||||
const ast &y = arg(p,1);
|
||||
int nargs = num_args(arg(con,0));
|
||||
for(int i = 0; i < nargs; i++)
|
||||
if(x == arg(arg(con,0),i) && y == arg(arg(con,1),i))
|
||||
return i;
|
||||
throw proof_error();
|
||||
}
|
||||
|
||||
/** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,...
|
||||
and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */
|
||||
|
||||
node make_congruence(const std::vector<ast> &p, const ast &con, const std::vector<ast> &prems){
|
||||
if(p.size() == 0)
|
||||
throw proof_error();
|
||||
if(p.size() == 1)
|
||||
return make_congruence(p[0],con,prems[0]);
|
||||
ast thing = con;
|
||||
ast res = mk_true();
|
||||
for(unsigned i = 0; i < p.size(); i++){
|
||||
int pos = find_congruence_position(p[i],thing);
|
||||
ast next = subst_in_arg_pos(pos,arg(p[i],1),arg(thing,0));
|
||||
ast goal = make(op(thing),arg(thing,0),next);
|
||||
ast equa = make_congruence(p[i],goal,prems[i]);
|
||||
if(i == 0)
|
||||
res = equa;
|
||||
else {
|
||||
ast trace = make(op(con),arg(con,0),arg(thing,0));
|
||||
ast equiv = make(Iff,trace,make(op(trace),arg(trace,0),next));
|
||||
ast foo = make_congruence(goal,equiv,equa);
|
||||
res = make_mp(equiv,res,foo);
|
||||
}
|
||||
thing = make(op(thing),next,arg(thing,1));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Interpolate a mixed congruence axiom. */
|
||||
|
||||
virtual ast make_mixed_congruence(const ast &x, const ast &y, const ast &p, const ast &con, const ast &prem1){
|
||||
|
@ -1037,7 +1311,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
get_placeholder(mk_not(con)),
|
||||
get_placeholder(xleqy),
|
||||
get_placeholder(yleqx)),
|
||||
conjs);
|
||||
conjs,1);
|
||||
}
|
||||
}
|
||||
return itp;
|
||||
|
@ -1054,6 +1328,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
itp = mk_true();
|
||||
break;
|
||||
default: { // mixed equality
|
||||
#if 0
|
||||
ast mid = get_placeholder(make(Equal,x,y));
|
||||
if(get_term_type(y) == LitA){
|
||||
std::swap(x,y);
|
||||
|
@ -1065,6 +1340,12 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
ast zleqmid = make(Leq,make_int("0"),mid);
|
||||
ast fark = make(contra,make_int("1"),mk_not(xleqy));
|
||||
itp = make(And,zleqmid,fark);
|
||||
#endif
|
||||
std::vector<ast> conjs; conjs.resize(2);
|
||||
conjs[0] = make(Equal,x,y);
|
||||
conjs[1] = mk_not(xleqy);
|
||||
itp = make(eq2leq,get_placeholder(conjs[0]),get_placeholder(conjs[1]));
|
||||
itp = make_contra_node(itp,conjs);
|
||||
}
|
||||
}
|
||||
return itp;
|
||||
|
@ -1083,10 +1364,17 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
itp = mk_true();
|
||||
break;
|
||||
default: {
|
||||
std::vector<ast> conjs; conjs.resize(2);
|
||||
conjs[0] = tleqc;
|
||||
conjs[1] = mk_not(con);
|
||||
itp = make(sum,get_placeholder(conjs[0]),d,get_placeholder(conjs[1]));
|
||||
itp = make_contra_node(itp,conjs);
|
||||
#if 0
|
||||
ast t = arg(tleqc,0);
|
||||
ast c = arg(tleqc,1);
|
||||
ast thing = make(contra,make_int("1"),mk_not(con));
|
||||
itp = make(And,make(Leq,make_int("0"),make(Idiv,get_placeholder(tleqc),d)),thing);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
std::vector<ast> conc; conc.push_back(con);
|
||||
|
@ -1095,6 +1383,130 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
}
|
||||
|
||||
|
||||
|
||||
// create a fresh variable for localization
|
||||
ast fresh_localization_var(const ast &term, int frame){
|
||||
std::ostringstream s;
|
||||
s << "%" << (localization_vars.size());
|
||||
ast var = make_var(s.str().c_str(),get_type(term));
|
||||
pv->sym_range(sym(var)) = pv->range_full(); // make this variable global
|
||||
localization_vars.push_back(LocVar(var,term,frame));
|
||||
return var;
|
||||
}
|
||||
|
||||
struct LocVar { // localization vars
|
||||
ast var; // a fresh variable
|
||||
ast term; // term it represents
|
||||
int frame; // frame in which it's defined
|
||||
LocVar(ast v, ast t, int f){var=v;term=t;frame=f;}
|
||||
};
|
||||
|
||||
std::vector<LocVar> localization_vars; // localization vars in order of creation
|
||||
hash_map<ast,ast> localization_map; // maps terms to their localization vars
|
||||
hash_map<ast,ast> localization_pf_map; // maps terms to proofs of their localizations
|
||||
|
||||
/* "localize" a term e to a given frame range, creating new symbols to
|
||||
represent non-local subterms. This returns the localized version e_l,
|
||||
as well as a proof thet e_l = l.
|
||||
*/
|
||||
|
||||
ast make_refl(const ast &e){
|
||||
return mk_true(); // TODO: is this right?
|
||||
}
|
||||
|
||||
|
||||
ast make_equiv(const ast &x, const ast &y){
|
||||
if(get_type(x) == bool_type())
|
||||
return make(Iff,x,y);
|
||||
else
|
||||
return make(Equal,x,y);
|
||||
}
|
||||
|
||||
ast localize_term(ast e, const prover::range &rng, ast &pf){
|
||||
ast orig_e = e;
|
||||
pf = make_refl(e); // proof that e = e
|
||||
|
||||
prover::range erng = pv->ast_scope(e);
|
||||
if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){
|
||||
return e; // this term occurs in range, so it's O.K.
|
||||
}
|
||||
|
||||
hash_map<ast,ast>::iterator it = localization_map.find(e);
|
||||
if(it != localization_map.end()){
|
||||
pf = localization_pf_map[e];
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// if is is non-local, we must first localize the arguments to
|
||||
// the range of its function symbol
|
||||
|
||||
int nargs = num_args(e);
|
||||
if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){
|
||||
prover::range frng = rng;
|
||||
if(op(e) == Uninterpreted){
|
||||
symb f = sym(e);
|
||||
prover::range srng = pv->sym_range(f);
|
||||
if(pv->ranges_intersect(srng,rng)) // localize to desired range if possible
|
||||
frng = pv->range_glb(srng,rng);
|
||||
}
|
||||
std::vector<ast> largs(nargs);
|
||||
std::vector<ast> eqs;
|
||||
std::vector<ast> pfs;
|
||||
for(int i = 0; i < nargs; i++){
|
||||
ast argpf;
|
||||
largs[i] = localize_term(arg(e,i),frng,argpf);
|
||||
frng = pv->range_glb(frng,pv->ast_scope(largs[i]));
|
||||
if(largs[i] != arg(e,i)){
|
||||
eqs.push_back(make_equiv(largs[i],arg(e,i)));
|
||||
pfs.push_back(argpf);
|
||||
}
|
||||
}
|
||||
|
||||
e = clone(e,largs);
|
||||
if(pfs.size())
|
||||
pf = make_congruence(eqs,make_equiv(e,orig_e),pfs);
|
||||
// assert(is_local(e));
|
||||
}
|
||||
|
||||
if(pv->ranges_intersect(pv->ast_scope(e),rng))
|
||||
return e; // this term occurs in range, so it's O.K.
|
||||
|
||||
// choose a frame for the constraint that is close to range
|
||||
int frame = pv->range_near(pv->ast_scope(e),rng);
|
||||
|
||||
ast new_var = fresh_localization_var(e,frame);
|
||||
localization_map[e] = new_var;
|
||||
std::vector<ast> foo; foo.push_back(make_equiv(new_var,e));
|
||||
ast bar = make_assumption(frame,foo);
|
||||
pf = make_transitivity(new_var,e,orig_e,bar,pf);
|
||||
localization_pf_map[orig_e] = pf;
|
||||
return new_var;
|
||||
}
|
||||
|
||||
node make_resolution(ast pivot, node premise1, node premise2) {
|
||||
std::vector<ast> lits;
|
||||
return make_resolution(pivot,lits,premise1,premise2);
|
||||
}
|
||||
|
||||
ast resolve_with_quantifier(const ast &pivot1, const ast &conj1,
|
||||
const ast &pivot2, const ast &conj2){
|
||||
if(is_not(arg(pivot1,1)))
|
||||
return resolve_with_quantifier(pivot2,conj2,pivot1,conj1);
|
||||
ast eqpf;
|
||||
ast P = arg(pivot1,1);
|
||||
ast Ploc = localize_term(P, rng, eqpf);
|
||||
ast pPloc = make_hypothesis(Ploc);
|
||||
ast pP = make_mp(make(Iff,Ploc,P),pPloc,eqpf);
|
||||
ast rP = make_resolution(P,conj1,pP);
|
||||
ast nP = mk_not(P);
|
||||
ast nPloc = mk_not(Ploc);
|
||||
ast neqpf = make_congruence(make(Iff,Ploc,P),make(Iff,nPloc,nP),eqpf);
|
||||
ast npPloc = make_hypothesis(nPloc);
|
||||
ast npP = make_mp(make(Iff,nPloc,nP),npPloc,neqpf);
|
||||
ast nrP = make_resolution(nP,conj2,npP);
|
||||
ast res = make_resolution(Ploc,rP,nrP);
|
||||
return res;
|
||||
}
|
||||
|
||||
ast get_contra_coeff(const ast &f){
|
||||
ast c = arg(f,0);
|
||||
|
@ -1129,6 +1541,15 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
return l;
|
||||
}
|
||||
|
||||
bool is_placeholder(const ast &e){
|
||||
if(op(e) == Uninterpreted){
|
||||
std::string name = string_of_symbol(sym(e));
|
||||
if(name.size() > 2 && name[0] == '@' and name[1] == 'p')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
iz3proof_itp_impl(prover *p, const prover::range &r, bool w)
|
||||
: iz3proof_itp(*p)
|
||||
|
@ -1144,11 +1565,13 @@ public:
|
|||
sum = function("@sum",3,boolintbooldom,bool_type());
|
||||
rotate_sum = function("@rotsum",2,boolbooldom,bool_type());
|
||||
leq2eq = function("@leq2eq",3,boolboolbooldom,bool_type());
|
||||
eq2leq = function("@eq2leq",2,boolbooldom,bool_type());
|
||||
cong = function("@cong",3,boolintbooldom,bool_type());
|
||||
exmid = function("@exmid",3,boolboolbooldom,bool_type());
|
||||
symm = function("@symm",1,booldom,bool_type());
|
||||
epsilon = make_var("@eps",int_type());
|
||||
modpon = function("@mp",3,boolboolbooldom,bool_type());
|
||||
no_proof = make_var("@nop",bool_type());
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -94,6 +94,11 @@ class iz3proof_itp : public iz3mgr {
|
|||
|
||||
virtual node make_congruence(const ast &xi_eq_yi, const ast &con, const ast &prem1) = 0;
|
||||
|
||||
/** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,...
|
||||
and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */
|
||||
|
||||
virtual node make_congruence(const std::vector<ast> &xi_eq_yi, const ast &con, const std::vector<ast> &prems) = 0;
|
||||
|
||||
/** Make a modus-ponens node. This takes derivations of |- x
|
||||
and |- x = y and produces |- y */
|
||||
|
||||
|
|
|
@ -895,7 +895,7 @@ public:
|
|||
my_cons.push_back(mk_not(arg(con,i)));
|
||||
my_coeffs.push_back(farkas_coeffs[i]);
|
||||
}
|
||||
ast farkas_con = normalize_inequality(sum_inequalities(farkas_coeffs,my_cons));
|
||||
ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons));
|
||||
my_cons.push_back(mk_not(farkas_con));
|
||||
my_coeffs.push_back(make_int("1"));
|
||||
std::vector<Iproof::node> my_hyps;
|
||||
|
@ -976,15 +976,10 @@ public:
|
|||
break;
|
||||
}
|
||||
case PR_MONOTONICITY: {
|
||||
// assume the premise is x = y
|
||||
ast x = arg(conc(prem(proof,0)),0);
|
||||
ast y = arg(conc(prem(proof,0)),1);
|
||||
#if 0
|
||||
AstSet &hyps = get_hyps(proof);
|
||||
std::vector<ast> hyps_vec; hyps_vec.resize(hyps.size());
|
||||
std::copy(hyps.begin(),hyps.end(),hyps_vec.begin());
|
||||
#endif
|
||||
res = iproof->make_congruence(conc(prem(proof,0)),con,args[0]);
|
||||
std::vector<ast> eqs; eqs.resize(args.size());
|
||||
for(unsigned i = 0; i < args.size(); i++)
|
||||
eqs[i] = conc(prem(proof,i));
|
||||
res = iproof->make_congruence(eqs,con,args);
|
||||
break;
|
||||
}
|
||||
case PR_REFLEXIVITY: {
|
||||
|
@ -1050,6 +1045,9 @@ public:
|
|||
throw unsupported();
|
||||
}
|
||||
break;
|
||||
case ArrayTheory: // nothing fancy for this
|
||||
res = iproof->make_axiom(lits);
|
||||
break;
|
||||
default:
|
||||
throw unsupported();
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
};
|
||||
|
||||
//#define IZ3_TRANSLATE_DIRECT2
|
||||
#ifndef _FOCI2
|
||||
#ifdef _FOCI2
|
||||
#define IZ3_TRANSLATE_DIRECT
|
||||
#else
|
||||
#define IZ3_TRANSLATE_FULL
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
Basic Euclidean solver for linear integer equations.
|
||||
This solver generates "explanations".
|
||||
This solver generates "explanations".
|
||||
|
|
|
@ -123,9 +123,9 @@ class heap_trie {
|
|||
}
|
||||
|
||||
// push nodes whose keys are <= key into vector.
|
||||
void find_le(Key key, ptr_vector<node>& nodes) {
|
||||
void find_le(KeyLE& le, Key key, ptr_vector<node>& nodes) {
|
||||
for (unsigned i = 0; i < m_nodes.size(); ++i) {
|
||||
if (KeyLE::le(m_nodes[i].first, key)) {
|
||||
if (le.le(m_nodes[i].first, key)) {
|
||||
node* n = m_nodes[i].second;
|
||||
if (n->ref_count() > 0){
|
||||
nodes.push_back(n);
|
||||
|
@ -179,6 +179,7 @@ class heap_trie {
|
|||
};
|
||||
|
||||
small_object_allocator m_alloc;
|
||||
KeyLE& m_le;
|
||||
unsigned m_num_keys;
|
||||
unsigned_vector m_keys;
|
||||
unsigned m_do_reshuffle;
|
||||
|
@ -189,8 +190,9 @@ class heap_trie {
|
|||
|
||||
public:
|
||||
|
||||
heap_trie():
|
||||
heap_trie(KeyLE& le):
|
||||
m_alloc("heap_trie"),
|
||||
m_le(le),
|
||||
m_num_keys(0),
|
||||
m_do_reshuffle(4),
|
||||
m_root(0),
|
||||
|
@ -255,7 +257,7 @@ public:
|
|||
for (unsigned i = 0; i < num_keys(); ++i) {
|
||||
for (unsigned j = 0; j < todo[index].size(); ++j) {
|
||||
++m_stats.m_num_find_le_nodes;
|
||||
to_trie(todo[index][j])->find_le(get_key(keys, i), todo[!index]);
|
||||
to_trie(todo[index][j])->find_le(m_le, get_key(keys, i), todo[!index]);
|
||||
}
|
||||
todo[index].reset();
|
||||
index = !index;
|
||||
|
@ -577,7 +579,7 @@ private:
|
|||
verbose_stream() << " ";
|
||||
}
|
||||
verbose_stream() << nodes[i].first << " <=? " << key << " rc:" << m->ref_count() << "\n";);
|
||||
if (m->ref_count() > 0 && KeyLE::le(nodes[i].first, key) && find_le(m, index+1, keys, check)) {
|
||||
if (m->ref_count() > 0 && m_le.le(nodes[i].first, key) && find_le(m, index+1, keys, check)) {
|
||||
if (i > 0) {
|
||||
std::swap(nodes[i], nodes[0]);
|
||||
}
|
|
@ -58,14 +58,13 @@ public:
|
|||
m_table.reset();
|
||||
}
|
||||
|
||||
bool find(offset_t idx, values const& vs, offset_t& found_idx) {
|
||||
bool find(offset_t idx, values const& vs) {
|
||||
// display_profile(idx, std::cout);
|
||||
int_table::iterator it = m_table.begin(), end = m_table.end();
|
||||
for (; it != end; ++it) {
|
||||
offset_t offs(*it);
|
||||
++m_stats.m_num_comparisons;
|
||||
if (*it != static_cast<int>(idx.m_offset) && hb.is_subsumed(idx, offs)) {
|
||||
found_idx = offs;
|
||||
++m_stats.m_num_hit;
|
||||
return true;
|
||||
}
|
||||
|
@ -163,20 +162,21 @@ private:
|
|||
|
||||
class hilbert_basis::value_index2 {
|
||||
struct key_le {
|
||||
static bool le(numeral const& n1, numeral const& n2) {
|
||||
return hilbert_basis::is_abs_geq(n2, n1);
|
||||
hilbert_basis& hb;
|
||||
key_le(hilbert_basis& hb): hb(hb) {}
|
||||
bool le(numeral const& n1, numeral const& n2) const {
|
||||
return hb.is_abs_geq(n2, n1);
|
||||
}
|
||||
};
|
||||
|
||||
typedef heap_trie<numeral, key_le, numeral::hash_proc, unsigned> ht;
|
||||
|
||||
struct checker : public ht::check_value {
|
||||
hilbert_basis* hb;
|
||||
offset_t m_value;
|
||||
offset_t* m_found;
|
||||
checker(): hb(0), m_found(0) {}
|
||||
virtual bool operator()(unsigned const& v) {
|
||||
if (m_value.m_offset != v && hb->is_subsumed(m_value, offset_t(v))) {
|
||||
*m_found = offset_t(v);
|
||||
checker(): hb(0) {}
|
||||
virtual bool operator()(unsigned const& v) {
|
||||
if (m_value.m_offset != v) { // && hb->is_subsumed(m_value, offset_t(v))) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -185,23 +185,25 @@ class hilbert_basis::value_index2 {
|
|||
}
|
||||
};
|
||||
hilbert_basis& hb;
|
||||
key_le m_le;
|
||||
ht m_trie;
|
||||
vector<unsigned> m_found;
|
||||
bool m_init;
|
||||
checker m_checker;
|
||||
vector<numeral> m_keys;
|
||||
unsigned m_offset;
|
||||
|
||||
numeral const* get_keys(values const& vs) {
|
||||
return vs()-1;
|
||||
return vs()-m_offset;
|
||||
}
|
||||
|
||||
public:
|
||||
value_index2(hilbert_basis& hb): hb(hb), m_init(false) {
|
||||
value_index2(hilbert_basis& hb):
|
||||
hb(hb),
|
||||
m_le(hb),
|
||||
m_trie(m_le),
|
||||
m_offset(1) {
|
||||
m_checker.hb = &hb;
|
||||
}
|
||||
|
||||
void insert(offset_t idx, values const& vs) {
|
||||
init();
|
||||
m_trie.insert(get_keys(vs), idx.m_offset);
|
||||
}
|
||||
|
||||
|
@ -209,15 +211,13 @@ public:
|
|||
m_trie.remove(get_keys(vs));
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_trie.reset(hb.get_num_vars()+1);
|
||||
m_keys.resize(hb.get_num_vars()+1);
|
||||
void reset(unsigned offset) {
|
||||
m_offset = offset;
|
||||
m_trie.reset(hb.get_num_vars()+m_offset);
|
||||
}
|
||||
|
||||
bool find(offset_t idx, values const& vs, offset_t& found_idx) {
|
||||
init();
|
||||
bool find(offset_t idx, values const& vs) {
|
||||
m_checker.m_value = idx;
|
||||
m_checker.m_found = &found_idx;
|
||||
return m_trie.find_le(get_keys(vs), m_checker);
|
||||
}
|
||||
|
||||
|
@ -236,14 +236,6 @@ public:
|
|||
void display(std::ostream& out) const {
|
||||
// m_trie.display(out);
|
||||
}
|
||||
|
||||
private:
|
||||
void init() {
|
||||
if (!m_init) {
|
||||
reset();
|
||||
m_init = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -254,6 +246,7 @@ class hilbert_basis::index {
|
|||
|
||||
// typedef value_index1 value_index;
|
||||
typedef value_index2 value_index;
|
||||
// typedef value_index3 value_index;
|
||||
|
||||
struct stats {
|
||||
unsigned m_num_find;
|
||||
|
@ -271,9 +264,10 @@ class hilbert_basis::index {
|
|||
value_index m_pos;
|
||||
value_index m_zero;
|
||||
stats m_stats;
|
||||
unsigned m_num_ineqs;
|
||||
|
||||
public:
|
||||
index(hilbert_basis& hb): hb(hb), m_pos(hb), m_zero(hb) {}
|
||||
index(hilbert_basis& hb): hb(hb), m_pos(hb), m_zero(hb), m_num_ineqs(0) {}
|
||||
|
||||
void insert(offset_t idx, values const& vs) {
|
||||
++m_stats.m_num_insert;
|
||||
|
@ -287,6 +281,7 @@ public:
|
|||
value_index* map = 0;
|
||||
if (!m_neg.find(vs.weight(), map)) {
|
||||
map = alloc(value_index, hb);
|
||||
map->reset(m_num_ineqs);
|
||||
m_neg.insert(vs.weight(), map);
|
||||
}
|
||||
map->insert(idx, vs);
|
||||
|
@ -305,29 +300,30 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool find(offset_t idx, values const& vs, offset_t& found_idx) {
|
||||
bool find(offset_t idx, values const& vs) {
|
||||
++m_stats.m_num_find;
|
||||
if (vs.weight().is_pos()) {
|
||||
return m_pos.find(idx, vs, found_idx);
|
||||
return m_pos.find(idx, vs);
|
||||
}
|
||||
else if (vs.weight().is_zero()) {
|
||||
return m_zero.find(idx, vs, found_idx);
|
||||
return m_zero.find(idx, vs);
|
||||
}
|
||||
else {
|
||||
value_index* map;
|
||||
return
|
||||
m_neg.find(vs.weight(), map) &&
|
||||
map->find(idx, vs, found_idx);
|
||||
map->find(idx, vs);
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
void reset(unsigned num_ineqs) {
|
||||
value_map::iterator it = m_neg.begin(), end = m_neg.end();
|
||||
for (; it != end; ++it) {
|
||||
it->m_value->reset();
|
||||
dealloc(it->m_value);
|
||||
}
|
||||
m_pos.reset();
|
||||
m_zero.reset();
|
||||
m_pos.reset(num_ineqs);
|
||||
m_zero.reset(num_ineqs);
|
||||
m_num_ineqs = num_ineqs;
|
||||
m_neg.reset();
|
||||
}
|
||||
|
||||
|
@ -678,15 +674,25 @@ bool hilbert_basis::is_invalid_offset(offset_t offs) {
|
|||
|
||||
void hilbert_basis::reset() {
|
||||
m_ineqs.reset();
|
||||
m_basis.reset();
|
||||
m_iseq.reset();
|
||||
m_store.reset();
|
||||
m_basis.reset();
|
||||
m_free_list.reset();
|
||||
m_active.reset();
|
||||
m_passive->reset();
|
||||
m_passive2->reset();
|
||||
m_sos.reset();
|
||||
m_zero.reset();
|
||||
m_index->reset();
|
||||
m_cancel = false;
|
||||
m_active.reset();
|
||||
if (m_passive) {
|
||||
m_passive->reset();
|
||||
}
|
||||
if (m_passive2) {
|
||||
m_passive2->reset();
|
||||
}
|
||||
if (m_index) {
|
||||
m_index->reset(1);
|
||||
}
|
||||
m_ints.reset();
|
||||
m_current_ineq = 0;
|
||||
|
||||
}
|
||||
|
||||
void hilbert_basis::collect_statistics(statistics& st) const {
|
||||
|
@ -702,42 +708,46 @@ void hilbert_basis::reset_statistics() {
|
|||
m_index->reset_statistics();
|
||||
}
|
||||
|
||||
void hilbert_basis::add_ge(num_vector const& v, numeral const& b) {
|
||||
void hilbert_basis::add_ge(rational_vector const& v, rational const& b) {
|
||||
SASSERT(m_ineqs.empty() || v.size() + 1 == m_ineqs.back().size());
|
||||
num_vector w;
|
||||
w.push_back(-b);
|
||||
w.append(v);
|
||||
w.push_back(to_numeral(-b));
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
w.push_back(to_numeral(v[i]));
|
||||
}
|
||||
m_ineqs.push_back(w);
|
||||
m_iseq.push_back(false);
|
||||
}
|
||||
|
||||
void hilbert_basis::add_le(num_vector const& v, numeral const& b) {
|
||||
num_vector w(v);
|
||||
void hilbert_basis::add_le(rational_vector const& v, rational const& b) {
|
||||
rational_vector w(v);
|
||||
for (unsigned i = 0; i < w.size(); ++i) {
|
||||
w[i].neg();
|
||||
}
|
||||
add_ge(w, -b);
|
||||
}
|
||||
|
||||
void hilbert_basis::add_eq(num_vector const& v, numeral const& b) {
|
||||
void hilbert_basis::add_eq(rational_vector const& v, rational const& b) {
|
||||
SASSERT(m_ineqs.empty() || v.size() + 1 == m_ineqs.back().size());
|
||||
num_vector w;
|
||||
w.push_back(-b);
|
||||
w.append(v);
|
||||
w.push_back(to_numeral(-b));
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
w.push_back(to_numeral(v[i]));
|
||||
}
|
||||
m_ineqs.push_back(w);
|
||||
m_iseq.push_back(true);
|
||||
}
|
||||
|
||||
void hilbert_basis::add_ge(num_vector const& v) {
|
||||
add_ge(v, numeral(0));
|
||||
void hilbert_basis::add_ge(rational_vector const& v) {
|
||||
add_ge(v, rational(0));
|
||||
}
|
||||
|
||||
void hilbert_basis::add_le(num_vector const& v) {
|
||||
add_le(v, numeral(0));
|
||||
void hilbert_basis::add_le(rational_vector const& v) {
|
||||
add_le(v, rational(0));
|
||||
}
|
||||
|
||||
void hilbert_basis::add_eq(num_vector const& v) {
|
||||
add_eq(v, numeral(0));
|
||||
void hilbert_basis::add_eq(rational_vector const& v) {
|
||||
add_eq(v, rational(0));
|
||||
}
|
||||
|
||||
void hilbert_basis::set_is_int(unsigned var_index) {
|
||||
|
@ -799,7 +809,7 @@ lbool hilbert_basis::saturate() {
|
|||
stopwatch sw;
|
||||
sw.start();
|
||||
lbool r = saturate(m_ineqs[m_current_ineq], m_iseq[m_current_ineq]);
|
||||
IF_VERBOSE(1,
|
||||
IF_VERBOSE(3,
|
||||
{ statistics st;
|
||||
collect_statistics(st);
|
||||
st.display(verbose_stream());
|
||||
|
@ -823,7 +833,7 @@ lbool hilbert_basis::saturate_orig(num_vector const& ineq, bool is_eq) {
|
|||
m_active.reset();
|
||||
m_passive->reset();
|
||||
m_zero.reset();
|
||||
m_index->reset();
|
||||
m_index->reset(m_current_ineq+1);
|
||||
int_table support;
|
||||
TRACE("hilbert_basis", display_ineq(tout, ineq, is_eq););
|
||||
iterator it = begin();
|
||||
|
@ -895,7 +905,7 @@ bool hilbert_basis::vector_lt(offset_t idx1, offset_t idx2) const {
|
|||
|
||||
lbool hilbert_basis::saturate(num_vector const& ineq, bool is_eq) {
|
||||
m_zero.reset();
|
||||
m_index->reset();
|
||||
m_index->reset(m_current_ineq+1);
|
||||
m_passive2->reset();
|
||||
m_sos.reset();
|
||||
TRACE("hilbert_basis", display_ineq(tout, ineq, is_eq););
|
||||
|
@ -974,19 +984,21 @@ lbool hilbert_basis::saturate(num_vector const& ineq, bool is_eq) {
|
|||
return m_basis.empty()?l_false:l_true;
|
||||
}
|
||||
|
||||
void hilbert_basis::get_basis_solution(unsigned i, num_vector& v, bool& is_initial) {
|
||||
void hilbert_basis::get_basis_solution(unsigned i, rational_vector& v, bool& is_initial) {
|
||||
offset_t offs = m_basis[i];
|
||||
v.reset();
|
||||
for (unsigned i = 1; i < get_num_vars(); ++i) {
|
||||
v.push_back(vec(offs)[i]);
|
||||
v.push_back(to_rational(vec(offs)[i]));
|
||||
}
|
||||
is_initial = !vec(offs)[0].is_zero();
|
||||
}
|
||||
|
||||
void hilbert_basis::get_ge(unsigned i, num_vector& v, numeral& b, bool& is_eq) {
|
||||
void hilbert_basis::get_ge(unsigned i, rational_vector& v, rational& b, bool& is_eq) {
|
||||
v.reset();
|
||||
v.append(m_ineqs[i].size() - 1, m_ineqs[i].c_ptr() + 1);
|
||||
b = -m_ineqs[i][0];
|
||||
for (unsigned j = 1; j < m_ineqs[i].size(); ++j) {
|
||||
v.push_back(to_rational(m_ineqs[i][j]));
|
||||
}
|
||||
b = to_rational(-m_ineqs[i][0]);
|
||||
is_eq = m_iseq[i];
|
||||
}
|
||||
|
||||
|
@ -996,11 +1008,9 @@ void hilbert_basis::select_inequality() {
|
|||
unsigned best = m_current_ineq;
|
||||
unsigned non_zeros = get_num_nonzeros(m_ineqs[best]);
|
||||
unsigned prod = get_ineq_product(m_ineqs[best]);
|
||||
//numeral diff = get_ineq_diff(m_ineqs[best]);
|
||||
for (unsigned j = best+1; prod != 0 && j < m_ineqs.size(); ++j) {
|
||||
unsigned non_zeros2 = get_num_nonzeros(m_ineqs[j]);
|
||||
unsigned prod2 = get_ineq_product(m_ineqs[j]);
|
||||
//numeral diff2 = get_ineq_diff(m_ineqs[j]);
|
||||
if (prod2 == 0) {
|
||||
prod = prod2;
|
||||
non_zeros = non_zeros2;
|
||||
|
@ -1009,7 +1019,6 @@ void hilbert_basis::select_inequality() {
|
|||
}
|
||||
if (non_zeros2 < non_zeros || (non_zeros2 == non_zeros && prod2 < prod)) {
|
||||
prod = prod2;
|
||||
// diff = diff2;
|
||||
non_zeros = non_zeros2;
|
||||
best = j;
|
||||
}
|
||||
|
@ -1121,8 +1130,7 @@ bool hilbert_basis::add_goal(offset_t idx) {
|
|||
|
||||
bool hilbert_basis::is_subsumed(offset_t idx) {
|
||||
|
||||
offset_t found_idx;
|
||||
if (m_index->find(idx, vec(idx), found_idx)) {
|
||||
if (m_index->find(idx, vec(idx))) {
|
||||
++m_stats.m_num_subsumptions;
|
||||
return true;
|
||||
}
|
||||
|
@ -1316,7 +1324,7 @@ bool hilbert_basis::is_geq(values const& v, values const& w) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool hilbert_basis::is_abs_geq(numeral const& v, numeral const& w) {
|
||||
bool hilbert_basis::is_abs_geq(numeral const& v, numeral const& w) const {
|
||||
if (w.is_neg()) {
|
||||
return v <= w;
|
||||
}
|
|
@ -18,6 +18,11 @@ Author:
|
|||
|
||||
Revision History:
|
||||
|
||||
Hilbert basis can be templatized
|
||||
based on traits that define numeral:
|
||||
as rational, mpz, checked_int64
|
||||
(checked or unchecked).
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _HILBERT_BASIS_H_
|
||||
|
@ -26,14 +31,28 @@ Revision History:
|
|||
#include "rational.h"
|
||||
#include "lbool.h"
|
||||
#include "statistics.h"
|
||||
#include "checked_int64.h"
|
||||
|
||||
typedef vector<rational> rational_vector;
|
||||
|
||||
class hilbert_basis {
|
||||
public:
|
||||
typedef rational numeral;
|
||||
|
||||
static const bool check = true;
|
||||
typedef checked_int64<check> numeral;
|
||||
typedef vector<numeral> num_vector;
|
||||
private:
|
||||
static checked_int64<check> to_numeral(rational const& r) {
|
||||
if (!r.is_int64()) {
|
||||
throw checked_int64<check>::overflow_exception();
|
||||
}
|
||||
return checked_int64<check>(r.get_int64());
|
||||
}
|
||||
static rational to_rational(checked_int64<check> const& i) {
|
||||
return rational(i.get_int64(), rational::i64());
|
||||
}
|
||||
|
||||
class value_index1;
|
||||
class value_index2;
|
||||
class value_index3;
|
||||
class index;
|
||||
class passive;
|
||||
class passive2;
|
||||
|
@ -112,7 +131,7 @@ private:
|
|||
unsigned get_num_vars() const;
|
||||
numeral get_weight(values const & val, num_vector const& ineq) const;
|
||||
bool is_geq(values const& v, values const& w) const;
|
||||
static bool is_abs_geq(numeral const& v, numeral const& w);
|
||||
bool is_abs_geq(numeral const& v, numeral const& w) const;
|
||||
bool is_subsumed(offset_t idx);
|
||||
bool is_subsumed(offset_t i, offset_t j) const;
|
||||
void recycle(offset_t idx);
|
||||
|
@ -147,16 +166,16 @@ public:
|
|||
// add inequality v*x >= 0
|
||||
// add inequality v*x <= 0
|
||||
// add equality v*x = 0
|
||||
void add_ge(num_vector const& v);
|
||||
void add_le(num_vector const& v);
|
||||
void add_eq(num_vector const& v);
|
||||
void add_ge(rational_vector const& v);
|
||||
void add_le(rational_vector const& v);
|
||||
void add_eq(rational_vector const& v);
|
||||
|
||||
// add inequality v*x >= b
|
||||
// add inequality v*x <= b
|
||||
// add equality v*x = b
|
||||
void add_ge(num_vector const& v, numeral const& b);
|
||||
void add_le(num_vector const& v, numeral const& b);
|
||||
void add_eq(num_vector const& v, numeral const& b);
|
||||
void add_ge(rational_vector const& v, rational const& b);
|
||||
void add_le(rational_vector const& v, rational const& b);
|
||||
void add_eq(rational_vector const& v, rational const& b);
|
||||
|
||||
void set_is_int(unsigned var_index);
|
||||
bool get_is_int(unsigned var_index) const;
|
||||
|
@ -164,10 +183,10 @@ public:
|
|||
lbool saturate();
|
||||
|
||||
unsigned get_basis_size() const { return m_basis.size(); }
|
||||
void get_basis_solution(unsigned i, num_vector& v, bool& is_initial);
|
||||
void get_basis_solution(unsigned i, rational_vector& v, bool& is_initial);
|
||||
|
||||
unsigned get_num_ineqs() const { return m_ineqs.size(); }
|
||||
void get_ge(unsigned i, num_vector& v, numeral& b, bool& is_eq);
|
||||
void get_ge(unsigned i, rational_vector& v, rational& b, bool& is_eq);
|
||||
|
||||
void set_cancel(bool f) { m_cancel = f; }
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
Template for interval arithmetic. The template can be instantiated using different numeral (integers/mpz, rationals/mpq, floating-point/mpf, etc) packages.
|
||||
The class im_default_config defines a default configuration for the template that uses rationals. It also shows what is the expected signature used by the template.
|
||||
The class im_default_config defines a default configuration for the template that uses rationals. It also shows what is the expected signature used by the template.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue