mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 01:24:08 +00:00
parent
ca498e20d1
commit
4ce6b53d95
|
@ -913,6 +913,11 @@ app* seq_decl_plugin::mk_string(zstring const& s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool seq_decl_plugin::is_considered_uninterpreted(func_decl * f) {
|
||||||
|
seq_util util(*m_manager);
|
||||||
|
return util.str.is_nth_u(f);
|
||||||
|
}
|
||||||
|
|
||||||
bool seq_decl_plugin::is_value(app* e) const {
|
bool seq_decl_plugin::is_value(app* e) const {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (is_app_of(e, m_family_id, OP_SEQ_EMPTY)) {
|
if (is_app_of(e, m_family_id, OP_SEQ_EMPTY)) {
|
||||||
|
|
|
@ -207,6 +207,7 @@ public:
|
||||||
|
|
||||||
bool has_re() const { return m_has_re; }
|
bool has_re() const { return m_has_re; }
|
||||||
|
|
||||||
|
bool is_considered_uninterpreted(func_decl * f) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class seq_util {
|
class seq_util {
|
||||||
|
|
|
@ -29,6 +29,12 @@ Revision History:
|
||||||
#include "model/model.h"
|
#include "model/model.h"
|
||||||
#include "model/model_params.hpp"
|
#include "model/model_params.hpp"
|
||||||
#include "model/model_evaluator.h"
|
#include "model/model_evaluator.h"
|
||||||
|
#include "model/array_factory.h"
|
||||||
|
#include "model/value_factory.h"
|
||||||
|
#include "model/seq_factory.h"
|
||||||
|
#include "model/datatype_factory.h"
|
||||||
|
#include "model/numeral_factory.h"
|
||||||
|
|
||||||
|
|
||||||
model::model(ast_manager & m):
|
model::model(ast_manager & m):
|
||||||
model_core(m),
|
model_core(m),
|
||||||
|
@ -88,40 +94,38 @@ bool model::eval_expr(expr * e, expr_ref & result, bool model_completion) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct model::value_proc : public some_value_proc {
|
value_factory* model::get_factory(sort* s) {
|
||||||
model & m_model;
|
if (m_factories.plugins().empty()) {
|
||||||
value_proc(model & m):m_model(m) {}
|
seq_util su(m);
|
||||||
expr * operator()(sort * s) override {
|
m_factories.register_plugin(alloc(array_factory, m, *this));
|
||||||
ptr_vector<expr> * u = nullptr;
|
m_factories.register_plugin(alloc(datatype_factory, m, *this));
|
||||||
if (m_model.m_usort2universe.find(s, u)) {
|
m_factories.register_plugin(alloc(bv_factory, m));
|
||||||
if (!u->empty())
|
m_factories.register_plugin(alloc(arith_factory, m));
|
||||||
return u->get(0);
|
m_factories.register_plugin(alloc(seq_factory, m, su.get_family_id(), *this));
|
||||||
}
|
}
|
||||||
return nullptr;
|
family_id fid = s->get_family_id();
|
||||||
}
|
return m_factories.get_plugin(fid);
|
||||||
};
|
}
|
||||||
|
|
||||||
expr * model::get_some_value(sort * s) {
|
expr * model::get_some_value(sort * s) {
|
||||||
value_proc p(*this);
|
ptr_vector<expr> * u = nullptr;
|
||||||
return m.get_some_value(s, &p);
|
if (m_usort2universe.find(s, u)) {
|
||||||
|
if (!u->empty())
|
||||||
|
return u->get(0);
|
||||||
|
}
|
||||||
|
return m.get_some_value(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr * model::get_fresh_value(sort * s) {
|
expr * model::get_fresh_value(sort * s) {
|
||||||
value_proc p(*this);
|
return get_factory(s)->get_fresh_value(s);
|
||||||
return m.get_some_value(s, &p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool model::get_some_values(sort * s, expr_ref& v1, expr_ref& v2) {
|
bool model::get_some_values(sort * s, expr_ref& v1, expr_ref& v2) {
|
||||||
v1 = get_some_value(s);
|
return get_factory(s)->get_some_values(s, v1, v2);
|
||||||
v2 = get_some_value(s);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_vector<expr> const & model::get_universe(sort * s) const {
|
ptr_vector<expr> const & model::get_universe(sort * s) const {
|
||||||
ptr_vector<expr> * u = nullptr;
|
return *m_usort2universe[s];
|
||||||
m_usort2universe.find(s, u);
|
|
||||||
SASSERT(u != nullptr);
|
|
||||||
return *u;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool model::has_uninterpreted_sort(sort * s) const {
|
bool model::has_uninterpreted_sort(sort * s) const {
|
||||||
|
|
|
@ -19,10 +19,13 @@ Revision History:
|
||||||
#ifndef MODEL_H_
|
#ifndef MODEL_H_
|
||||||
#define MODEL_H_
|
#define MODEL_H_
|
||||||
|
|
||||||
|
#include "util/ref.h"
|
||||||
|
#include "util/vector.h"
|
||||||
|
#include "ast/ast_translation.h"
|
||||||
|
#include "util/plugin_manager.h"
|
||||||
#include "model/model_core.h"
|
#include "model/model_core.h"
|
||||||
#include "model/model_evaluator.h"
|
#include "model/model_evaluator.h"
|
||||||
#include "util/ref.h"
|
#include "model/value_factory.h"
|
||||||
#include "ast/ast_translation.h"
|
|
||||||
|
|
||||||
class model;
|
class model;
|
||||||
typedef ref<model> model_ref;
|
typedef ref<model> model_ref;
|
||||||
|
@ -37,7 +40,7 @@ protected:
|
||||||
model_evaluator m_mev;
|
model_evaluator m_mev;
|
||||||
bool m_cleaned;
|
bool m_cleaned;
|
||||||
bool m_inline;
|
bool m_inline;
|
||||||
struct value_proc;
|
plugin_manager<value_factory> m_factories;
|
||||||
|
|
||||||
struct deps_collector;
|
struct deps_collector;
|
||||||
struct occs_collector;
|
struct occs_collector;
|
||||||
|
@ -52,6 +55,7 @@ protected:
|
||||||
expr_ref cleanup_expr(top_sort& ts, expr* e, unsigned current_partition);
|
expr_ref cleanup_expr(top_sort& ts, expr* e, unsigned current_partition);
|
||||||
void remove_decls(ptr_vector<func_decl> & decls, func_decl_set const & s);
|
void remove_decls(ptr_vector<func_decl> & decls, func_decl_set const & s);
|
||||||
bool can_inline_def(top_sort& ts, func_decl* f);
|
bool can_inline_def(top_sort& ts, func_decl* f);
|
||||||
|
value_factory* get_factory(sort* s);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
model(ast_manager & m);
|
model(ast_manager & m);
|
||||||
|
|
149
src/model/seq_factory.h
Normal file
149
src/model/seq_factory.h
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2011 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
theory_seq_empty.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
<abstract>
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Nikolaj Bjorner (nbjorner) 2011-14-11
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef SEQ_FACTORY_H_
|
||||||
|
#define SEQ_FACTORY_H_
|
||||||
|
|
||||||
|
#include "ast/seq_decl_plugin.h"
|
||||||
|
#include "model/model_core.h"
|
||||||
|
|
||||||
|
class seq_factory : public value_factory {
|
||||||
|
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
|
||||||
|
model_core& m_model;
|
||||||
|
ast_manager& m;
|
||||||
|
seq_util u;
|
||||||
|
symbol_set m_strings;
|
||||||
|
unsigned m_next;
|
||||||
|
std::string m_unique_delim;
|
||||||
|
obj_map<sort, expr*> m_unique_sequences;
|
||||||
|
expr_ref_vector m_trail;
|
||||||
|
public:
|
||||||
|
|
||||||
|
seq_factory(ast_manager & m, family_id fid, model_core& md):
|
||||||
|
value_factory(m, fid),
|
||||||
|
m_model(md),
|
||||||
|
m(m),
|
||||||
|
u(m),
|
||||||
|
m_next(0),
|
||||||
|
m_unique_delim("!"),
|
||||||
|
m_trail(m)
|
||||||
|
{
|
||||||
|
m_strings.insert(symbol(""));
|
||||||
|
m_strings.insert(symbol("a"));
|
||||||
|
m_strings.insert(symbol("b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_trail(expr* e) {
|
||||||
|
m_trail.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_prefix(char const* p) {
|
||||||
|
m_unique_delim = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic method for setting unique sequences
|
||||||
|
void set_prefix(expr* uniq) {
|
||||||
|
m_trail.push_back(uniq);
|
||||||
|
m_unique_sequences.insert(m.get_sort(uniq), uniq);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr* get_some_value(sort* s) override {
|
||||||
|
if (u.is_seq(s)) {
|
||||||
|
return u.str.mk_empty(s);
|
||||||
|
}
|
||||||
|
sort* seq = nullptr;
|
||||||
|
if (u.is_re(s, seq)) {
|
||||||
|
return u.re.mk_to_re(u.str.mk_empty(seq));
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool get_some_values(sort* s, expr_ref& v1, expr_ref& v2) override {
|
||||||
|
if (u.is_string(s)) {
|
||||||
|
v1 = u.str.mk_string(symbol("a"));
|
||||||
|
v2 = u.str.mk_string(symbol("b"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
sort* ch;
|
||||||
|
if (u.is_seq(s, ch)) {
|
||||||
|
if (m_model.get_some_values(ch, v1, v2)) {
|
||||||
|
v1 = u.str.mk_unit(v1);
|
||||||
|
v2 = u.str.mk_unit(v2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
expr* get_fresh_value(sort* s) override {
|
||||||
|
if (u.is_string(s)) {
|
||||||
|
while (true) {
|
||||||
|
std::ostringstream strm;
|
||||||
|
strm << m_unique_delim << std::hex << m_next++ << std::dec << m_unique_delim;
|
||||||
|
symbol sym(strm.str().c_str());
|
||||||
|
if (m_strings.contains(sym)) continue;
|
||||||
|
m_strings.insert(sym);
|
||||||
|
return u.str.mk_string(sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort* seq = nullptr, *ch = nullptr;
|
||||||
|
if (u.is_re(s, seq)) {
|
||||||
|
expr* v0 = get_fresh_value(seq);
|
||||||
|
return u.re.mk_to_re(v0);
|
||||||
|
}
|
||||||
|
if (u.is_char(s)) {
|
||||||
|
//char s[2] = { ++m_char, 0 };
|
||||||
|
//return u.str.mk_char(zstring(s), 0);
|
||||||
|
return u.str.mk_char(zstring("a"), 0);
|
||||||
|
}
|
||||||
|
if (u.is_seq(s, ch)) {
|
||||||
|
expr* v = m_model.get_fresh_value(ch);
|
||||||
|
if (!v) return nullptr;
|
||||||
|
return u.str.mk_unit(v);
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
void register_value(expr* n) override {
|
||||||
|
symbol sym;
|
||||||
|
if (u.str.is_string(n, sym)) {
|
||||||
|
m_strings.insert(sym);
|
||||||
|
if (sym.str().find(m_unique_delim) != std::string::npos) {
|
||||||
|
add_new_delim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
void add_new_delim() {
|
||||||
|
bool found = true;
|
||||||
|
while (found) {
|
||||||
|
found = false;
|
||||||
|
m_unique_delim += "!";
|
||||||
|
symbol_set::iterator it = m_strings.begin(), end = m_strings.end();
|
||||||
|
for (; it != end && !found; ++it) {
|
||||||
|
found = it->str().find(m_unique_delim) != std::string::npos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -31,7 +31,6 @@ Revision History:
|
||||||
#include "model/model_core.h"
|
#include "model/model_core.h"
|
||||||
#include "model/model_evaluator.h"
|
#include "model/model_evaluator.h"
|
||||||
#include "model/value_factory.h"
|
#include "model/value_factory.h"
|
||||||
#include "util/plugin_manager.h"
|
|
||||||
#include "ast/arith_decl_plugin.h"
|
#include "ast/arith_decl_plugin.h"
|
||||||
#include "ast/func_decl_dependencies.h"
|
#include "ast/func_decl_dependencies.h"
|
||||||
#include "model/model.h"
|
#include "model/model.h"
|
||||||
|
|
|
@ -21,131 +21,9 @@ Revision History:
|
||||||
|
|
||||||
#include "smt/smt_theory.h"
|
#include "smt/smt_theory.h"
|
||||||
#include "ast/seq_decl_plugin.h"
|
#include "ast/seq_decl_plugin.h"
|
||||||
|
#include "model/seq_factory.h"
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
class seq_factory : public value_factory {
|
|
||||||
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
|
|
||||||
proto_model& m_model;
|
|
||||||
ast_manager& m;
|
|
||||||
seq_util u;
|
|
||||||
symbol_set m_strings;
|
|
||||||
unsigned m_next;
|
|
||||||
std::string m_unique_delim;
|
|
||||||
obj_map<sort, expr*> m_unique_sequences;
|
|
||||||
expr_ref_vector m_trail;
|
|
||||||
public:
|
|
||||||
|
|
||||||
seq_factory(ast_manager & m, family_id fid, proto_model& md):
|
|
||||||
value_factory(m, fid),
|
|
||||||
m_model(md),
|
|
||||||
m(m),
|
|
||||||
u(m),
|
|
||||||
m_next(0),
|
|
||||||
m_unique_delim("!"),
|
|
||||||
m_trail(m)
|
|
||||||
{
|
|
||||||
m_strings.insert(symbol(""));
|
|
||||||
m_strings.insert(symbol("a"));
|
|
||||||
m_strings.insert(symbol("b"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_trail(expr* e) {
|
|
||||||
m_trail.push_back(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_prefix(char const* p) {
|
|
||||||
m_unique_delim = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// generic method for setting unique sequences
|
|
||||||
void set_prefix(expr* uniq) {
|
|
||||||
m_trail.push_back(uniq);
|
|
||||||
m_unique_sequences.insert(m.get_sort(uniq), uniq);
|
|
||||||
}
|
|
||||||
|
|
||||||
expr* get_some_value(sort* s) override {
|
|
||||||
if (u.is_seq(s)) {
|
|
||||||
return u.str.mk_empty(s);
|
|
||||||
}
|
|
||||||
sort* seq = nullptr;
|
|
||||||
if (u.is_re(s, seq)) {
|
|
||||||
return u.re.mk_to_re(u.str.mk_empty(seq));
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
bool get_some_values(sort* s, expr_ref& v1, expr_ref& v2) override {
|
|
||||||
if (u.is_string(s)) {
|
|
||||||
v1 = u.str.mk_string(symbol("a"));
|
|
||||||
v2 = u.str.mk_string(symbol("b"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
sort* ch;
|
|
||||||
if (u.is_seq(s, ch)) {
|
|
||||||
if (m_model.get_some_values(ch, v1, v2)) {
|
|
||||||
v1 = u.str.mk_unit(v1);
|
|
||||||
v2 = u.str.mk_unit(v2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NOT_IMPLEMENTED_YET();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
expr* get_fresh_value(sort* s) override {
|
|
||||||
if (u.is_string(s)) {
|
|
||||||
while (true) {
|
|
||||||
std::ostringstream strm;
|
|
||||||
strm << m_unique_delim << std::hex << m_next++ << std::dec << m_unique_delim;
|
|
||||||
symbol sym(strm.str().c_str());
|
|
||||||
if (m_strings.contains(sym)) continue;
|
|
||||||
m_strings.insert(sym);
|
|
||||||
return u.str.mk_string(sym);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort* seq = nullptr, *ch = nullptr;
|
|
||||||
if (u.is_re(s, seq)) {
|
|
||||||
expr* v0 = get_fresh_value(seq);
|
|
||||||
return u.re.mk_to_re(v0);
|
|
||||||
}
|
|
||||||
if (u.is_char(s)) {
|
|
||||||
//char s[2] = { ++m_char, 0 };
|
|
||||||
//return u.str.mk_char(zstring(s), 0);
|
|
||||||
return u.str.mk_char(zstring("a"), 0);
|
|
||||||
}
|
|
||||||
if (u.is_seq(s, ch)) {
|
|
||||||
expr* v = m_model.get_fresh_value(ch);
|
|
||||||
if (!v) return nullptr;
|
|
||||||
return u.str.mk_unit(v);
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
void register_value(expr* n) override {
|
|
||||||
symbol sym;
|
|
||||||
if (u.str.is_string(n, sym)) {
|
|
||||||
m_strings.insert(sym);
|
|
||||||
if (sym.str().find(m_unique_delim) != std::string::npos) {
|
|
||||||
add_new_delim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
|
|
||||||
void add_new_delim() {
|
|
||||||
bool found = true;
|
|
||||||
while (found) {
|
|
||||||
found = false;
|
|
||||||
m_unique_delim += "!";
|
|
||||||
symbol_set::iterator it = m_strings.begin(), end = m_strings.end();
|
|
||||||
for (; it != end && !found; ++it) {
|
|
||||||
found = it->str().find(m_unique_delim) != std::string::npos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class theory_seq_empty : public theory {
|
class theory_seq_empty : public theory {
|
||||||
bool m_used;
|
bool m_used;
|
||||||
|
|
Loading…
Reference in a new issue