3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-28 11:25:51 +00:00

added symbolic automata complement for sequences

This commit is contained in:
Loris D'Antoni 2016-07-28 13:50:05 -07:00
parent 5f449b5c0d
commit 73bd4acfc5
5 changed files with 174 additions and 180 deletions

View file

@ -273,6 +273,95 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_minim
return alloc(automaton_t, m, new_init, new_final, new_moves);
}
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_determinstic(automaton_t& a) {
return mk_determinstic_param(a);
}
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_complement(automaton_t& a) {
return mk_determinstic_param(a, true);
}
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_determinstic_param(automaton_t& a, bool flip_acceptance = false) {
vector<std::pair<vector<bool>, ref_t>> min_terms;
vector<ref_t> predicates;
map<uint_set, unsigned, uint_set::hash, uint_set::eq> s2id; // set of states to unique id
vector<uint_set> id2s; // unique id to set of b-states
uint_set set;
unsigned_vector vector;
moves_t new_mvs; // moves in the resulting automaton
unsigned_vector new_final_states; // new final states
unsigned p_state_id = 0; // next state identifier
// adds non-final states of a to final if flipping and and final otherwise
if (a.is_final_configuration(set) != flip_acceptance) {
new_final_states.push_back(p_state_id);
}
set.insert(a.init()); // initial state as aset
s2id.insert(set, p_state_id++); // the index to the initial state is 0
id2s.push_back(set);
svector<uint_set> todo; //States to visit
todo.push_back(set);
uint_set state;
moves_t mvsA;
new_mvs.reset();
// or just make todo a vector whose indices coincide with state_id.
while (!todo.empty()) {
uint_set state = todo.back();
unsigned state_id = s2id[state];
todo.pop_back();
mvsA.reset();
min_terms.reset();
predicates.reset();
a.get_moves_from_states(state, mvsA);
for (unsigned j = 0; j < mvsA.size(); ++j) {
ref_t mv_guard(mvsA[j].t(),m);
predicates.push_back(mv_guard);
}
min_terms = generate_min_terms(predicates);
for (unsigned j = 0; j < min_terms.size(); ++j) {
set = uint_set();
for (unsigned i = 0; i < mvsA.size(); ++i) {
if (min_terms[j].first[i])
set.insert(mvsA[i].dst());
}
bool is_new = !s2id.contains(set);
if (is_new) {
if (a.is_final_configuration(set) != flip_acceptance) {
new_final_states.push_back(p_state_id);
}
s2id.insert(set, p_state_id++);
id2s.push_back(set);
todo.push_back(set);
}
new_mvs.push_back(move_t(m, state_id, s2id[set], min_terms[j].second));
}
}
if (new_final_states.empty()) {
return alloc(automaton_t, m);
}
return alloc(automaton_t, m, 0, new_final_states, new_mvs);
}
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_product(automaton_t& a, automaton_t& b) {
u2_map<unsigned> pair2id;
@ -362,130 +451,11 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_produ
}
}
#if 0
template<class T, class M>
unsigned symbolic_automata<T, M>::get_product_state_id(u2_map<unsigned>& pair2id, unsigned_pair const& p, unsigned& id) {
unsigned result = 0;
if (!pair2id.find(p, result)) {
result = id++;
pair2id.insert(p, result);
}
return result;
}
#endif
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_difference(automaton_t& a, automaton_t& b) {
#if 0
map<uint_set, unsigned, uint_set_hash, uint_set_eq> bs2id; // set of b-states to unique id
vector<uintset> id2bs; // unique id to set of b-states
u2_map<unsigned> pair2id; // pair of states to new state id
unsigned sink_state = UINT_MAX;
uint_set bset;
moves_t new_moves; // moves in the resulting automaton
unsigned_vector new_final_states; // new final states
unsigned p_state_id = 0; // next state identifier
bs2id.insert(uint_set(), sink_state); // the sink state has no b-states
bset.insert(b.init()); // the initial state has a single initial b state
bs2id.insert(bset, 0); // the index to the initial b state is 0
id2bs.push_back(bset);
if (!b.is_final_state(b.init()) && a.is_final_state(a.init())) {
new_final_states.push_back(p_state_id);
}
svector<unsigned_pair> todo;
unsigned_pair state(a.init(), 0);
todo.push_back(state);
pair2id.insert(state, p_state_id++);
// or just make todo a vector whose indices coincide with state_id.
while (!todo.empty()) {
state = todo.back();
unsigned state_id = pair2id[state];
todo.pop_back();
mvsA.reset();
a.get_moves_from(state.first, mvsA, true);
if (state.second == sink_state) {
for (unsigned i = 0; i < mvsA.size(); ++i) {
unsigned_pair dst(mvsA[i].dst(), sink_state);
bool is_new = !pair2id.contains(dst);
unsigned dst_id = get_product_state_id(pair2id, dst, p_state_id);
new_moves.push_back(move_t(m, state_id, dst_id, mvsA[i].t()));
if (is_new && a.is_final_state(mvsA[i].dst())) {
new_final_states.push_back(dst_id);
todo.push_back(dst);
}
}
}
else {
get_moves_from(b, id2bs[state.second], mvsB);
generate_min_terms(mvsB, min_terms);
for (unsigned j = 0; j < min_terms.size(); ++j) {
for (unsigned i = 0; i < mvsA.size(); ++i) {
ref_t cond(m_ba.mk_and(mvsA[i].t(), min_terms[j].second), m);
switch (m_ba.is_sat(cond)) {
case l_false:
break;
case l_true:
ab_combinations.push_back(ab_comb(i, min_terms[j].first, cond));
break;
case l_undef:
return 0;
}
}
}
for (unsigned i = 0; i < ab_combinations.size(); ++i) {
move_t const& mvA = mvsA[ab_combinations[i].A];
bset.reset();
bool is_final = a.is_final_state(mvA.dst());
for (unsigned j = 0; j < mvsB.size(); ++j) {
if (ab_combinations[i].B[j]) {
bset.insert(mvsB[j].dst());
is_final &= !b.is_final_state(mvsB[j].dst());
}
}
unsigned new_b;
if (bset.empty()) {
new_b = sink_state;
}
else if (!bs2id.find(bset, new_b)) {
new_b = id2bs.size();
id2bs.push_back(bset);
bs2id.insert(bset, new_b);
}
unsigned_pair dst(mvA.dst(), new_b);
bool is_new = !pair2id.contains(dst);
dst_id = get_product_state_id(pair2id, dst, p_state_id);
move_t new_move(m, state_id, dst_id, ab_combinations[i].cond);
new_moves.push_back(new_move);
if (is_new) {
if (is_final) {
new_final_states.push_back(dst_id);
}
todo.push_back(dst);
}
}
}
}
if (new_final_states.empty()) {
return alloc(automaton_t, m);
}
automaton_t* result = alloc(automaton_t, m, 0, new_final_states, new_moves);
#if 0
result->isEpsilonFree = true;
if (A.IsDeterministic)
result->isDeterministic = true;
result->EliminateDeadStates();
#endif
return result;
#endif
return 0;
return mk_product(a,mk_complement(b));
}
#endif