mirror of
https://github.com/Z3Prover/z3
synced 2025-05-09 00:35:47 +00:00
Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
3f9edad676
commit
e9eab22e5c
1186 changed files with 381859 additions and 0 deletions
257
lib/value_factory.h
Normal file
257
lib/value_factory.h
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
value_factory.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-10-28.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _VALUE_FACTORY_H_
|
||||
#define _VALUE_FACTORY_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
/**
|
||||
\brief Auxiliary object used during model construction.
|
||||
*/
|
||||
class value_factory {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
family_id m_fid;
|
||||
public:
|
||||
value_factory(ast_manager & m, family_id fid);
|
||||
|
||||
virtual ~value_factory();
|
||||
|
||||
/**
|
||||
\brief Return some value of the given sort. The result is always different from zero.
|
||||
*/
|
||||
virtual expr * get_some_value(sort * s) = 0;
|
||||
|
||||
/**
|
||||
\brief Return two distinct values of the given sort. The results are stored in v1 and v2.
|
||||
Return false if the intended interpretation of the given sort has only one element.
|
||||
*/
|
||||
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) = 0;
|
||||
|
||||
/**
|
||||
\brief Return a fresh value of the given sort.
|
||||
Return 0 if it is not possible to do that (e.g., the sort is finite).
|
||||
*/
|
||||
virtual expr * get_fresh_value(sort * s) = 0;
|
||||
|
||||
/**
|
||||
\brief Used to register that the given value was used in model construction.
|
||||
So, get_fresh_value cannot return this value anymore.
|
||||
*/
|
||||
virtual void register_value(expr * n) = 0;
|
||||
|
||||
family_id get_family_id() const { return m_fid; }
|
||||
};
|
||||
|
||||
class basic_factory : public value_factory {
|
||||
public:
|
||||
basic_factory(ast_manager & m);
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2);
|
||||
|
||||
virtual expr * get_fresh_value(sort * s);
|
||||
|
||||
virtual void register_value(expr * n) { }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Template for value factories for numeric (and enumeration-like) sorts
|
||||
*/
|
||||
template<typename Number>
|
||||
class simple_factory : public value_factory {
|
||||
protected:
|
||||
struct value_set {
|
||||
obj_hashtable<expr> m_values;
|
||||
Number m_next;
|
||||
value_set():
|
||||
m_next(0) {
|
||||
}
|
||||
};
|
||||
|
||||
typedef obj_map<sort, value_set *> sort2value_set;
|
||||
|
||||
sort2value_set m_sort2value_set;
|
||||
expr_ref_vector m_values;
|
||||
sort_ref_vector m_sorts;
|
||||
ptr_vector<value_set> m_sets;
|
||||
|
||||
value_set * get_value_set(sort * s) {
|
||||
value_set * set = 0;
|
||||
if (!m_sort2value_set.find(s, set)) {
|
||||
set = alloc(value_set);
|
||||
m_sort2value_set.insert(s, set);
|
||||
m_sorts.push_back(s);
|
||||
m_sets.push_back(set);
|
||||
}
|
||||
SASSERT(set != 0);
|
||||
DEBUG_CODE({
|
||||
value_set * set2 = 0;
|
||||
SASSERT(m_sort2value_set.find(s, set2));
|
||||
SASSERT(set == set2);
|
||||
});
|
||||
return set;
|
||||
}
|
||||
|
||||
virtual app * mk_value_core(Number const & val, sort * s) = 0;
|
||||
|
||||
app * mk_value(Number const & val, sort * s, bool & is_new) {
|
||||
value_set * set = get_value_set(s);
|
||||
app * new_val = mk_value_core(val, s);
|
||||
is_new = false;
|
||||
if (!set->m_values.contains(new_val)) {
|
||||
m_values.push_back(new_val);
|
||||
set->m_values.insert(new_val);
|
||||
is_new = true;
|
||||
}
|
||||
SASSERT(set->m_values.contains(new_val));
|
||||
return new_val;
|
||||
}
|
||||
|
||||
public:
|
||||
simple_factory(ast_manager & m, family_id fid):
|
||||
value_factory(m, fid),
|
||||
m_values(m),
|
||||
m_sorts(m) {
|
||||
}
|
||||
|
||||
virtual ~simple_factory() {
|
||||
std::for_each(m_sets.begin(), m_sets.end(), delete_proc<value_set>());
|
||||
}
|
||||
|
||||
virtual expr * get_some_value(sort * s) {
|
||||
value_set * set = 0;
|
||||
expr * result = 0;
|
||||
if (m_sort2value_set.find(s, set) && !set->m_values.empty())
|
||||
result = *(set->m_values.begin());
|
||||
else
|
||||
result = mk_value(Number(0), s);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||
value_set * set = 0;
|
||||
if (m_sort2value_set.find(s, set)) {
|
||||
switch (set->m_values.size()) {
|
||||
case 0:
|
||||
v1 = mk_value(Number(0), s);
|
||||
v2 = mk_value(Number(1), s);
|
||||
break;
|
||||
case 1:
|
||||
v1 = *(set->m_values.begin());
|
||||
v2 = mk_value(Number(0), s);
|
||||
if (v1 == v2)
|
||||
v2 = mk_value(Number(1), s);
|
||||
break;
|
||||
default:
|
||||
obj_hashtable<expr>::iterator it = set->m_values.begin();
|
||||
v1 = *it;
|
||||
++it;
|
||||
v2 = *it;
|
||||
break;
|
||||
}
|
||||
SASSERT(v1 != v2);
|
||||
return true;
|
||||
}
|
||||
v1 = mk_value(Number(0), s);
|
||||
v2 = mk_value(Number(1), s);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual expr * get_fresh_value(sort * s) {
|
||||
value_set * set = get_value_set(s);
|
||||
bool is_new = false;
|
||||
expr * result = 0;
|
||||
Number & next = set->m_next;
|
||||
while (!is_new) {
|
||||
result = mk_value(next, s, is_new);
|
||||
next++;
|
||||
}
|
||||
SASSERT(result != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void register_value(expr * n) {
|
||||
sort * s = this->m_manager.get_sort(n);
|
||||
value_set * set = get_value_set(s);
|
||||
if (!set->m_values.contains(n)) {
|
||||
m_values.push_back(n);
|
||||
set->m_values.insert(n);
|
||||
}
|
||||
}
|
||||
|
||||
virtual app * mk_value(Number const & val, sort * s) {
|
||||
bool is_new;
|
||||
return mk_value(val, s, is_new);
|
||||
}
|
||||
|
||||
unsigned get_num_sorts() const { return m_sorts.size(); }
|
||||
|
||||
sort * get_sort(unsigned idx) const { return m_sorts.get(idx); }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Factory for creating values for uninterpreted sorts and user
|
||||
declared (uninterpreted) sorts.
|
||||
*/
|
||||
class user_sort_factory : public simple_factory<unsigned> {
|
||||
obj_hashtable<sort> m_finite; //!< set of sorts that are marked as finite.
|
||||
obj_hashtable<expr> m_empty_universe;
|
||||
virtual app * mk_value_core(unsigned const & val, sort * s);
|
||||
public:
|
||||
user_sort_factory(ast_manager & m);
|
||||
virtual ~user_sort_factory() {}
|
||||
|
||||
/**
|
||||
\brief Make the universe of \c s finite, by preventing new
|
||||
elements to be added to its universe.
|
||||
*/
|
||||
void freeze_universe(sort * s);
|
||||
|
||||
/**
|
||||
\brief Return true if the universe of \c s is frozen and finite.
|
||||
*/
|
||||
bool is_finite(sort * s) const {
|
||||
return m_finite.contains(s);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return the "known" universe of \c s. It doesn't matter whether
|
||||
s is finite or not. If \c s is finite, then it is the whole universe.
|
||||
*/
|
||||
obj_hashtable<expr> const & get_known_universe(sort * s) const;
|
||||
|
||||
/**
|
||||
\brief Return sorts with finite interpretations.
|
||||
*/
|
||||
obj_hashtable<sort> const & get_finite_sorts() const { return m_finite; }
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2);
|
||||
|
||||
virtual expr * get_fresh_value(sort * s);
|
||||
|
||||
virtual void register_value(expr * n);
|
||||
};
|
||||
|
||||
#endif /* _VALUE_FACTORY_H_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue