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
464
lib/dl_context.h
Normal file
464
lib/dl_context.h
Normal file
|
@ -0,0 +1,464 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
dl_context.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2010-05-18.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _DL_CONTEXT_H_
|
||||
#define _DL_CONTEXT_H_
|
||||
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"front_end_params.h"
|
||||
#include"map.h"
|
||||
#include"th_rewriter.h"
|
||||
#include"str_hashtable.h"
|
||||
#include"var_subst.h"
|
||||
#include"dl_base.h"
|
||||
#include"dl_costs.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"dl_relation_manager.h"
|
||||
#include"dl_rule_set.h"
|
||||
#include"pdr_dl_interface.h"
|
||||
#include"dl_bmc_engine.h"
|
||||
#include"lbool.h"
|
||||
#include"statistics.h"
|
||||
#include"params.h"
|
||||
#include"trail.h"
|
||||
#include"dl_external_relation.h"
|
||||
#include"model_converter.h"
|
||||
#include"proof_converter.h"
|
||||
#include"model2expr.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
class rule_transformer;
|
||||
|
||||
enum execution_result {
|
||||
OK,
|
||||
TIMEOUT,
|
||||
MEMOUT,
|
||||
INPUT_ERROR
|
||||
};
|
||||
|
||||
class context {
|
||||
public:
|
||||
typedef unsigned finite_element;
|
||||
enum sort_kind {
|
||||
SK_UINT64,
|
||||
SK_SYMBOL
|
||||
};
|
||||
|
||||
private:
|
||||
class sort_domain;
|
||||
class symbol_sort_domain;
|
||||
class uint64_sort_domain;
|
||||
class restore_rules;
|
||||
class contains_pred;
|
||||
|
||||
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
|
||||
typedef map<symbol, func_decl*, symbol_hash_proc, symbol_eq_proc> sym2decl;
|
||||
typedef obj_map<const func_decl, svector<symbol> > pred2syms;
|
||||
typedef obj_map<const sort, sort_domain*> sort_domain_map;
|
||||
typedef vector<std::pair<func_decl*,relation_fact> > fact_vector;
|
||||
|
||||
|
||||
ast_manager & m;
|
||||
front_end_params& m_fparams;
|
||||
params_ref m_params;
|
||||
dl_decl_util m_decl_util;
|
||||
th_rewriter m_rewriter;
|
||||
var_subst m_var_subst;
|
||||
relation_manager m_rmanager;
|
||||
rule_manager m_rule_manager;
|
||||
|
||||
trail_stack<context> m_trail;
|
||||
ast_ref_vector m_pinned;
|
||||
app_ref_vector m_vars;
|
||||
sort_domain_map m_sorts;
|
||||
func_decl_set m_preds;
|
||||
sym2decl m_preds_by_name;
|
||||
pred2syms m_argument_var_names;
|
||||
decl_set m_output_preds;
|
||||
rule_set m_rule_set;
|
||||
expr_ref_vector m_background;
|
||||
|
||||
scoped_ptr<pdr::dl_interface> m_pdr;
|
||||
scoped_ptr<bmc> m_bmc;
|
||||
|
||||
bool m_closed;
|
||||
bool m_saturation_was_run;
|
||||
execution_result m_last_status;
|
||||
relation_base * m_last_result_relation;
|
||||
expr_ref m_last_answer;
|
||||
DL_ENGINE m_engine;
|
||||
volatile bool m_cancel;
|
||||
fact_vector m_table_facts;
|
||||
|
||||
bool is_fact(app * head) const;
|
||||
bool has_sort_domain(relation_sort s) const;
|
||||
sort_domain & get_sort_domain(relation_sort s);
|
||||
const sort_domain & get_sort_domain(relation_sort s) const;
|
||||
|
||||
relation_plugin & get_ordinary_relation_plugin(symbol relation_name);
|
||||
|
||||
class engine_type_proc;
|
||||
|
||||
|
||||
public:
|
||||
context(ast_manager & m, front_end_params& params, params_ref const& p = params_ref());
|
||||
~context();
|
||||
void reset();
|
||||
|
||||
void push();
|
||||
void pop();
|
||||
|
||||
relation_base & get_relation(func_decl * pred) { return get_rmanager().get_relation(pred); }
|
||||
relation_base * try_get_relation(func_decl * pred) const { return get_rmanager().try_get_relation(pred); }
|
||||
|
||||
bool saturation_was_run() const { return m_saturation_was_run; }
|
||||
void notify_saturation_was_run() { m_saturation_was_run = true; }
|
||||
|
||||
/**
|
||||
\brief Store the relation \c rel under the predicate \c pred. The \c context object
|
||||
takes over the ownership of the relation object.
|
||||
*/
|
||||
void store_relation(func_decl * pred, relation_base * rel) {
|
||||
get_rmanager().store_relation(pred, rel);
|
||||
}
|
||||
|
||||
void configure_engine();
|
||||
|
||||
ast_manager & get_manager() const { return m; }
|
||||
relation_manager & get_rmanager() { return m_rmanager; }
|
||||
const relation_manager & get_rmanager() const { return m_rmanager; }
|
||||
rule_manager & get_rule_manager() { return m_rule_manager; }
|
||||
front_end_params & get_fparams() const { return m_fparams; }
|
||||
params_ref const& get_params() const { return m_params; }
|
||||
DL_ENGINE get_engine() { configure_engine(); return m_engine; }
|
||||
th_rewriter& get_rewriter() { return m_rewriter; }
|
||||
var_subst & get_var_subst() { return m_var_subst; }
|
||||
dl_decl_util & get_decl_util() { return m_decl_util; }
|
||||
|
||||
bool output_profile() const { return m_params.get_bool(":output-profile", false); }
|
||||
bool fix_unbound_vars() const { return m_params.get_bool(":fix-unbound-vars", false); }
|
||||
symbol default_table() const { return m_params.get_sym(":default-table", symbol("sparse")); }
|
||||
symbol default_relation() const { return m_params.get_sym(":default-relation", external_relation_plugin::get_name()); }
|
||||
symbol default_table_checker() const { return m_params.get_sym(":default-table-checker", symbol("sparse")); }
|
||||
bool default_table_checked() const { return m_params.get_bool(":default-table-checked", false); }
|
||||
bool dbg_fpr_nonempty_relation_signature() const { return m_params.get_bool(":dbg-fpr-nonempty-relation-signatures", false); }
|
||||
unsigned dl_profile_milliseconds_threshold() const { return m_params.get_uint(":profile-milliseconds-threshold", 0); }
|
||||
bool all_or_nothing_deltas() const { return m_params.get_bool(":all-or-nothing-deltas", false); }
|
||||
bool compile_with_widening() const { return m_params.get_bool(":compile-with-widening", false); }
|
||||
bool unbound_compressor() const { return m_params.get_bool(":unbound-compressor", true); }
|
||||
bool similarity_compressor() const { return m_params.get_bool(":similarity-compressor", true); }
|
||||
unsigned similarity_compressor_threshold() const { return m_params.get_uint(":similarity-compressor-threshold", 11); }
|
||||
unsigned soft_timeout() const { return m_fparams.m_soft_timeout; }
|
||||
unsigned initial_restart_timeout() const { return m_params.get_uint(":initial-restart-timeout", 0); }
|
||||
bool generate_explanations() const { return m_params.get_bool(":generate-explanations", false); }
|
||||
bool explanations_on_relation_level() const { return m_params.get_bool(":explanations-on-relation-level", false); }
|
||||
bool magic_sets_for_queries() const { return m_params.get_bool(":magic-sets-for-queries", false); }
|
||||
bool eager_emptiness_checking() const { return m_params.get_bool(":eager-emptiness-checking", true); }
|
||||
|
||||
void register_finite_sort(sort * s, sort_kind k);
|
||||
|
||||
/**
|
||||
Register uninterpreted constant to be used as an implicitly quantified variable.
|
||||
The variable gets quantified in the formula passed to rule::mk_rule_from_horn.
|
||||
*/
|
||||
|
||||
void register_variable(func_decl* var);
|
||||
|
||||
app_ref_vector const& get_variables() const { return m_vars; }
|
||||
|
||||
/**
|
||||
Register datalog relation.
|
||||
|
||||
If names is true, we associate the predicate with its name, so that it can be
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
\brief Create a fresh head predicate declaration.
|
||||
|
||||
*/
|
||||
func_decl * mk_fresh_head_predicate(symbol const & prefix, symbol const & suffix,
|
||||
unsigned arity, sort * const * domain, func_decl* orig_pred=0);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return number of a symbol in a DK_SYMBOL kind sort (\see register_sort() )
|
||||
*/
|
||||
finite_element get_constant_number(relation_sort sort, symbol s);
|
||||
/**
|
||||
\brief Return number of a symbol in a DK_UINT64 kind sort (\see register_sort() )
|
||||
*/
|
||||
finite_element get_constant_number(relation_sort srt, uint64 el);
|
||||
|
||||
/**
|
||||
\brief Output name of constant with number \c num in sort \c sort.
|
||||
*/
|
||||
void print_constant_name(relation_sort sort, uint64 num, std::ostream & out);
|
||||
|
||||
bool try_get_sort_constant_count(relation_sort srt, uint64 & constant_count);
|
||||
|
||||
uint64 get_sort_size_estimate(relation_sort srt);
|
||||
|
||||
/**
|
||||
\brief Assign names of variables used in the declaration of a predicate.
|
||||
|
||||
These names are used when printing out the relations to make the output conform
|
||||
to the one of bddbddb.
|
||||
*/
|
||||
void set_argument_names(const func_decl * pred, svector<symbol> var_names);
|
||||
symbol get_argument_name(const func_decl * pred, unsigned arg_index);
|
||||
|
||||
void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt,
|
||||
symbol * const relation_names);
|
||||
|
||||
void set_output_predicate(func_decl * pred);
|
||||
bool is_output_predicate(func_decl * pred) { return m_output_preds.contains(pred); }
|
||||
const decl_set & get_output_predicates() const { return m_output_preds; }
|
||||
|
||||
rule_set const & get_rules() { return m_rule_set; }
|
||||
|
||||
void add_fact(app * head);
|
||||
void add_fact(func_decl * pred, const relation_fact & fact);
|
||||
|
||||
|
||||
void add_rule(rule_ref& r);
|
||||
void add_rules(rule_ref_vector& rs);
|
||||
|
||||
void assert_expr(expr* e);
|
||||
expr_ref get_background_assertion();
|
||||
|
||||
/**
|
||||
Method exposed from API for adding rules.
|
||||
*/
|
||||
void add_rule(expr* rl, symbol const& name);
|
||||
|
||||
|
||||
/**
|
||||
Update a named rule.
|
||||
*/
|
||||
void update_rule(expr* rl, symbol const& name);
|
||||
|
||||
/**
|
||||
Retrieve the maximal number of relevant unfoldings of 'pred'
|
||||
with respect to the current state.
|
||||
*/
|
||||
unsigned get_num_levels(func_decl* pred);
|
||||
|
||||
/**
|
||||
Retrieve the current cover of 'pred' up to 'level' unfoldings.
|
||||
Return just the delta that is known at 'level'. To
|
||||
obtain the full set of properties of 'pred' one should query
|
||||
at 'level+1', 'level+2' etc, and include level=-1.
|
||||
*/
|
||||
expr_ref get_cover_delta(int level, func_decl* pred);
|
||||
|
||||
/**
|
||||
Add a property of predicate 'pred' at 'level'.
|
||||
It gets pushed forward when possible.
|
||||
*/
|
||||
void add_cover(int level, func_decl* pred, expr* property);
|
||||
|
||||
/**
|
||||
\brief Check rule subsumption.
|
||||
*/
|
||||
bool check_subsumes(rule const& stronger_rule, rule const& weaker_rule);
|
||||
|
||||
/**
|
||||
\brief Check if rule is well-formed according to engine.
|
||||
*/
|
||||
void check_rule(rule_ref& r);
|
||||
|
||||
/**
|
||||
\brief Return true if facts to \c pred can be added using the \c add_table_fact() function.
|
||||
|
||||
This function should return true if \c pred is represented by a table_relation
|
||||
and there is no transformation of relation values before they are put into the
|
||||
table.
|
||||
*/
|
||||
bool can_add_table_fact(func_decl * pred);
|
||||
void add_table_fact(func_decl * pred, const table_fact & fact);
|
||||
void add_table_fact(func_decl * pred, unsigned num_args, unsigned args[]);
|
||||
|
||||
/**
|
||||
\brief To be called after all rules are added.
|
||||
*/
|
||||
void close();
|
||||
void ensure_closed();
|
||||
|
||||
/**
|
||||
\brief Undo the effect of the \c close operation.
|
||||
*/
|
||||
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);
|
||||
|
||||
void apply_default_transformation(model_converter_ref& mc, proof_converter_ref& pc);
|
||||
|
||||
void collect_params(param_descrs& r);
|
||||
|
||||
void updt_params(params_ref const& p);
|
||||
|
||||
void collect_predicates(decl_set & res);
|
||||
/**
|
||||
\brief Restrict the set of used predicates to \c res.
|
||||
|
||||
The function deallocates unsused relations, it does not deal with rules.
|
||||
*/
|
||||
void restrict_predicates(const decl_set & res);
|
||||
|
||||
void display_rules(std::ostream & out) const {
|
||||
m_rule_set.display(out);
|
||||
}
|
||||
void display_facts(std::ostream & out) const {
|
||||
m_rmanager.display(out);
|
||||
}
|
||||
|
||||
void display(std::ostream & out) const {
|
||||
display_rules(out);
|
||||
display_facts(out);
|
||||
}
|
||||
|
||||
void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// basic usage methods
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
void cancel();
|
||||
|
||||
void cleanup();
|
||||
|
||||
/**
|
||||
\brief check if query 'q' is satisfied under asserted rules and background.
|
||||
|
||||
If successful, return OK and into \c result assign a relation with all
|
||||
tuples matching the query. Otherwise return reason for failure and do not modify
|
||||
\c result.
|
||||
|
||||
The numbers of variables in the query body must form a contiguous sequence
|
||||
starting from zero.
|
||||
|
||||
The caller becomes an owner of the relation object returned in \c result. The
|
||||
relation object, however, should not outlive the datalog context since it is
|
||||
linked to a relation plugin in the context.
|
||||
*/
|
||||
|
||||
lbool query(expr* q);
|
||||
|
||||
/**
|
||||
Query multiple output relations.
|
||||
*/
|
||||
lbool dl_query(unsigned num_rels, func_decl * const* rels);
|
||||
|
||||
/**
|
||||
Reset tables that are under negation.
|
||||
*/
|
||||
void reset_negated_tables();
|
||||
|
||||
/**
|
||||
Just reset all tables.
|
||||
*/
|
||||
void reset_tables();
|
||||
|
||||
/**
|
||||
\brief retrieve last proof status.
|
||||
*/
|
||||
execution_result get_status();
|
||||
|
||||
/**
|
||||
\brief retrieve formula corresponding to query that returns l_true.
|
||||
The formula describes one or more instances of the existential variables
|
||||
in the query that are derivable.
|
||||
*/
|
||||
expr* get_answer_as_formula();
|
||||
|
||||
|
||||
void collect_statistics(statistics& st);
|
||||
|
||||
/**
|
||||
\brief Display a certificate for reachability and/or unreachability.
|
||||
*/
|
||||
bool display_certificate(std::ostream& out);
|
||||
|
||||
/**
|
||||
\brief query result if it contains fact.
|
||||
*/
|
||||
bool result_contains_fact(relation_fact const& f);
|
||||
|
||||
/**
|
||||
\brief display facts generated for query.
|
||||
*/
|
||||
void display_output_facts(std::ostream & out) const {
|
||||
m_rmanager.display_output_tables(out);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief expose datalog saturation for test.
|
||||
*/
|
||||
lbool dl_saturate();
|
||||
|
||||
private:
|
||||
|
||||
void ensure_pdr();
|
||||
|
||||
void ensure_bmc();
|
||||
|
||||
void new_query();
|
||||
|
||||
lbool dl_query(expr* query);
|
||||
|
||||
lbool pdr_query(expr* query);
|
||||
|
||||
lbool bmc_query(expr* query);
|
||||
|
||||
void check_quantifier_free(rule_ref& r);
|
||||
void check_uninterpreted_free(rule_ref& r);
|
||||
void check_existential_tail(rule_ref& r);
|
||||
void check_positive_predicates(rule_ref& r);
|
||||
|
||||
// auxilary functions for SMT2 pretty-printer.
|
||||
void declare_vars(expr_ref_vector& rules, mk_fresh_name& mk_fresh, std::ostream& out);
|
||||
|
||||
//undefined and private copy constructor and operator=
|
||||
context(const context&);
|
||||
context& operator=(const context&);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* _DL_CONTEXT_H_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue