z3-z3-4.13.0.src.smt.smt_model_generator.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smt_model_generator.h
Abstract:
The model generator builds a (partial) model for the ground
formulas in the logical context.
The model finder (smt_model_finder.h) tries to extend the
partial model to satisfy the quantifiers. Main invariant:
the new model still satisfies the ground formulas.
The model checker (smt_model_checker.h) checks whether the (new)
model satisfies the quantifiers. If it doesn't, new instances are
added.
Author:
Leonardo de Moura (leonardo) 2008-10-29.
Revision History:
--*/
#pragma once
#include "ast/ast.h"
#include "smt/smt_types.h"
#include "util/obj_hashtable.h"
#include "util/map.h"
#include "util/ref.h"
class value_factory;
class proto_model;
namespace smt {
// -----------------------------
//
// This module builds an interpretation for each relevant expression in the logical context.
//
// 1) The interpretation of boolean constants is their truth value in the logical context.
//
// 2) The interpretation of expressions associated with enodes is built using functors (model_value_proc).
// Theories as arrays and datatypes many need the interpretation of some expressions to be built before the interpretation of others.
// We say this is a dependency. Moreover, some values must be fresh. That is, they should be different
// from all other values associated with enodes of a given sort. For example, the array theory
// uses fresh values to make sure that some array constants are different from each other.
//
// So a dependency for building the interpretation of an enode N can be:
// a) a fresh value (stub) of sort S: it must be built after the interpretation of all enodes of sort S were assigned.
//
// b) an enode N': the interpretation of N' must be built before the interpretation of N.
//
// We say a 'source' is an fresh value or an enode. Note that every dependency is a source,
// but not every source is a dependency.
//
// We use these dependencies to sort (using a topological sort) the sources. The sorted 'sources' specify the
// order the interpretations will be built.
//
// Assumptions regarding dependencies:
//
// - They are acyclic.
//
// - All dependencies are marked as relevant.
//
// - A fresh value stub of sort S depends (implicitly) on all enodes of sort S (that are not associated with fresh values).
// So an enode of sort S may not have a dependency of sort S.
//
// ------------------------------
/**
\brief Stub for extra fresh value.
*/
struct extra_fresh_value {
sort * m_sort;
unsigned m_idx;
expr * m_value;
public:
extra_fresh_value(sort * s, unsigned idx):m_sort(s), m_idx(idx), m_value(nullptr) {}
sort * get_sort() const { return m_sort; }
unsigned get_idx() const { return m_idx; }
void set_value(expr * n) { SASSERT(!m_value); m_value = n; }
expr * get_value() const { return m_value; }
};
/**
\brief Theories such as arrays and datatypes may need some values to be already available when
building a value. We say this a dependency. Object of this class are used to track such dependencies.
Example: to build the value (cons 10 nil), the values 10 and nil should be already available.
*/
class model_value_dependency {
bool m_fresh; //!< True if the dependency is a new fresh value;
union {
enode * m_enode; //!< When m_fresh == false, contains an enode dependency.
extra_fresh_value * m_value; //!< When m_fresh == true, contains the sort of the fresh value
};
public:
model_value_dependency():m_fresh(true), m_value(nullptr) { }
explicit model_value_dependency(enode * n):m_fresh(false), m_enode(n->get_root()) {}
explicit model_value_dependency(extra_fresh_value * v) :m_fresh(true), m_value(v) { SASSERT(v); }
bool is_fresh_value() const { return m_fresh; }
enode * get_enode() const { SASSERT(!is_fresh_value()); return m_enode; }
extra_fresh_value * get_value() const { SASSERT(is_fresh_value()); return m_value; }
};
std::ostream& operator<<(std::ostream& out, model_value_dependency const& d);
typedef model_value_dependency source;
struct source_hash_proc {
unsigned operator()(source const & s) const { return s.is_fresh_value() ? hash_u_u(17, s.get_value()->get_idx()) : hash_u_u(13, s.get_enode()->get_owner_id()); }
};
struct source_eq_proc {
bool operator()(source const & s1, source const & s2) const {
if (s1.is_fresh_value() != s2.is_fresh_value())
return false;
if (s1.is_fresh_value())
return s1.get_value()->get_idx() == s2.get_value()->get_idx();
else
return s1.get_enode() == s2.get_enode();
}
};
typedef map