3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-28 11:25:51 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2015-12-25 15:22:26 -08:00
parent 4a5b645d88
commit 31302ec851
7 changed files with 386 additions and 134 deletions

View file

@ -100,8 +100,7 @@ public:
automaton(M& m, unsigned init, unsigned_vector const& final, moves const& mvs): m(m) {
m_init = init;
for (unsigned i = 0; i < final.size(); ++i) {
m_final_states.push_back(final[i]);
m_final_set.insert(final[i]);
add_to_final_states(final[i]);
}
for (unsigned i = 0; i < mvs.size(); ++i) {
move const& mv = mvs[i];
@ -110,8 +109,7 @@ public:
m_delta.resize(n+1, moves());
m_delta_inv.resize(n+1, moves());
}
m_delta[mv.src()].push_back(mv);
m_delta_inv[mv.dst()].push_back(mv);
add(mv);
}
}
@ -125,8 +123,7 @@ public:
m_delta[i].push_back(move(m, i, i + 1, seq[i]));
m_delta[i + 1].push_back(move(m, i, i + 1, seq[i]));
}
m_final_states.push_back(seq.size());
m_final_set.insert(seq.size());
add_to_final_states(seq.size());
}
// The automaton that accepts t
@ -135,10 +132,8 @@ public:
m_init(0) {
m_delta.resize(2, moves());
m_delta_inv.resize(2, moves());
m_final_set.insert(1);
m_final_states.push_back(1);
m_delta[0].push_back(move(m, 0, 1, t));
m_delta_inv[1].push_back(move(m, 0, 1, t));
add_to_final_states(1);
add(move(m, 0, 1, t));
}
automaton(automaton const& other):
@ -257,13 +252,24 @@ public:
return alloc(automaton, m, init, final, mvs);
}
void add_init_to_final() {
if (!m_final_set.contains(m_init)) {
m_final_set.insert(m_init);
m_final_states.push_back(m_init);
void add_to_final_states(unsigned s) {
if (!is_final_state(s)) {
m_final_set.insert(s);
m_final_states.push_back(s);
}
}
void remove_from_final_states(unsigned s) {
if (is_final_state(s)) {
m_final_set.remove(s);
m_final_states.erase(s);
}
}
void add_init_to_final_states() {
add_to_final_states(init());
}
void add_final_to_init_moves() {
for (unsigned i = 0; i < m_final_states.size(); ++i) {
unsigned state = m_final_states[i];
@ -273,16 +279,69 @@ public:
found = (mvs[j].dst() == m_init) && mvs[j].is_epsilon();
}
if (!found) {
m_delta[state].push_back(move(m, state, m_init));
m_delta_inv[m_init].push_back(move(m, state, m_init));
add(move(m, state, m_init));
}
}
}
// remove states that only have epsilon transitions.
// remove epsilon transitions
// src - e -> dst
// in_degree(src) = 1, final(src) => final(dst), src0 != src
// src0 - t -> src - e -> dst => src0 - t -> dst
// out_degree(dst) = 1, final(dst) => final(src), dst != dst1
// src - e -> dst - t -> dst1 => src - t -> dst1
void compress() {
// TBD
for (unsigned i = 0; i < m_delta.size(); ++i) {
for (unsigned j = 0; j < m_delta[i].size(); ++j) {
move const& mv = m_delta[i][j];
unsigned src = mv.src();
unsigned dst = mv.dst();
SASSERT(src == i);
if (mv.is_epsilon()) {
if (src == dst) {
// just remove this edge.
}
else if (1 == in_degree(src) && init() != src && (!is_final_state(src) || is_final_state(dst))) {
move const& mv0 = m_delta_inv[src][0];
unsigned src0 = mv0.src();
T* t = mv0.t();
SASSERT(mv0.dst() == src);
if (src0 == src) {
continue;
}
add(move(m, src0, dst, t));
remove(src0, src, t);
}
else if (1 == out_degree(dst) && init() != dst && (!is_final_state(dst) || is_final_state(src))) {
move const& mv1 = m_delta[dst][0];
unsigned dst1 = mv1.dst();
T* t = mv1.t();
SASSERT(mv1.src() == dst);
if (dst1 == dst) {
continue;
}
add(move(m, src, dst1, t));
remove(dst, dst1, t);
}
else {
continue;
}
remove(src, dst, 0);
--j;
}
}
}
while (true) {
SASSERT(!m_delta.empty());
unsigned src = m_delta.size() - 1;
if (in_degree(src) == 0 && init() != src) {
remove_from_final_states(src);
m_delta.pop_back();
}
else {
break;
}
}
}
bool is_sequence(unsigned& length) const {
@ -356,11 +415,11 @@ public:
void get_inv_epsilon_closure(unsigned state, unsigned_vector& states) {
get_epsilon_closure(state, m_delta_inv, states);
}
void get_moves_from(unsigned state, moves& mvs) const {
get_moves(state, m_delta, mvs);
void get_moves_from(unsigned state, moves& mvs, bool epsilon_closure = true) const {
get_moves(state, m_delta, mvs, epsilon_closure);
}
void get_moves_to(unsigned state, moves& mvs) {
get_moves(state, m_delta_inv, mvs);
void get_moves_to(unsigned state, moves& mvs, bool epsilon_closure = true) {
get_moves(state, m_delta_inv, mvs, epsilon_closure);
}
template<class D>
@ -384,9 +443,41 @@ public:
return out;
}
private:
void add(move const& mv) {
m_delta[mv.src()].push_back(mv);
m_delta_inv[mv.dst()].push_back(mv);
}
unsigned find_move(unsigned src, unsigned dst, T* t, moves const& mvs) {
for (unsigned i = 0; i < mvs.size(); ++i) {
move const& mv = mvs[i];
if (mv.src() == src && mv.dst() == dst && t == mv.t()) {
return i;
}
}
UNREACHABLE();
return UINT_MAX;
}
void remove(unsigned src, unsigned dst, T* t, moves& mvs) {
remove(find_move(src, dst, t, mvs), mvs);
}
void remove(unsigned src, unsigned dst, T* t) {
remove(src, dst, t, m_delta[src]);
remove(src, dst, t, m_delta_inv[dst]);
}
void remove(unsigned index, moves& mvs) {
mvs[index] = mvs.back();
mvs.pop_back();
}
mutable unsigned_vector m_states1, m_states2;
void get_moves(unsigned state, vector<moves> const& delta, moves& mvs) const {
void get_moves(unsigned state, vector<moves> const& delta, moves& mvs, bool epsilon_closure) const {
m_states1.reset();
m_states2.reset();
get_epsilon_closure(state, delta, m_states1);
@ -396,10 +487,15 @@ private:
for (unsigned j = 0; j < mv1.size(); ++j) {
move const& mv = mv1[j];
if (!mv.is_epsilon()) {
m_states2.reset();
get_epsilon_closure(mv.dst(), delta, m_states2);
for (unsigned k = 0; k < m_states2.size(); ++k) {
mvs.push_back(move(m, mv.src(), m_states2[k], mv.t()));
if (epsilon_closure) {
m_states2.reset();
get_epsilon_closure(mv.dst(), delta, m_states2);
for (unsigned k = 0; k < m_states2.size(); ++k) {
mvs.push_back(move(m, state, m_states2[k], mv.t()));
}
}
else {
mvs.push_back(move(m, state, mv.dst(), mv.t()));
}
}
}