3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-09-03 16:48:06 +00:00

add E(T) functionality for bv and ac functions

Add an option to register EUF modulo theories,
The current theory with a unit test is BV.
The arithmetic theory plugs into an AC completion. It is partially finished, pending setting up testing and implementing handling of shared terms.
This commit is contained in:
Nikolaj Bjorner 2023-11-12 15:39:45 -08:00
parent 9ce47ab460
commit 65a8c162f5
19 changed files with 1830 additions and 21 deletions

View file

@ -38,6 +38,7 @@ add_executable(test-z3
dl_util.cpp
doc.cpp
egraph.cpp
euf_bv_plugin.cpp
escaped.cpp
ex.cpp
expr_rand.cpp

180
src/test/euf_bv_plugin.cpp Normal file
View file

@ -0,0 +1,180 @@
/*++
Copyright (c) 2023 Microsoft Corporation
--*/
#include "util/util.h"
#include "util/timer.h"
#include "ast/euf/euf_egraph.h"
#include "ast/euf/euf_bv_plugin.h"
#include "ast/reg_decl_plugins.h"
#include "ast/ast_pp.h"
#include <iostream>
euf::enode* get_node(euf::egraph& g, expr* e) {
auto* n = g.find(e);
if (n)
return n;
euf::enode_vector args;
for (expr* arg : *to_app(e))
args.push_back(get_node(g, arg));
return g.mk(e, 0, args.size(), args.data());
}
// align slices, and propagate extensionality
static void test1() {
ast_manager m;
reg_decl_plugins(m);
euf::egraph g(m);
g.add_plugins();
bv_util bv(m);
sort_ref u32(bv.mk_sort(32), m);
expr_ref x(m.mk_const("x", u32), m);
expr_ref y(m.mk_const("y", u32), m);
expr_ref x3(bv.mk_extract(31, 16, x), m);
expr_ref x2(bv.mk_extract(15, 8, x), m);
expr_ref x1(bv.mk_extract(7, 0, x), m);
expr_ref y3(bv.mk_extract(31, 24, y), m);
expr_ref y2(bv.mk_extract(23, 8, y), m);
expr_ref y1(bv.mk_extract(7, 0, y), m);
expr_ref xx(bv.mk_concat(x1, bv.mk_concat(x2, x3)), m);
expr_ref yy(bv.mk_concat(y1, bv.mk_concat(y2, y3)), m);
auto* nx = get_node(g, xx);
auto* ny = get_node(g, yy);
TRACE("bv", tout << "before merge\n" << g << "\n");
g.merge(nx, ny, nullptr);
TRACE("bv", tout << "before propagate\n" << g << "\n");
g.propagate();
TRACE("bv", tout << "after propagate\n" << g << "\n");
std::cout << g << "\n";
SASSERT(nx->get_root() == ny->get_root());
}
// propagate values down
static void test2() {
ast_manager m;
reg_decl_plugins(m);
euf::egraph g(m);
g.add_plugins();
bv_util bv(m);
sort_ref u32(bv.mk_sort(32), m);
expr_ref x(m.mk_const("x", u32), m);
expr_ref x3(bv.mk_extract(31, 16, x), m);
expr_ref x2(bv.mk_extract(15, 8, x), m);
expr_ref x1(bv.mk_extract(7, 0, x), m);
expr_ref xx(bv.mk_concat(x1, bv.mk_concat(x2, x3)), m);
g.merge(get_node(g, xx), get_node(g, bv.mk_numeral((1 << 27) + (1 << 17) + (1 << 3), 32)), nullptr);
g.propagate();
SASSERT(get_node(g, x1)->get_root()->interpreted());
SASSERT(get_node(g, x2)->get_root()->interpreted());
SASSERT(get_node(g, x3)->get_root()->interpreted());
SASSERT(get_node(g, x)->get_root()->interpreted());
}
// propagate values up
static void test3() {
ast_manager m;
reg_decl_plugins(m);
euf::egraph g(m);
g.add_plugins();
bv_util bv(m);
sort_ref u32(bv.mk_sort(32), m);
expr_ref x(m.mk_const("x", u32), m);
expr_ref x3(bv.mk_extract(31, 16, x), m);
expr_ref x2(bv.mk_extract(15, 8, x), m);
expr_ref x1(bv.mk_extract(7, 0, x), m);
expr_ref xx(bv.mk_concat(bv.mk_concat(x1, x2), x3), m);
expr_ref y(m.mk_const("y", u32), m);
g.merge(get_node(g, xx), get_node(g, y), nullptr);
g.merge(get_node(g, x1), get_node(g, bv.mk_numeral(2, 8)), nullptr);
g.merge(get_node(g, x2), get_node(g, bv.mk_numeral(8, 8)), nullptr);
g.propagate();
SASSERT(get_node(g, bv.mk_concat(x1, x2))->get_root()->interpreted());
SASSERT(get_node(g, x1)->get_root()->interpreted());
SASSERT(get_node(g, x2)->get_root()->interpreted());
}
// propagate extract up
static void test4() {
// concat(a, x[J]), a = x[I] => x[IJ] = concat(x[I],x[J])
ast_manager m;
reg_decl_plugins(m);
euf::egraph g(m);
g.add_plugins();
bv_util bv(m);
sort_ref u32(bv.mk_sort(32), m);
sort_ref u8(bv.mk_sort(8), m);
sort_ref u16(bv.mk_sort(16), m);
expr_ref a(m.mk_const("a", u8), m);
expr_ref x(m.mk_const("x", u32), m);
expr_ref y(m.mk_const("y", u16), m);
expr_ref x1(bv.mk_extract(15, 8, x), m);
expr_ref x2(bv.mk_extract(23, 16, x), m);
g.merge(get_node(g, bv.mk_concat(a, x2)), get_node(g, y), nullptr);
g.merge(get_node(g, x1), get_node(g, a), nullptr);
g.propagate();
TRACE("bv", tout << g << "\n");
SASSERT(get_node(g, bv.mk_extract(23, 8, x))->get_root() == get_node(g, y)->get_root());
}
// iterative slicing
static void test5() {
ast_manager m;
reg_decl_plugins(m);
euf::egraph g(m);
g.add_plugins();
bv_util bv(m);
sort_ref u32(bv.mk_sort(32), m);
expr_ref x(m.mk_const("x", u32), m);
expr_ref x1(bv.mk_extract(31, 4, x), m);
expr_ref x2(bv.mk_extract(27, 0, x), m);
auto* nx = get_node(g, x1);
auto* ny = get_node(g, x2);
TRACE("bv", tout << "before merge\n" << g << "\n");
g.merge(nx, ny, nullptr);
TRACE("bv", tout << "before propagate\n" << g << "\n");
g.propagate();
TRACE("bv", tout << "after propagate\n" << g << "\n");
std::cout << g << "\n";
}
// iterative slicing
static void test6() {
ast_manager m;
reg_decl_plugins(m);
euf::egraph g(m);
g.add_plugins();
bv_util bv(m);
sort_ref u32(bv.mk_sort(32), m);
expr_ref x(m.mk_const("x", u32), m);
expr_ref x1(bv.mk_extract(31, 3, x), m);
expr_ref x2(bv.mk_extract(28, 0, x), m);
auto* nx = get_node(g, x1);
auto* ny = get_node(g, x2);
TRACE("bv", tout << "before merge\n" << g << "\n");
g.merge(nx, ny, nullptr);
TRACE("bv", tout << "before propagate\n" << g << "\n");
g.propagate();
TRACE("bv", tout << "after propagate\n" << g << "\n");
std::cout << g << "\n";
}
void tst_euf_bv_plugin() {
enable_trace("bv");
enable_trace("plugin");
test6();
return;
test1();
test2();
test3();
test4();
test5();
test6();
}

View file

@ -270,4 +270,5 @@ int main(int argc, char ** argv) {
TST(slicing);
TST(totalizer);
TST(distribution);
TST(euf_bv_plugin);
}