mirror of
https://github.com/Z3Prover/z3
synced 2025-04-26 02:25:32 +00:00
152 lines
4.6 KiB
C++
152 lines
4.6 KiB
C++
/*++
|
|
Copyright (c) 2015 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
symbolic_automata.h
|
|
|
|
Abstract:
|
|
|
|
Symbolic Automata over Boolean Algebras, a la Margus Veanes Automata library.
|
|
|
|
Author:
|
|
|
|
Nikolaj Bjorner (nbjorner) 2016-02-27.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "math/automata/automaton.h"
|
|
#include "math/automata/boolean_algebra.h"
|
|
|
|
|
|
template<class T, class M = default_value_manager<T> >
|
|
class symbolic_automata {
|
|
typedef automaton<T, M> automaton_t;
|
|
typedef boolean_algebra<T*> ba_t;
|
|
typedef typename automaton_t::move move_t;
|
|
typedef vector<move_t> moves_t;
|
|
typedef obj_ref<T, M> ref_t;
|
|
typedef ref_vector<T, M> refs_t;
|
|
typedef std::pair<unsigned, unsigned> unsigned_pair;
|
|
template<class V> class u2_map : public map<unsigned_pair, V, pair_hash<unsigned_hash, unsigned_hash>, default_eq<unsigned_pair> > {};
|
|
|
|
|
|
M& m;
|
|
ba_t& m_ba;
|
|
|
|
|
|
class block {
|
|
uint_set m_set;
|
|
unsigned m_rep;
|
|
bool m_rep_chosen;
|
|
public:
|
|
|
|
block(): m_rep(0), m_rep_chosen(false) {}
|
|
|
|
block(uint_set const& s):
|
|
m_set(s),
|
|
m_rep(0),
|
|
m_rep_chosen(false) {
|
|
}
|
|
|
|
block(unsigned_vector const& vs) {
|
|
for (unsigned i = 0; i < vs.size(); ++i) {
|
|
m_set.insert(vs[i]);
|
|
}
|
|
m_rep_chosen = false;
|
|
m_rep = 0;
|
|
}
|
|
|
|
block& operator=(block const& b) {
|
|
m_set = b.m_set;
|
|
m_rep = 0;
|
|
m_rep_chosen = false;
|
|
return *this;
|
|
}
|
|
|
|
unsigned get_representative() {
|
|
if (!m_rep_chosen) {
|
|
uint_set::iterator it = m_set.begin();
|
|
if (m_set.end() != it) {
|
|
m_rep = *it;
|
|
}
|
|
m_rep_chosen = true;
|
|
}
|
|
return m_rep;
|
|
}
|
|
|
|
void insert(unsigned i) { m_set.insert(i); }
|
|
bool contains(unsigned i) const { return m_set.contains(i); }
|
|
bool is_empty() const { return m_set.empty(); }
|
|
unsigned size() const { return m_set.num_elems(); }
|
|
void remove(unsigned i) { m_set.remove(i); m_rep_chosen = false; }
|
|
void clear() { m_set.reset(); m_rep_chosen = false; }
|
|
uint_set::iterator begin() const { return m_set.begin(); }
|
|
uint_set::iterator end() const { return m_set.end(); }
|
|
};
|
|
|
|
void add_block(block const& p1, unsigned p0_index, unsigned_vector& blocks, vector<block>& pblocks, unsigned_vector& W);
|
|
|
|
public:
|
|
symbolic_automata(M& m, ba_t& ba): m(m), m_ba(ba) {}
|
|
automaton_t* mk_determinstic(automaton_t& a);
|
|
automaton_t* mk_complement(automaton_t& a);
|
|
automaton_t* remove_epsilons(automaton_t& a);
|
|
automaton_t* mk_total(automaton_t& a);
|
|
automaton_t* mk_minimize(automaton_t& a);
|
|
automaton_t* mk_minimize_total(automaton_t& a);
|
|
automaton_t* mk_difference(automaton_t& a, automaton_t& b);
|
|
automaton_t* mk_product(automaton_t& a, automaton_t& b);
|
|
|
|
private:
|
|
automaton_t* mk_determinstic_param(automaton_t& a, bool flip_acceptance);
|
|
|
|
vector<std::pair<vector<bool>, ref_t> > generate_min_terms(vector<ref_t> &constraints) {
|
|
vector<std::pair<vector<bool>, ref_t> > min_terms;
|
|
|
|
ref_t curr_pred(m_ba.mk_true(), m);
|
|
vector<bool> curr_bv;
|
|
|
|
generate_min_terms_rec(constraints, min_terms, 0, curr_bv, curr_pred);
|
|
|
|
return min_terms;
|
|
}
|
|
void generate_min_terms_rec(vector<ref_t> &constraints, vector<std::pair<vector<bool>, ref_t> > &min_terms, unsigned i, vector<bool> &curr_bv, ref_t &curr_pred) {
|
|
lbool is_sat = m_ba.is_sat(curr_pred);
|
|
if (is_sat == l_undef)
|
|
throw default_exception("incomplete theory: unable to generate min-terms");
|
|
|
|
if (is_sat != l_true) {
|
|
return;
|
|
}
|
|
|
|
if (i == constraints.size()) {
|
|
min_terms.push_back(std::pair<vector<bool>, ref_t>(curr_bv, curr_pred));
|
|
}
|
|
else {
|
|
//true case
|
|
curr_bv.push_back(true);
|
|
ref_t new_pred_pos(m_ba.mk_and(curr_pred, constraints[i]), m);
|
|
generate_min_terms_rec(constraints, min_terms, i + 1, curr_bv, new_pred_pos);
|
|
curr_bv.pop_back();
|
|
|
|
//false case
|
|
curr_bv.push_back(false);
|
|
ref_t neg(m_ba.mk_not(constraints[i]), m);
|
|
ref_t new_pred_neg(m_ba.mk_and(curr_pred, neg), m);
|
|
generate_min_terms_rec(constraints, min_terms, i + 1, curr_bv, new_pred_neg);
|
|
curr_bv.pop_back();
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|