ltl2aa: implement EConcat
This commit is contained in:
parent
af91b0f376
commit
3e451c408b
1 changed files with 61 additions and 8 deletions
|
|
@ -71,34 +71,43 @@ namespace spot
|
||||||
aut_->new_edge(init_state, dst, e.cond, acc);
|
aut_->new_edge(init_state, dst, e.cond, acc);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned copy_sere_aut_to_res(twa_graph_ptr sere_aut)
|
unsigned copy_sere_aut_to_res(twa_graph_ptr sere_aut,
|
||||||
|
std::map<unsigned, unsigned>& old_to_new,
|
||||||
|
std::vector<unsigned>* acc_states = nullptr,
|
||||||
|
bool use_accepting_sink = true)
|
||||||
{
|
{
|
||||||
|
unsigned ns = sere_aut->num_states();
|
||||||
|
|
||||||
|
// TODO: create all new states at once, keeping an initial offset (the
|
||||||
|
// number of states already present in aut_)
|
||||||
aut_->copy_ap_of(sere_aut);
|
aut_->copy_ap_of(sere_aut);
|
||||||
std::map<unsigned, unsigned> old_to_new;
|
|
||||||
auto register_state = [&](unsigned st) -> unsigned {
|
auto register_state = [&](unsigned st) -> unsigned {
|
||||||
auto p = old_to_new.emplace(st, 0);
|
auto p = old_to_new.emplace(st, 0);
|
||||||
if (p.second)
|
if (p.second)
|
||||||
{
|
{
|
||||||
unsigned new_st = aut_->new_state();
|
unsigned new_st = aut_->new_state();
|
||||||
p.first->second = new_st;
|
p.first->second = new_st;
|
||||||
|
if (acc_states != nullptr && sere_aut->state_is_accepting(st))
|
||||||
|
acc_states->push_back(new_st);
|
||||||
}
|
}
|
||||||
return p.first->second;
|
return p.first->second;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned ns = sere_aut->num_states();
|
|
||||||
for (unsigned st = 0; st < ns; ++st)
|
for (unsigned st = 0; st < ns; ++st)
|
||||||
{
|
{
|
||||||
unsigned new_st = register_state(st);
|
unsigned new_st = register_state(st);
|
||||||
for (const auto& e : sere_aut->out(st))
|
for (const auto& e : sere_aut->out(st))
|
||||||
{
|
{
|
||||||
if (sere_aut->state_is_accepting(e.dst))
|
if (use_accepting_sink && sere_aut->state_is_accepting(e.dst))
|
||||||
aut_->new_edge(new_st, accepting_sink_, e.cond);
|
aut_->new_edge(new_st, accepting_sink_, e.cond);
|
||||||
else
|
else
|
||||||
aut_->new_edge(new_st, register_state(e.dst), e.cond);
|
aut_->new_edge(new_st, register_state(e.dst), e.cond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return register_state(sere_aut->get_init_state_number());
|
auto it = old_to_new.find(sere_aut->get_init_state_number());
|
||||||
|
assert(it != old_to_new.end());
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -272,6 +281,47 @@ namespace spot
|
||||||
return init_state;
|
return init_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case op::EConcat:
|
||||||
|
{
|
||||||
|
unsigned rhs_init = recurse(f[1]);
|
||||||
|
const auto& dict = aut_->get_dict();
|
||||||
|
twa_graph_ptr sere_aut = derive_finite_automaton_with_first(f[0], dict);
|
||||||
|
|
||||||
|
// TODO: this should be a std::vector<bool> !
|
||||||
|
std::vector<unsigned> acc_states;
|
||||||
|
std::map<unsigned, unsigned> old_to_new;
|
||||||
|
copy_sere_aut_to_res(sere_aut, old_to_new, &acc_states, false);
|
||||||
|
|
||||||
|
std::vector<unsigned> acc_edges;
|
||||||
|
unsigned ns = sere_aut->num_states();
|
||||||
|
for (unsigned st = 0; st < ns; ++st)
|
||||||
|
{
|
||||||
|
auto it = old_to_new.find(st);
|
||||||
|
assert(it != old_to_new.end());
|
||||||
|
unsigned new_st = it->second;
|
||||||
|
|
||||||
|
for (auto& e : aut_->out(new_st))
|
||||||
|
{
|
||||||
|
e.acc = acc_cond::mark_t{0};
|
||||||
|
if (std::find(acc_states.begin(), acc_states.end(), e.dst)
|
||||||
|
!= acc_states.end())
|
||||||
|
acc_edges.push_back(aut_->edge_number(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i : acc_edges)
|
||||||
|
{
|
||||||
|
auto& e1 = aut_->edge_storage(i);
|
||||||
|
for (const auto& e2 : aut_->out(rhs_init))
|
||||||
|
aut_->new_edge(e1.src, e2.dst, e1.cond & e2.cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = old_to_new.find(sere_aut->get_init_state_number());
|
||||||
|
assert(it != old_to_new.end());
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
case op::UConcat:
|
case op::UConcat:
|
||||||
{
|
{
|
||||||
unsigned rhs_init = recurse(f[1]);
|
unsigned rhs_init = recurse(f[1]);
|
||||||
|
|
@ -375,7 +425,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
twa_graph_ptr sere_aut =
|
twa_graph_ptr sere_aut =
|
||||||
derive_finite_automaton_with_first(f[0], aut_->get_dict());
|
derive_finite_automaton_with_first(f[0], aut_->get_dict());
|
||||||
return copy_sere_aut_to_res(sere_aut);
|
std::map<unsigned, unsigned> old_to_new;
|
||||||
|
return copy_sere_aut_to_res(sere_aut, old_to_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
case op::NegClosure:
|
case op::NegClosure:
|
||||||
|
|
@ -384,7 +435,6 @@ namespace spot
|
||||||
case op::Xor:
|
case op::Xor:
|
||||||
case op::Implies:
|
case op::Implies:
|
||||||
case op::Equiv:
|
case op::Equiv:
|
||||||
case op::EConcat:
|
|
||||||
case op::EConcatMarked:
|
case op::EConcatMarked:
|
||||||
case op::OrRat:
|
case op::OrRat:
|
||||||
case op::AndRat:
|
case op::AndRat:
|
||||||
|
|
@ -419,7 +469,10 @@ namespace spot
|
||||||
aut->set_init_state(init_state);
|
aut->set_init_state(init_state);
|
||||||
|
|
||||||
if (purge_dead_states)
|
if (purge_dead_states)
|
||||||
|
{
|
||||||
aut->purge_dead_states();
|
aut->purge_dead_states();
|
||||||
|
aut->merge_edges();
|
||||||
|
}
|
||||||
|
|
||||||
return aut;
|
return aut;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue