mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 02:45:51 +00:00
Merge branch 'unstable' into contrib
This commit is contained in:
commit
f773f35517
177 changed files with 8165 additions and 2548 deletions
|
@ -61,6 +61,10 @@ Version 4.3.2
|
|||
|
||||
- Fixed bugs in the C++ API (Thanks to Andrey Kupriyanov).
|
||||
|
||||
- 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
|
||||
=============
|
||||
|
||||
|
|
|
@ -883,6 +883,29 @@ void incremental_example3() {
|
|||
std::cout << s.check(a2) << "\n";
|
||||
}
|
||||
|
||||
void enum_sort_example() {
|
||||
std::cout << "enumeration sort example\n";
|
||||
context ctx;
|
||||
const char * enum_names[] = { "a", "b", "c" };
|
||||
func_decl_vector enum_consts(ctx);
|
||||
func_decl_vector enum_testers(ctx);
|
||||
sort s = ctx.enumeration_sort("enumT", 3, enum_names, enum_consts, enum_testers);
|
||||
// enum_consts[0] is a func_decl of arity 0.
|
||||
// we convert it to an expression using the operator()
|
||||
expr a = enum_consts[0]();
|
||||
expr b = enum_consts[1]();
|
||||
expr x = ctx.constant("x", s);
|
||||
expr test = (x==a) && (x==b);
|
||||
std::cout << "1: " << test << std::endl;
|
||||
tactic qe(ctx, "ctx-solver-simplify");
|
||||
goal g(ctx);
|
||||
g.add(test);
|
||||
expr res(ctx);
|
||||
apply_result result_of_elimination = qe.apply(g);
|
||||
goal result_goal = result_of_elimination[0];
|
||||
std::cout << "2: " << result_goal.as_expr() << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
demorgan(); std::cout << "\n";
|
||||
|
@ -917,6 +940,7 @@ int main() {
|
|||
incremental_example1(); std::cout << "\n";
|
||||
incremental_example2(); std::cout << "\n";
|
||||
incremental_example3(); std::cout << "\n";
|
||||
enum_sort_example(); std::cout << "\n";
|
||||
std::cout << "done\n";
|
||||
}
|
||||
catch (exception & ex) {
|
||||
|
|
|
@ -197,7 +197,7 @@ class JavaExample
|
|||
TestFailedException
|
||||
{
|
||||
Solver s = ctx.mkSolver();
|
||||
s.assert_(f);
|
||||
s.add(f);
|
||||
if (s.check() != sat)
|
||||
throw new TestFailedException();
|
||||
if (sat == Status.SATISFIABLE)
|
||||
|
@ -213,7 +213,7 @@ class JavaExample
|
|||
System.out.println("\nTactical solver: " + s);
|
||||
|
||||
for (BoolExpr a : g.getFormulas())
|
||||
s.assert_(a);
|
||||
s.add(a);
|
||||
System.out.println("Solver: " + s);
|
||||
|
||||
if (s.check() != sat)
|
||||
|
@ -266,8 +266,8 @@ class JavaExample
|
|||
p.add("mbqi", useMBQI);
|
||||
s.setParameters(p);
|
||||
for (BoolExpr a : assumptions)
|
||||
s.assert_(a);
|
||||
s.assert_(ctx.mkNot(f));
|
||||
s.add(a);
|
||||
s.add(ctx.mkNot(f));
|
||||
Status q = s.check();
|
||||
|
||||
switch (q)
|
||||
|
@ -299,8 +299,8 @@ class JavaExample
|
|||
p.add("mbqi", useMBQI);
|
||||
s.setParameters(p);
|
||||
for (BoolExpr a : assumptions)
|
||||
s.assert_(a);
|
||||
s.assert_(ctx.mkNot(f));
|
||||
s.add(a);
|
||||
s.add(ctx.mkNot(f));
|
||||
Status q = s.check();
|
||||
|
||||
switch (q)
|
||||
|
@ -326,9 +326,9 @@ class JavaExample
|
|||
ArithExpr yr = (ArithExpr) ctx.mkConst(ctx.mkSymbol("y"),
|
||||
ctx.mkRealSort());
|
||||
Goal g4 = ctx.mkGoal(true, false, false);
|
||||
g4.assert_(ctx.mkGt(xr, ctx.mkReal(10, 1)));
|
||||
g4.assert_(ctx.mkEq(yr, ctx.mkAdd(xr, ctx.mkReal(1, 1))));
|
||||
g4.assert_(ctx.mkGt(yr, ctx.mkReal(1, 1)));
|
||||
g4.add(ctx.mkGt(xr, ctx.mkReal(10, 1)));
|
||||
g4.add(ctx.mkEq(yr, ctx.mkAdd(xr, ctx.mkReal(1, 1))));
|
||||
g4.add(ctx.mkGt(yr, ctx.mkReal(1, 1)));
|
||||
|
||||
ApplyResult ar = applyTactic(ctx, ctx.mkTactic("simplify"), g4);
|
||||
if (ar.getNumSubgoals() == 1
|
||||
|
@ -345,7 +345,7 @@ class JavaExample
|
|||
|
||||
Solver s = ctx.mkSolver();
|
||||
for (BoolExpr e : ar.getSubgoals()[0].getFormulas())
|
||||
s.assert_(e);
|
||||
s.add(e);
|
||||
Status q = s.check();
|
||||
System.out.println("Solver says: " + q);
|
||||
System.out.println("Model: \n" + s.getModel());
|
||||
|
@ -367,7 +367,7 @@ class JavaExample
|
|||
ctx.mkBitVecSort(32));
|
||||
ArrayExpr aex = (ArrayExpr) ctx.mkConst(ctx.mkSymbol("MyArray"), asort);
|
||||
Expr sel = ctx.mkSelect(aex, ctx.mkInt(0));
|
||||
g.assert_(ctx.mkEq(sel, ctx.mkBV(42, 32)));
|
||||
g.add(ctx.mkEq(sel, ctx.mkBV(42, 32)));
|
||||
Symbol xs = ctx.mkSymbol("x");
|
||||
IntExpr xc = (IntExpr) ctx.mkConst(xs, ctx.getIntSort());
|
||||
|
||||
|
@ -377,11 +377,11 @@ class JavaExample
|
|||
Expr[] fargs = { ctx.mkConst(xs, ctx.getIntSort()) };
|
||||
IntExpr fapp = (IntExpr) ctx.mkApp(fd, fargs);
|
||||
|
||||
g.assert_(ctx.mkEq(ctx.mkAdd(xc, fapp), ctx.mkInt(123)));
|
||||
g.add(ctx.mkEq(ctx.mkAdd(xc, fapp), ctx.mkInt(123)));
|
||||
|
||||
Solver s = ctx.mkSolver();
|
||||
for (BoolExpr a : g.getFormulas())
|
||||
s.assert_(a);
|
||||
s.add(a);
|
||||
System.out.println("Solver: " + s);
|
||||
|
||||
Status q = s.check();
|
||||
|
@ -574,8 +574,8 @@ class JavaExample
|
|||
ctx.mkEq(X[i][j], ctx.mkInt(instance[i][j]))));
|
||||
|
||||
Solver s = ctx.mkSolver();
|
||||
s.assert_(sudoku_c);
|
||||
s.assert_(instance_c);
|
||||
s.add(sudoku_c);
|
||||
s.add(instance_c);
|
||||
|
||||
if (s.check() == Status.SATISFIABLE)
|
||||
{
|
||||
|
@ -798,14 +798,14 @@ class JavaExample
|
|||
BoolExpr nontrivial_eq = ctx.mkEq(fapp, fapp2);
|
||||
|
||||
Goal g = ctx.mkGoal(true, false, false);
|
||||
g.assert_(trivial_eq);
|
||||
g.assert_(nontrivial_eq);
|
||||
g.add(trivial_eq);
|
||||
g.add(nontrivial_eq);
|
||||
System.out.println("Goal: " + g);
|
||||
|
||||
Solver solver = ctx.mkSolver();
|
||||
|
||||
for (BoolExpr a : g.getFormulas())
|
||||
solver.assert_(a);
|
||||
solver.add(a);
|
||||
|
||||
if (solver.check() != Status.SATISFIABLE)
|
||||
throw new TestFailedException();
|
||||
|
@ -820,7 +820,7 @@ class JavaExample
|
|||
if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedSat())
|
||||
throw new TestFailedException();
|
||||
|
||||
g.assert_(ctx.mkEq(ctx.mkNumeral(1, ctx.mkBitVecSort(32)),
|
||||
g.add(ctx.mkEq(ctx.mkNumeral(1, ctx.mkBitVecSort(32)),
|
||||
ctx.mkNumeral(2, ctx.mkBitVecSort(32))));
|
||||
ar = applyTactic(ctx, ctx.mkTactic("smt"), g);
|
||||
if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedUnsat())
|
||||
|
@ -832,7 +832,7 @@ class JavaExample
|
|||
throw new TestFailedException();
|
||||
|
||||
g2 = ctx.mkGoal(true, true, false);
|
||||
g2.assert_(ctx.mkFalse());
|
||||
g2.add(ctx.mkFalse());
|
||||
ar = applyTactic(ctx, ctx.mkTactic("smt"), g2);
|
||||
if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedUnsat())
|
||||
throw new TestFailedException();
|
||||
|
@ -840,10 +840,10 @@ class JavaExample
|
|||
Goal g3 = ctx.mkGoal(true, true, false);
|
||||
Expr xc = ctx.mkConst(ctx.mkSymbol("x"), ctx.getIntSort());
|
||||
Expr yc = ctx.mkConst(ctx.mkSymbol("y"), ctx.getIntSort());
|
||||
g3.assert_(ctx.mkEq(xc, ctx.mkNumeral(1, ctx.getIntSort())));
|
||||
g3.assert_(ctx.mkEq(yc, ctx.mkNumeral(2, ctx.getIntSort())));
|
||||
g3.add(ctx.mkEq(xc, ctx.mkNumeral(1, ctx.getIntSort())));
|
||||
g3.add(ctx.mkEq(yc, ctx.mkNumeral(2, ctx.getIntSort())));
|
||||
BoolExpr constr = ctx.mkEq(xc, yc);
|
||||
g3.assert_(constr);
|
||||
g3.add(constr);
|
||||
ar = applyTactic(ctx, ctx.mkTactic("smt"), g3);
|
||||
if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedUnsat())
|
||||
throw new TestFailedException();
|
||||
|
@ -1110,13 +1110,13 @@ class JavaExample
|
|||
|
||||
// Use a solver for QF_BV
|
||||
Solver s = ctx.mkSolver("QF_BV");
|
||||
s.assert_(eq);
|
||||
s.add(eq);
|
||||
Status res = s.check();
|
||||
System.out.println("solver result: " + res);
|
||||
|
||||
// Or perhaps a tactic for QF_BV
|
||||
Goal g = ctx.mkGoal(true, false, false);
|
||||
g.assert_(eq);
|
||||
g.add(eq);
|
||||
|
||||
Tactic t = ctx.mkTactic("qfbv");
|
||||
ApplyResult ar = t.apply(g);
|
||||
|
@ -1139,7 +1139,7 @@ class JavaExample
|
|||
BoolExpr q = ctx.mkEq(x, y);
|
||||
|
||||
Goal g = ctx.mkGoal(true, false, false);
|
||||
g.assert_(q);
|
||||
g.add(q);
|
||||
|
||||
Tactic t1 = ctx.mkTactic("qfbv");
|
||||
Tactic t2 = ctx.mkTactic("qfbv");
|
||||
|
@ -1341,7 +1341,7 @@ class JavaExample
|
|||
/* assert x >= "big number" */
|
||||
BoolExpr c1 = ctx.mkGe(x, big_number);
|
||||
System.out.println("assert: x >= 'big number'");
|
||||
solver.assert_(c1);
|
||||
solver.add(c1);
|
||||
|
||||
/* create a backtracking point */
|
||||
System.out.println("push");
|
||||
|
@ -1350,7 +1350,7 @@ class JavaExample
|
|||
/* assert x <= 3 */
|
||||
BoolExpr c2 = ctx.mkLe(x, three);
|
||||
System.out.println("assert: x <= 3");
|
||||
solver.assert_(c2);
|
||||
solver.add(c2);
|
||||
|
||||
/* context is inconsistent at this point */
|
||||
if (solver.check() != Status.UNSATISFIABLE)
|
||||
|
@ -1375,7 +1375,7 @@ class JavaExample
|
|||
/* assert y > x */
|
||||
BoolExpr c3 = ctx.mkGt(y, x);
|
||||
System.out.println("assert: y > x");
|
||||
solver.assert_(c3);
|
||||
solver.add(c3);
|
||||
|
||||
/* the context is still consistent. */
|
||||
if (solver.check() != Status.SATISFIABLE)
|
||||
|
@ -1911,10 +1911,10 @@ class JavaExample
|
|||
Solver solver = ctx.mkSolver();
|
||||
|
||||
/* assert x < y */
|
||||
solver.assert_(ctx.mkLt(x, y));
|
||||
solver.add(ctx.mkLt(x, y));
|
||||
|
||||
/* assert x > 2 */
|
||||
solver.assert_(ctx.mkGt(x, two));
|
||||
solver.add(ctx.mkGt(x, two));
|
||||
|
||||
/* find model for the constraints above */
|
||||
Model model = null;
|
||||
|
@ -1964,9 +1964,9 @@ class JavaExample
|
|||
Solver solver = ctx.mkSolver();
|
||||
|
||||
/* assert tup1 != tup2 */
|
||||
solver.assert_(ctx.mkNot(ctx.mkEq(tup1, tup2)));
|
||||
solver.add(ctx.mkNot(ctx.mkEq(tup1, tup2)));
|
||||
/* assert first tup1 = first tup2 */
|
||||
solver.assert_(ctx.mkEq(ctx.mkApp(first, tup1), ctx.mkApp(first, tup2)));
|
||||
solver.add(ctx.mkEq(ctx.mkApp(first, tup1), ctx.mkApp(first, tup2)));
|
||||
|
||||
/* find model for the constraints above */
|
||||
Model model = null;
|
||||
|
@ -2014,7 +2014,7 @@ class JavaExample
|
|||
// Assert all feasible bounds.
|
||||
for (int i = 0; i < num_Exprs; ++i)
|
||||
{
|
||||
solver.assert_(ctx.mkBVULE(to_minimize[i],
|
||||
solver.add(ctx.mkBVULE(to_minimize[i],
|
||||
ctx.mkBV(upper[i], 32)));
|
||||
}
|
||||
|
||||
|
@ -2050,7 +2050,7 @@ class JavaExample
|
|||
{
|
||||
last_upper = (upper[i] + lower[i]) / 2;
|
||||
last_index = i;
|
||||
solver.assert_(ctx.mkBVULE(to_minimize[i],
|
||||
solver.add(ctx.mkBVULE(to_minimize[i],
|
||||
ctx.mkBV(last_upper, 32)));
|
||||
some_work = true;
|
||||
break;
|
||||
|
@ -2074,7 +2074,7 @@ class JavaExample
|
|||
|
||||
Solver solver = ctx.mkSolver();
|
||||
|
||||
solver.assert_(ctx.mkBVULE(x, ctx.mkBVAdd(y, z)));
|
||||
solver.add(ctx.mkBVULE(x, ctx.mkBVAdd(y, z)));
|
||||
checkSmall(ctx, solver, x, y, z);
|
||||
}
|
||||
|
||||
|
@ -2120,10 +2120,10 @@ class JavaExample
|
|||
BoolExpr f3 = ctx.mkOr(ctx.mkNot(pa), ctx.mkNot(pc));
|
||||
BoolExpr f4 = pd;
|
||||
|
||||
solver.assert_(ctx.mkOr(f1, p1));
|
||||
solver.assert_(ctx.mkOr(f2, p2));
|
||||
solver.assert_(ctx.mkOr(f3, p3));
|
||||
solver.assert_(ctx.mkOr(f4, p4));
|
||||
solver.add(ctx.mkOr(f1, p1));
|
||||
solver.add(ctx.mkOr(f2, p2));
|
||||
solver.add(ctx.mkOr(f3, p3));
|
||||
solver.add(ctx.mkOr(f4, p4));
|
||||
Status result = solver.check(assumptions);
|
||||
|
||||
if (result == Status.UNSATISFIABLE)
|
||||
|
|
|
@ -30,12 +30,12 @@ CC=getenv("CC", None)
|
|||
CPPFLAGS=getenv("CPPFLAGS", "")
|
||||
CXXFLAGS=getenv("CXXFLAGS", "")
|
||||
LDFLAGS=getenv("LDFLAGS", "")
|
||||
JAVA=getenv("JAVA", "java")
|
||||
JAVAC=getenv("JAVAC", "javac")
|
||||
JAVA_HOME=getenv("JAVA_HOME", None)
|
||||
JNI_HOME=getenv("JNI_HOME", None)
|
||||
|
||||
CXX_COMPILERS=['g++', 'clang++']
|
||||
C_COMPILERS=['gcc', 'clang']
|
||||
JAVAC=None
|
||||
JAR=None
|
||||
PYTHON_PACKAGE_DIR=distutils.sysconfig.get_python_lib()
|
||||
BUILD_DIR='build'
|
||||
REV_BUILD_DIR='..'
|
||||
|
@ -206,23 +206,6 @@ def test_openmp(cc):
|
|||
t.commit()
|
||||
return exec_compiler_cmd([cc, CPPFLAGS, 'tstomp.cpp', LDFLAGS, '-fopenmp']) == 0
|
||||
|
||||
def check_java():
|
||||
t = TempFile('Hello.java')
|
||||
t.add('public class Hello { public static void main(String[] args) { System.out.println("Hello, World"); }}\n')
|
||||
t.commit()
|
||||
if is_verbose():
|
||||
print("Testing %s..." % JAVAC)
|
||||
r = exec_cmd([JAVAC, 'Hello.java'])
|
||||
if r != 0:
|
||||
raise MKException('Failed testing Java compiler. Set environment variable JAVAC with the path to the Java compiler')
|
||||
if is_verbose():
|
||||
print("Testing %s..." % JAVA)
|
||||
r = exec_cmd([JAVA, 'Hello'])
|
||||
rmf('Hello.class')
|
||||
if r != 0:
|
||||
raise MKException('Failed testing Java program. Set environment variable JAVA with the path to the Java virtual machine')
|
||||
find_java_home()
|
||||
|
||||
def find_jni_h(path):
|
||||
for root, dirs, files in os.walk(path):
|
||||
for f in files:
|
||||
|
@ -230,41 +213,110 @@ def find_jni_h(path):
|
|||
return root
|
||||
return False
|
||||
|
||||
def find_java_home():
|
||||
global JAVA_HOME
|
||||
if JAVA_HOME != None:
|
||||
if is_verbose():
|
||||
print("Checking jni.h...")
|
||||
if os.path.exists(os.path.join(JAVA_HOME, 'include', 'jni.h')):
|
||||
return
|
||||
def check_java():
|
||||
global JNI_HOME
|
||||
global JAVAC
|
||||
global JAR
|
||||
|
||||
JDK_HOME = getenv('JDK_HOME', None) # we only need to check this locally.
|
||||
|
||||
if is_verbose():
|
||||
print("Finding JAVA_HOME...")
|
||||
t = TempFile('output')
|
||||
null = open(os.devnull, 'wb')
|
||||
print("Finding javac ...")
|
||||
|
||||
if JDK_HOME != None:
|
||||
if IS_WINDOWS:
|
||||
JAVAC = os.path.join(JDK_HOME, 'bin', 'javac.exe')
|
||||
else:
|
||||
JAVAC = os.path.join(JDK_HOME, 'bin', 'javac')
|
||||
|
||||
if not os.path.exists(JAVAC):
|
||||
raise MKException("Failed to detect javac at '%s/bin'; the environment variable JDK_HOME is probably set to the wrong path." % os.path.join(JDK_HOME))
|
||||
else:
|
||||
# Search for javac in the path.
|
||||
ind = 'javac';
|
||||
if IS_WINDOWS:
|
||||
ind = ind + '.exe'
|
||||
paths = os.getenv('PATH', None)
|
||||
if paths:
|
||||
spaths = paths.split(os.pathsep)
|
||||
for i in range(0, len(spaths)):
|
||||
cmb = os.path.join(spaths[i], ind)
|
||||
if os.path.exists(cmb):
|
||||
JAVAC = cmb
|
||||
break
|
||||
|
||||
if JAVAC == None:
|
||||
raise MKException('No java compiler in the path, please adjust your PATH or set JDK_HOME to the location of the JDK.')
|
||||
|
||||
if is_verbose():
|
||||
print("Finding jar ...")
|
||||
|
||||
if IS_WINDOWS:
|
||||
JAR = os.path.join(os.path.dirname(JAVAC), 'jar.exe')
|
||||
else:
|
||||
JAR = os.path.join(os.path.dirname(JAVAC), 'jar')
|
||||
|
||||
if not os.path.exists(JAR):
|
||||
raise MKException("Failed to detect jar at '%s'; the environment variable JDK_HOME is probably set to the wrong path." % os.path.join(JDK_HOME))
|
||||
|
||||
if is_verbose():
|
||||
print("Testing %s..." % JAVAC)
|
||||
|
||||
t = TempFile('Hello.java')
|
||||
t.add('public class Hello { public static void main(String[] args) { System.out.println("Hello, World"); }}\n')
|
||||
t.commit()
|
||||
|
||||
oo = TempFile('output')
|
||||
eo = TempFile('errout')
|
||||
try:
|
||||
subprocess.call([JAVA, '-verbose'], stdout=t.fname, stderr=null)
|
||||
t.commit()
|
||||
subprocess.call([JAVAC, 'Hello.java', '-verbose'], stdout=oo.fname, stderr=eo.fname)
|
||||
oo.commit()
|
||||
eo.commit()
|
||||
except:
|
||||
raise MKException('Failed to find JAVA_HOME')
|
||||
open_pat = re.compile("\[Opened (.*)\]")
|
||||
t = open('output', 'r')
|
||||
for line in t:
|
||||
m = open_pat.match(line)
|
||||
if m:
|
||||
# Remove last 3 directives from m.group(1)
|
||||
print(m.group(1))
|
||||
tmp = m.group(1).split(os.sep)
|
||||
path = string.join(tmp[:len(tmp) - 3], os.sep)
|
||||
if is_verbose():
|
||||
print("Checking jni.h...")
|
||||
jni_dir = find_jni_h(path)
|
||||
if not jni_dir:
|
||||
raise MKException("Failed to detect jni.h at '%s'.Possible solution: set JAVA_HOME with the path to JDK." % os.path.join(path, 'include'))
|
||||
JAVA_HOME = os.path.split(jni_dir)[0]
|
||||
if is_verbose():
|
||||
print('JAVA_HOME=%s' % JAVA_HOME)
|
||||
return
|
||||
raise MKException('Failed to find JAVA_HOME')
|
||||
raise MKException('Found, but failed to run Java compiler at %s' % (JAVAC))
|
||||
|
||||
os.remove('Hello.class')
|
||||
|
||||
if is_verbose():
|
||||
print("Finding jni.h...")
|
||||
|
||||
if JNI_HOME != None:
|
||||
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...
|
||||
t = open('errout', 'r')
|
||||
open_pat = re.compile("\[search path for class files: (.*)\]")
|
||||
cdirs = []
|
||||
for line in t:
|
||||
m = open_pat.match(line)
|
||||
if m:
|
||||
libdirs = m.group(1).split(',')
|
||||
for libdir in libdirs:
|
||||
q = os.path.dirname(libdir)
|
||||
if cdirs.count(q) == 0:
|
||||
cdirs.append(q)
|
||||
|
||||
# ... plus some heuristic ones.
|
||||
extra_dirs = []
|
||||
|
||||
# For the libraries, even the JDK usually uses a JRE that comes with it. To find the
|
||||
# headers we have to go a little bit higher up.
|
||||
for dir in cdirs:
|
||||
extra_dirs.append(os.path.abspath(os.path.join(dir, '..')))
|
||||
|
||||
if IS_OSX: # Apparently Apple knows best where to put stuff...
|
||||
extra_dirs.append('/System/Library/Frameworks/JavaVM.framework/Headers/')
|
||||
|
||||
cdirs[len(cdirs):] = extra_dirs
|
||||
|
||||
for dir in cdirs:
|
||||
q = find_jni_h(dir)
|
||||
if q != False:
|
||||
JNI_HOME = q
|
||||
|
||||
if JNI_HOME == None:
|
||||
raise MKException("Failed to detect jni.h. Possible solution: set JNI_HOME with the path to JDK.")
|
||||
|
||||
def is64():
|
||||
return sys.maxsize >= 2**32
|
||||
|
@ -399,9 +451,8 @@ def display_help(exit_code):
|
|||
print(" LDFLAGS Linker flags, e.g., -L<lib dir> if you have libraries in a non-standard directory")
|
||||
print(" CPPFLAGS Preprocessor flags, e.g., -I<include dir> if you have header files in a non-standard directory")
|
||||
print(" CXXFLAGS C++ compiler flags")
|
||||
print(" JAVA Java virtual machine (only relevant if -j or --java option is provided)")
|
||||
print(" JAVAC Java compiler (only relevant if -j or --java option is provided)")
|
||||
print(" JAVA_HOME JDK installation directory (only relevant if -j or --java option is provided)")
|
||||
print(" JDK_HOME JDK installation directory (only relevant if -j or --java option is provided)")
|
||||
print(" JNI_HOME JNI bindings directory (only relevant if -j or --java option is provided)")
|
||||
exit(exit_code)
|
||||
|
||||
# Parse configuration option for mk_make script
|
||||
|
@ -1082,11 +1133,14 @@ class JavaDLLComponent(Component):
|
|||
self.manifest_file = manifest_file
|
||||
|
||||
def mk_makefile(self, out):
|
||||
global JAVAC
|
||||
global JAR
|
||||
|
||||
if is_java_enabled():
|
||||
mk_dir(os.path.join(BUILD_DIR, 'api', 'java', 'classes'))
|
||||
dllfile = '%s$(SO_EXT)' % self.dll_name
|
||||
out.write('libz3java$(SO_EXT): libz3$(SO_EXT) %s\n' % os.path.join(self.to_src_dir, 'Native.cpp'))
|
||||
t = '\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/java/Native$(OBJ_EXT) -I"%s/include" -I"%s/include/PLATFORM" -I%s %s/Native.cpp\n' % (JAVA_HOME, JAVA_HOME, get_component('api').to_src_dir, self.to_src_dir)
|
||||
t = '\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/java/Native$(OBJ_EXT) -I"%s" -I"%s/PLATFORM" -I%s %s/Native.cpp\n' % (JNI_HOME, JNI_HOME, get_component('api').to_src_dir, self.to_src_dir)
|
||||
if IS_OSX:
|
||||
t = t.replace('PLATFORM', 'darwin')
|
||||
elif IS_LINUX:
|
||||
|
@ -1108,6 +1162,9 @@ class JavaDLLComponent(Component):
|
|||
deps += '%s ' % os.path.join(self.to_src_dir, 'enumerations', jfile)
|
||||
out.write(deps)
|
||||
out.write('\n')
|
||||
if IS_WINDOWS:
|
||||
JAVAC = '"%s"' % JAVAC
|
||||
JAR = '"%s"' % JAR
|
||||
t = ('\t%s %s.java -d %s\n' % (JAVAC, os.path.join(self.to_src_dir, 'enumerations', '*'), os.path.join('api', 'java', 'classes')))
|
||||
out.write(t)
|
||||
t = ('\t%s -cp %s %s.java -d %s\n' % (JAVAC,
|
||||
|
@ -1115,7 +1172,7 @@ class JavaDLLComponent(Component):
|
|||
os.path.join(self.to_src_dir, '*'),
|
||||
os.path.join('api', 'java', 'classes')))
|
||||
out.write(t)
|
||||
out.write('\tjar cfm %s.jar %s -C %s .\n' % (self.package_name,
|
||||
out.write('\t%s cfm %s.jar %s -C %s .\n' % (JAR, self.package_name,
|
||||
os.path.join(self.to_src_dir, 'manifest'),
|
||||
os.path.join('api', 'java', 'classes')))
|
||||
out.write('java: %s.jar\n\n' % self.package_name)
|
||||
|
@ -1387,9 +1444,8 @@ def mk_config():
|
|||
if is_verbose():
|
||||
print('64-bit: %s' % is64())
|
||||
if is_java_enabled():
|
||||
print('Java Home: %s' % JAVA_HOME)
|
||||
print('JNI Bindings: %s' % JNI_HOME)
|
||||
print('Java Compiler: %s' % JAVAC)
|
||||
print('Java VM: %s' % JAVA)
|
||||
else:
|
||||
global CXX, CC, GMP, CPPFLAGS, CXXFLAGS, LDFLAGS
|
||||
ARITH = "internal"
|
||||
|
@ -1491,9 +1547,8 @@ def mk_config():
|
|||
print('gprof: enabled')
|
||||
print('Python version: %s' % distutils.sysconfig.get_python_version())
|
||||
if is_java_enabled():
|
||||
print('Java Home: %s' % JAVA_HOME)
|
||||
print('JNI Bindings: %s' % JNI_HOME)
|
||||
print('Java Compiler: %s' % JAVAC)
|
||||
print('Java VM: %s' % JAVA)
|
||||
|
||||
def mk_install(out):
|
||||
out.write('install:\n')
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -681,7 +681,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);
|
||||
|
|
|
@ -266,7 +266,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 +291,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 +358,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 +415,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace z3 {
|
|||
class statistics;
|
||||
class apply_result;
|
||||
class fixedpoint;
|
||||
template<typename T> class ast_vector_tpl;
|
||||
typedef ast_vector_tpl<ast> ast_vector;
|
||||
typedef ast_vector_tpl<expr> expr_vector;
|
||||
typedef ast_vector_tpl<sort> sort_vector;
|
||||
typedef ast_vector_tpl<func_decl> func_decl_vector;
|
||||
|
||||
inline void set_param(char const * param, char const * value) { Z3_global_param_set(param, value); }
|
||||
inline void set_param(char const * param, bool value) { Z3_global_param_set(param, value ? "true" : "false"); }
|
||||
|
@ -190,7 +195,13 @@ namespace z3 {
|
|||
Example: Given a context \c c, <tt>c.array_sort(c.int_sort(), c.bool_sort())</tt> is an array sort from integer to Boolean.
|
||||
*/
|
||||
sort array_sort(sort d, sort r);
|
||||
|
||||
/**
|
||||
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
|
||||
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
|
||||
and in \c ts the predicates for testing if terms of the enumeration sort correspond to an enumeration.
|
||||
*/
|
||||
sort enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts);
|
||||
|
||||
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(char const * name, sort const & domain, sort const & range);
|
||||
|
@ -240,8 +251,8 @@ namespace z3 {
|
|||
array(unsigned sz):m_size(sz) { m_array = new T[sz]; }
|
||||
~array() { delete[] m_array; }
|
||||
unsigned size() const { return m_size; }
|
||||
T & operator[](unsigned i) { assert(i < m_size); return m_array[i]; }
|
||||
T const & operator[](unsigned i) const { assert(i < m_size); return m_array[i]; }
|
||||
T & operator[](int i) { assert(0 <= i); assert(static_cast<unsigned>(i) < m_size); return m_array[i]; }
|
||||
T const & operator[](int i) const { assert(0 <= i); assert(static_cast<unsigned>(i) < m_size); return m_array[i]; }
|
||||
T const * ptr() const { return m_array; }
|
||||
T * ptr() { return m_array; }
|
||||
};
|
||||
|
@ -414,6 +425,7 @@ namespace z3 {
|
|||
|
||||
bool is_const() const { return arity() == 0; }
|
||||
|
||||
expr operator()() const;
|
||||
expr operator()(unsigned n, expr const * args) const;
|
||||
expr operator()(expr const & a) const;
|
||||
expr operator()(int a) const;
|
||||
|
@ -1004,7 +1016,7 @@ namespace z3 {
|
|||
~ast_vector_tpl() { Z3_ast_vector_dec_ref(ctx(), m_vector); }
|
||||
operator Z3_ast_vector() const { return m_vector; }
|
||||
unsigned size() const { return Z3_ast_vector_size(ctx(), m_vector); }
|
||||
T operator[](unsigned i) const { Z3_ast r = Z3_ast_vector_get(ctx(), m_vector, i); check_error(); return cast_ast<T>()(ctx(), r); }
|
||||
T operator[](int i) const { assert(0 <= i); Z3_ast r = Z3_ast_vector_get(ctx(), m_vector, i); check_error(); return cast_ast<T>()(ctx(), r); }
|
||||
void push_back(T const & e) { Z3_ast_vector_push(ctx(), m_vector, e); check_error(); }
|
||||
void resize(unsigned sz) { Z3_ast_vector_resize(ctx(), m_vector, sz); check_error(); }
|
||||
T back() const { return operator[](size() - 1); }
|
||||
|
@ -1020,11 +1032,6 @@ 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; }
|
||||
};
|
||||
|
||||
typedef ast_vector_tpl<ast> ast_vector;
|
||||
typedef ast_vector_tpl<expr> expr_vector;
|
||||
typedef ast_vector_tpl<sort> sort_vector;
|
||||
typedef ast_vector_tpl<func_decl> func_decl_vector;
|
||||
|
||||
class func_entry : public object {
|
||||
Z3_func_entry m_entry;
|
||||
void init(Z3_func_entry e) {
|
||||
|
@ -1105,7 +1112,10 @@ namespace z3 {
|
|||
func_decl get_const_decl(unsigned i) const { Z3_func_decl r = Z3_model_get_const_decl(ctx(), m_model, i); check_error(); return func_decl(ctx(), r); }
|
||||
func_decl get_func_decl(unsigned i) const { Z3_func_decl r = Z3_model_get_func_decl(ctx(), m_model, i); check_error(); return func_decl(ctx(), r); }
|
||||
unsigned size() const { return num_consts() + num_funcs(); }
|
||||
func_decl operator[](unsigned i) const { return i < num_consts() ? get_const_decl(i) : get_func_decl(i - num_consts()); }
|
||||
func_decl operator[](int i) const {
|
||||
assert(0 <= i);
|
||||
return static_cast<unsigned>(i) < num_consts() ? get_const_decl(i) : get_func_decl(i - num_consts());
|
||||
}
|
||||
|
||||
expr get_const_interp(func_decl c) const {
|
||||
check_context(*this, c);
|
||||
|
@ -1253,7 +1263,7 @@ namespace z3 {
|
|||
}
|
||||
void add(expr const & f) { check_context(*this, f); Z3_goal_assert(ctx(), m_goal, f); check_error(); }
|
||||
unsigned size() const { return Z3_goal_size(ctx(), m_goal); }
|
||||
expr operator[](unsigned i) const { Z3_ast r = Z3_goal_formula(ctx(), m_goal, i); check_error(); return expr(ctx(), r); }
|
||||
expr operator[](int i) const { assert(0 <= i); Z3_ast r = Z3_goal_formula(ctx(), m_goal, i); check_error(); return expr(ctx(), r); }
|
||||
Z3_goal_prec precision() const { return Z3_goal_precision(ctx(), m_goal); }
|
||||
bool inconsistent() const { return Z3_goal_inconsistent(ctx(), m_goal) != 0; }
|
||||
unsigned depth() const { return Z3_goal_depth(ctx(), m_goal); }
|
||||
|
@ -1261,6 +1271,19 @@ namespace z3 {
|
|||
unsigned num_exprs() const { return Z3_goal_num_exprs(ctx(), m_goal); }
|
||||
bool is_decided_sat() const { return Z3_goal_is_decided_sat(ctx(), m_goal) != 0; }
|
||||
bool is_decided_unsat() const { return Z3_goal_is_decided_unsat(ctx(), m_goal) != 0; }
|
||||
expr as_expr() const {
|
||||
unsigned n = size();
|
||||
if (n == 0)
|
||||
return ctx().bool_val(false);
|
||||
else if (n == 1)
|
||||
return operator[](0);
|
||||
else {
|
||||
array<Z3_ast> args(n);
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
args[i] = operator[](i);
|
||||
return expr(ctx(), Z3_mk_and(ctx(), n, args.ptr()));
|
||||
}
|
||||
}
|
||||
friend std::ostream & operator<<(std::ostream & out, goal const & g) { out << Z3_goal_to_string(g.ctx(), g); return out; }
|
||||
};
|
||||
|
||||
|
@ -1283,8 +1306,7 @@ namespace z3 {
|
|||
return *this;
|
||||
}
|
||||
unsigned size() const { return Z3_apply_result_get_num_subgoals(ctx(), m_apply_result); }
|
||||
goal operator[](unsigned i) const { Z3_goal r = Z3_apply_result_get_subgoal(ctx(), m_apply_result, i); check_error(); return goal(ctx(), r); }
|
||||
goal operator[](int i) const { assert(i >= 0); return this->operator[](static_cast<unsigned>(i)); }
|
||||
goal operator[](int i) const { assert(0 <= i); Z3_goal r = Z3_apply_result_get_subgoal(ctx(), m_apply_result, i); check_error(); return goal(ctx(), r); }
|
||||
model convert_model(model const & m, unsigned i = 0) const {
|
||||
check_context(*this, m);
|
||||
Z3_model new_m = Z3_apply_result_convert_model(ctx(), m_apply_result, i, m);
|
||||
|
@ -1437,6 +1459,17 @@ namespace z3 {
|
|||
inline sort context::real_sort() { Z3_sort s = Z3_mk_real_sort(m_ctx); check_error(); return sort(*this, s); }
|
||||
inline sort context::bv_sort(unsigned sz) { Z3_sort s = Z3_mk_bv_sort(m_ctx, sz); check_error(); return sort(*this, s); }
|
||||
inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
|
||||
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
|
||||
array<Z3_symbol> _enum_names(n);
|
||||
for (unsigned i = 0; i < n; i++) { _enum_names[i] = Z3_mk_string_symbol(*this, enum_names[i]); }
|
||||
array<Z3_func_decl> _cs(n);
|
||||
array<Z3_func_decl> _ts(n);
|
||||
Z3_symbol _name = Z3_mk_string_symbol(*this, name);
|
||||
sort s = to_sort(*this, Z3_mk_enumeration_sort(*this, _name, n, _enum_names.ptr(), _cs.ptr(), _ts.ptr()));
|
||||
check_error();
|
||||
for (unsigned i = 0; i < n; i++) { cs.push_back(func_decl(*this, _cs[i])); ts.push_back(func_decl(*this, _ts[i])); }
|
||||
return s;
|
||||
}
|
||||
|
||||
inline func_decl context::function(symbol const & name, unsigned arity, sort const * domain, sort const & range) {
|
||||
array<Z3_sort> args(arity);
|
||||
|
@ -1538,6 +1571,11 @@ namespace z3 {
|
|||
return expr(ctx(), r);
|
||||
|
||||
}
|
||||
inline expr func_decl::operator()() const {
|
||||
Z3_ast r = Z3_mk_app(ctx(), *this, 0, 0);
|
||||
ctx().check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
inline expr func_decl::operator()(expr const & a) const {
|
||||
check_context(*this, a);
|
||||
Z3_ast args[1] = { a };
|
||||
|
|
|
@ -34,8 +34,7 @@ namespace Microsoft.Z3
|
|||
public uint NumFields
|
||||
{
|
||||
get
|
||||
{
|
||||
init();
|
||||
{
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
@ -48,8 +47,11 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
init();
|
||||
return m_constructorDecl;
|
||||
IntPtr constructor = IntPtr.Zero;
|
||||
IntPtr tester = IntPtr.Zero;
|
||||
IntPtr[] accessors = new IntPtr[n];
|
||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
||||
return new FuncDecl(Context, constructor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,8 +63,11 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
init();
|
||||
return m_testerDecl;
|
||||
IntPtr constructor = IntPtr.Zero;
|
||||
IntPtr tester = IntPtr.Zero;
|
||||
IntPtr[] accessors = new IntPtr[n];
|
||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
||||
return new FuncDecl(Context, tester);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,8 +79,14 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl[]>() != null);
|
||||
init();
|
||||
return m_accessorDecls;
|
||||
IntPtr constructor = IntPtr.Zero;
|
||||
IntPtr tester = IntPtr.Zero;
|
||||
IntPtr[] accessors = new IntPtr[n];
|
||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
||||
FuncDecl[] t = new FuncDecl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
t[i] = new FuncDecl(Context, accessors[i]);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,25 +96,11 @@ namespace Microsoft.Z3
|
|||
~Constructor()
|
||||
{
|
||||
Native.Z3_del_constructor(Context.nCtx, NativeObject);
|
||||
}
|
||||
|
||||
#region Object invariant
|
||||
|
||||
[ContractInvariantMethod]
|
||||
private void ObjectInvariant()
|
||||
{
|
||||
Contract.Invariant(m_testerDecl == null || m_constructorDecl != null);
|
||||
Contract.Invariant(m_testerDecl == null || m_accessorDecls != null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Internal
|
||||
readonly private uint n = 0;
|
||||
private FuncDecl m_testerDecl = null;
|
||||
private FuncDecl m_constructorDecl = null;
|
||||
private FuncDecl[] m_accessorDecls = null;
|
||||
|
||||
private uint n = 0;
|
||||
|
||||
internal Constructor(Context ctx, Symbol name, Symbol recognizer, Symbol[] fieldNames,
|
||||
Sort[] sorts, uint[] sortRefs)
|
||||
: base(ctx)
|
||||
|
@ -129,24 +126,6 @@ namespace Microsoft.Z3
|
|||
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
Contract.Ensures(m_constructorDecl != null);
|
||||
Contract.Ensures(m_testerDecl != null);
|
||||
Contract.Ensures(m_accessorDecls != null);
|
||||
|
||||
if (m_testerDecl != null) return;
|
||||
IntPtr constructor = IntPtr.Zero;
|
||||
IntPtr tester = IntPtr.Zero;
|
||||
IntPtr[] accessors = new IntPtr[n];
|
||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
||||
m_constructorDecl = new FuncDecl(Context, constructor);
|
||||
m_testerDecl = new FuncDecl(Context, tester);
|
||||
m_accessorDecls = new FuncDecl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
m_accessorDecls[i] = new FuncDecl(Context, accessors[i]);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,11 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl[]>() != null);
|
||||
|
||||
return _constdecls;
|
||||
uint n = Native.Z3_get_datatype_sort_num_constructors(Context.nCtx, NativeObject);
|
||||
FuncDecl[] t = new FuncDecl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
t[i] = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i));
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,8 +52,11 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Expr[]>() != null);
|
||||
|
||||
return _consts;
|
||||
FuncDecl[] cds = ConstDecls;
|
||||
Expr[] t = new Expr[cds.Length];
|
||||
for (uint i = 0; i < t.Length; i++)
|
||||
t[i] = Context.MkApp(cds[i]);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,28 +68,15 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl[]>() != null);
|
||||
|
||||
return _testerdecls;
|
||||
uint n = Native.Z3_get_datatype_sort_num_constructors(Context.nCtx, NativeObject);
|
||||
FuncDecl[] t = new FuncDecl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
t[i] = new FuncDecl(Context, Native.Z3_get_datatype_sort_recognizer(Context.nCtx, NativeObject, i));
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
#region Object Invariant
|
||||
|
||||
[ContractInvariantMethod]
|
||||
private void ObjectInvariant()
|
||||
{
|
||||
Contract.Invariant(this._constdecls != null);
|
||||
Contract.Invariant(this._testerdecls != null);
|
||||
Contract.Invariant(this._consts != null);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal
|
||||
readonly private FuncDecl[] _constdecls = null, _testerdecls = null;
|
||||
readonly private Expr[] _consts = null;
|
||||
|
||||
internal EnumSort(Context ctx, Symbol name, Symbol[] enumNames)
|
||||
: base(ctx)
|
||||
{
|
||||
|
@ -96,15 +89,6 @@ namespace Microsoft.Z3
|
|||
IntPtr[] n_testers = new IntPtr[n];
|
||||
NativeObject = Native.Z3_mk_enumeration_sort(ctx.nCtx, name.NativeObject, (uint)n,
|
||||
Symbol.ArrayToNative(enumNames), n_constdecls, n_testers);
|
||||
_constdecls = new FuncDecl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
_constdecls[i] = new FuncDecl(ctx, n_constdecls[i]);
|
||||
_testerdecls = new FuncDecl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
_testerdecls[i] = new FuncDecl(ctx, n_testers[i]);
|
||||
_consts = new Expr[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
_consts[i] = ctx.MkApp(_constdecls[i]);
|
||||
}
|
||||
#endregion
|
||||
};
|
||||
|
|
|
@ -78,6 +78,14 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alias for Assert.
|
||||
/// </summary>
|
||||
public void Add(params BoolExpr[] constraints)
|
||||
{
|
||||
Assert(constraints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register predicate as recursive relation.
|
||||
/// </summary>
|
||||
|
|
|
@ -90,6 +90,14 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alias for Assert.
|
||||
/// </summary>
|
||||
public void Add(params BoolExpr[] constraints)
|
||||
{
|
||||
Assert(constraints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the goal contains `false'.
|
||||
/// </summary>
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
return nilDecl;
|
||||
return new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<Expr>() != null);
|
||||
return nilConst;
|
||||
return Context.MkApp(NilDecl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
return isNilDecl;
|
||||
return new FuncDecl(Context, Native.Z3_get_datatype_sort_recognizer(Context.nCtx, NativeObject, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
return consDecl;
|
||||
return new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
return isConsDecl;
|
||||
return new FuncDecl(Context, Native.Z3_get_datatype_sort_recognizer(Context.nCtx, NativeObject, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
return headDecl;
|
||||
return new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor_accessor(Context.nCtx, NativeObject, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,31 +109,11 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
Contract.Ensures(Contract.Result<FuncDecl>() != null);
|
||||
return tailDecl;
|
||||
return new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor_accessor(Context.nCtx, NativeObject, 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
#region Object Invariant
|
||||
|
||||
[ContractInvariantMethod]
|
||||
private void ObjectInvariant()
|
||||
{
|
||||
Contract.Invariant(nilConst != null);
|
||||
Contract.Invariant(nilDecl != null);
|
||||
Contract.Invariant(isNilDecl != null);
|
||||
Contract.Invariant(consDecl != null);
|
||||
Contract.Invariant(isConsDecl != null);
|
||||
Contract.Invariant(headDecl != null);
|
||||
Contract.Invariant(tailDecl != null);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal
|
||||
readonly private FuncDecl nilDecl, isNilDecl, consDecl, isConsDecl, headDecl, tailDecl;
|
||||
readonly private Expr nilConst;
|
||||
|
||||
#region Internal
|
||||
internal ListSort(Context ctx, Symbol name, Sort elemSort)
|
||||
: base(ctx)
|
||||
{
|
||||
|
@ -141,22 +121,12 @@ namespace Microsoft.Z3
|
|||
Contract.Requires(name != null);
|
||||
Contract.Requires(elemSort != null);
|
||||
|
||||
IntPtr inil = IntPtr.Zero,
|
||||
iisnil = IntPtr.Zero,
|
||||
icons = IntPtr.Zero,
|
||||
iiscons = IntPtr.Zero,
|
||||
ihead = IntPtr.Zero,
|
||||
itail = IntPtr.Zero;
|
||||
IntPtr inil = IntPtr.Zero, iisnil = IntPtr.Zero,
|
||||
icons = IntPtr.Zero, iiscons = IntPtr.Zero,
|
||||
ihead = IntPtr.Zero, itail = IntPtr.Zero;
|
||||
|
||||
NativeObject = Native.Z3_mk_list_sort(ctx.nCtx, name.NativeObject, elemSort.NativeObject,
|
||||
ref inil, ref iisnil, ref icons, ref iiscons, ref ihead, ref itail);
|
||||
nilDecl = new FuncDecl(ctx, inil);
|
||||
isNilDecl = new FuncDecl(ctx, iisnil);
|
||||
consDecl = new FuncDecl(ctx, icons);
|
||||
isConsDecl = new FuncDecl(ctx, iiscons);
|
||||
headDecl = new FuncDecl(ctx, ihead);
|
||||
tailDecl = new FuncDecl(ctx, itail);
|
||||
nilConst = ctx.MkConst(nilDecl);
|
||||
ref inil, ref iisnil, ref icons, ref iiscons, ref ihead, ref itail);
|
||||
}
|
||||
#endregion
|
||||
};
|
||||
|
|
|
@ -117,6 +117,14 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alias for Assert.
|
||||
/// </summary>
|
||||
public void Add(params BoolExpr[] constraints)
|
||||
{
|
||||
Assert(constraints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert multiple constraints into the solver, and track them (in the unsat) core
|
||||
/// using the Boolean constants in ps.
|
||||
|
|
|
@ -16,8 +16,7 @@ public class Constructor extends Z3Object
|
|||
* @throws Z3Exception
|
||||
**/
|
||||
public int getNumFields() throws Z3Exception
|
||||
{
|
||||
init();
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -27,8 +26,11 @@ public class Constructor extends Z3Object
|
|||
**/
|
||||
public FuncDecl ConstructorDecl() throws Z3Exception
|
||||
{
|
||||
init();
|
||||
return m_constructorDecl;
|
||||
Native.LongPtr constructor = new Native.LongPtr();
|
||||
Native.LongPtr tester = new Native.LongPtr();
|
||||
long[] accessors = new long[n];
|
||||
Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors);
|
||||
return new FuncDecl(getContext(), constructor.value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,8 +39,11 @@ public class Constructor extends Z3Object
|
|||
**/
|
||||
public FuncDecl getTesterDecl() throws Z3Exception
|
||||
{
|
||||
init();
|
||||
return m_testerDecl;
|
||||
Native.LongPtr constructor = new Native.LongPtr();
|
||||
Native.LongPtr tester = new Native.LongPtr();
|
||||
long[] accessors = new long[n];
|
||||
Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors);
|
||||
return new FuncDecl(getContext(), tester.value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,8 +52,14 @@ public class Constructor extends Z3Object
|
|||
**/
|
||||
public FuncDecl[] getAccessorDecls() throws Z3Exception
|
||||
{
|
||||
init();
|
||||
return m_accessorDecls;
|
||||
Native.LongPtr constructor = new Native.LongPtr();
|
||||
Native.LongPtr tester = new Native.LongPtr();
|
||||
long[] accessors = new long[n];
|
||||
Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors);
|
||||
FuncDecl[] t = new FuncDecl[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
t[i] = new FuncDecl(getContext(), accessors[i]);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,9 +71,6 @@ public class Constructor extends Z3Object
|
|||
}
|
||||
|
||||
private int n = 0;
|
||||
private FuncDecl m_testerDecl = null;
|
||||
private FuncDecl m_constructorDecl = null;
|
||||
private FuncDecl[] m_accessorDecls = null;
|
||||
|
||||
Constructor(Context ctx, Symbol name, Symbol recognizer,
|
||||
Symbol[] fieldNames, Sort[] sorts, int[] sortRefs)
|
||||
|
@ -87,21 +95,4 @@ public class Constructor extends Z3Object
|
|||
Sort.arrayToNative(sorts), sortRefs));
|
||||
|
||||
}
|
||||
|
||||
private void init() throws Z3Exception
|
||||
{
|
||||
if (m_testerDecl != null)
|
||||
return;
|
||||
Native.LongPtr constructor = new Native.LongPtr();
|
||||
Native.LongPtr tester = new Native.LongPtr();
|
||||
long[] accessors = new long[n];
|
||||
Native.queryConstructor(getContext().nCtx(), getNativeObject(), n,
|
||||
constructor, tester, accessors);
|
||||
m_constructorDecl = new FuncDecl(getContext(), constructor.value);
|
||||
m_testerDecl = new FuncDecl(getContext(), tester.value);
|
||||
m_accessorDecls = new FuncDecl[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
m_accessorDecls[i] = new FuncDecl(getContext(), accessors[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,30 +14,39 @@ public class EnumSort extends Sort
|
|||
/**
|
||||
* The function declarations of the constants in the enumeration.
|
||||
**/
|
||||
public FuncDecl[] getConstDecls()
|
||||
public FuncDecl[] getConstDecls() throws Z3Exception
|
||||
{
|
||||
return _constdecls;
|
||||
int n = Native.getDatatypeSortNumConstructors(getContext().nCtx(), getNativeObject());
|
||||
FuncDecl[] t = new FuncDecl[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
t[i] = new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), i));
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constants in the enumeration.
|
||||
**/
|
||||
public Expr[] getConsts()
|
||||
{
|
||||
return _consts;
|
||||
public Expr[] getConsts() throws Z3Exception
|
||||
{
|
||||
FuncDecl[] cds = getConstDecls();
|
||||
Expr[] t = new Expr[cds.length];
|
||||
for (int i = 0; i < t.length; i++)
|
||||
t[i] = getContext().mkApp(cds[i]);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* The test predicates for the constants in the enumeration.
|
||||
**/
|
||||
public FuncDecl[] getTesterDecls()
|
||||
public FuncDecl[] getTesterDecls() throws Z3Exception
|
||||
{
|
||||
return _testerdecls;
|
||||
int n = Native.getDatatypeSortNumConstructors(getContext().nCtx(), getNativeObject());
|
||||
FuncDecl[] t = new FuncDecl[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
t[i] = new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), i));
|
||||
return t;
|
||||
}
|
||||
|
||||
private FuncDecl[] _constdecls = null, _testerdecls = null;
|
||||
private Expr[] _consts = null;
|
||||
|
||||
EnumSort(Context ctx, Symbol name, Symbol[] enumNames) throws Z3Exception
|
||||
{
|
||||
super(ctx);
|
||||
|
@ -47,15 +56,6 @@ public class EnumSort extends Sort
|
|||
long[] n_testers = new long[n];
|
||||
setNativeObject(Native.mkEnumerationSort(ctx.nCtx(),
|
||||
name.getNativeObject(), (int) n, Symbol.arrayToNative(enumNames),
|
||||
n_constdecls, n_testers));
|
||||
_constdecls = new FuncDecl[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
_constdecls[i] = new FuncDecl(ctx, n_constdecls[i]);
|
||||
_testerdecls = new FuncDecl[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
_testerdecls[i] = new FuncDecl(ctx, n_testers[i]);
|
||||
_consts = new Expr[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
_consts[i] = ctx.mkApp(_constdecls[i], (Expr[])null);
|
||||
n_constdecls, n_testers));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@ public class Fixedpoint extends Z3Object
|
|||
*
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public void assert_(BoolExpr ... constraints) throws Z3Exception
|
||||
public void add(BoolExpr ... constraints) throws Z3Exception
|
||||
{
|
||||
getContext().checkContextMatch(constraints);
|
||||
for (BoolExpr a : constraints)
|
||||
|
|
|
@ -65,7 +65,7 @@ public class Goal extends Z3Object
|
|||
*
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public void assert_(BoolExpr ... constraints) throws Z3Exception
|
||||
public void add(BoolExpr ... constraints) throws Z3Exception
|
||||
{
|
||||
getContext().checkContextMatch(constraints);
|
||||
for (BoolExpr c : constraints)
|
||||
|
|
|
@ -13,65 +13,68 @@ public class ListSort extends Sort
|
|||
{
|
||||
/**
|
||||
* The declaration of the nil function of this list sort.
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public FuncDecl getNilDecl()
|
||||
public FuncDecl getNilDecl() throws Z3Exception
|
||||
{
|
||||
return nilDecl;
|
||||
return new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* The empty list.
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public Expr getNil()
|
||||
public Expr getNil() throws Z3Exception
|
||||
{
|
||||
return nilConst;
|
||||
return getContext().mkApp(getNilDecl());
|
||||
}
|
||||
|
||||
/**
|
||||
* The declaration of the isNil function of this list sort.
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public FuncDecl getIsNilDecl()
|
||||
public FuncDecl getIsNilDecl() throws Z3Exception
|
||||
{
|
||||
return isNilDecl;
|
||||
return new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* The declaration of the cons function of this list sort.
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public FuncDecl getConsDecl()
|
||||
public FuncDecl getConsDecl() throws Z3Exception
|
||||
{
|
||||
return consDecl;
|
||||
return new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* The declaration of the isCons function of this list sort.
|
||||
* @throws Z3Exception
|
||||
*
|
||||
**/
|
||||
public FuncDecl getIsConsDecl()
|
||||
public FuncDecl getIsConsDecl() throws Z3Exception
|
||||
{
|
||||
return isConsDecl;
|
||||
return new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* The declaration of the head function of this list sort.
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public FuncDecl getHeadDecl()
|
||||
public FuncDecl getHeadDecl() throws Z3Exception
|
||||
{
|
||||
return headDecl;
|
||||
return new FuncDecl(getContext(), Native.getDatatypeSortConstructorAccessor(getContext().nCtx(), getNativeObject(), 1, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* The declaration of the tail function of this list sort.
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public FuncDecl getTailDecl()
|
||||
public FuncDecl getTailDecl() throws Z3Exception
|
||||
{
|
||||
return tailDecl;
|
||||
return new FuncDecl(getContext(), Native.getDatatypeSortConstructorAccessor(getContext().nCtx(), getNativeObject(), 1, 1));
|
||||
}
|
||||
|
||||
private FuncDecl nilDecl, isNilDecl, consDecl, isConsDecl, headDecl,
|
||||
tailDecl;
|
||||
private Expr nilConst;
|
||||
|
||||
ListSort(Context ctx, Symbol name, Sort elemSort) throws Z3Exception
|
||||
{
|
||||
super(ctx);
|
||||
|
@ -83,12 +86,5 @@ public class ListSort extends Sort
|
|||
setNativeObject(Native.mkListSort(ctx.nCtx(), name.getNativeObject(),
|
||||
elemSort.getNativeObject(), inil, iisnil, icons, iiscons, ihead,
|
||||
itail));
|
||||
nilDecl = new FuncDecl(ctx, inil.value);
|
||||
isNilDecl = new FuncDecl(ctx, iisnil.value);
|
||||
consDecl = new FuncDecl(ctx, icons.value);
|
||||
isConsDecl = new FuncDecl(ctx, iiscons.value);
|
||||
headDecl = new FuncDecl(ctx, ihead.value);
|
||||
tailDecl = new FuncDecl(ctx, itail.value);
|
||||
nilConst = ctx.mkConst(nilDecl);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -94,7 +94,7 @@ public class Solver extends Z3Object
|
|||
*
|
||||
* @throws Z3Exception
|
||||
**/
|
||||
public void assert_(BoolExpr... constraints) throws Z3Exception
|
||||
public void add(BoolExpr... constraints) throws Z3Exception
|
||||
{
|
||||
getContext().checkContextMatch(constraints);
|
||||
for (BoolExpr a : constraints)
|
||||
|
|
|
@ -701,7 +701,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
|
||||
...
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ast_list.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Quick hack to have lists of ASTs.
|
||||
The lists have hash-consing.
|
||||
This is a substitute for the old expr_lists implemented on top of the ASTs.
|
||||
The new lists live in a different manager and do not affect the ast_manager.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-01-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _AST_LIST_H_
|
||||
#define _AST_LIST_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
template<typename AST>
|
||||
class ast_list_manager_tpl;
|
||||
|
||||
template<typename AST>
|
||||
class ast_list_tpl {
|
||||
public:
|
||||
typedef ast_list_tpl list;
|
||||
private:
|
||||
unsigned m_id;
|
||||
unsigned m_is_nil:1;
|
||||
unsigned m_ref_count:31;
|
||||
AST * m_head;
|
||||
list * m_tail;
|
||||
|
||||
ast_list_tpl():
|
||||
m_is_nil(true),
|
||||
m_ref_count(0),
|
||||
m_head(0),
|
||||
m_tail(0) {
|
||||
}
|
||||
|
||||
ast_list_tpl(AST * h, list * t):
|
||||
m_is_nil(false),
|
||||
m_ref_count(0),
|
||||
m_head(h),
|
||||
m_tail(t) {
|
||||
}
|
||||
|
||||
friend class ast_list_manager_tpl<AST>;
|
||||
|
||||
struct hash_proc;
|
||||
friend struct hash_proc;
|
||||
|
||||
struct hash_proc {
|
||||
unsigned operator()(ast_list_tpl * l) const {
|
||||
unsigned h1 = l->m_head ? l->m_head->get_id() : 5;
|
||||
unsigned h2 = l->m_tail ? l->m_tail->get_id() : 7;
|
||||
return hash_u_u(h1, h2);
|
||||
}
|
||||
};
|
||||
|
||||
struct eq_proc;
|
||||
friend struct eq_proc;
|
||||
|
||||
struct eq_proc {
|
||||
bool operator()(ast_list_tpl * l1, ast_list_tpl * l2) const {
|
||||
return l1->m_head == l2->m_head && l1->m_tail == l2->m_tail;
|
||||
}
|
||||
};
|
||||
|
||||
typedef ptr_hashtable<list, hash_proc, eq_proc> table; // for hash consing
|
||||
|
||||
public:
|
||||
unsigned get_id() const { return m_id; }
|
||||
unsigned get_ref_count() const { return m_ref_count; }
|
||||
unsigned hash() const { return m_id; }
|
||||
|
||||
friend inline bool is_nil(list const * l) { return l->m_is_nil == true; }
|
||||
friend inline bool is_cons(list const * l) { return !is_nil(l); }
|
||||
friend inline AST * head(list const * l) { SASSERT(is_cons(l)); return l->m_head; }
|
||||
friend inline list * tail(list const * l) { SASSERT(is_cons(l)); return l->m_tail; }
|
||||
};
|
||||
|
||||
template<typename AST>
|
||||
class ast_list_manager_tpl {
|
||||
public:
|
||||
typedef ast_list_tpl<AST> list;
|
||||
typedef obj_hashtable<list> list_set;
|
||||
private:
|
||||
typedef typename list::table table;
|
||||
ast_manager & m_manager;
|
||||
small_object_allocator m_allocator;
|
||||
table m_table;
|
||||
id_gen m_id_gen;
|
||||
list m_nil;
|
||||
|
||||
public:
|
||||
ast_list_manager_tpl(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_nil() {
|
||||
m_nil.m_id = m_id_gen.mk();
|
||||
m_nil.m_ref_count = 1;
|
||||
}
|
||||
|
||||
void inc_ref(list * l) {
|
||||
if (l != 0) {
|
||||
l->m_ref_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void dec_ref(list * l) {
|
||||
while (l != 0) {
|
||||
SASSERT(l->m_ref_count > 0);
|
||||
l->m_ref_count--;
|
||||
if (l->m_ref_count > 0)
|
||||
return;
|
||||
SASSERT(l != &m_nil);
|
||||
m_table.erase(l);
|
||||
m_manager.dec_ref(l->m_head);
|
||||
m_id_gen.recycle(l->m_id);
|
||||
list * old_l = l;
|
||||
l = l->m_tail;
|
||||
m_allocator.deallocate(sizeof(list), old_l);
|
||||
}
|
||||
}
|
||||
|
||||
list * mk_nil() { return &m_nil; }
|
||||
|
||||
list * mk_cons(AST * h, list * l) {
|
||||
list tmp(h, l);
|
||||
list * r = 0;
|
||||
if (m_table.find(&tmp, r))
|
||||
return r;
|
||||
r = new (m_allocator.allocate(sizeof(list))) list(h, l);
|
||||
m_manager.inc_ref(h);
|
||||
inc_ref(l);
|
||||
r->m_id = m_id_gen.mk();
|
||||
m_table.insert(r);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
typedef ast_list_tpl<expr> expr_list;
|
||||
typedef ast_list_manager_tpl<expr> expr_list_manager;
|
||||
|
||||
typedef ast_list_tpl<quantifier> quantifier_list;
|
||||
typedef ast_list_manager_tpl<quantifier> quantifier_list_manager;
|
||||
|
||||
typedef obj_ref<expr_list, expr_list_manager> expr_list_ref;
|
||||
typedef obj_ref<quantifier_list, quantifier_list_manager> quantifier_list_ref;
|
||||
typedef ref_vector<expr_list, expr_list_manager> expr_list_ref_vector;
|
||||
typedef ref_vector<quantifier_list, quantifier_list_manager> quantifier_list_ref_vector;
|
||||
|
||||
#endif
|
|
@ -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); }
|
||||
|
|
|
@ -766,7 +766,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 +774,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); }
|
||||
|
|
|
@ -151,6 +151,10 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete
|
|||
if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) {
|
||||
m_manager->raise_exception("expecting two integer parameters to floating point sort");
|
||||
}
|
||||
if (parameters[0].get_int() <= 1 || parameters[1].get_int() <= 1)
|
||||
m_manager->raise_exception("floating point sorts need parameters > 1");
|
||||
if (parameters[0].get_int() > parameters[1].get_int())
|
||||
m_manager->raise_exception("floating point sorts with ebits > sbits are currently not supported");
|
||||
return mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
|
||||
case ROUNDING_MODE_SORT:
|
||||
return mk_rm_sort();
|
||||
|
@ -349,27 +353,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)
|
||||
m_manager->raise_exception("invalid number of arguments to asFloat operator");
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,6 +491,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;
|
||||
|
|
|
@ -140,6 +140,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); }
|
||||
|
||||
|
|
|
@ -596,8 +596,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";);
|
||||
|
@ -791,7 +792,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();
|
||||
|
@ -809,7 +813,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -981,14 +981,6 @@ br_status arith_rewriter::mk_to_real_core(expr * arg, expr_ref & result) {
|
|||
result = m_util.mk_numeral(a, false);
|
||||
return BR_DONE;
|
||||
}
|
||||
#if 0
|
||||
// The following rewriting rule is not correct.
|
||||
// It is used only for making experiments.
|
||||
if (m_util.is_to_int(arg)) {
|
||||
result = to_app(arg)->get_arg(0);
|
||||
return BR_DONE;
|
||||
}
|
||||
#endif
|
||||
// push to_real over OP_ADD, OP_MUL
|
||||
if (m_push_to_real) {
|
||||
if (m_util.is_add(arg) || m_util.is_mul(arg)) {
|
||||
|
|
165
src/ast/rewriter/ast_counter.cpp
Normal file
165
src/ast/rewriter/ast_counter.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*++
|
||||
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();
|
||||
::get_free_vars(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;
|
||||
while (!m_todo.empty()) {
|
||||
expr* e = m_todo.back();
|
||||
unsigned scope = m_scopes.back();
|
||||
m_todo.pop_back();
|
||||
m_scopes.pop_back();
|
||||
if (m_visited.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
m_visited.mark(e, true);
|
||||
switch(e->get_kind()) {
|
||||
case AST_QUANTIFIER: {
|
||||
quantifier* q = to_quantifier(e);
|
||||
m_todo.push_back(q->get_expr());
|
||||
m_scopes.push_back(scope + q->get_num_decls());
|
||||
break;
|
||||
}
|
||||
case AST_VAR: {
|
||||
if (to_var(e)->get_idx() >= scope + max_var) {
|
||||
has_var = true;
|
||||
max_var = to_var(e)->get_idx() - scope;
|
||||
}
|
||||
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));
|
||||
m_scopes.push_back(scope);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_visited.reset();
|
||||
return max_var;
|
||||
}
|
||||
|
||||
|
||||
unsigned var_counter::get_max_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
m_scopes.push_back(0);
|
||||
return get_max_var(has_var);
|
||||
}
|
||||
|
||||
unsigned var_counter::get_next_var(expr* e) {
|
||||
bool has_var = false;
|
||||
m_todo.push_back(e);
|
||||
m_scopes.push_back(0);
|
||||
unsigned mv = get_max_var(has_var);
|
||||
if (has_var) mv++;
|
||||
return mv;
|
||||
}
|
||||
|
107
src/ast/rewriter/ast_counter.h
Normal file
107
src/ast/rewriter/ast_counter.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*++
|
||||
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) {}
|
||||
|
||||
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;
|
||||
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,9 @@ 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();
|
||||
}
|
|
@ -38,6 +38,8 @@ public:
|
|||
void operator()(expr_ref& e) { (*this)(e.get(), e); }
|
||||
|
||||
void operator()(expr* src, expr_ref& e);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif /* __EXPR_SAFE_REPLACE_H__ */
|
|
@ -77,14 +77,23 @@ 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)) {
|
||||
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 (m_util.is_value(args[1], q_mpf)) {
|
||||
mpf v;
|
||||
m_util.fm().set(v, ebits, sbits, rm, q_mpf);
|
||||
result = m_util.mk_value(v);
|
||||
m_util.fm().del(v);
|
||||
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])) &&
|
||||
|
@ -217,8 +226,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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -465,7 +466,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;
|
||||
|
|
|
@ -34,9 +34,9 @@ public:
|
|||
expr_dependency_ref & core) {
|
||||
#pragma omp critical (echo_tactic)
|
||||
{
|
||||
m_ctx.diagnostic_stream() << m_msg;
|
||||
m_ctx.regular_stream() << m_msg;
|
||||
if (m_newline)
|
||||
m_ctx.diagnostic_stream() << std::endl;
|
||||
m_ctx.regular_stream() << std::endl;
|
||||
}
|
||||
skip_tactic::operator()(in, result, mc, pc, core);
|
||||
}
|
||||
|
|
|
@ -80,3 +80,8 @@ void model_v2_pp(std::ostream & out, model_core const & md, bool partial) {
|
|||
display_constants(out, md);
|
||||
display_functions(out, md, partial);
|
||||
}
|
||||
|
||||
// debugging support
|
||||
void pp(model_core const & md) {
|
||||
model_v2_pp(std::cout, md, false);
|
||||
}
|
||||
|
|
|
@ -441,6 +441,7 @@ protected:
|
|||
unsigned m_sym_idx;
|
||||
std::string m_path;
|
||||
str2sort m_sort_dict;
|
||||
|
||||
|
||||
// true if an error occured during the current call to the parse_stream
|
||||
// function
|
||||
|
@ -812,7 +813,8 @@ protected:
|
|||
}
|
||||
f = m_manager.mk_func_decl(s, domain.size(), domain.c_ptr(), m_manager.mk_bool_sort());
|
||||
|
||||
m_context.register_predicate(f);
|
||||
m_context.register_predicate(f, true);
|
||||
|
||||
while (tok == TK_ID) {
|
||||
char const* pred_pragma = m_lexer->get_token_data();
|
||||
if(strcmp(pred_pragma, "printtuples")==0 || strcmp(pred_pragma, "outputtuples")==0) {
|
||||
|
|
|
@ -233,7 +233,7 @@ namespace datalog {
|
|||
table_fact row;
|
||||
for(; it!=iend; ++it) {
|
||||
it->get_fact(row);
|
||||
to_remove.append(row);
|
||||
to_remove.push_back(row);
|
||||
}
|
||||
remove_facts(to_remove.size(), to_remove.c_ptr());
|
||||
}
|
||||
|
@ -325,9 +325,20 @@ namespace datalog {
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Default method for complementation.
|
||||
|
||||
It assumes that the compiler creates only tables with
|
||||
at most one column (0 or 1 columns).
|
||||
Complementation of tables with more than one columns
|
||||
is transformed into a cross product of complements and/or
|
||||
difference.
|
||||
|
||||
*/
|
||||
table_base * table_base::complement(func_decl* p, const table_element * func_columns) const {
|
||||
const table_signature & sig = get_signature();
|
||||
SASSERT(sig.functional_columns()==0 || func_columns!=0);
|
||||
SASSERT(sig.first_functional() <= 1);
|
||||
|
||||
table_base * res = get_plugin().mk_empty(sig);
|
||||
|
||||
|
@ -335,16 +346,14 @@ namespace datalog {
|
|||
fact.resize(sig.first_functional());
|
||||
fact.append(sig.functional_columns(), func_columns);
|
||||
|
||||
if(sig.first_functional()==0) {
|
||||
if(empty()) {
|
||||
if (sig.first_functional() == 0) {
|
||||
if (empty()) {
|
||||
res->add_fact(fact);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if(sig.first_functional()!=1) { //now we support only tables with one non-functional column
|
||||
NOT_IMPLEMENTED_YET();
|
||||
}
|
||||
VERIFY(sig.first_functional() == 1);
|
||||
|
||||
uint64 upper_bound = get_signature()[0];
|
||||
bool empty_table = empty();
|
||||
|
@ -356,51 +365,13 @@ namespace datalog {
|
|||
warning_msg(buffer.str().c_str());
|
||||
}
|
||||
|
||||
for(table_element i=0; i<upper_bound; i++) {
|
||||
fact[0]=i;
|
||||
for(table_element i = 0; i < upper_bound; i++) {
|
||||
fact[0] = i;
|
||||
if(empty_table || !contains_fact(fact)) {
|
||||
res->add_fact(fact);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
#if 0
|
||||
svector<unsigned> var_arg_indexes(arity);
|
||||
var_arg_indexes.fill(0);
|
||||
|
||||
svector<unsigned> var_arg_domain_sizes = s;
|
||||
|
||||
unsigned var_cnt=var_arg_indexes.size();
|
||||
table_fact fact;
|
||||
fact.resize(arity);
|
||||
fact.fill(0);
|
||||
unsigned depth=arity;
|
||||
|
||||
while(true) {
|
||||
if(depth==arity) {
|
||||
SASSERT(!res->contains_fact(fact));
|
||||
if(empty_table || !contains_fact(fact)) {
|
||||
res->add_fact(fact);
|
||||
}
|
||||
depth--;
|
||||
}
|
||||
else if(fact[depth]==s[depth]-1) {
|
||||
val_indexes[depth]=0;
|
||||
if(depth==0) {
|
||||
break;
|
||||
}
|
||||
depth--;
|
||||
}
|
||||
else {
|
||||
SASSERT(val_indexes[depth]<var_arg_domain_sizes[depth]);
|
||||
unsigned arg_idx = var_arg_indexes[depth];
|
||||
unsigned val_idx = val_indexes[depth]++;
|
||||
head_args[arg_idx]=ctx.get_arith().mk_numeral(rational(val_idx), true);
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
void table_base::display(std::ostream & out) const {
|
||||
|
@ -468,23 +439,21 @@ namespace datalog {
|
|||
expr_ref_vector disjs(m);
|
||||
expr_ref_vector conjs(m);
|
||||
dl_decl_util util(m);
|
||||
bool_rewriter brw(m);
|
||||
table_fact fact;
|
||||
iterator it = begin();
|
||||
iterator iend = end();
|
||||
for(; it!=iend; ++it) {
|
||||
for(; it != iend; ++it) {
|
||||
const row_interface & r = *it;
|
||||
r.get_fact(fact);
|
||||
conjs.reset();
|
||||
for (unsigned i = 0; i < fact.size(); ++i) {
|
||||
conjs.push_back(m.mk_eq(m.mk_var(i, sig[i]), util.mk_numeral(fact[i], sig[i])));
|
||||
}
|
||||
switch(conjs.size()) {
|
||||
case 0: disjs.push_back(m.mk_true()); break;
|
||||
case 1: disjs.push_back(conjs[0].get()); break;
|
||||
default: disjs.push_back(m.mk_and(conjs.size(), conjs.c_ptr())); break;
|
||||
}
|
||||
brw.mk_and(conjs.size(), conjs.c_ptr(), fml);
|
||||
disjs.push_back(fml);
|
||||
}
|
||||
bool_rewriter(m).mk_or(disjs.size(), disjs.c_ptr(), fml);
|
||||
brw.mk_or(disjs.size(), disjs.c_ptr(), fml);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -233,6 +233,7 @@ namespace datalog {
|
|||
|
||||
symbol const& get_name() const { return m_name; }
|
||||
|
||||
virtual void set_cancel(bool f) {}
|
||||
|
||||
relation_manager & get_manager() const { return m_manager; }
|
||||
ast_manager& get_ast_manager() const { return datalog::get_ast_manager_from_rel_manager(m_manager); }
|
||||
|
|
|
@ -307,7 +307,7 @@ namespace datalog {
|
|||
r1->to_formula(concl);
|
||||
scoped_proof _sp(m);
|
||||
|
||||
proof* p = m.mk_asserted(fml);
|
||||
proof* p = r->get_proof();
|
||||
proof* premises[2] = { pr, p };
|
||||
|
||||
positions.push_back(std::make_pair(0, 1));
|
||||
|
@ -320,7 +320,7 @@ namespace datalog {
|
|||
else {
|
||||
r2->to_formula(concl);
|
||||
scoped_proof _sp(m);
|
||||
proof* p = m.mk_asserted(fml);
|
||||
proof* p = r->get_proof();
|
||||
if (sub.empty()) {
|
||||
pr = p;
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ namespace datalog {
|
|||
pred = r->get_decl(0);
|
||||
}
|
||||
scoped_proof _sp(m);
|
||||
apply(m, b.m_pc.get(), pr);
|
||||
apply(m, b.m_ctx.get_proof_converter().get(), pr);
|
||||
b.m_answer = pr;
|
||||
return l_true;
|
||||
}
|
||||
|
@ -474,6 +474,9 @@ namespace datalog {
|
|||
}
|
||||
|
||||
proof_ref get_proof(model_ref& md, func_decl* pred, app* prop, unsigned level) {
|
||||
if (b.m_cancel) {
|
||||
return proof_ref(0, m);
|
||||
}
|
||||
TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";);
|
||||
|
||||
expr_ref prop_r(m), prop_v(m), fml(m), prop_body(m), tmp(m), body(m);
|
||||
|
@ -497,7 +500,7 @@ namespace datalog {
|
|||
SASSERT(r);
|
||||
r->to_formula(fml);
|
||||
IF_VERBOSE(1, verbose_stream() << mk_pp(fml, m) << "\n";);
|
||||
prs.push_back(m.mk_asserted(fml));
|
||||
prs.push_back(r->get_proof());
|
||||
unsigned sz = r->get_uninterpreted_tail_size();
|
||||
|
||||
ptr_vector<sort> rule_vars;
|
||||
|
@ -536,8 +539,9 @@ namespace datalog {
|
|||
model_ref md;
|
||||
b.m_solver.get_model(md);
|
||||
IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0););
|
||||
proof_ref pr = get_proof(md, b.m_query_pred, to_app(level_query), level);
|
||||
apply(m, b.m_pc.get(), pr);
|
||||
proof_ref pr(m);
|
||||
pr = get_proof(md, b.m_query_pred, to_app(level_query), level);
|
||||
apply(m, b.m_ctx.get_proof_converter().get(), pr);
|
||||
b.m_answer = pr;
|
||||
}
|
||||
|
||||
|
@ -1034,7 +1038,7 @@ namespace datalog {
|
|||
var_subst vs(m, false);
|
||||
mk_subst(*rules[i], path, trace, sub);
|
||||
rules[i]->to_formula(fml);
|
||||
prs.push_back(m.mk_asserted(fml));
|
||||
prs.push_back(rules[i]->get_proof());
|
||||
unsigned sz = trace->get_num_args();
|
||||
if (sub.empty() && sz == 0) {
|
||||
pr = prs[0].get();
|
||||
|
@ -1112,7 +1116,6 @@ namespace datalog {
|
|||
}
|
||||
|
||||
void mk_answer(model_ref& md, expr_ref& trace, expr_ref& path) {
|
||||
proof_ref pr(m);
|
||||
IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0););
|
||||
md->eval(trace, trace);
|
||||
md->eval(path, path);
|
||||
|
@ -1120,7 +1123,11 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < b.m_solver.size(); ++i) {
|
||||
verbose_stream() << mk_pp(b.m_solver.get_formulas()[i], m) << "\n";
|
||||
});
|
||||
b.m_answer = get_proof(md, to_app(trace), to_app(path));
|
||||
scoped_proof _sp(m);
|
||||
proof_ref pr(m);
|
||||
pr = get_proof(md, to_app(trace), to_app(path));
|
||||
apply(m, b.m_ctx.get_proof_converter().get(), pr);
|
||||
b.m_answer = pr;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1155,6 +1162,9 @@ namespace datalog {
|
|||
private:
|
||||
|
||||
void get_model(unsigned level) {
|
||||
if (b.m_cancel) {
|
||||
return;
|
||||
}
|
||||
rule_manager& rm = b.m_ctx.get_rule_manager();
|
||||
expr_ref level_query = mk_level_predicate(b.m_query_pred, level);
|
||||
model_ref md;
|
||||
|
@ -1212,7 +1222,7 @@ namespace datalog {
|
|||
r1->to_formula(concl);
|
||||
scoped_proof _sp(m);
|
||||
|
||||
proof* p = m.mk_asserted(fml);
|
||||
proof* p = r->get_proof();
|
||||
proof* premises[2] = { pr, p };
|
||||
|
||||
positions.push_back(std::make_pair(0, 1));
|
||||
|
@ -1225,7 +1235,7 @@ namespace datalog {
|
|||
else {
|
||||
r2->to_formula(concl);
|
||||
scoped_proof _sp(m);
|
||||
proof* p = m.mk_asserted(fml);
|
||||
proof* p = r->get_proof();
|
||||
if (sub.empty()) {
|
||||
pr = p;
|
||||
}
|
||||
|
@ -1245,7 +1255,7 @@ namespace datalog {
|
|||
pred = r->get_decl(0);
|
||||
}
|
||||
scoped_proof _sp(m);
|
||||
apply(m, b.m_pc.get(), pr);
|
||||
apply(m, b.m_ctx.get_proof_converter().get(), pr);
|
||||
b.m_answer = pr;
|
||||
}
|
||||
|
||||
|
@ -1409,6 +1419,7 @@ namespace datalog {
|
|||
|
||||
m_ctx.ensure_opened();
|
||||
m_rules.reset();
|
||||
|
||||
datalog::rule_manager& rule_manager = m_ctx.get_rule_manager();
|
||||
datalog::rule_set old_rules(m_ctx.get_rules());
|
||||
datalog::rule_ref_vector query_rules(rule_manager);
|
||||
|
@ -1417,16 +1428,14 @@ namespace datalog {
|
|||
m_ctx.add_rules(query_rules);
|
||||
expr_ref bg_assertion = m_ctx.get_background_assertion();
|
||||
|
||||
model_converter_ref mc = datalog::mk_skip_model_converter();
|
||||
m_pc = datalog::mk_skip_proof_converter();
|
||||
m_ctx.set_output_predicate(m_query_pred);
|
||||
m_ctx.apply_default_transformation(mc, m_pc);
|
||||
m_ctx.apply_default_transformation();
|
||||
|
||||
if (m_ctx.get_params().slice()) {
|
||||
datalog::rule_transformer transformer(m_ctx);
|
||||
datalog::mk_slice* slice = alloc(datalog::mk_slice, m_ctx);
|
||||
transformer.register_plugin(slice);
|
||||
m_ctx.transform_rules(transformer, mc, m_pc);
|
||||
m_ctx.transform_rules(transformer);
|
||||
m_query_pred = slice->get_predicate(m_query_pred.get());
|
||||
m_ctx.set_output_predicate(m_query_pred);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ namespace datalog {
|
|||
func_decl_ref m_query_pred;
|
||||
expr_ref m_answer;
|
||||
volatile bool m_cancel;
|
||||
proof_converter_ref m_pc;
|
||||
|
||||
void checkpoint();
|
||||
|
||||
|
|
|
@ -287,9 +287,6 @@ namespace datalog {
|
|||
|
||||
bool check_table::well_formed() const {
|
||||
get_plugin().m_count++;
|
||||
if (get_plugin().m_count == 497) {
|
||||
std::cout << "here\n";
|
||||
}
|
||||
iterator it = m_tocheck->begin(), end = m_tocheck->end();
|
||||
for (; it != end; ++it) {
|
||||
table_fact fact;
|
||||
|
@ -354,8 +351,8 @@ namespace datalog {
|
|||
return result;
|
||||
}
|
||||
|
||||
table_base * check_table::complement(func_decl* p) const {
|
||||
check_table* result = alloc(check_table, get_plugin(), get_signature(), m_tocheck->complement(p), m_checker->complement(p));
|
||||
table_base * check_table::complement(func_decl* p, const table_element * func_columns) const {
|
||||
check_table* result = alloc(check_table, get_plugin(), get_signature(), m_tocheck->complement(p, func_columns), m_checker->complement(p, func_columns));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace datalog {
|
|||
virtual void add_fact(const table_fact & f);
|
||||
virtual void remove_fact(const table_element* fact);
|
||||
virtual bool contains_fact(const table_fact & f) const;
|
||||
virtual table_base * complement(func_decl* p) const;
|
||||
virtual table_base * complement(func_decl* p, const table_element * func_columns = 0) const;
|
||||
virtual table_base * clone() const;
|
||||
|
||||
virtual iterator begin() const { SASSERT(well_formed()); return m_tocheck->begin(); }
|
||||
|
|
|
@ -229,12 +229,12 @@ public:
|
|||
status = dlctx.query(m_target);
|
||||
}
|
||||
catch (z3_error & ex) {
|
||||
ctx.regular_stream() << "(error \"query failed: " << ex.msg() << "\")" << std::endl;
|
||||
throw ex;
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
ctx.regular_stream() << "(error \"query failed: " << ex.msg() << "\")" << std::endl;
|
||||
}
|
||||
dlctx.cleanup();
|
||||
}
|
||||
switch (status) {
|
||||
case l_false:
|
||||
|
@ -250,6 +250,7 @@ public:
|
|||
ctx.regular_stream() << "unknown\n";
|
||||
switch(dlctx.get_status()) {
|
||||
case datalog::INPUT_ERROR:
|
||||
ctx.regular_stream() << "input error\n";
|
||||
break;
|
||||
|
||||
case datalog::MEMOUT:
|
||||
|
@ -261,12 +262,21 @@ public:
|
|||
break;
|
||||
|
||||
case datalog::OK:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
||||
case datalog::CANCELED:
|
||||
ctx.regular_stream() << "canceled\n";
|
||||
dlctx.display_profile(ctx.regular_stream());
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
dlctx.cleanup();
|
||||
print_statistics(ctx);
|
||||
m_target = 0;
|
||||
}
|
||||
|
|
|
@ -384,8 +384,8 @@ namespace datalog {
|
|||
void compiler::get_local_indexes_for_projection(rule * r, unsigned_vector & res) {
|
||||
SASSERT(r->get_positive_tail_size()==2);
|
||||
ast_manager & m = m_context.get_manager();
|
||||
var_counter counter;
|
||||
counter.count_vars(m, r);
|
||||
rule_counter counter;
|
||||
counter.count_rule_vars(m, r);
|
||||
app * t1 = r->get_tail(0);
|
||||
app * t2 = r->get_tail(1);
|
||||
counter.count_vars(m, t1, -1);
|
||||
|
@ -707,6 +707,7 @@ namespace datalog {
|
|||
|
||||
//update the head relation
|
||||
make_union(new_head_reg, head_reg, delta_reg, use_widening, acc);
|
||||
make_dealloc_non_void(new_head_reg, acc);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
@ -1028,21 +1029,23 @@ namespace datalog {
|
|||
func_decl * head_pred = *preds.begin();
|
||||
const rule_vector & rules = m_rule_set.get_predicate_rules(head_pred);
|
||||
|
||||
|
||||
|
||||
reg_idx output_delta;
|
||||
if(!output_deltas.find(head_pred, output_delta)) {
|
||||
if (!output_deltas.find(head_pred, output_delta)) {
|
||||
output_delta = execution_context::void_register;
|
||||
}
|
||||
|
||||
rule_vector::const_iterator it = rules.begin();
|
||||
rule_vector::const_iterator end = rules.end();
|
||||
for(; it!=end; ++it) {
|
||||
for (; it != end; ++it) {
|
||||
rule * r = *it;
|
||||
SASSERT(r->get_head()->get_decl()==head_pred);
|
||||
|
||||
compile_rule_evaluation(r, input_deltas, output_delta, false, acc);
|
||||
}
|
||||
|
||||
if(add_saturation_marks) {
|
||||
if (add_saturation_marks) {
|
||||
//now the predicate is saturated, so we may mark it as such
|
||||
acc.push_back(instruction::mk_mark_saturated(m_context.get_manager(), head_pred));
|
||||
}
|
||||
|
@ -1068,7 +1071,7 @@ namespace datalog {
|
|||
for(; sit!=send; ++sit) {
|
||||
func_decl_set & strat_preds = **sit;
|
||||
|
||||
if(all_saturated(strat_preds)) {
|
||||
if (all_saturated(strat_preds)) {
|
||||
//all predicates in stratum are saturated, so no need to compile rules for them
|
||||
continue;
|
||||
}
|
||||
|
@ -1084,7 +1087,7 @@ namespace datalog {
|
|||
tout << "\n";
|
||||
);
|
||||
|
||||
if(is_nonrecursive_stratum(strat_preds)) {
|
||||
if (is_nonrecursive_stratum(strat_preds)) {
|
||||
//this stratum contains just a single non-recursive rule
|
||||
compile_nonrecursive_stratum(strat_preds, input_deltas, output_deltas, add_saturation_marks, acc);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@ Revision History:
|
|||
#include"dl_mk_partial_equiv.h"
|
||||
#include"dl_mk_bit_blast.h"
|
||||
#include"dl_mk_array_blast.h"
|
||||
#include"dl_mk_karr_invariants.h"
|
||||
#include"dl_mk_quantifier_abstraction.h"
|
||||
#include"dl_mk_quantifier_instantiation.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"expr_abstract.h"
|
||||
|
||||
|
@ -223,14 +226,18 @@ namespace datalog {
|
|||
m_rewriter(m),
|
||||
m_var_subst(m),
|
||||
m_rule_manager(*this),
|
||||
m_transf(*this),
|
||||
m_trail(*this),
|
||||
m_pinned(m),
|
||||
m_vars(m),
|
||||
m_rule_set(*this),
|
||||
m_transformed_rule_set(*this),
|
||||
m_rule_fmls(m),
|
||||
m_background(m),
|
||||
m_mc(0),
|
||||
m_closed(false),
|
||||
m_saturation_was_run(false),
|
||||
m_last_status(OK),
|
||||
m_last_answer(m),
|
||||
m_engine(LAST_ENGINE),
|
||||
m_cancel(false) {
|
||||
|
@ -295,14 +302,6 @@ namespace datalog {
|
|||
return m_preds.contains(pred);
|
||||
}
|
||||
|
||||
func_decl * context::try_get_predicate_decl(symbol pred_name) const {
|
||||
func_decl * res;
|
||||
if (!m_preds_by_name.find(pred_name, res)) {
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void context::register_variable(func_decl* var) {
|
||||
m_vars.push_back(m.mk_const(var));
|
||||
}
|
||||
|
@ -354,7 +353,6 @@ namespace datalog {
|
|||
m_pinned.push_back(decl);
|
||||
m_preds.insert(decl);
|
||||
if (named) {
|
||||
SASSERT(!m_preds_by_name.contains(decl->get_name()));
|
||||
m_preds_by_name.insert(decl->get_name(), decl);
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +439,7 @@ namespace datalog {
|
|||
func_decl* new_pred =
|
||||
m.mk_fresh_func_decl(prefix, suffix, arity, domain, m.mk_bool_sort());
|
||||
|
||||
register_predicate(new_pred);
|
||||
register_predicate(new_pred, true);
|
||||
|
||||
if (m_rel.get()) {
|
||||
m_rel->inherit_predicate_kind(new_pred, orig_pred);
|
||||
|
@ -472,8 +470,11 @@ namespace datalog {
|
|||
void context::flush_add_rules() {
|
||||
datalog::rule_manager& rm = get_rule_manager();
|
||||
datalog::rule_ref_vector rules(rm);
|
||||
scoped_proof_mode _scp(m, generate_proof_trace()?PGM_FINE:PGM_DISABLED);
|
||||
for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
|
||||
rm.mk_rule(m_rule_fmls[i].get(), rules, m_rule_names[i]);
|
||||
expr* fml = m_rule_fmls[i].get();
|
||||
proof* p = generate_proof_trace()?m.mk_asserted(fml):0;
|
||||
rm.mk_rule(fml, p, rules, m_rule_names[i]);
|
||||
}
|
||||
add_rules(rules);
|
||||
m_rule_fmls.reset();
|
||||
|
@ -487,7 +488,11 @@ namespace datalog {
|
|||
void context::update_rule(expr* rl, symbol const& name) {
|
||||
datalog::rule_manager& rm = get_rule_manager();
|
||||
datalog::rule_ref_vector rules(rm);
|
||||
rm.mk_rule(rl, rules, name);
|
||||
proof* p = 0;
|
||||
if (generate_proof_trace()) {
|
||||
p = m.mk_asserted(rl);
|
||||
}
|
||||
rm.mk_rule(rl, p, rules, name);
|
||||
if (rules.size() != 1) {
|
||||
std::stringstream strm;
|
||||
strm << "Rule " << name << " has a non-trivial body. It cannot be modified";
|
||||
|
@ -681,7 +686,7 @@ namespace datalog {
|
|||
todo.push_back(e2);
|
||||
}
|
||||
else if (is_quantifier(e)) {
|
||||
todo.append(to_quantifier(e)->get_expr());
|
||||
todo.push_back(to_quantifier(e)->get_expr());
|
||||
}
|
||||
else if ((m.is_eq(e, e1, e2) || m.is_iff(e, e1, e2)) &&
|
||||
m.is_true(e1)) {
|
||||
|
@ -735,6 +740,9 @@ namespace datalog {
|
|||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
if (generate_proof_trace() && !r->get_proof()) {
|
||||
m_rule_manager.mk_rule_asserted_proof(*r.get());
|
||||
}
|
||||
}
|
||||
|
||||
void context::add_rule(rule_ref& r) {
|
||||
|
@ -772,6 +780,10 @@ namespace datalog {
|
|||
add_fact(head->get_decl(), fact);
|
||||
}
|
||||
|
||||
bool context::has_facts(func_decl * pred) const {
|
||||
return m_rel && m_rel->has_facts(pred);
|
||||
}
|
||||
|
||||
void context::add_table_fact(func_decl * pred, const table_fact & fact) {
|
||||
if (get_engine() == DATALOG_ENGINE) {
|
||||
ensure_rel();
|
||||
|
@ -824,28 +836,28 @@ namespace datalog {
|
|||
m_closed = false;
|
||||
}
|
||||
|
||||
void context::transform_rules(model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
rule_transformer transf(*this);
|
||||
transf.register_plugin(alloc(mk_filter_rules,*this));
|
||||
transf.register_plugin(alloc(mk_simple_joins,*this));
|
||||
void context::transform_rules() {
|
||||
m_transf.reset();
|
||||
m_transf.register_plugin(alloc(mk_filter_rules,*this));
|
||||
m_transf.register_plugin(alloc(mk_simple_joins,*this));
|
||||
|
||||
if (unbound_compressor()) {
|
||||
transf.register_plugin(alloc(mk_unbound_compressor,*this));
|
||||
m_transf.register_plugin(alloc(mk_unbound_compressor,*this));
|
||||
}
|
||||
|
||||
if (similarity_compressor()) {
|
||||
transf.register_plugin(alloc(mk_similarity_compressor, *this,
|
||||
m_transf.register_plugin(alloc(mk_similarity_compressor, *this,
|
||||
similarity_compressor_threshold()));
|
||||
}
|
||||
transf.register_plugin(alloc(datalog::mk_partial_equivalence_transformer, *this));
|
||||
m_transf.register_plugin(alloc(datalog::mk_partial_equivalence_transformer, *this));
|
||||
|
||||
transform_rules(transf, mc, pc);
|
||||
transform_rules(m_transf);
|
||||
}
|
||||
|
||||
void context::transform_rules(rule_transformer& transf, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
|
||||
void context::transform_rules(rule_transformer& transf) {
|
||||
SASSERT(m_closed); //we must finish adding rules before we start transforming them
|
||||
TRACE("dl", display_rules(tout););
|
||||
if (transf(m_rule_set, mc, pc)) {
|
||||
if (transf(m_rule_set)) {
|
||||
//we have already ensured the negation is stratified and transformations
|
||||
//should not break the stratification
|
||||
m_rule_set.ensure_closed();
|
||||
|
@ -860,34 +872,47 @@ namespace datalog {
|
|||
m_rule_set.add_rules(rs);
|
||||
}
|
||||
|
||||
void context::apply_default_transformation(model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
ensure_closed();
|
||||
datalog::rule_transformer transf(*this);
|
||||
transf.register_plugin(alloc(datalog::mk_coi_filter, *this));
|
||||
transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this));
|
||||
void context::record_transformed_rules() {
|
||||
m_transformed_rule_set.reset();
|
||||
m_transformed_rule_set.add_rules(m_rule_set);
|
||||
}
|
||||
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 35005));
|
||||
transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 35000));
|
||||
transf.register_plugin(alloc(datalog::mk_coi_filter, *this, 34990));
|
||||
transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this, 34980));
|
||||
void context::apply_default_transformation() {
|
||||
ensure_closed();
|
||||
m_transf.reset();
|
||||
m_transf.register_plugin(alloc(datalog::mk_coi_filter, *this));
|
||||
m_transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this));
|
||||
|
||||
m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 35005));
|
||||
m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 35000));
|
||||
m_transf.register_plugin(alloc(datalog::mk_coi_filter, *this, 34990));
|
||||
m_transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this, 34980));
|
||||
|
||||
//and another round of inlining
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34975));
|
||||
transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34970));
|
||||
transf.register_plugin(alloc(datalog::mk_coi_filter, *this, 34960));
|
||||
transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this, 34950));
|
||||
m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34975));
|
||||
m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34970));
|
||||
m_transf.register_plugin(alloc(datalog::mk_coi_filter, *this, 34960));
|
||||
m_transf.register_plugin(alloc(datalog::mk_interp_tail_simplifier, *this, 34950));
|
||||
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34940));
|
||||
transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34930));
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34920));
|
||||
transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34910));
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34900));
|
||||
transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34890));
|
||||
transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34880));
|
||||
m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34940));
|
||||
m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34930));
|
||||
m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34920));
|
||||
m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34910));
|
||||
m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34900));
|
||||
m_transf.register_plugin(alloc(datalog::mk_rule_inliner, *this, 34890));
|
||||
m_transf.register_plugin(alloc(datalog::mk_subsumption_checker, *this, 34880));
|
||||
|
||||
transf.register_plugin(alloc(datalog::mk_bit_blast, *this, 35000));
|
||||
transf.register_plugin(alloc(datalog::mk_array_blast, *this, 36000));
|
||||
transform_rules(transf, mc, pc);
|
||||
|
||||
if (get_params().quantify_arrays()) {
|
||||
m_transf.register_plugin(alloc(datalog::mk_quantifier_abstraction, *this, 33000));
|
||||
m_transf.register_plugin(alloc(datalog::mk_array_blast, *this, 32500));
|
||||
}
|
||||
m_transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, *this, 32000));
|
||||
|
||||
m_transf.register_plugin(alloc(datalog::mk_bit_blast, *this, 35000));
|
||||
m_transf.register_plugin(alloc(datalog::mk_array_blast, *this, 36000));
|
||||
m_transf.register_plugin(alloc(datalog::mk_karr_invariants, *this, 36010));
|
||||
transform_rules(m_transf);
|
||||
}
|
||||
|
||||
void context::collect_params(param_descrs& p) {
|
||||
|
@ -928,18 +953,21 @@ namespace datalog {
|
|||
|
||||
void context::cancel() {
|
||||
m_cancel = true;
|
||||
m_last_status = CANCELED;
|
||||
m_transf.cancel();
|
||||
if (m_pdr.get()) m_pdr->cancel();
|
||||
if (m_bmc.get()) m_bmc->cancel();
|
||||
if (m_rel.get()) m_rel->cancel();
|
||||
if (m_tab.get()) m_tab->cancel();
|
||||
if (m_rel.get()) m_rel->set_cancel(true);
|
||||
}
|
||||
|
||||
void context::cleanup() {
|
||||
m_cancel = false;
|
||||
m_last_status = OK;
|
||||
if (m_pdr.get()) m_pdr->cleanup();
|
||||
if (m_bmc.get()) m_bmc->cleanup();
|
||||
if (m_rel.get()) m_rel->cleanup();
|
||||
if (m_tab.get()) m_tab->cleanup();
|
||||
if (m_rel.get()) m_rel->set_cancel(false);
|
||||
}
|
||||
|
||||
class context::engine_type_proc {
|
||||
|
@ -1031,6 +1059,8 @@ namespace datalog {
|
|||
}
|
||||
|
||||
void context::new_query() {
|
||||
m_mc = mk_skip_model_converter();
|
||||
|
||||
flush_add_rules();
|
||||
m_last_status = OK;
|
||||
m_last_answer = 0;
|
||||
|
@ -1142,6 +1172,7 @@ namespace datalog {
|
|||
switch(get_engine()) {
|
||||
case DATALOG_ENGINE:
|
||||
return false;
|
||||
case PDR_ENGINE:
|
||||
case QPDR_ENGINE:
|
||||
ensure_pdr();
|
||||
m_pdr->display_certificate(out);
|
||||
|
@ -1160,6 +1191,20 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
void context::display_profile(std::ostream& out) const {
|
||||
out << "\n---------------\n";
|
||||
out << "Original rules\n";
|
||||
display_rules(out);
|
||||
|
||||
out << "\n---------------\n";
|
||||
out << "Transformed rules\n";
|
||||
m_transformed_rule_set.display(out);
|
||||
|
||||
if (m_rel) {
|
||||
m_rel->display_profile(out);
|
||||
}
|
||||
}
|
||||
|
||||
void context::reset_statistics() {
|
||||
if (m_pdr) {
|
||||
m_pdr->reset_statistics();
|
||||
|
@ -1192,7 +1237,7 @@ namespace datalog {
|
|||
return m_rel->result_contains_fact(f);
|
||||
}
|
||||
|
||||
// TBD: algebraic data-types declarations will not be printed.
|
||||
// NB: algebraic data-types declarations will not be printed.
|
||||
class free_func_visitor {
|
||||
ast_manager& m;
|
||||
func_decl_set m_funcs;
|
||||
|
@ -1235,7 +1280,7 @@ namespace datalog {
|
|||
ptr_vector<sort> sorts;
|
||||
get_free_vars(m_rule_fmls[i].get(), sorts);
|
||||
if (!sorts.empty()) {
|
||||
rm.mk_rule(m_rule_fmls[i].get(), rule_refs, m_rule_names[i]);
|
||||
rm.mk_rule(m_rule_fmls[i].get(), 0, rule_refs, m_rule_names[i]);
|
||||
m_rule_fmls[i] = m_rule_fmls.back();
|
||||
m_rule_names[i] = m_rule_names.back();
|
||||
m_rule_fmls.pop_back();
|
||||
|
@ -1252,7 +1297,7 @@ namespace datalog {
|
|||
}
|
||||
for (unsigned i = 0; i < m_rule_fmls.size(); ++i) {
|
||||
rules.push_back(m_rule_fmls[i].get());
|
||||
names.push_back(m_rule_names[i]);
|
||||
names.push_back(m_rule_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,19 +42,18 @@ Revision History:
|
|||
#include"params.h"
|
||||
#include"trail.h"
|
||||
#include"model_converter.h"
|
||||
#include"proof_converter.h"
|
||||
#include"model2expr.h"
|
||||
#include"smt_params.h"
|
||||
#include"dl_rule_transformer.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
class rule_transformer;
|
||||
|
||||
enum execution_result {
|
||||
OK,
|
||||
TIMEOUT,
|
||||
MEMOUT,
|
||||
INPUT_ERROR
|
||||
INPUT_ERROR,
|
||||
CANCELED
|
||||
};
|
||||
|
||||
class context {
|
||||
|
@ -85,7 +84,7 @@ namespace datalog {
|
|||
th_rewriter m_rewriter;
|
||||
var_subst m_var_subst;
|
||||
rule_manager m_rule_manager;
|
||||
|
||||
rule_transformer m_transf;
|
||||
trail_stack<context> m_trail;
|
||||
ast_ref_vector m_pinned;
|
||||
app_ref_vector m_vars;
|
||||
|
@ -94,9 +93,12 @@ namespace datalog {
|
|||
sym2decl m_preds_by_name;
|
||||
pred2syms m_argument_var_names;
|
||||
rule_set m_rule_set;
|
||||
rule_set m_transformed_rule_set;
|
||||
expr_ref_vector m_rule_fmls;
|
||||
svector<symbol> m_rule_names;
|
||||
expr_ref_vector m_background;
|
||||
model_converter_ref m_mc;
|
||||
proof_converter_ref m_pc;
|
||||
|
||||
scoped_ptr<pdr::dl_interface> m_pdr;
|
||||
scoped_ptr<bmc> m_bmc;
|
||||
|
@ -110,6 +112,8 @@ namespace datalog {
|
|||
DL_ENGINE m_engine;
|
||||
volatile bool m_cancel;
|
||||
|
||||
|
||||
|
||||
bool is_fact(app * head) const;
|
||||
bool has_sort_domain(relation_sort s) const;
|
||||
sort_domain & get_sort_domain(relation_sort s);
|
||||
|
@ -140,6 +144,7 @@ namespace datalog {
|
|||
var_subst & get_var_subst() { return m_var_subst; }
|
||||
dl_decl_util & get_decl_util() { return m_decl_util; }
|
||||
|
||||
bool generate_proof_trace() const { return m_params.generate_proof_trace(); }
|
||||
bool output_profile() const { return m_params.output_profile(); }
|
||||
bool fix_unbound_vars() const { return m_params.fix_unbound_vars(); }
|
||||
symbol default_table() const { return m_params.default_table(); }
|
||||
|
@ -178,18 +183,22 @@ namespace datalog {
|
|||
retrieved by the try_get_predicate_decl() function. Auxiliary predicates introduced
|
||||
e.g. by rule transformations do not need to be named.
|
||||
*/
|
||||
void register_predicate(func_decl * pred, bool named = true);
|
||||
void register_predicate(func_decl * pred, bool named);
|
||||
|
||||
bool is_predicate(func_decl * pred) const;
|
||||
|
||||
|
||||
/**
|
||||
\brief If a predicate name has a \c func_decl object assigned, return pointer to it;
|
||||
otherwise return 0.
|
||||
|
||||
|
||||
Not all \c func_decl object used as relation identifiers need to be assigned to their
|
||||
names. Generally, the names coming from the parses are registered here.
|
||||
*/
|
||||
func_decl * try_get_predicate_decl(symbol pred_name) const;
|
||||
*/
|
||||
func_decl * try_get_predicate_decl(symbol const& pred_name) const {
|
||||
func_decl * res = 0;
|
||||
m_preds_by_name.find(pred_name, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create a fresh head predicate declaration.
|
||||
|
@ -240,6 +249,7 @@ namespace datalog {
|
|||
void add_fact(app * head);
|
||||
void add_fact(func_decl * pred, const relation_fact & fact);
|
||||
|
||||
bool has_facts(func_decl * pred) const;
|
||||
|
||||
void add_rule(rule_ref& r);
|
||||
void add_rules(rule_ref_vector& rs);
|
||||
|
@ -313,11 +323,17 @@ namespace datalog {
|
|||
void reopen();
|
||||
void ensure_opened();
|
||||
|
||||
void transform_rules(model_converter_ref& mc, proof_converter_ref& pc);
|
||||
void transform_rules(rule_transformer& trans, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
void replace_rules(rule_set & rs);
|
||||
model_converter_ref& get_model_converter() { return m_mc; }
|
||||
void add_model_converter(model_converter* mc) { m_mc = concat(m_mc.get(), mc); }
|
||||
proof_converter_ref& get_proof_converter() { return m_pc; }
|
||||
void add_proof_converter(proof_converter* pc) { m_pc = concat(m_pc.get(), pc); }
|
||||
|
||||
void apply_default_transformation(model_converter_ref& mc, proof_converter_ref& pc);
|
||||
void transform_rules();
|
||||
void transform_rules(rule_transformer& transf);
|
||||
void replace_rules(rule_set & rs);
|
||||
void record_transformed_rules();
|
||||
|
||||
void apply_default_transformation();
|
||||
|
||||
void collect_params(param_descrs& r);
|
||||
|
||||
|
@ -342,6 +358,8 @@ namespace datalog {
|
|||
|
||||
void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out);
|
||||
|
||||
void display_profile(std::ostream& out) const;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// basic usage methods
|
||||
|
@ -349,6 +367,7 @@ namespace datalog {
|
|||
// -----------------------------------
|
||||
|
||||
void cancel();
|
||||
bool canceled() const { return m_cancel; }
|
||||
|
||||
void cleanup();
|
||||
void reset_cancel() { cleanup(); }
|
||||
|
|
|
@ -58,14 +58,18 @@ namespace datalog {
|
|||
reset_timelimit();
|
||||
}
|
||||
|
||||
rel_context& execution_context::get_rel_context() {
|
||||
return m_context.get_rel_context();
|
||||
}
|
||||
|
||||
struct compare_size_proc {
|
||||
typedef std::pair<unsigned, unsigned> pr;
|
||||
bool operator()(pr const& a, pr const& b) const {
|
||||
return a.second > b.second;
|
||||
}
|
||||
|
||||
};
|
||||
void execution_context::report_big_relations(unsigned threshold, std::ostream & out) {
|
||||
|
||||
void execution_context::report_big_relations(unsigned threshold, std::ostream & out) const {
|
||||
unsigned n = register_count();
|
||||
svector<std::pair<unsigned, unsigned> > sizes;
|
||||
size_t total_bytes = 0;
|
||||
|
@ -110,6 +114,7 @@ namespace datalog {
|
|||
|
||||
bool execution_context::should_terminate() {
|
||||
return
|
||||
m_context.canceled() ||
|
||||
memory::above_high_watermark() ||
|
||||
(m_stopwatch &&
|
||||
m_timelimit_ms != 0 &&
|
||||
|
@ -135,7 +140,7 @@ namespace datalog {
|
|||
process_costs();
|
||||
}
|
||||
|
||||
void instruction::display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const {
|
||||
void instruction::display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const {
|
||||
out << indentation;
|
||||
display_head_impl(ctx, out);
|
||||
if (ctx.output_profile()) {
|
||||
|
@ -182,7 +187,7 @@ namespace datalog {
|
|||
virtual void make_annotations(execution_context & ctx) {
|
||||
ctx.set_register_annotation(m_reg, m_pred->get_name().bare_str());
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
const char * rel_name = m_pred->get_name().bare_str();
|
||||
if (m_store) {
|
||||
out << "store " << m_reg << " into " << rel_name;
|
||||
|
@ -213,7 +218,7 @@ namespace datalog {
|
|||
virtual void make_annotations(execution_context & ctx) {
|
||||
ctx.set_register_annotation(m_reg, "alloc");
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "dealloc " << m_reg;
|
||||
}
|
||||
};
|
||||
|
@ -248,7 +253,7 @@ namespace datalog {
|
|||
ctx.set_register_annotation(m_src, str);
|
||||
}
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << (m_clone ? "clone " : "move ") << m_src << " into " << m_tgt;
|
||||
}
|
||||
};
|
||||
|
@ -304,11 +309,11 @@ namespace datalog {
|
|||
virtual void make_annotations(execution_context & ctx) {
|
||||
m_body->make_annotations(ctx);
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const {
|
||||
out << "while";
|
||||
print_container(m_controls, out);
|
||||
}
|
||||
virtual void display_body_impl(rel_context & ctx, std::ostream & out, std::string indentation) const {
|
||||
virtual void display_body_impl(rel_context const & ctx, std::ostream & out, std::string indentation) const {
|
||||
m_body->display_indented(ctx, out, indentation+" ");
|
||||
}
|
||||
};
|
||||
|
@ -385,7 +390,7 @@ namespace datalog {
|
|||
ctx.get_register_annotation(m_rel1, a1);
|
||||
ctx.set_register_annotation(m_res, "join " + a1 + " " + a2);
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const {
|
||||
out << "join " << m_rel1;
|
||||
print_container(m_cols1, out);
|
||||
out << " and " << m_rel2;
|
||||
|
@ -434,7 +439,7 @@ namespace datalog {
|
|||
a << "filter_equal " << m_col << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value);
|
||||
ctx.set_register_annotation(m_reg, a.str());
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "filter_equal " << m_reg << " col: " << m_col << " val: "
|
||||
<< ctx.get_rmanager().to_nice_string(m_value);
|
||||
}
|
||||
|
@ -476,7 +481,7 @@ namespace datalog {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "filter_identical " << m_reg << " ";
|
||||
print_container(m_cols, out);
|
||||
}
|
||||
|
@ -519,7 +524,7 @@ namespace datalog {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "filter_interpreted " << m_reg << " using "
|
||||
<< mk_pp(m_cond, m_cond.get_manager());
|
||||
}
|
||||
|
@ -619,12 +624,16 @@ namespace datalog {
|
|||
return true;
|
||||
}
|
||||
virtual void make_annotations(execution_context & ctx) {
|
||||
std::string str;
|
||||
if (ctx.get_register_annotation(m_tgt, str) && m_delta!=execution_context::void_register) {
|
||||
ctx.set_register_annotation(m_delta, "delta of "+str);
|
||||
std::string str = "union";
|
||||
if (!ctx.get_register_annotation(m_tgt, str)) {
|
||||
ctx.set_register_annotation(m_tgt, "union");
|
||||
}
|
||||
if (m_delta != execution_context::void_register) {
|
||||
str = "delta of " + str;
|
||||
}
|
||||
ctx.set_register_annotation(m_delta, str);
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << (m_widen ? "widen " : "union ") << m_src << " into " << m_tgt;
|
||||
if (m_delta!=execution_context::void_register) {
|
||||
out << " with delta " << m_delta;
|
||||
|
@ -678,7 +687,7 @@ namespace datalog {
|
|||
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << (m_projection ? "project " : "rename ") << m_src << " into " << m_tgt;
|
||||
out << (m_projection ? " deleting columns " : " with cycle ");
|
||||
print_container(m_cols, out);
|
||||
|
@ -739,7 +748,7 @@ namespace datalog {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "join_project " << m_rel1;
|
||||
print_container(m_cols1, out);
|
||||
out << " and " << m_rel2;
|
||||
|
@ -800,7 +809,7 @@ namespace datalog {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "select_equal_and_project " << m_src <<" into " << m_result << " col: " << m_col
|
||||
<< " val: " << ctx.get_rmanager().to_nice_string(m_value);
|
||||
}
|
||||
|
@ -854,7 +863,7 @@ namespace datalog {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "filter_by_negation on " << m_tgt;
|
||||
print_container(m_cols1, out);
|
||||
out << " with " << m_neg_rel;
|
||||
|
@ -892,7 +901,7 @@ namespace datalog {
|
|||
ctx.set_reg(m_tgt, rel);
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "mk_unary_singleton into " << m_tgt << " sort:"
|
||||
<< ctx.get_rmanager().to_nice_string(m_sig[0]) << " val:"
|
||||
<< ctx.get_rmanager().to_nice_string(m_sig[0], m_fact[0]);
|
||||
|
@ -922,7 +931,7 @@ namespace datalog {
|
|||
ctx.set_reg(m_tgt, ctx.get_rel_context().get_rmanager().mk_full_relation(m_sig, m_pred));
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "mk_total into " << m_tgt << " sort:"
|
||||
<< ctx.get_rmanager().to_nice_string(m_sig);
|
||||
}
|
||||
|
@ -947,7 +956,7 @@ namespace datalog {
|
|||
ctx.get_rel_context().get_rmanager().mark_saturated(m_pred);
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "mark_saturated " << m_pred->get_name().bare_str();
|
||||
}
|
||||
virtual void make_annotations(execution_context & ctx) {
|
||||
|
@ -970,7 +979,7 @@ namespace datalog {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const {
|
||||
out << "instr_assert_signature of " << m_tgt << " signature:";
|
||||
print_container(m_sig, out);
|
||||
}
|
||||
|
@ -1042,7 +1051,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
void instruction_block::display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const {
|
||||
void instruction_block::display_indented(rel_context const& ctx, std::ostream & out, std::string indentation) const {
|
||||
instr_seq_type::const_iterator it = m_data.begin();
|
||||
instr_seq_type::const_iterator end = m_data.end();
|
||||
for(; it!=end; ++it) {
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace datalog {
|
|||
|
||||
class execution_context;
|
||||
class instruction_block;
|
||||
class rel_context;
|
||||
|
||||
inline void check_overflow(unsigned i) {
|
||||
if (i == UINT_MAX) {
|
||||
|
@ -78,7 +79,7 @@ namespace datalog {
|
|||
|
||||
void reset();
|
||||
|
||||
rel_context & get_rel_context() { return m_context.get_rel_context(); };
|
||||
rel_context & get_rel_context();
|
||||
|
||||
void set_timelimit(unsigned time_in_ms);
|
||||
void reset_timelimit();
|
||||
|
@ -91,10 +92,9 @@ namespace datalog {
|
|||
|
||||
If register contains zero, it should be treated as if it contains an empty relation.
|
||||
*/
|
||||
reg_type reg(reg_idx i) {
|
||||
if (i>=m_registers.size()) {
|
||||
check_overflow(i);
|
||||
m_registers.resize(i+1,0);
|
||||
reg_type reg(reg_idx i) const {
|
||||
if (i >= m_registers.size()) {
|
||||
return 0;
|
||||
}
|
||||
return m_registers[i];
|
||||
}
|
||||
|
@ -102,27 +102,29 @@ namespace datalog {
|
|||
\brief Return value of the register and assign zero into it place.
|
||||
*/
|
||||
reg_type release_reg(reg_idx i) {
|
||||
SASSERT(i<m_registers.size());
|
||||
SASSERT(i < m_registers.size());
|
||||
SASSERT(m_registers[i]);
|
||||
reg_type res = m_registers[i];
|
||||
m_registers[i] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Assign value to a register. If it was non-empty, deallocate its content first.
|
||||
*/
|
||||
void set_reg(reg_idx i, reg_type val) {
|
||||
if(i>=m_registers.size()) {
|
||||
if (i >= m_registers.size()) {
|
||||
check_overflow(i);
|
||||
m_registers.resize(i+1,0);
|
||||
}
|
||||
if(m_registers[i]) {
|
||||
if (m_registers[i]) {
|
||||
m_registers[i]->deallocate();
|
||||
}
|
||||
m_registers[i]=val;
|
||||
m_registers[i] = val;
|
||||
}
|
||||
|
||||
void make_empty(reg_idx i) {
|
||||
if(reg(i)) {
|
||||
if (reg(i)) {
|
||||
set_reg(i, 0);
|
||||
}
|
||||
}
|
||||
|
@ -130,14 +132,16 @@ namespace datalog {
|
|||
unsigned register_count() const {
|
||||
return m_registers.size();
|
||||
}
|
||||
|
||||
bool get_register_annotation(reg_idx reg, std::string & res) const {
|
||||
return m_reg_annotation.find(reg, res);
|
||||
}
|
||||
|
||||
void set_register_annotation(reg_idx reg, std::string str) {
|
||||
m_reg_annotation.insert(reg, str);
|
||||
}
|
||||
|
||||
void report_big_relations(unsigned threshold, std::ostream & out);
|
||||
void report_big_relations(unsigned threshold, std::ostream & out) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -208,7 +212,7 @@ namespace datalog {
|
|||
|
||||
The newline character at the end should not be printed.
|
||||
*/
|
||||
virtual void display_head_impl(rel_context & ctx, std::ostream & out) const {
|
||||
virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const {
|
||||
out << "<instruction>";
|
||||
}
|
||||
/**
|
||||
|
@ -216,7 +220,7 @@ namespace datalog {
|
|||
|
||||
Each line must be prepended by \c indentation and ended by a newline character.
|
||||
*/
|
||||
virtual void display_body_impl(rel_context & ctx, std::ostream & out, std::string indentation) const {}
|
||||
virtual void display_body_impl(rel_context const & ctx, std::ostream & out, std::string indentation) const {}
|
||||
public:
|
||||
typedef execution_context::reg_type reg_type;
|
||||
typedef execution_context::reg_idx reg_idx;
|
||||
|
@ -227,10 +231,10 @@ namespace datalog {
|
|||
|
||||
virtual void make_annotations(execution_context & ctx) = 0;
|
||||
|
||||
void display(rel_context & ctx, std::ostream & out) const {
|
||||
void display(rel_context const& ctx, std::ostream & out) const {
|
||||
display_indented(ctx, out, "");
|
||||
}
|
||||
void display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const;
|
||||
void display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const;
|
||||
|
||||
static instruction * mk_load(ast_manager & m, func_decl * pred, reg_idx tgt);
|
||||
/**
|
||||
|
@ -329,10 +333,10 @@ namespace datalog {
|
|||
|
||||
void make_annotations(execution_context & ctx);
|
||||
|
||||
void display(rel_context & ctx, std::ostream & out) const {
|
||||
void display(rel_context const & ctx, std::ostream & out) const {
|
||||
display_indented(ctx, out, "");
|
||||
}
|
||||
void display_indented(rel_context & ctx, std::ostream & out, std::string indentation) const;
|
||||
void display_indented(rel_context const & ctx, std::ostream & out, std::string indentation) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
|||
#include "optional.h"
|
||||
#include "ast_pp.h"
|
||||
#include "dl_interval_relation.h"
|
||||
#include "bool_rewriter.h"
|
||||
|
||||
|
||||
namespace datalog {
|
||||
|
@ -30,8 +31,7 @@ namespace datalog {
|
|||
interval_relation_plugin::interval_relation_plugin(relation_manager& m):
|
||||
relation_plugin(interval_relation_plugin::get_name(), m),
|
||||
m_empty(m_dep),
|
||||
m_arith(get_ast_manager()),
|
||||
m_bsimp(get_ast_manager()) {
|
||||
m_arith(get_ast_manager()) {
|
||||
}
|
||||
|
||||
bool interval_relation_plugin::can_handle_signature(const relation_signature & sig) {
|
||||
|
@ -374,7 +374,6 @@ namespace datalog {
|
|||
void interval_relation::to_formula(expr_ref& fml) const {
|
||||
ast_manager& m = get_plugin().get_ast_manager();
|
||||
arith_util& arith = get_plugin().m_arith;
|
||||
basic_simplifier_plugin& bsimp = get_plugin().m_bsimp;
|
||||
expr_ref_vector conjs(m);
|
||||
relation_signature const& sig = get_signature();
|
||||
for (unsigned i = 0; i < sig.size(); ++i) {
|
||||
|
@ -405,7 +404,8 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
}
|
||||
bsimp.mk_and(conjs.size(), conjs.c_ptr(), fml);
|
||||
bool_rewriter br(m);
|
||||
br.mk_and(conjs.size(), conjs.c_ptr(), fml);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ namespace datalog {
|
|||
v_dependency_manager m_dep;
|
||||
interval m_empty;
|
||||
arith_util m_arith;
|
||||
basic_simplifier_plugin m_bsimp;
|
||||
|
||||
class join_fn;
|
||||
class project_fn;
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace datalog {
|
|||
m(ctx.get_manager()),
|
||||
a(m),
|
||||
rm(ctx.get_rule_manager()),
|
||||
m_rewriter(m, m_params){
|
||||
m_rewriter(m, m_params),
|
||||
m_simplifier(ctx) {
|
||||
m_params.set_bool("expand_select_store",true);
|
||||
m_rewriter.updt_params(m_params);
|
||||
}
|
||||
|
@ -197,39 +198,31 @@ namespace datalog {
|
|||
}
|
||||
|
||||
fml2 = m.mk_implies(body, head);
|
||||
rm.mk_rule(fml2, new_rules, r.name());
|
||||
proof_ref p(m);
|
||||
rm.mk_rule(fml2, p, new_rules, r.name());
|
||||
SASSERT(new_rules.size() == 1);
|
||||
|
||||
TRACE("dl", new_rules[0]->display(m_ctx, tout << "new rule\n"););
|
||||
|
||||
rules.add_rule(new_rules[0].get());
|
||||
if (m_pc) {
|
||||
new_rules[0]->to_formula(fml2);
|
||||
m_pc->insert(fml1, fml2);
|
||||
rule_ref new_rule(rm);
|
||||
if (m_simplifier.transform_rule(new_rules[0].get(), new_rule)) {
|
||||
rules.add_rule(new_rule.get());
|
||||
rm.mk_rule_rewrite_proof(r, *new_rule.get());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
rule_set * mk_array_blast::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
ref<equiv_proof_converter> epc;
|
||||
if (pc) {
|
||||
epc = alloc(equiv_proof_converter, m);
|
||||
}
|
||||
m_pc = epc.get();
|
||||
rule_set * mk_array_blast::operator()(rule_set const & source) {
|
||||
|
||||
rule_set* rules = alloc(rule_set, m_ctx);
|
||||
rule_set::iterator it = source.begin(), end = source.end();
|
||||
bool change = false;
|
||||
for (; it != end; ++it) {
|
||||
for (; !m_ctx.canceled() && it != end; ++it) {
|
||||
change = blast(**it, *rules) || change;
|
||||
}
|
||||
if (!change) {
|
||||
dealloc(rules);
|
||||
rules = 0;
|
||||
}
|
||||
if (pc) {
|
||||
pc = concat(pc.get(), epc.get());
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ Revision History:
|
|||
#include"dl_context.h"
|
||||
#include"dl_rule_set.h"
|
||||
#include"dl_rule_transformer.h"
|
||||
#include"dl_mk_interp_tail_simplifier.h"
|
||||
#include "equiv_proof_converter.h"
|
||||
#include "array_decl_plugin.h"
|
||||
|
||||
|
@ -37,7 +38,7 @@ namespace datalog {
|
|||
rule_manager& rm;
|
||||
params_ref m_params;
|
||||
th_rewriter m_rewriter;
|
||||
equiv_proof_converter* m_pc;
|
||||
mk_interp_tail_simplifier m_simplifier;
|
||||
|
||||
typedef obj_map<app, var*> defs_t;
|
||||
|
||||
|
@ -49,13 +50,13 @@ namespace datalog {
|
|||
|
||||
public:
|
||||
/**
|
||||
\brief Create rule transformer that extracts universal quantifiers (over recursive predicates).
|
||||
\brief Create rule transformer that removes array stores and selects by ackermannization.
|
||||
*/
|
||||
mk_array_blast(context & ctx, unsigned priority);
|
||||
|
||||
virtual ~mk_array_blast();
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ Revision History:
|
|||
#include "bit_blaster_rewriter.h"
|
||||
#include "rewriter_def.h"
|
||||
#include "ast_pp.h"
|
||||
|
||||
#include "expr_safe_replace.h"
|
||||
#include "filter_model_converter.h"
|
||||
#include "dl_mk_interp_tail_simplifier.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
@ -35,6 +37,73 @@ namespace datalog {
|
|||
// P(bv(x,y)) :- P_bv(x,y)
|
||||
// Query
|
||||
|
||||
// this model converter should be composed with a filter converter
|
||||
// that gets rid of the new functions.
|
||||
class bit_blast_model_converter : public model_converter {
|
||||
ast_manager& m;
|
||||
bv_util m_bv;
|
||||
func_decl_ref_vector m_old_funcs;
|
||||
func_decl_ref_vector m_new_funcs;
|
||||
public:
|
||||
bit_blast_model_converter(ast_manager& m):
|
||||
m(m),
|
||||
m_bv(m),
|
||||
m_old_funcs(m),
|
||||
m_new_funcs(m) {}
|
||||
|
||||
void insert(func_decl* old_f, func_decl* new_f) {
|
||||
m_old_funcs.push_back(old_f);
|
||||
m_new_funcs.push_back(new_f);
|
||||
}
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator) {
|
||||
return alloc(bit_blast_model_converter, m);
|
||||
}
|
||||
|
||||
virtual void operator()(model_ref & model) {
|
||||
for (unsigned i = 0; i < m_new_funcs.size(); ++i) {
|
||||
func_decl* p = m_new_funcs[i].get();
|
||||
func_decl* q = m_old_funcs[i].get();
|
||||
func_interp* f = model->get_func_interp(p);
|
||||
expr_ref body(m);
|
||||
unsigned arity_p = p->get_arity();
|
||||
unsigned arity_q = q->get_arity();
|
||||
SASSERT(0 < arity_p);
|
||||
model->register_decl(p, f);
|
||||
func_interp* g = alloc(func_interp, m, arity_q);
|
||||
|
||||
if (f) {
|
||||
body = f->get_interp();
|
||||
SASSERT(!f->is_partial());
|
||||
SASSERT(body);
|
||||
}
|
||||
else {
|
||||
body = m.mk_false();
|
||||
}
|
||||
unsigned idx = 0;
|
||||
expr_ref arg(m), proj(m);
|
||||
expr_safe_replace sub(m);
|
||||
for (unsigned j = 0; j < arity_q; ++j) {
|
||||
sort* s = q->get_domain(j);
|
||||
arg = m.mk_var(j, s);
|
||||
if (m_bv.is_bv_sort(s)) {
|
||||
expr* args[1] = { arg };
|
||||
unsigned sz = m_bv.get_bv_size(s);
|
||||
for (unsigned k = 0; k < sz; ++k) {
|
||||
proj = m.mk_app(m_bv.get_family_id(), OP_BIT2BOOL, 1, args);
|
||||
sub.insert(m.mk_var(idx++, m.mk_bool_sort()), proj);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sub.insert(m.mk_var(idx++, s), arg);
|
||||
}
|
||||
}
|
||||
sub(body);
|
||||
g->set_else(body);
|
||||
model->register_decl(q, g);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class expand_mkbv_cfg : public default_rewriter_cfg {
|
||||
|
||||
|
@ -43,7 +112,8 @@ namespace datalog {
|
|||
ast_manager& m;
|
||||
bv_util m_util;
|
||||
expr_ref_vector m_args, m_f_vars, m_g_vars;
|
||||
func_decl_ref_vector m_pinned;
|
||||
func_decl_ref_vector m_old_funcs;
|
||||
func_decl_ref_vector m_new_funcs;
|
||||
obj_map<func_decl,func_decl*> m_pred2blast;
|
||||
|
||||
|
||||
|
@ -57,10 +127,14 @@ namespace datalog {
|
|||
m_args(m),
|
||||
m_f_vars(m),
|
||||
m_g_vars(m),
|
||||
m_pinned(m)
|
||||
m_old_funcs(m),
|
||||
m_new_funcs(m)
|
||||
{}
|
||||
|
||||
~expand_mkbv_cfg() {}
|
||||
|
||||
func_decl_ref_vector const& old_funcs() const { return m_old_funcs; }
|
||||
func_decl_ref_vector const& new_funcs() const { return m_new_funcs; }
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
rule_manager& rm = m_context.get_rule_manager();
|
||||
|
@ -105,13 +179,18 @@ namespace datalog {
|
|||
domain.push_back(m.get_sort(m_args[i].get()));
|
||||
}
|
||||
g = m_context.mk_fresh_head_predicate(f->get_name(), symbol("bv"), m_args.size(), domain.c_ptr(), f);
|
||||
m_pinned.push_back(g);
|
||||
m_old_funcs.push_back(f);
|
||||
m_new_funcs.push_back(g);
|
||||
m_pred2blast.insert(f, g);
|
||||
|
||||
// Create rule f(mk_mkbv(args)) :- g(args)
|
||||
|
||||
fml = m.mk_implies(m.mk_app(g, m_g_vars.size(), m_g_vars.c_ptr()), m.mk_app(f, m_f_vars.size(), m_f_vars.c_ptr()));
|
||||
rm.mk_rule(fml, m_rules, g->get_name());
|
||||
proof_ref pr(m);
|
||||
if (m_context.generate_proof_trace()) {
|
||||
pr = m.mk_asserted(fml); // or a def?
|
||||
}
|
||||
rm.mk_rule(fml, pr, m_rules, g->get_name());
|
||||
}
|
||||
result = m.mk_app(g, m_args.size(), m_args.c_ptr());
|
||||
result_pr = 0;
|
||||
|
@ -134,18 +213,25 @@ namespace datalog {
|
|||
ast_manager & m;
|
||||
params_ref m_params;
|
||||
rule_ref_vector m_rules;
|
||||
mk_interp_tail_simplifier m_simplifier;
|
||||
bit_blaster_rewriter m_blaster;
|
||||
expand_mkbv m_rewriter;
|
||||
|
||||
|
||||
bool blast(expr_ref& fml) {
|
||||
bool blast(rule *r, expr_ref& fml) {
|
||||
proof_ref pr(m);
|
||||
expr_ref fml1(m), fml2(m);
|
||||
m_blaster(fml, fml1, pr);
|
||||
m_rewriter(fml1, fml2);
|
||||
TRACE("dl", tout << mk_pp(fml, m) << " -> " << mk_pp(fml1, m) << " -> " << mk_pp(fml2, m) << "\n";);
|
||||
if (fml2 != fml) {
|
||||
fml = fml2;
|
||||
expr_ref fml1(m), fml2(m), fml3(m);
|
||||
rule_ref r2(m_context.get_rule_manager());
|
||||
// We need to simplify rule before bit-blasting.
|
||||
if (!m_simplifier.transform_rule(r, r2)) {
|
||||
r2 = r;
|
||||
}
|
||||
r2->to_formula(fml1);
|
||||
m_blaster(fml1, fml2, pr);
|
||||
m_rewriter(fml2, fml3);
|
||||
TRACE("dl", tout << mk_pp(fml, m) << " -> " << mk_pp(fml2, m) << " -> " << mk_pp(fml3, m) << "\n";);
|
||||
if (fml3 != fml) {
|
||||
fml = fml3;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -163,6 +249,7 @@ namespace datalog {
|
|||
m(ctx.get_manager()),
|
||||
m_params(ctx.get_params().p),
|
||||
m_rules(ctx.get_rule_manager()),
|
||||
m_simplifier(ctx),
|
||||
m_blaster(ctx.get_manager(), m_params),
|
||||
m_rewriter(ctx.get_manager(), ctx, m_rules) {
|
||||
m_params.set_bool("blast_full", true);
|
||||
|
@ -170,24 +257,25 @@ namespace datalog {
|
|||
m_blaster.updt_params(m_params);
|
||||
}
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
// TODO mc, pc
|
||||
rule_set * operator()(rule_set const & source) {
|
||||
// TODO pc
|
||||
if (!m_context.get_params().bit_blast()) {
|
||||
return 0;
|
||||
}
|
||||
if (m_context.get_engine() != PDR_ENGINE) {
|
||||
return 0;
|
||||
}
|
||||
rule_manager& rm = m_context.get_rule_manager();
|
||||
unsigned sz = source.get_num_rules();
|
||||
expr_ref fml(m);
|
||||
reset();
|
||||
rule_set * result = alloc(rule_set, m_context);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
for (unsigned i = 0; !m_context.canceled() && i < sz; ++i) {
|
||||
rule * r = source.get_rule(i);
|
||||
r->to_formula(fml);
|
||||
if (blast(fml)) {
|
||||
rm.mk_rule(fml, m_rules, r->name());
|
||||
r->to_formula(fml);
|
||||
if (blast(r, fml)) {
|
||||
proof_ref pr(m);
|
||||
if (m_context.generate_proof_trace()) {
|
||||
pr = m.mk_asserted(fml); // loses original proof of r.
|
||||
}
|
||||
rm.mk_rule(fml, pr, m_rules, r->name());
|
||||
}
|
||||
else {
|
||||
m_rules.push_back(r);
|
||||
|
@ -197,6 +285,18 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < m_rules.size(); ++i) {
|
||||
result->add_rule(m_rules.get(i));
|
||||
}
|
||||
|
||||
if (m_context.get_model_converter()) {
|
||||
filter_model_converter* fmc = alloc(filter_model_converter, m);
|
||||
bit_blast_model_converter* bvmc = alloc(bit_blast_model_converter, m);
|
||||
func_decl_ref_vector const& old_funcs = m_rewriter.m_cfg.old_funcs();
|
||||
func_decl_ref_vector const& new_funcs = m_rewriter.m_cfg.new_funcs();
|
||||
for (unsigned i = 0; i < old_funcs.size(); ++i) {
|
||||
fmc->insert(new_funcs[i]);
|
||||
bvmc->insert(old_funcs[i], new_funcs[i]);
|
||||
}
|
||||
m_context.add_model_converter(concat(bvmc, fmc));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -210,8 +310,8 @@ namespace datalog {
|
|||
dealloc(m_impl);
|
||||
}
|
||||
|
||||
rule_set * mk_bit_blast::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
return (*m_impl)(source, mc, pc);
|
||||
rule_set * mk_bit_blast::operator()(rule_set const & source) {
|
||||
return (*m_impl)(source);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
Functor for bit-blasting a rule set
|
||||
|
||||
Author:
|
||||
|
||||
|
@ -19,32 +19,17 @@ Revision History:
|
|||
#ifndef _DL_MK_BIT_BLAST_H_
|
||||
#define _DL_MK_BIT_BLAST_H_
|
||||
|
||||
#include<utility>
|
||||
|
||||
#include"map.h"
|
||||
#include"obj_pair_hashtable.h"
|
||||
#include"dl_context.h"
|
||||
#include"dl_rule_set.h"
|
||||
#include"dl_rule_transformer.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
/**
|
||||
\brief Functor for bit-blasting a rule set.
|
||||
*/
|
||||
|
||||
class mk_bit_blast : public rule_transformer::plugin {
|
||||
class impl;
|
||||
|
||||
impl* m_impl;
|
||||
void blast(expr_ref& b);
|
||||
void reset();
|
||||
|
||||
impl* m_impl;
|
||||
public:
|
||||
mk_bit_blast(context & ctx, unsigned priority = 35000);
|
||||
~mk_bit_blast();
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
~mk_bit_blast();
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace datalog {
|
|||
tail.push_back(to_app(fml));
|
||||
is_neg.push_back(false);
|
||||
res = rm.mk(head, tail.size(), tail.c_ptr(), is_neg.c_ptr(), tgt->name());
|
||||
if (m_pc) {
|
||||
if (m_ctx.generate_proof_trace()) {
|
||||
src.to_formula(fml1);
|
||||
tgt->to_formula(fml2);
|
||||
res->to_formula(fml);
|
||||
|
@ -142,12 +142,13 @@ namespace datalog {
|
|||
sort* domain[3] = { ps, ps, m.mk_bool_sort() };
|
||||
func_decl* merge = m.mk_func_decl(symbol("merge-clauses"), 3, domain, ps); // TBD: ad-hoc proof rule
|
||||
expr* args[3] = { m.mk_asserted(fml1), m.mk_asserted(fml2), fml };
|
||||
m_pc->insert(m.mk_app(merge, 3, args));
|
||||
// ...m_pc->insert(m.mk_app(merge, 3, args));
|
||||
#else
|
||||
svector<std::pair<unsigned, unsigned> > pos;
|
||||
vector<expr_ref_vector> substs;
|
||||
proof* p = m.mk_asserted(fml1);
|
||||
m_pc->insert(m.mk_hyper_resolve(1, &p, fml, pos, substs));
|
||||
proof* p = src.get_proof();
|
||||
p = m.mk_hyper_resolve(1, &p, fml, pos, substs);
|
||||
res->set_proof(m, p);
|
||||
#endif
|
||||
}
|
||||
tgt = res;
|
||||
|
@ -170,13 +171,7 @@ namespace datalog {
|
|||
return true;
|
||||
}
|
||||
|
||||
rule_set * mk_coalesce::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
m_pc = 0;
|
||||
ref<replace_proof_converter> rpc;
|
||||
if (pc) {
|
||||
rpc = alloc(replace_proof_converter, m);
|
||||
m_pc = rpc.get();
|
||||
}
|
||||
rule_set * mk_coalesce::operator()(rule_set const & source) {
|
||||
rule_set* rules = alloc(rule_set, m_ctx);
|
||||
rule_set::decl2rules::iterator it = source.begin_grouped_rules(), end = source.end_grouped_rules();
|
||||
for (; it != end; ++it) {
|
||||
|
@ -195,9 +190,6 @@ namespace datalog {
|
|||
rules->add_rule(r1.get());
|
||||
}
|
||||
}
|
||||
if (pc) {
|
||||
pc = concat(pc.get(), rpc.get());
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ namespace datalog {
|
|||
rule_manager& rm;
|
||||
expr_ref_vector m_sub1, m_sub2;
|
||||
unsigned m_idx;
|
||||
replace_proof_converter* m_pc;
|
||||
|
||||
void mk_pred(app_ref& pred, app* p1, app* p2);
|
||||
|
||||
|
@ -53,7 +52,7 @@ namespace datalog {
|
|||
*/
|
||||
mk_coalesce(context & ctx);
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -33,10 +33,7 @@ namespace datalog {
|
|||
// -----------------------------------
|
||||
|
||||
|
||||
rule_set * mk_coi_filter::operator()(
|
||||
rule_set const & source,
|
||||
model_converter_ref& mc,
|
||||
proof_converter_ref& pc)
|
||||
rule_set * mk_coi_filter::operator()(rule_set const & source)
|
||||
{
|
||||
if (source.get_num_rules()==0) {
|
||||
return 0;
|
||||
|
@ -81,7 +78,7 @@ namespace datalog {
|
|||
if (interesting_preds.contains(pred)) {
|
||||
res->add_rule(r);
|
||||
}
|
||||
else if (mc.get()) {
|
||||
else if (m_context.get_model_converter()) {
|
||||
pruned_preds.insert(pred);
|
||||
}
|
||||
}
|
||||
|
@ -90,14 +87,14 @@ namespace datalog {
|
|||
res = 0;
|
||||
}
|
||||
|
||||
if (res && mc) {
|
||||
if (res && m_context.get_model_converter()) {
|
||||
decl_set::iterator end = pruned_preds.end();
|
||||
decl_set::iterator it = pruned_preds.begin();
|
||||
extension_model_converter* mc0 = alloc(extension_model_converter, m);
|
||||
for (; it != end; ++it) {
|
||||
mc0->insert(*it, m.mk_true());
|
||||
}
|
||||
mc = concat(mc.get(), mc0);
|
||||
m_context.add_model_converter(mc0);
|
||||
}
|
||||
|
||||
return res.detach();
|
||||
|
|
|
@ -38,10 +38,7 @@ namespace datalog {
|
|||
m(ctx.get_manager()),
|
||||
m_context(ctx) {}
|
||||
|
||||
|
||||
rule_set * operator()(rule_set const & source,
|
||||
model_converter_ref& mc,
|
||||
proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -174,11 +174,9 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
virtual void deallocate() {
|
||||
get_plugin().recycle(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
|
@ -708,8 +706,8 @@ namespace datalog {
|
|||
}
|
||||
|
||||
rule * mk_explanations::get_e_rule(rule * r) {
|
||||
var_counter ctr;
|
||||
ctr.count_vars(m_manager, r);
|
||||
rule_counter ctr;
|
||||
ctr.count_rule_vars(m_manager, r);
|
||||
unsigned max_var;
|
||||
unsigned next_var = ctr.get_max_positive(max_var) ? (max_var+1) : 0;
|
||||
unsigned head_var = next_var++;
|
||||
|
@ -875,14 +873,12 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
rule_set * mk_explanations::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
SASSERT(!mc && !pc);
|
||||
rule_set * mk_explanations::operator()(rule_set const & source) {
|
||||
|
||||
if(source.get_num_rules()==0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_context.collect_predicates(m_original_preds);
|
||||
|
||||
rule_set * res = alloc(rule_set, m_context);
|
||||
transform_facts(m_context.get_rel_context().get_rmanager());
|
||||
transform_rules(source, *res);
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace datalog {
|
|||
return get_union_decl(m_context);
|
||||
}
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
static expr* get_explanation(relation_base const& r);
|
||||
};
|
||||
|
|
|
@ -168,7 +168,15 @@ namespace datalog {
|
|||
fml = m.mk_implies(m.mk_and(fmls.size(), fmls.c_ptr()), r.get_head());
|
||||
TRACE("dl", tout << "new rule\n" << mk_pp(fml, m) << "\n";);
|
||||
rule_ref_vector rules(rm);
|
||||
rm.mk_rule(fml, rules, r.name());
|
||||
proof_ref pr(m);
|
||||
if (m_ctx.generate_proof_trace()) {
|
||||
scoped_proof _scp(m);
|
||||
expr_ref fml1(m);
|
||||
r.to_formula(fml1);
|
||||
pr = m.mk_rewrite(fml1, fml);
|
||||
pr = m.mk_modus_ponens(r.get_proof(), pr);
|
||||
}
|
||||
rm.mk_rule(fml, pr, rules, r.name());
|
||||
for (unsigned i = 0; i < rules.size(); ++i) {
|
||||
new_rules.add_rule(rules[i].get());
|
||||
m_quantifiers.insert(rules[i].get(), alloc(quantifier_ref_vector, qs));
|
||||
|
@ -347,7 +355,7 @@ namespace datalog {
|
|||
m_quantifiers.reset();
|
||||
}
|
||||
|
||||
rule_set * mk_extract_quantifiers::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
rule_set * mk_extract_quantifiers::operator()(rule_set const & source) {
|
||||
reset();
|
||||
rule_set::iterator it = source.begin(), end = source.end();
|
||||
for (; !m_has_quantifiers && it != end; ++it) {
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace datalog {
|
|||
|
||||
void set_query(func_decl* q);
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
bool has_quantifiers() { return m_has_quantifiers; }
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ namespace datalog {
|
|||
rule * filter_rule = m_context.get_rule_manager().mk(filter_head, 1, &filter_tail, (const bool *)0);
|
||||
filter_rule->set_accounting_parent_object(m_context, m_current);
|
||||
m_result->add_rule(filter_rule);
|
||||
m_context.get_rule_manager().mk_rule_asserted_proof(*filter_rule);
|
||||
}
|
||||
else {
|
||||
dealloc(key);
|
||||
|
@ -135,12 +136,13 @@ namespace datalog {
|
|||
}
|
||||
new_is_negated.push_back(r->is_neg_tail(i));
|
||||
}
|
||||
if(rule_modified) {
|
||||
if (rule_modified) {
|
||||
remove_duplicate_tails(new_tail, new_is_negated);
|
||||
SASSERT(new_tail.size() == new_is_negated.size());
|
||||
rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr());
|
||||
new_rule->set_accounting_parent_object(m_context, m_current);
|
||||
m_result->add_rule(new_rule);
|
||||
m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *new_rule);
|
||||
m_modified = true;
|
||||
}
|
||||
else {
|
||||
|
@ -148,7 +150,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
rule_set * mk_filter_rules::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
rule_set * mk_filter_rules::operator()(rule_set const & source) {
|
||||
// TODO mc, pc
|
||||
m_tail2filter.reset();
|
||||
m_result = alloc(rule_set, m_context);
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace datalog {
|
|||
/**
|
||||
\brief Return a new rule set where only filter rules contain atoms with repeated variables and/or values.
|
||||
*/
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace datalog {
|
|||
// -----------------------------------
|
||||
|
||||
void mk_interp_tail_simplifier::rule_substitution::reset(rule * r) {
|
||||
unsigned var_cnt = m_context.get_rule_manager().get_var_counter().get_max_var(*r)+1;
|
||||
unsigned var_cnt = m_context.get_rule_manager().get_counter().get_max_rule_var(*r)+1;
|
||||
m_subst.reset();
|
||||
m_subst.reserve(1, var_cnt);
|
||||
m_rule = r;
|
||||
|
@ -296,18 +296,40 @@ namespace datalog {
|
|||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
|
||||
proof_ref & result_pr)
|
||||
{
|
||||
if (m.is_not(f)) {
|
||||
|
||||
if (m.is_not(f) && (m.is_and(args[0]) || m.is_or(args[0]))) {
|
||||
SASSERT(num==1);
|
||||
if (m.is_and(args[0]) || m.is_or(args[0])) {
|
||||
expr_ref e(m.mk_not(args[0]),m);
|
||||
if (push_toplevel_junction_negation_inside(e)) {
|
||||
result = e;
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
expr_ref tmp(m);
|
||||
app* a = to_app(args[0]);
|
||||
m_app_args.reset();
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
m_brwr.mk_not(a->get_arg(i), tmp);
|
||||
m_app_args.push_back(tmp);
|
||||
}
|
||||
if (m.is_and(args[0])) {
|
||||
result = m.mk_or(m_app_args.size(), m_app_args.c_ptr());
|
||||
}
|
||||
else {
|
||||
result = m.mk_and(m_app_args.size(), m_app_args.c_ptr());
|
||||
}
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (!m.is_and(f) && !m.is_or(f)) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
if (num == 0) {
|
||||
if (m.is_and(f)) {
|
||||
result = m.mk_true();
|
||||
}
|
||||
else {
|
||||
result = m.mk_false();
|
||||
}
|
||||
return BR_DONE;
|
||||
}
|
||||
if (num == 1) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
if (!m.is_and(f) && !m.is_or(f)) { return BR_FAILED; }
|
||||
if (num<2) { return BR_FAILED; }
|
||||
|
||||
m_app_args.reset();
|
||||
m_app_args.append(num, args);
|
||||
|
@ -318,30 +340,18 @@ namespace datalog {
|
|||
|
||||
bool have_rewritten_args = false;
|
||||
|
||||
if (m.is_or(f) || m.is_and(f)) {
|
||||
have_rewritten_args = detect_equivalences(m_app_args, m.is_or(f));
|
||||
#if 0
|
||||
if (have_rewritten_args) {
|
||||
std::sort(m_app_args.c_ptr(), m_app_args.c_ptr()+m_app_args.size(), m_expr_cmp);
|
||||
|
||||
app_ref orig(m.mk_app(f, num, args),m);
|
||||
app_ref res(m.mk_app(f, m_app_args.size(), m_app_args.c_ptr()),m);
|
||||
std::cout<<"s:"<<mk_pp(orig, m)<<"\n";
|
||||
std::cout<<"t:"<<mk_pp(res, m)<<"\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
have_rewritten_args = detect_equivalences(m_app_args, m.is_or(f));
|
||||
|
||||
if (m_app_args.size()==1) {
|
||||
result = m_app_args[0].get();
|
||||
}
|
||||
else {
|
||||
if (m.is_and(f)) {
|
||||
m_brwr.mk_and(m_app_args.size(), m_app_args.c_ptr(), result);
|
||||
result = m.mk_and(m_app_args.size(), m_app_args.c_ptr());
|
||||
}
|
||||
else {
|
||||
SASSERT(m.is_or(f));
|
||||
m_brwr.mk_or(m_app_args.size(), m_app_args.c_ptr(), result);
|
||||
result = m.mk_or(m_app_args.size(), m_app_args.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +479,7 @@ namespace datalog {
|
|||
start:
|
||||
unsigned u_len = r->get_uninterpreted_tail_size();
|
||||
unsigned len = r->get_tail_size();
|
||||
if (u_len==len) {
|
||||
if (u_len == len) {
|
||||
res = r;
|
||||
return true;
|
||||
}
|
||||
|
@ -504,34 +514,29 @@ namespace datalog {
|
|||
expr_ref simp_res(m);
|
||||
simplify_expr(itail.get(), simp_res);
|
||||
|
||||
modified |= itail.get()!=simp_res.get();
|
||||
|
||||
if (is_app(simp_res.get())) {
|
||||
itail = to_app(simp_res.get());
|
||||
}
|
||||
else if (m.is_bool(simp_res)) {
|
||||
itail = m.mk_eq(simp_res, m.mk_true());
|
||||
}
|
||||
else {
|
||||
throw default_exception("simplification resulted in non-boolean non-function");
|
||||
}
|
||||
|
||||
if (m.is_false(itail.get())) {
|
||||
//the tail member is never true, so we may delete the rule
|
||||
modified |= itail.get() != simp_res.get();
|
||||
|
||||
if (m.is_false(simp_res)) {
|
||||
TRACE("dl", r->display(m_context, tout << "rule is infeasible\n"););
|
||||
return false;
|
||||
}
|
||||
if (!m.is_true(itail.get())) {
|
||||
//if the simplified tail is not a tautology, we add it to the rule
|
||||
tail.push_back(itail);
|
||||
tail_neg.push_back(false);
|
||||
}
|
||||
else {
|
||||
modified = true;
|
||||
}
|
||||
SASSERT(m.is_bool(simp_res));
|
||||
|
||||
SASSERT(tail.size() == tail_neg.size());
|
||||
if (modified) {
|
||||
expr_ref_vector conjs(m);
|
||||
flatten_and(simp_res, conjs);
|
||||
for (unsigned i = 0; i < conjs.size(); ++i) {
|
||||
expr* e = conjs[i].get();
|
||||
if (is_app(e)) {
|
||||
tail.push_back(to_app(e));
|
||||
}
|
||||
else {
|
||||
tail.push_back(m.mk_eq(e, m.mk_true()));
|
||||
}
|
||||
tail_neg.push_back(false);
|
||||
}
|
||||
|
||||
SASSERT(tail.size() == tail_neg.size());
|
||||
res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr());
|
||||
res->set_accounting_parent_object(m_context, r);
|
||||
}
|
||||
|
@ -541,8 +546,8 @@ namespace datalog {
|
|||
|
||||
rule_ref pro_var_eq_result(m_context.get_rule_manager());
|
||||
if (propagate_variable_equivalences(res, pro_var_eq_result)) {
|
||||
SASSERT(var_counter().get_max_var(*r.get())==0 ||
|
||||
var_counter().get_max_var(*r.get()) > var_counter().get_max_var(*pro_var_eq_result.get()));
|
||||
SASSERT(rule_counter().get_max_rule_var(*r.get())==0 ||
|
||||
rule_counter().get_max_rule_var(*r.get()) > rule_counter().get_max_rule_var(*pro_var_eq_result.get()));
|
||||
r = pro_var_eq_result;
|
||||
goto start;
|
||||
}
|
||||
|
@ -554,11 +559,13 @@ namespace datalog {
|
|||
|
||||
bool mk_interp_tail_simplifier::transform_rules(const rule_set & orig, rule_set & tgt) {
|
||||
bool modified = false;
|
||||
rule_manager& rm = m_context.get_rule_manager();
|
||||
rule_set::iterator rit = orig.begin();
|
||||
rule_set::iterator rend = orig.end();
|
||||
for (; rit!=rend; ++rit) {
|
||||
rule_ref new_rule(m_context.get_rule_manager());
|
||||
rule_ref new_rule(rm);
|
||||
if (transform_rule(*rit, new_rule)) {
|
||||
rm.mk_rule_rewrite_proof(**rit, *new_rule.get());
|
||||
bool is_modified = *rit != new_rule;
|
||||
modified |= is_modified;
|
||||
tgt.add_rule(new_rule);
|
||||
|
@ -570,8 +577,7 @@ namespace datalog {
|
|||
return modified;
|
||||
}
|
||||
|
||||
rule_set * mk_interp_tail_simplifier::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
// TODO mc, pc
|
||||
rule_set * mk_interp_tail_simplifier::operator()(rule_set const & source) {
|
||||
if (source.get_num_rules() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace datalog {
|
|||
*/
|
||||
bool transform_rule(rule * r, rule_ref& res);
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
1062
src/muz_qe/dl_mk_karr_invariants.cpp
Normal file
1062
src/muz_qe/dl_mk_karr_invariants.cpp
Normal file
File diff suppressed because it is too large
Load diff
136
src/muz_qe/dl_mk_karr_invariants.h
Normal file
136
src/muz_qe/dl_mk_karr_invariants.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_karr_invariants.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Extract integer linear invariants.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-08
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _DL_MK_KARR_INVARIANTS_H_
|
||||
#define _DL_MK_KARR_INVARIANTS_H_
|
||||
|
||||
#include"dl_context.h"
|
||||
#include"dl_rule_set.h"
|
||||
#include"dl_rule_transformer.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"hilbert_basis.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
/**
|
||||
\brief Rule transformer that strengthens bodies with invariants.
|
||||
*/
|
||||
|
||||
struct matrix {
|
||||
vector<vector<rational> > A;
|
||||
vector<rational> b;
|
||||
svector<bool> eq;
|
||||
unsigned size() const { return A.size(); }
|
||||
void reset() { A.reset(); b.reset(); eq.reset(); }
|
||||
matrix& operator=(matrix const& other);
|
||||
void append(matrix const& other) { A.append(other.A); b.append(other.b); eq.append(other.eq); }
|
||||
void display(std::ostream& out) const;
|
||||
static void display_row(
|
||||
std::ostream& out, vector<rational> const& row, rational const& b, bool is_eq);
|
||||
static void display_ineq(
|
||||
std::ostream& out, vector<rational> const& row, rational const& b, bool is_eq);
|
||||
};
|
||||
|
||||
class mk_karr_invariants : public rule_transformer::plugin {
|
||||
|
||||
class add_invariant_model_converter;
|
||||
|
||||
context& m_ctx;
|
||||
ast_manager& m;
|
||||
rule_manager& rm;
|
||||
context m_inner_ctx;
|
||||
arith_util a;
|
||||
void update_body(rel_context& rctx, rule_set& result, rule& r);
|
||||
|
||||
public:
|
||||
mk_karr_invariants(context & ctx, unsigned priority);
|
||||
|
||||
virtual ~mk_karr_invariants();
|
||||
|
||||
virtual void cancel();
|
||||
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
};
|
||||
|
||||
class karr_relation;
|
||||
|
||||
class karr_relation_plugin : public relation_plugin {
|
||||
arith_util a;
|
||||
hilbert_basis m_hb;
|
||||
|
||||
class join_fn;
|
||||
class project_fn;
|
||||
class rename_fn;
|
||||
class union_fn;
|
||||
class filter_equal_fn;
|
||||
class filter_identical_fn;
|
||||
class filter_interpreted_fn;
|
||||
friend class karr_relation;
|
||||
public:
|
||||
karr_relation_plugin(relation_manager& rm):
|
||||
relation_plugin(karr_relation_plugin::get_name(), rm),
|
||||
a(get_ast_manager())
|
||||
{}
|
||||
|
||||
virtual bool can_handle_signature(const relation_signature & sig) {
|
||||
for (unsigned i = 0; i < sig.size(); ++i) {
|
||||
if (a.is_int(sig[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static symbol get_name() { return symbol("karr_relation"); }
|
||||
|
||||
virtual void set_cancel(bool f);
|
||||
|
||||
virtual relation_base * mk_empty(const relation_signature & s);
|
||||
|
||||
virtual relation_base * mk_full(func_decl* p, const relation_signature & s);
|
||||
|
||||
static karr_relation& get(relation_base& r);
|
||||
static karr_relation const & get(relation_base const& r);
|
||||
|
||||
virtual relation_join_fn * mk_join_fn(
|
||||
const relation_base & t1, const relation_base & t2,
|
||||
unsigned col_cnt, const unsigned * cols1, const unsigned * cols2);
|
||||
virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt,
|
||||
const unsigned * removed_cols);
|
||||
virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len,
|
||||
const unsigned * permutation_cycle);
|
||||
virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src,
|
||||
const relation_base * delta);
|
||||
virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt,
|
||||
const unsigned * identical_cols);
|
||||
virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value,
|
||||
unsigned col);
|
||||
virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition);
|
||||
private:
|
||||
bool dualizeI(matrix& dst, matrix const& src);
|
||||
void dualizeH(matrix& dst, matrix const& src);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* _DL_MK_KARR_INVARIANTS_H_ */
|
||||
|
113
src/muz_qe/dl_mk_loop_counter.cpp
Normal file
113
src/muz_qe/dl_mk_loop_counter.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_loop_counter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Add loop counter argument to relations.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-31
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"dl_mk_loop_counter.h"
|
||||
#include"dl_context.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
mk_loop_counter::mk_loop_counter(context & ctx, unsigned priority):
|
||||
plugin(priority),
|
||||
m(ctx.get_manager()),
|
||||
a(m),
|
||||
m_refs(m) {
|
||||
}
|
||||
|
||||
mk_loop_counter::~mk_loop_counter() { }
|
||||
|
||||
app_ref mk_loop_counter::add_arg(app* fn, unsigned idx) {
|
||||
expr_ref_vector args(m);
|
||||
func_decl* new_fn, *old_fn = fn->get_decl();
|
||||
args.append(fn->get_num_args(), fn->get_args());
|
||||
args.push_back(m.mk_var(idx, a.mk_int()));
|
||||
|
||||
if (!m_old2new.find(old_fn, new_fn)) {
|
||||
ptr_vector<sort> domain;
|
||||
domain.append(fn->get_num_args(), old_fn->get_domain());
|
||||
domain.push_back(a.mk_int());
|
||||
new_fn = m.mk_func_decl(old_fn->get_name(), domain.size(), domain.c_ptr(), old_fn->get_range());
|
||||
m_old2new.insert(old_fn, new_fn);
|
||||
m_new2old.insert(new_fn, old_fn);
|
||||
m_refs.push_back(new_fn);
|
||||
}
|
||||
return app_ref(m.mk_app(new_fn, args.size(), args.c_ptr()), m);
|
||||
}
|
||||
|
||||
rule_set * mk_loop_counter::operator()(rule_set const & source) {
|
||||
m_refs.reset();
|
||||
m_old2new.reset();
|
||||
m_new2old.reset();
|
||||
context& ctx = source.get_context();
|
||||
rule_manager& rm = source.get_rule_manager();
|
||||
rule_set * result = alloc(rule_set, ctx);
|
||||
unsigned sz = source.get_num_rules();
|
||||
rule_ref new_rule(rm);
|
||||
app_ref_vector tail(m);
|
||||
app_ref head(m);
|
||||
svector<bool> neg;
|
||||
rule_counter& vc = rm.get_counter();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
tail.reset();
|
||||
neg.reset();
|
||||
rule & r = *source.get_rule(i);
|
||||
unsigned cnt = vc.get_max_rule_var(r)+1;
|
||||
unsigned utsz = r.get_uninterpreted_tail_size();
|
||||
unsigned tsz = r.get_tail_size();
|
||||
for (unsigned j = 0; j < utsz; ++j, ++cnt) {
|
||||
tail.push_back(add_arg(r.get_tail(j), cnt));
|
||||
neg.push_back(r.is_neg_tail(j));
|
||||
ctx.register_predicate(tail.back()->get_decl(), false);
|
||||
}
|
||||
for (unsigned j = utsz; j < tsz; ++j) {
|
||||
tail.push_back(r.get_tail(j));
|
||||
neg.push_back(false);
|
||||
}
|
||||
head = add_arg(r.get_head(), cnt);
|
||||
ctx.register_predicate(head->get_decl(), false);
|
||||
// set the loop counter to be an increment of the previous
|
||||
bool found = false;
|
||||
unsigned last = head->get_num_args()-1;
|
||||
for (unsigned j = 0; !found && j < utsz; ++j) {
|
||||
if (head->get_decl() == tail[j]->get_decl()) {
|
||||
tail.push_back(m.mk_eq(head->get_arg(last),
|
||||
a.mk_add(tail[j]->get_arg(last),
|
||||
a.mk_numeral(rational(1), true))));
|
||||
neg.push_back(false);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// initialize loop counter to 0 if none was found.
|
||||
if (!found) {
|
||||
expr_ref_vector args(m);
|
||||
args.append(head->get_num_args(), head->get_args());
|
||||
args[last] = a.mk_numeral(rational(0), true);
|
||||
head = m.mk_app(head->get_decl(), args.size(), args.c_ptr());
|
||||
}
|
||||
|
||||
new_rule = rm.mk(head, tail.size(), tail.c_ptr(), neg.c_ptr(), r.name(), true);
|
||||
result->add_rule(new_rule);
|
||||
}
|
||||
|
||||
// model converter: remove references to extra argument.
|
||||
// proof converter: remove references to extra argument as well.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
47
src/muz_qe/dl_mk_loop_counter.h
Normal file
47
src/muz_qe/dl_mk_loop_counter.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_loop_counter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Add loop counter argument to relations.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2013-03-31
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _DL_MK_LOOP_COUNTER_H_
|
||||
#define _DL_MK_LOOP_COUNTER_H_
|
||||
|
||||
#include"dl_rule_transformer.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
class mk_loop_counter : public rule_transformer::plugin {
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
func_decl_ref_vector m_refs;
|
||||
obj_map<func_decl, func_decl*> m_new2old;
|
||||
obj_map<func_decl, func_decl*> m_old2new;
|
||||
|
||||
app_ref add_arg(app* fn, unsigned idx);
|
||||
public:
|
||||
mk_loop_counter(context & ctx, unsigned priority = 33000);
|
||||
~mk_loop_counter();
|
||||
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
func_decl* get_old(func_decl* f) const { return m_new2old.find(f); }
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _DL_MK_LOOP_COUNTER_H_ */
|
||||
|
|
@ -317,8 +317,8 @@ namespace datalog {
|
|||
m_rules.push_back(r);
|
||||
}
|
||||
|
||||
rule_set * mk_magic_sets::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
SASSERT(!mc && !pc);
|
||||
rule_set * mk_magic_sets::operator()(rule_set const & source) {
|
||||
SASSERT(!m_context.get_model_converter());
|
||||
unsigned init_rule_cnt = source.get_num_rules();
|
||||
{
|
||||
func_decl_set intentional;
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace datalog {
|
|||
*/
|
||||
mk_magic_sets(context & ctx, rule * goal_rule);
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -86,8 +86,8 @@ namespace datalog {
|
|||
}
|
||||
|
||||
|
||||
rule_set * mk_partial_equivalence_transformer::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
// TODO mc, pc
|
||||
rule_set * mk_partial_equivalence_transformer::operator()(rule_set const & source) {
|
||||
// TODO mc
|
||||
|
||||
if (source.get_num_rules() == 0) {
|
||||
return 0;
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace datalog {
|
|||
m(ctx.get_manager()),
|
||||
m_context(ctx) {}
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
private:
|
||||
|
||||
|
|
367
src/muz_qe/dl_mk_quantifier_abstraction.cpp
Normal file
367
src/muz_qe/dl_mk_quantifier_abstraction.cpp
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_quantifier_abstraction.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Create quantified Horn clauses from benchmarks with arrays.
|
||||
|
||||
Author:
|
||||
|
||||
Ken McMillan
|
||||
Andrey Rybalchenko
|
||||
Nikolaj Bjorner (nbjorner) 2013-04-02
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "dl_mk_quantifier_abstraction.h"
|
||||
#include "dl_context.h"
|
||||
#include "expr_safe_replace.h"
|
||||
#include "expr_abstract.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
||||
// model converter:
|
||||
// Given model for P^(x, y, i, a[i])
|
||||
// create model: P(x,y,a) == forall i . P^(x,y,i,a[i])
|
||||
// requires substitution and list of bound variables.
|
||||
|
||||
class mk_quantifier_abstraction::qa_model_converter : public model_converter {
|
||||
ast_manager& m;
|
||||
func_decl_ref_vector m_old_funcs;
|
||||
func_decl_ref_vector m_new_funcs;
|
||||
vector<expr_ref_vector> m_subst;
|
||||
vector<sort_ref_vector> m_sorts;
|
||||
vector<svector<bool> > m_bound;
|
||||
|
||||
public:
|
||||
|
||||
qa_model_converter(ast_manager& m):
|
||||
m(m), m_old_funcs(m), m_new_funcs(m) {}
|
||||
|
||||
virtual ~qa_model_converter() {}
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator) {
|
||||
return alloc(qa_model_converter, m);
|
||||
}
|
||||
|
||||
void insert(func_decl* old_p, func_decl* new_p, expr_ref_vector& sub, sort_ref_vector& sorts, svector<bool> const& bound) {
|
||||
m_old_funcs.push_back(old_p);
|
||||
m_new_funcs.push_back(new_p);
|
||||
m_subst.push_back(sub);
|
||||
m_bound.push_back(bound);
|
||||
m_sorts.push_back(sorts);
|
||||
}
|
||||
|
||||
virtual void operator()(model_ref & old_model) {
|
||||
model_ref new_model = alloc(model, m);
|
||||
for (unsigned i = 0; i < m_new_funcs.size(); ++i) {
|
||||
func_decl* p = m_new_funcs[i].get();
|
||||
func_decl* q = m_old_funcs[i].get();
|
||||
expr_ref_vector const& sub = m_subst[i];
|
||||
sort_ref_vector const& sorts = m_sorts[i];
|
||||
svector<bool> const& is_bound = m_bound[i];
|
||||
func_interp* f = old_model->get_func_interp(p);
|
||||
expr_ref body(m);
|
||||
unsigned arity_p = p->get_arity();
|
||||
unsigned arity_q = q->get_arity();
|
||||
SASSERT(0 < arity_p);
|
||||
func_interp* g = alloc(func_interp, m, arity_q);
|
||||
|
||||
if (f) {
|
||||
body = f->get_interp();
|
||||
SASSERT(!f->is_partial());
|
||||
SASSERT(body);
|
||||
}
|
||||
else {
|
||||
body = m.mk_false();
|
||||
}
|
||||
// Create quantifier wrapper around body.
|
||||
|
||||
TRACE("dl", tout << mk_pp(body, m) << "\n";);
|
||||
// 1. replace variables by the compound terms from
|
||||
// the original predicate.
|
||||
expr_safe_replace rep(m);
|
||||
for (unsigned i = 0; i < sub.size(); ++i) {
|
||||
rep.insert(m.mk_var(i, m.get_sort(sub[i])), sub[i]);
|
||||
}
|
||||
rep(body);
|
||||
rep.reset();
|
||||
|
||||
TRACE("dl", tout << mk_pp(body, m) << "\n";);
|
||||
// 2. replace bound variables by constants.
|
||||
expr_ref_vector consts(m), bound(m), free(m);
|
||||
svector<symbol> names;
|
||||
ptr_vector<sort> bound_sorts;
|
||||
for (unsigned i = 0; i < sorts.size(); ++i) {
|
||||
sort* s = sorts[i];
|
||||
consts.push_back(m.mk_fresh_const("C", s));
|
||||
rep.insert(m.mk_var(i, s), consts.back());
|
||||
if (is_bound[i]) {
|
||||
bound.push_back(consts.back());
|
||||
names.push_back(symbol(i));
|
||||
bound_sorts.push_back(s);
|
||||
}
|
||||
else {
|
||||
free.push_back(consts.back());
|
||||
}
|
||||
}
|
||||
rep(body);
|
||||
rep.reset();
|
||||
|
||||
TRACE("dl", tout << mk_pp(body, m) << "\n";);
|
||||
// 3. abstract and quantify those variables that should be bound.
|
||||
expr_abstract(m, 0, bound.size(), bound.c_ptr(), body, body);
|
||||
body = m.mk_forall(names.size(), bound_sorts.c_ptr(), names.c_ptr(), body);
|
||||
|
||||
TRACE("dl", tout << mk_pp(body, m) << "\n";);
|
||||
// 4. replace remaining constants by variables.
|
||||
for (unsigned i = 0; i < free.size(); ++i) {
|
||||
rep.insert(free[i].get(), m.mk_var(i, m.get_sort(free[i].get())));
|
||||
}
|
||||
rep(body);
|
||||
g->set_else(body);
|
||||
TRACE("dl", tout << mk_pp(body, m) << "\n";);
|
||||
|
||||
new_model->register_decl(q, g);
|
||||
}
|
||||
old_model = new_model;
|
||||
}
|
||||
};
|
||||
|
||||
mk_quantifier_abstraction::mk_quantifier_abstraction(
|
||||
context & ctx, unsigned priority):
|
||||
plugin(priority),
|
||||
m(ctx.get_manager()),
|
||||
m_ctx(ctx),
|
||||
a(m),
|
||||
m_refs(m) {
|
||||
}
|
||||
|
||||
mk_quantifier_abstraction::~mk_quantifier_abstraction() {
|
||||
}
|
||||
|
||||
func_decl* mk_quantifier_abstraction::declare_pred(func_decl* old_p) {
|
||||
|
||||
if (m_ctx.is_output_predicate(old_p)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned sz = old_p->get_arity();
|
||||
unsigned num_arrays = 0;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (a.is_array(old_p->get_domain(i))) {
|
||||
num_arrays++;
|
||||
}
|
||||
}
|
||||
if (num_arrays == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
func_decl* new_p = 0;
|
||||
if (!m_old2new.find(old_p, new_p)) {
|
||||
expr_ref_vector sub(m), vars(m);
|
||||
svector<bool> bound;
|
||||
sort_ref_vector domain(m), sorts(m);
|
||||
expr_ref arg(m);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
sort* s0 = old_p->get_domain(i);
|
||||
unsigned lookahead = 0;
|
||||
sort* s = s0;
|
||||
while (a.is_array(s)) {
|
||||
lookahead += get_array_arity(s);
|
||||
s = get_array_range(s);
|
||||
}
|
||||
arg = m.mk_var(bound.size() + lookahead, s0);
|
||||
s = s0;
|
||||
while (a.is_array(s)) {
|
||||
unsigned arity = get_array_arity(s);
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned j = 0; j < arity; ++j) {
|
||||
sort* s1 = get_array_domain(s, j);
|
||||
domain.push_back(s1);
|
||||
args.push_back(m.mk_var(bound.size(), s1));
|
||||
bound.push_back(true);
|
||||
sorts.push_back(s1);
|
||||
}
|
||||
arg = mk_select(arg, args.size(), args.c_ptr());
|
||||
s = get_array_range(s);
|
||||
}
|
||||
domain.push_back(s);
|
||||
bound.push_back(false);
|
||||
sub.push_back(arg);
|
||||
sorts.push_back(s0);
|
||||
}
|
||||
SASSERT(old_p->get_range() == m.mk_bool_sort());
|
||||
new_p = m.mk_func_decl(old_p->get_name(), domain.size(), domain.c_ptr(), old_p->get_range());
|
||||
m_refs.push_back(new_p);
|
||||
m_ctx.register_predicate(new_p, false);
|
||||
if (m_mc) {
|
||||
m_mc->insert(old_p, new_p, sub, sorts, bound);
|
||||
}
|
||||
m_old2new.insert(old_p, new_p);
|
||||
}
|
||||
return new_p;
|
||||
}
|
||||
|
||||
app_ref mk_quantifier_abstraction::mk_head(app* p, unsigned idx) {
|
||||
func_decl* new_p = declare_pred(p->get_decl());
|
||||
if (!new_p) {
|
||||
return app_ref(p, m);
|
||||
}
|
||||
expr_ref_vector args(m);
|
||||
expr_ref arg(m);
|
||||
unsigned sz = p->get_num_args();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
arg = p->get_arg(i);
|
||||
sort* s = m.get_sort(arg);
|
||||
while (a.is_array(s)) {
|
||||
unsigned arity = get_array_arity(s);
|
||||
for (unsigned j = 0; j < arity; ++j) {
|
||||
args.push_back(m.mk_var(idx++, get_array_domain(s, j)));
|
||||
}
|
||||
arg = mk_select(arg, arity, args.c_ptr()+args.size()-arity);
|
||||
s = get_array_range(s);
|
||||
}
|
||||
args.push_back(arg);
|
||||
}
|
||||
TRACE("dl",
|
||||
tout << mk_pp(new_p, m) << "\n";
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
tout << mk_pp(args[i].get(), m) << "\n";
|
||||
});
|
||||
return app_ref(m.mk_app(new_p, args.size(), args.c_ptr()), m);
|
||||
}
|
||||
|
||||
app_ref mk_quantifier_abstraction::mk_tail(app* p) {
|
||||
func_decl* old_p = p->get_decl();
|
||||
func_decl* new_p = declare_pred(old_p);
|
||||
if (!new_p) {
|
||||
return app_ref(p, m);
|
||||
}
|
||||
SASSERT(new_p->get_arity() > old_p->get_arity());
|
||||
unsigned num_extra_args = new_p->get_arity() - old_p->get_arity();
|
||||
var_shifter shift(m);
|
||||
expr_ref p_shifted(m);
|
||||
shift(p, num_extra_args, p_shifted);
|
||||
app* ps = to_app(p_shifted);
|
||||
expr_ref_vector args(m);
|
||||
app_ref_vector pats(m);
|
||||
sort_ref_vector vars(m);
|
||||
svector<symbol> names;
|
||||
expr_ref arg(m);
|
||||
unsigned idx = 0;
|
||||
unsigned sz = p->get_num_args();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
arg = ps->get_arg(i);
|
||||
sort* s = m.get_sort(arg);
|
||||
bool is_pattern = false;
|
||||
while (a.is_array(s)) {
|
||||
is_pattern = true;
|
||||
unsigned arity = get_array_arity(s);
|
||||
for (unsigned j = 0; j < arity; ++j) {
|
||||
vars.push_back(get_array_domain(s, j));
|
||||
names.push_back(symbol(idx));
|
||||
args.push_back(m.mk_var(idx++, vars.back()));
|
||||
}
|
||||
arg = mk_select(arg, arity, args.c_ptr()+args.size()-arity);
|
||||
s = get_array_range(s);
|
||||
}
|
||||
if (is_pattern) {
|
||||
pats.push_back(to_app(arg));
|
||||
}
|
||||
args.push_back(arg);
|
||||
}
|
||||
expr* pat = 0;
|
||||
expr_ref pattern(m);
|
||||
pattern = m.mk_pattern(pats.size(), pats.c_ptr());
|
||||
pat = pattern.get();
|
||||
app_ref result(m);
|
||||
symbol qid, skid;
|
||||
result = m.mk_app(new_p, args.size(), args.c_ptr());
|
||||
result = m.mk_eq(m.mk_forall(vars.size(), vars.c_ptr(), names.c_ptr(), result, 1, qid, skid, 1, &pat), m.mk_true());
|
||||
return result;
|
||||
}
|
||||
|
||||
expr * mk_quantifier_abstraction::mk_select(expr* arg, unsigned num_args, expr* const* args) {
|
||||
ptr_vector<expr> args2;
|
||||
args2.push_back(arg);
|
||||
args2.append(num_args, args);
|
||||
return a.mk_select(args2.size(), args2.c_ptr());
|
||||
}
|
||||
|
||||
rule_set * mk_quantifier_abstraction::operator()(rule_set const & source) {
|
||||
TRACE("dl", tout << "quantify " << source.get_num_rules() << " " << m_ctx.get_params().quantify_arrays() << "\n";);
|
||||
if (!m_ctx.get_params().quantify_arrays()) {
|
||||
return 0;
|
||||
}
|
||||
unsigned sz = source.get_num_rules();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
rule& r = *source.get_rule(i);
|
||||
if (r.has_negation()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_refs.reset();
|
||||
m_old2new.reset();
|
||||
m_new2old.reset();
|
||||
rule_manager& rm = source.get_rule_manager();
|
||||
rule_ref new_rule(rm);
|
||||
expr_ref_vector tail(m);
|
||||
app_ref head(m);
|
||||
expr_ref fml(m);
|
||||
rule_counter& vc = rm.get_counter();
|
||||
|
||||
if (m_ctx.get_model_converter()) {
|
||||
m_mc = alloc(qa_model_converter, m);
|
||||
}
|
||||
rule_set * result = alloc(rule_set, m_ctx);
|
||||
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
tail.reset();
|
||||
rule & r = *source.get_rule(i);
|
||||
TRACE("dl", r.display(m_ctx, tout); );
|
||||
unsigned cnt = vc.get_max_rule_var(r)+1;
|
||||
unsigned utsz = r.get_uninterpreted_tail_size();
|
||||
unsigned tsz = r.get_tail_size();
|
||||
for (unsigned j = 0; j < utsz; ++j) {
|
||||
tail.push_back(mk_tail(r.get_tail(j)));
|
||||
}
|
||||
for (unsigned j = utsz; j < tsz; ++j) {
|
||||
tail.push_back(r.get_tail(j));
|
||||
}
|
||||
head = mk_head(r.get_head(), cnt);
|
||||
fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head);
|
||||
rule_ref_vector added_rules(rm);
|
||||
proof_ref pr(m);
|
||||
rm.mk_rule(fml, pr, added_rules);
|
||||
result->add_rules(added_rules.size(), added_rules.c_ptr());
|
||||
TRACE("dl", added_rules.back()->display(m_ctx, tout););
|
||||
}
|
||||
|
||||
// proof converter: proofs are not necessarily preserved using this transformation.
|
||||
|
||||
if (m_old2new.empty()) {
|
||||
dealloc(result);
|
||||
dealloc(m_mc);
|
||||
result = 0;
|
||||
}
|
||||
else {
|
||||
m_ctx.add_model_converter(m_mc);
|
||||
}
|
||||
m_mc = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
64
src/muz_qe/dl_mk_quantifier_abstraction.h
Normal file
64
src/muz_qe/dl_mk_quantifier_abstraction.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_quantifier_abstraction.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Convert clauses with array arguments to predicates
|
||||
into Quantified Horn clauses.
|
||||
|
||||
Author:
|
||||
|
||||
Ken McMillan
|
||||
Andrey Rybalchenko
|
||||
Nikolaj Bjorner (nbjorner) 2013-04-02
|
||||
|
||||
Revision History:
|
||||
|
||||
Based on approach suggested in SAS 2013 paper
|
||||
"On Solving Universally Quantified Horn Clauses"
|
||||
|
||||
--*/
|
||||
#ifndef _DL_MK_QUANTIFIER_ABSTRACTION_H_
|
||||
#define _DL_MK_QUANTIFIER_ABSTRACTION_H_
|
||||
|
||||
|
||||
#include"dl_rule_transformer.h"
|
||||
#include"array_decl_plugin.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
class context;
|
||||
|
||||
class mk_quantifier_abstraction : public rule_transformer::plugin {
|
||||
class qa_model_converter;
|
||||
ast_manager& m;
|
||||
context& m_ctx;
|
||||
array_util a;
|
||||
func_decl_ref_vector m_refs;
|
||||
obj_map<func_decl, func_decl*> m_new2old;
|
||||
obj_map<func_decl, func_decl*> m_old2new;
|
||||
qa_model_converter* m_mc;
|
||||
|
||||
func_decl* declare_pred(func_decl* old_p);
|
||||
app_ref mk_head(app* p, unsigned idx);
|
||||
app_ref mk_tail(app* p);
|
||||
expr* mk_select(expr* a, unsigned num_args, expr* const* args);
|
||||
|
||||
public:
|
||||
mk_quantifier_abstraction(context & ctx, unsigned priority);
|
||||
|
||||
virtual ~mk_quantifier_abstraction();
|
||||
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* _DL_MK_QUANTIFIER_ABSTRACTION_H_ */
|
||||
|
299
src/muz_qe/dl_mk_quantifier_instantiation.cpp
Normal file
299
src/muz_qe/dl_mk_quantifier_instantiation.cpp
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_quantifier_instantiation.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Convert Quantified Horn clauses into non-quantified clauses using
|
||||
instantiation.
|
||||
|
||||
Author:
|
||||
|
||||
Ken McMillan
|
||||
Andrey Rybalchenko
|
||||
Nikolaj Bjorner (nbjorner) 2013-04-02
|
||||
|
||||
Revision History:
|
||||
|
||||
Based on approach suggested in the SAS 2013 paper
|
||||
"On Solving Universally Quantified Horn Clauses"
|
||||
|
||||
--*/
|
||||
|
||||
#include "dl_mk_quantifier_instantiation.h"
|
||||
#include "dl_context.h"
|
||||
#include "pattern_inference.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
mk_quantifier_instantiation::mk_quantifier_instantiation(
|
||||
context & ctx, unsigned priority):
|
||||
plugin(priority),
|
||||
m(ctx.get_manager()),
|
||||
m_ctx(ctx),
|
||||
m_var2cnst(m),
|
||||
m_cnst2var(m) {
|
||||
}
|
||||
|
||||
mk_quantifier_instantiation::~mk_quantifier_instantiation() {
|
||||
}
|
||||
|
||||
void mk_quantifier_instantiation::extract_quantifiers(rule& r, expr_ref_vector& conjs, quantifier_ref_vector& qs) {
|
||||
conjs.reset();
|
||||
qs.reset();
|
||||
unsigned tsz = r.get_tail_size();
|
||||
for (unsigned j = 0; j < tsz; ++j) {
|
||||
conjs.push_back(r.get_tail(j));
|
||||
}
|
||||
datalog::flatten_and(conjs);
|
||||
for (unsigned j = 0; j < conjs.size(); ++j) {
|
||||
expr* e = conjs[j].get();
|
||||
quantifier* q;
|
||||
if (rule_manager::is_forall(m, e, q)) {
|
||||
qs.push_back(q);
|
||||
conjs[j] = conjs.back();
|
||||
conjs.pop_back();
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mk_quantifier_instantiation::instantiate_quantifier(quantifier* q, expr_ref_vector & conjs) {
|
||||
expr_ref qe(m);
|
||||
qe = q;
|
||||
m_var2cnst(qe);
|
||||
q = to_quantifier(qe);
|
||||
if (q->get_num_patterns() == 0) {
|
||||
proof_ref new_pr(m);
|
||||
pattern_inference_params params;
|
||||
pattern_inference infer(m, params);
|
||||
infer(q, qe, new_pr);
|
||||
q = to_quantifier(qe);
|
||||
}
|
||||
unsigned num_patterns = q->get_num_patterns();
|
||||
for (unsigned i = 0; i < num_patterns; ++i) {
|
||||
expr * pat = q->get_pattern(i);
|
||||
SASSERT(m.is_pattern(pat));
|
||||
instantiate_quantifier(q, to_app(pat), conjs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mk_quantifier_instantiation::instantiate_quantifier(quantifier* q, app* pat, expr_ref_vector & conjs) {
|
||||
m_binding.reset();
|
||||
m_binding.resize(q->get_num_decls());
|
||||
term_pairs todo;
|
||||
match(0, pat, 0, todo, q, conjs);
|
||||
}
|
||||
|
||||
void mk_quantifier_instantiation::match(unsigned i, app* pat, unsigned j, term_pairs& todo, quantifier* q, expr_ref_vector& conjs) {
|
||||
TRACE("dl", tout << "match" << mk_pp(pat, m) << "\n";);
|
||||
while (j < todo.size()) {
|
||||
expr* p = todo[j].first;
|
||||
expr* t = todo[j].second;
|
||||
if (is_var(p)) {
|
||||
unsigned idx = to_var(p)->get_idx();
|
||||
if (!m_binding[idx]) {
|
||||
m_binding[idx] = t;
|
||||
match(i, pat, j + 1, todo, q, conjs);
|
||||
m_binding[idx] = 0;
|
||||
return;
|
||||
}
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
if (!is_app(p)) {
|
||||
return;
|
||||
}
|
||||
app* a1 = to_app(p);
|
||||
unsigned id = t->get_id();
|
||||
unsigned next_id = id;
|
||||
unsigned sz = todo.size();
|
||||
do {
|
||||
expr* t2 = m_terms[next_id];
|
||||
if (is_app(t2)) {
|
||||
app* a2 = to_app(t2);
|
||||
if (a1->get_decl() == a2->get_decl() &&
|
||||
a1->get_num_args() == a2->get_num_args()) {
|
||||
for (unsigned k = 0; k < a1->get_num_args(); ++k) {
|
||||
todo.push_back(std::make_pair(a1->get_arg(k), a2->get_arg(k)));
|
||||
}
|
||||
match(i, pat, j + 1, todo, q, conjs);
|
||||
todo.resize(sz);
|
||||
}
|
||||
}
|
||||
next_id = m_uf.next(next_id);
|
||||
}
|
||||
while (next_id != id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i == pat->get_num_args()) {
|
||||
yield_binding(q, conjs);
|
||||
return;
|
||||
}
|
||||
expr* arg = pat->get_arg(i);
|
||||
ptr_vector<expr>* terms = 0;
|
||||
|
||||
if (m_funs.find(to_app(arg)->get_decl(), terms)) {
|
||||
for (unsigned k = 0; k < terms->size(); ++k) {
|
||||
todo.push_back(std::make_pair(arg, (*terms)[k]));
|
||||
match(i + 1, pat, j, todo, q, conjs);
|
||||
todo.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mk_quantifier_instantiation::yield_binding(quantifier* q, expr_ref_vector& conjs) {
|
||||
DEBUG_CODE(
|
||||
for (unsigned i = 0; i < m_binding.size(); ++i) {
|
||||
SASSERT(m_binding[i]);
|
||||
});
|
||||
m_binding.reverse();
|
||||
expr_ref res(m);
|
||||
instantiate(m, q, m_binding.c_ptr(), res);
|
||||
m_binding.reverse();
|
||||
m_cnst2var(res);
|
||||
conjs.push_back(res);
|
||||
TRACE("dl", tout << mk_pp(q, m) << "\n==>\n" << mk_pp(res, m) << "\n";);
|
||||
}
|
||||
|
||||
void mk_quantifier_instantiation::collect_egraph(expr* e) {
|
||||
expr* e1, *e2;
|
||||
m_todo.push_back(e);
|
||||
expr_fast_mark1 visited;
|
||||
while (!m_todo.empty()) {
|
||||
e = m_todo.back();
|
||||
m_todo.pop_back();
|
||||
if (visited.is_marked(e)) {
|
||||
continue;
|
||||
}
|
||||
unsigned n = e->get_id();
|
||||
if (n >= m_terms.size()) {
|
||||
m_terms.resize(n+1);
|
||||
}
|
||||
m_terms[n] = e;
|
||||
visited.mark(e);
|
||||
if (m.is_eq(e, e1, e2) || m.is_iff(e, e1, e2)) {
|
||||
m_uf.merge(e1->get_id(), e2->get_id());
|
||||
}
|
||||
if (is_app(e)) {
|
||||
app* ap = to_app(e);
|
||||
ptr_vector<expr>* terms = 0;
|
||||
if (!m_funs.find(ap->get_decl(), terms)) {
|
||||
terms = alloc(ptr_vector<expr>);
|
||||
m_funs.insert(ap->get_decl(), terms);
|
||||
}
|
||||
terms->push_back(e);
|
||||
m_todo.append(ap->get_num_args(), ap->get_args());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mk_quantifier_instantiation::instantiate_rule(rule& r, expr_ref_vector& conjs, quantifier_ref_vector& qs, rule_set& rules) {
|
||||
rule_manager& rm = m_ctx.get_rule_manager();
|
||||
expr_ref fml(m), cnst(m);
|
||||
var_ref var(m);
|
||||
ptr_vector<sort> sorts;
|
||||
r.get_vars(sorts);
|
||||
m_uf.reset();
|
||||
m_terms.reset();
|
||||
m_var2cnst.reset();
|
||||
m_cnst2var.reset();
|
||||
fml = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
|
||||
for (unsigned i = 0; i < sorts.size(); ++i) {
|
||||
if (!sorts[i]) {
|
||||
sorts[i] = m.mk_bool_sort();
|
||||
}
|
||||
var = m.mk_var(i, sorts[i]);
|
||||
cnst = m.mk_fresh_const("C", sorts[i]);
|
||||
m_var2cnst.insert(var, cnst);
|
||||
m_cnst2var.insert(cnst, var);
|
||||
}
|
||||
|
||||
fml = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
m_var2cnst(fml);
|
||||
collect_egraph(fml);
|
||||
|
||||
for (unsigned i = 0; i < qs.size(); ++i) {
|
||||
instantiate_quantifier(qs[i].get(), conjs);
|
||||
}
|
||||
obj_map<func_decl, ptr_vector<expr>*>::iterator it = m_funs.begin(), end = m_funs.end();
|
||||
for (; it != end; ++it) {
|
||||
dealloc(it->m_value);
|
||||
}
|
||||
m_funs.reset();
|
||||
|
||||
fml = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
fml = m.mk_implies(fml, r.get_head());
|
||||
TRACE("dl", r.display(m_ctx, tout); tout << mk_pp(fml, m) << "\n";);
|
||||
|
||||
rule_ref_vector added_rules(rm);
|
||||
proof_ref pr(m);
|
||||
rm.mk_rule(fml, pr, added_rules);
|
||||
if (r.get_proof()) {
|
||||
// use def-axiom to encode that new rule is a weakening of the original.
|
||||
proof* p1 = r.get_proof();
|
||||
for (unsigned i = 0; i < added_rules.size(); ++i) {
|
||||
rule* r2 = added_rules[i].get();
|
||||
r2->to_formula(fml);
|
||||
pr = m.mk_modus_ponens(m.mk_def_axiom(m.mk_implies(m.get_fact(p1), fml)), p1);
|
||||
r2->set_proof(m, pr);
|
||||
}
|
||||
}
|
||||
rules.add_rules(added_rules.size(), added_rules.c_ptr());
|
||||
}
|
||||
|
||||
rule_set * mk_quantifier_instantiation::operator()(rule_set const & source) {
|
||||
TRACE("dl", tout << m_ctx.get_params().instantiate_quantifiers() << "\n";);
|
||||
if (!m_ctx.get_params().instantiate_quantifiers()) {
|
||||
return 0;
|
||||
}
|
||||
bool has_quantifiers = false;
|
||||
unsigned sz = source.get_num_rules();
|
||||
for (unsigned i = 0; !has_quantifiers && i < sz; ++i) {
|
||||
rule& r = *source.get_rule(i);
|
||||
has_quantifiers = has_quantifiers || r.has_quantifiers();
|
||||
if (r.has_negation()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!has_quantifiers) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr_ref_vector conjs(m);
|
||||
quantifier_ref_vector qs(m);
|
||||
rule_set * result = alloc(rule_set, m_ctx);
|
||||
|
||||
bool instantiated = false;
|
||||
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
rule * r = source.get_rule(i);
|
||||
extract_quantifiers(*r, conjs, qs);
|
||||
if (qs.empty()) {
|
||||
result->add_rule(r);
|
||||
}
|
||||
else {
|
||||
instantiate_rule(*r, conjs, qs, *result);
|
||||
instantiated = true;
|
||||
}
|
||||
}
|
||||
|
||||
// model convertion: identity function.
|
||||
|
||||
if (!instantiated) {
|
||||
dealloc(result);
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
136
src/muz_qe/dl_mk_quantifier_instantiation.h
Normal file
136
src/muz_qe/dl_mk_quantifier_instantiation.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*++
|
||||
Copyright (c) 2013 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_mk_quantifier_instantiation.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Convert Quantified Horn clauses into non-quantified clauses using
|
||||
instantiation.
|
||||
|
||||
Author:
|
||||
|
||||
Ken McMillan
|
||||
Andrey Rybalchenko
|
||||
Nikolaj Bjorner (nbjorner) 2013-04-02
|
||||
|
||||
Revision History:
|
||||
|
||||
Based on approach suggested in the SAS 2013 paper
|
||||
"On Solving Universally Quantified Horn Clauses"
|
||||
|
||||
--*/
|
||||
#ifndef _DL_MK_QUANTIFIER_INSTANTIATION_H_
|
||||
#define _DL_MK_QUANTIFIER_INSTANTIATION_H_
|
||||
|
||||
|
||||
#include"dl_rule_transformer.h"
|
||||
#include"expr_safe_replace.h"
|
||||
|
||||
|
||||
namespace datalog {
|
||||
|
||||
class context;
|
||||
|
||||
class mk_quantifier_instantiation : public rule_transformer::plugin {
|
||||
typedef svector<std::pair<expr*,expr*> > term_pairs;
|
||||
|
||||
class union_find {
|
||||
unsigned_vector m_find;
|
||||
unsigned_vector m_size;
|
||||
unsigned_vector m_next;
|
||||
|
||||
void ensure_size(unsigned v) {
|
||||
while (v >= get_num_vars()) {
|
||||
mk_var();
|
||||
}
|
||||
}
|
||||
public:
|
||||
unsigned mk_var() {
|
||||
unsigned r = m_find.size();
|
||||
m_find.push_back(r);
|
||||
m_size.push_back(1);
|
||||
m_next.push_back(r);
|
||||
return r;
|
||||
}
|
||||
unsigned get_num_vars() const { return m_find.size(); }
|
||||
|
||||
unsigned find(unsigned v) const {
|
||||
if (v >= get_num_vars()) {
|
||||
return v;
|
||||
}
|
||||
while (true) {
|
||||
unsigned new_v = m_find[v];
|
||||
if (new_v == v)
|
||||
return v;
|
||||
v = new_v;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned next(unsigned v) const {
|
||||
if (v >= get_num_vars()) {
|
||||
return v;
|
||||
}
|
||||
return m_next[v];
|
||||
}
|
||||
|
||||
bool is_root(unsigned v) const {
|
||||
return v >= get_num_vars() || m_find[v] == v;
|
||||
}
|
||||
|
||||
void merge(unsigned v1, unsigned v2) {
|
||||
unsigned r1 = find(v1);
|
||||
unsigned r2 = find(v2);
|
||||
if (r1 == r2)
|
||||
return;
|
||||
ensure_size(v1);
|
||||
ensure_size(v2);
|
||||
if (m_size[r1] > m_size[r2])
|
||||
std::swap(r1, r2);
|
||||
m_find[r1] = r2;
|
||||
m_size[r2] += m_size[r1];
|
||||
std::swap(m_next[r1], m_next[r2]);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_find.reset();
|
||||
m_next.reset();
|
||||
m_size.reset();
|
||||
}
|
||||
};
|
||||
|
||||
ast_manager& m;
|
||||
context& m_ctx;
|
||||
expr_safe_replace m_var2cnst;
|
||||
expr_safe_replace m_cnst2var;
|
||||
union_find m_uf;
|
||||
ptr_vector<expr> m_todo;
|
||||
ptr_vector<expr> m_terms;
|
||||
ptr_vector<expr> m_binding;
|
||||
obj_map<func_decl, ptr_vector<expr>*> m_funs;
|
||||
|
||||
|
||||
void extract_quantifiers(rule& r, expr_ref_vector& conjs, quantifier_ref_vector& qs);
|
||||
void collect_egraph(expr* e);
|
||||
void instantiate_rule(rule& r, expr_ref_vector& conjs, quantifier_ref_vector& qs, rule_set& rules);
|
||||
void instantiate_quantifier(quantifier* q, expr_ref_vector & conjs);
|
||||
void instantiate_quantifier(quantifier* q, app* pat, expr_ref_vector & conjs);
|
||||
void match(unsigned i, app* pat, unsigned j, term_pairs& todo, quantifier* q, expr_ref_vector& conjs);
|
||||
void yield_binding(quantifier* q, expr_ref_vector& conjs);
|
||||
|
||||
public:
|
||||
mk_quantifier_instantiation(context & ctx, unsigned priority);
|
||||
|
||||
virtual ~mk_quantifier_instantiation();
|
||||
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* _DL_MK_QUANTIFIER_INSTANTIATION_H_ */
|
||||
|
|
@ -65,8 +65,8 @@ namespace datalog {
|
|||
// -----------------------------------
|
||||
|
||||
bool rule_unifier::unify_rules(const rule& tgt, unsigned tgt_idx, const rule& src) {
|
||||
var_counter& vc = m_rm.get_var_counter();
|
||||
unsigned var_cnt = std::max(vc.get_max_var(tgt), vc.get_max_var(src))+1;
|
||||
rule_counter& vc = m_rm.get_counter();
|
||||
unsigned var_cnt = std::max(vc.get_max_rule_var(tgt), vc.get_max_rule_var(src))+1;
|
||||
m_subst.reset();
|
||||
m_subst.reserve(2, var_cnt);
|
||||
|
||||
|
@ -181,10 +181,10 @@ namespace datalog {
|
|||
}
|
||||
|
||||
if (m_unifier.apply(tgt, tail_index, src, res)) {
|
||||
if (m_pc) {
|
||||
if (m_context.generate_proof_trace()) {
|
||||
expr_ref_vector s1 = m_unifier.get_rule_subst(tgt, true);
|
||||
expr_ref_vector s2 = m_unifier.get_rule_subst(src, false);
|
||||
datalog::resolve_rule(m_pc, tgt, src, tail_index, s1, s2, *res.get());
|
||||
datalog::resolve_rule(tgt, src, tail_index, s1, s2, *res.get());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -241,8 +241,10 @@ namespace datalog {
|
|||
return false;
|
||||
}
|
||||
|
||||
//these conditions are optional, they avoid possible exponential increase
|
||||
//in the size of the problem
|
||||
//
|
||||
// these conditions are optional, they avoid possible exponential increase
|
||||
// in the size of the problem
|
||||
//
|
||||
|
||||
return
|
||||
//m_head_pred_non_empty_tails_ctr.get(pred)<=1
|
||||
|
@ -733,7 +735,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
// initialize substitution.
|
||||
var_counter& vc = m_rm.get_var_counter();
|
||||
rule_counter& vc = m_rm.get_counter();
|
||||
unsigned max_var = 0;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
rule* r = acc[i].get();
|
||||
|
@ -820,7 +822,7 @@ namespace datalog {
|
|||
del_rule(r2, j);
|
||||
}
|
||||
|
||||
max_var = std::max(max_var, vc.get_max_var(*r.get()));
|
||||
max_var = std::max(max_var, vc.get_max_rule_var(*r.get()));
|
||||
m_subst.reserve_vars(max_var+1);
|
||||
|
||||
}
|
||||
|
@ -837,11 +839,10 @@ namespace datalog {
|
|||
return done_something;
|
||||
}
|
||||
|
||||
rule_set * mk_rule_inliner::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
rule_set * mk_rule_inliner::operator()(rule_set const & source) {
|
||||
|
||||
bool something_done = false;
|
||||
ref<horn_subsume_model_converter> hsmc;
|
||||
ref<replace_proof_converter> hpc;
|
||||
|
||||
if (source.get_num_rules() == 0) {
|
||||
return 0;
|
||||
|
@ -855,14 +856,10 @@ namespace datalog {
|
|||
}
|
||||
|
||||
|
||||
if (mc) {
|
||||
if (m_context.get_model_converter()) {
|
||||
hsmc = alloc(horn_subsume_model_converter, m);
|
||||
}
|
||||
if (pc) {
|
||||
hpc = alloc(replace_proof_converter, m);
|
||||
}
|
||||
m_mc = hsmc.get();
|
||||
m_pc = hpc.get();
|
||||
|
||||
scoped_ptr<rule_set> res = alloc(rule_set, m_context);
|
||||
|
||||
|
@ -886,12 +883,7 @@ namespace datalog {
|
|||
res = 0;
|
||||
}
|
||||
else {
|
||||
if (mc) {
|
||||
mc = concat(mc.get(), hsmc.get());
|
||||
}
|
||||
if (pc) {
|
||||
pc = concat(pc.get(), hpc.get());
|
||||
}
|
||||
m_context.add_model_converter(hsmc.get());
|
||||
}
|
||||
|
||||
return res.detach();
|
||||
|
|
|
@ -114,7 +114,6 @@ namespace datalog {
|
|||
ast_counter m_tail_pred_ctr;
|
||||
rule_set m_inlined_rules;
|
||||
horn_subsume_model_converter* m_mc;
|
||||
replace_proof_converter* m_pc;
|
||||
|
||||
|
||||
//used in try_to_inline_rule and do_eager_inlining
|
||||
|
@ -188,7 +187,6 @@ namespace datalog {
|
|||
m_pinned(m_rm),
|
||||
m_inlined_rules(m_context),
|
||||
m_mc(0),
|
||||
m_pc(0),
|
||||
m_unifier(ctx),
|
||||
m_head_index(m),
|
||||
m_tail_index(m),
|
||||
|
@ -198,7 +196,7 @@ namespace datalog {
|
|||
{}
|
||||
virtual ~mk_rule_inliner() { }
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace datalog {
|
|||
/**
|
||||
Allows to traverse head and positive tails in a single for loop starting from -1
|
||||
*/
|
||||
app * get_by_tail_index(rule * r, int idx) {
|
||||
static app * get_by_tail_index(rule * r, int idx) {
|
||||
if(idx==-1) {
|
||||
return r->get_head();
|
||||
}
|
||||
|
@ -51,11 +51,11 @@ namespace datalog {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
int aux_compare(T a, T b) {
|
||||
static int aux_compare(T a, T b) {
|
||||
return (a>b) ? 1 : ( (a==b) ? 0 : -1);
|
||||
}
|
||||
|
||||
int compare_var_args(app* t1, app* t2) {
|
||||
static int compare_var_args(app* t1, app* t2) {
|
||||
SASSERT(t1->get_num_args()==t2->get_num_args());
|
||||
int res;
|
||||
unsigned n = t1->get_num_args();
|
||||
|
@ -73,7 +73,7 @@ namespace datalog {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int compare_args(app* t1, app* t2, int & skip_countdown) {
|
||||
static int compare_args(app* t1, app* t2, int & skip_countdown) {
|
||||
SASSERT(t1->get_num_args()==t2->get_num_args());
|
||||
int res;
|
||||
unsigned n = t1->get_num_args();
|
||||
|
@ -98,7 +98,7 @@ namespace datalog {
|
|||
Two rules are in the same rough similarity class if they differ only in constant arguments
|
||||
of positive uninterpreted predicates.
|
||||
*/
|
||||
int rough_compare(rule * r1, rule * r2) {
|
||||
static int rough_compare(rule * r1, rule * r2) {
|
||||
int res = aux_compare(r1->get_tail_size(), r2->get_tail_size());
|
||||
if(res!=0) { return res; }
|
||||
res = aux_compare(r1->get_uninterpreted_tail_size(), r2->get_uninterpreted_tail_size());
|
||||
|
@ -129,7 +129,7 @@ namespace datalog {
|
|||
\c r1 and \c r2 must be equal according to the \c rough_compare function for this function
|
||||
to be called.
|
||||
*/
|
||||
int total_compare(rule * r1, rule * r2, int skipped_arg_index = INT_MAX) {
|
||||
static int total_compare(rule * r1, rule * r2, int skipped_arg_index = INT_MAX) {
|
||||
SASSERT(rough_compare(r1, r2)==0);
|
||||
int pos_tail_sz = r1->get_positive_tail_size();
|
||||
for(int i=-1; i<pos_tail_sz; i++) {
|
||||
|
@ -165,7 +165,7 @@ namespace datalog {
|
|||
|
||||
typedef svector<const_info> info_vector;
|
||||
|
||||
void collect_const_indexes(app * t, int tail_index, info_vector & res) {
|
||||
static void collect_const_indexes(app * t, int tail_index, info_vector & res) {
|
||||
unsigned n = t->get_num_args();
|
||||
for(unsigned i=0; i<n; i++) {
|
||||
if(is_var(t->get_arg(i))) {
|
||||
|
@ -175,7 +175,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
void collect_const_indexes(rule * r, info_vector & res) {
|
||||
static void collect_const_indexes(rule * r, info_vector & res) {
|
||||
collect_const_indexes(r->get_head(), -1, res);
|
||||
unsigned pos_tail_sz = r->get_positive_tail_size();
|
||||
for(unsigned i=0; i<pos_tail_sz; i++) {
|
||||
|
@ -184,7 +184,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
template<class T>
|
||||
void collect_orphan_consts(rule * r, const info_vector & const_infos, T & tgt) {
|
||||
static void collect_orphan_consts(rule * r, const info_vector & const_infos, T & tgt) {
|
||||
unsigned const_cnt = const_infos.size();
|
||||
tgt.reset();
|
||||
for(unsigned i=0; i<const_cnt; i++) {
|
||||
|
@ -198,7 +198,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
template<class T>
|
||||
void collect_orphan_sorts(rule * r, const info_vector & const_infos, T & tgt) {
|
||||
static void collect_orphan_sorts(rule * r, const info_vector & const_infos, T & tgt) {
|
||||
unsigned const_cnt = const_infos.size();
|
||||
tgt.reset();
|
||||
for(unsigned i=0; i<const_cnt; i++) {
|
||||
|
@ -215,7 +215,7 @@ namespace datalog {
|
|||
\brief From the \c tail_indexes and \c arg_indexes remove elements corresponding to constants
|
||||
that are the same in rules \c *first ... \c *(after_last-1).
|
||||
*/
|
||||
void remove_stable_constants(rule_vector::iterator first, rule_vector::iterator after_last,
|
||||
static void remove_stable_constants(rule_vector::iterator first, rule_vector::iterator after_last,
|
||||
info_vector & const_infos) {
|
||||
SASSERT(after_last-first>1);
|
||||
unsigned const_cnt = const_infos.size();
|
||||
|
@ -252,7 +252,7 @@ namespace datalog {
|
|||
first constant that is equal to it in all the rules. If there is no such, it will contain
|
||||
its own index.
|
||||
*/
|
||||
void detect_equal_constants(rule_vector::iterator first, rule_vector::iterator after_last,
|
||||
static void detect_equal_constants(rule_vector::iterator first, rule_vector::iterator after_last,
|
||||
info_vector & const_infos) {
|
||||
SASSERT(first!=after_last);
|
||||
unsigned const_cnt = const_infos.size();
|
||||
|
@ -302,7 +302,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
unsigned get_constant_count(rule * r) {
|
||||
static unsigned get_constant_count(rule * r) {
|
||||
unsigned res = r->get_head()->get_num_args() - count_variable_arguments(r->get_head());
|
||||
unsigned pos_tail_sz = r->get_positive_tail_size();
|
||||
for(unsigned i=0; i<pos_tail_sz; i++) {
|
||||
|
@ -311,7 +311,7 @@ namespace datalog {
|
|||
return res;
|
||||
}
|
||||
|
||||
bool initial_comparator(rule * r1, rule * r2) {
|
||||
static bool initial_comparator(rule * r1, rule * r2) {
|
||||
int res = rough_compare(r1, r2);
|
||||
if(res!=0) { return res>0; }
|
||||
return total_compare(r1, r2)>0;
|
||||
|
@ -372,10 +372,10 @@ namespace datalog {
|
|||
new_negs.push_back(r->is_neg_tail(i));
|
||||
}
|
||||
|
||||
var_counter var_ctr;
|
||||
var_ctr.count_vars(m_manager, r);
|
||||
rule_counter ctr;
|
||||
ctr.count_rule_vars(m_manager, r);
|
||||
unsigned max_var_idx, new_var_idx_base;
|
||||
if(var_ctr.get_max_positive(max_var_idx)) {
|
||||
if(ctr.get_max_positive(max_var_idx)) {
|
||||
new_var_idx_base = max_var_idx+1;
|
||||
}
|
||||
else {
|
||||
|
@ -500,8 +500,8 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
rule_set * mk_similarity_compressor::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
// TODO mc, pc
|
||||
rule_set * mk_similarity_compressor::operator()(rule_set const & source) {
|
||||
// TODO mc
|
||||
m_modified = false;
|
||||
unsigned init_rule_cnt = source.get_num_rules();
|
||||
SASSERT(m_rules.empty());
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace datalog {
|
|||
public:
|
||||
mk_similarity_compressor(context & ctx, unsigned threshold_count);
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -310,8 +310,8 @@ namespace datalog {
|
|||
}
|
||||
|
||||
void register_rule(rule * r) {
|
||||
var_counter counter;
|
||||
counter.count_vars(m, r, 1);
|
||||
rule_counter counter;
|
||||
counter.count_rule_vars(m, r, 1);
|
||||
|
||||
ptr_vector<app> & rule_content =
|
||||
m_rules_content.insert_if_not_there2(r, ptr_vector<app>())->get_data().m_value;
|
||||
|
@ -706,19 +706,19 @@ namespace datalog {
|
|||
negs.c_ptr());
|
||||
|
||||
new_rule->set_accounting_parent_object(m_context, orig_r);
|
||||
|
||||
m_context.get_rule_manager().mk_rule_rewrite_proof(*orig_r, *new_rule);
|
||||
result->add_rule(new_rule);
|
||||
}
|
||||
while(!m_introduced_rules.empty()) {
|
||||
while (!m_introduced_rules.empty()) {
|
||||
result->add_rule(m_introduced_rules.back());
|
||||
m_context.get_rule_manager().mk_rule_asserted_proof(*m_introduced_rules.back());
|
||||
m_introduced_rules.pop_back();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
rule_set * mk_simple_joins::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
// TODO mc, pc
|
||||
rule_set * mk_simple_joins::operator()(rule_set const & source) {
|
||||
rule_set rs_aux_copy(m_context);
|
||||
rs_aux_copy.add_rules(source);
|
||||
if(!rs_aux_copy.is_closed()) {
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace datalog {
|
|||
public:
|
||||
mk_simple_joins(context & ctx);
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -164,10 +164,8 @@ namespace datalog {
|
|||
TRACE("dl", tout << "does not have fact\n" << mk_pp(fact, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
expr_ref fml(m);
|
||||
proof_ref new_p(m);
|
||||
r->to_formula(fml);
|
||||
new_p = m.mk_asserted(fml);
|
||||
new_p = r->get_proof();
|
||||
m_pinned_exprs.push_back(new_p);
|
||||
m_todo.pop_back();
|
||||
m_new_proof.insert(p, new_p);
|
||||
|
@ -784,6 +782,9 @@ namespace datalog {
|
|||
rm.fix_unbound_vars(new_rule, false);
|
||||
|
||||
TRACE("dl", r.display(m_ctx, tout << "replacing:\n"); new_rule->display(m_ctx, tout << "by:\n"););
|
||||
if (m_ctx.generate_proof_trace()) {
|
||||
rm.mk_rule_asserted_proof(*new_rule.get());
|
||||
}
|
||||
}
|
||||
else {
|
||||
new_rule = &r;
|
||||
|
@ -801,7 +802,7 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
rule_set * mk_slice::operator()(rule_set const & src, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
rule_set * mk_slice::operator()(rule_set const & src) {
|
||||
for (unsigned i = 0; i < src.get_num_rules(); ++i) {
|
||||
if (src.get_rule(i)->has_quantifiers()) {
|
||||
return 0;
|
||||
|
@ -809,10 +810,10 @@ namespace datalog {
|
|||
}
|
||||
ref<slice_proof_converter> spc;
|
||||
ref<slice_model_converter> smc;
|
||||
if (pc) {
|
||||
spc = alloc(slice_proof_converter, m_ctx);
|
||||
if (m_ctx.generate_proof_trace()) {
|
||||
spc = alloc(slice_proof_converter, m_ctx);
|
||||
}
|
||||
if (mc) {
|
||||
if (m_ctx.get_model_converter()) {
|
||||
smc = alloc(slice_model_converter, *this, m);
|
||||
}
|
||||
m_pc = spc.get();
|
||||
|
@ -834,8 +835,8 @@ namespace datalog {
|
|||
m_mc->add_sliceable(it->m_key, it->m_value);
|
||||
}
|
||||
}
|
||||
pc = concat(pc.get(), spc.get());
|
||||
mc = concat(mc.get(), smc.get());
|
||||
m_ctx.add_proof_converter(spc.get());
|
||||
m_ctx.add_model_converter(smc.get());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace datalog {
|
|||
|
||||
virtual ~mk_slice() { }
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
|
||||
func_decl* get_predicate(func_decl* p) { func_decl* q = p; m_predicates.find(p, q); return q; }
|
||||
|
||||
|
|
|
@ -166,7 +166,8 @@ namespace datalog {
|
|||
res = m_context.get_rule_manager().mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr());
|
||||
res->set_accounting_parent_object(m_context, r);
|
||||
m_context.get_rule_manager().fix_unbound_vars(res, true);
|
||||
|
||||
m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *res.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -208,10 +209,10 @@ namespace datalog {
|
|||
continue;
|
||||
}
|
||||
rule * defining_rule;
|
||||
TRUSTME(m_total_relation_defining_rules.find(head_pred, defining_rule));
|
||||
if(defining_rule) {
|
||||
VERIFY(m_total_relation_defining_rules.find(head_pred, defining_rule));
|
||||
if (defining_rule) {
|
||||
rule_ref totality_rule(m_context.get_rule_manager());
|
||||
TRUSTME(transform_rule(defining_rule, subs_index, totality_rule));
|
||||
VERIFY(transform_rule(defining_rule, subs_index, totality_rule));
|
||||
if(defining_rule!=totality_rule) {
|
||||
modified = true;
|
||||
}
|
||||
|
@ -331,8 +332,8 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
rule_set * mk_subsumption_checker::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) {
|
||||
// TODO mc, pc
|
||||
rule_set * mk_subsumption_checker::operator()(rule_set const & source) {
|
||||
// TODO mc
|
||||
|
||||
m_have_new_total_rule = false;
|
||||
collect_ground_unconditional_rule_heads(source);
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace datalog {
|
|||
reset_dealloc_values(m_ground_unconditional_rule_heads);
|
||||
}
|
||||
|
||||
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
||||
rule_set * operator()(rule_set const & source);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue