IAR: Add pretty print option and better lookup of existing states

* spot/twaalgos/rabin2parity.cc, spot/twaalgos/rabin2parity.hh: here.
This commit is contained in:
Florian Renkin 2020-02-21 10:54:28 +01:00
parent 8a4a4b9fff
commit 5d021a18d6
2 changed files with 64 additions and 22 deletions

View file

@ -63,10 +63,13 @@ namespace spot
} }
public: public:
explicit iar_generator(const const_twa_graph_ptr& a, explicit iar_generator(const const_twa_graph_ptr& a,
const std::vector<acc_cond::rs_pair>& p) const std::vector<acc_cond::rs_pair>& p,
const bool pretty_print)
: aut_(a) : aut_(a)
, pairs_(p) , pairs_(p)
, scc_(scc_info(a)) , scc_(scc_info(a))
, pretty_print_(pretty_print)
, state2pos_iar_states(aut_->num_states(), -1U)
{} {}
twa_graph_ptr twa_graph_ptr
@ -94,6 +97,30 @@ namespace spot
// there could be quite a number of unreachable states, prune them // there could be quite a number of unreachable states, prune them
res_->purge_unreachable_states(); res_->purge_unreachable_states();
if (pretty_print_)
{
unsigned nstates = res_->num_states();
auto names = new std::vector<std::string>(nstates);
for (auto e : res_->edges())
{
unsigned s = e.src;
iar_state iar = num2iar.at(s);
std::ostringstream st;
st << iar.state << ' ';
if (iar.perm.empty())
st << '[';
char sep = '[';
for (unsigned h: iar.perm)
{
st << sep << h;
sep = ',';
}
st << ']';
(*names)[s] = st.str();
}
res_->set_named_prop("state-names", names);
}
return res_; return res_;
} }
@ -112,6 +139,11 @@ namespace spot
unsigned nb = res_->new_state(); unsigned nb = res_->new_state();
iar2num[s] = nb; iar2num[s] = nb;
num2iar[nb] = s; num2iar[nb] = s;
unsigned iar_pos = iar_states.size();
unsigned old_newest_pos = state2pos_iar_states[s.state];
state2pos_iar_states[s.state] = iar_pos;
iar_states.push_back(
std::pair<iar_state, unsigned>(s, old_newest_pos));
todo.push_back(s); todo.push_back(s);
return nb; return nb;
} }
@ -191,16 +223,21 @@ namespace spot
// transition, they move at the front of new_perm in any // transition, they move at the front of new_perm in any
// order. Check whether there already exists an iar_state // order. Check whether there already exists an iar_state
// that matches this condition. // that matches this condition.
for (unsigned i = 0; i != num2iar.size(); ++i)
if (num2iar[i].state == e.dst) auto iar_pos = state2pos_iar_states[e.dst];
if (std::equal(new_perm.begin() + seen_nb, while (iar_pos != -1U)
new_perm.end(), {
num2iar[i].perm.begin() + seen_nb)) iar_state& tmp = iar_states[iar_pos].first;
{ iar_pos = iar_states[iar_pos].second;
dst = num2iar[i]; if (std::equal(new_perm.begin() + seen_nb,
dst_num = i; new_perm.end(),
break; tmp.perm.begin() + seen_nb))
} {
dst = tmp;
dst_num = iar2num[dst];
break;
}
}
// if such a state was not found, build it // if such a state was not found, build it
if (dst_num == -1U) if (dst_num == -1U)
{ {
@ -210,13 +247,14 @@ namespace spot
// find the maximal index encountered by this transition // find the maximal index encountered by this transition
unsigned maxint = -1U; unsigned maxint = -1U;
for (unsigned k = 0; k != current.perm.size(); ++k) for (int k = current.perm.size() - 1; k >= 0; --k)
{ {
unsigned pk = current.perm[k]; unsigned pk = current.perm[k];
if (!inf(pk) || if (!inf(pk) ||
(e.acc & (pairs_[pk].fin | pairs_[pk].inf))) (e.acc & (pairs_[pk].fin | pairs_[pk].inf))) {
// k increases in the loop, so k > maxint necessarily maxint = k;
maxint = k; break;
}
} }
acc_cond::mark_t acc = {}; acc_cond::mark_t acc = {};
@ -280,6 +318,7 @@ namespace spot
const std::vector<acc_cond::rs_pair>& pairs_; const std::vector<acc_cond::rs_pair>& pairs_;
const scc_info scc_; const scc_info scc_;
twa_graph_ptr res_; twa_graph_ptr res_;
bool pretty_print_;
// to be used when entering a new SCC // to be used when entering a new SCC
// maps a state of aut_ onto an iar_state with the appropriate perm // maps a state of aut_ onto an iar_state with the appropriate perm
@ -287,11 +326,14 @@ namespace spot
std::map<iar_state, unsigned> iar2num; std::map<iar_state, unsigned> iar2num;
std::map<unsigned, iar_state> num2iar; std::map<unsigned, iar_state> num2iar;
std::vector<unsigned> state2pos_iar_states;
std::vector<std::pair<iar_state, unsigned>> iar_states;
}; };
} }
twa_graph_ptr twa_graph_ptr
iar_maybe(const const_twa_graph_ptr& aut) iar_maybe(const const_twa_graph_ptr& aut, bool pretty_print)
{ {
std::vector<acc_cond::rs_pair> pairs; std::vector<acc_cond::rs_pair> pairs;
if (!aut->acc().is_rabin_like(pairs)) if (!aut->acc().is_rabin_like(pairs))
@ -299,20 +341,20 @@ namespace spot
return nullptr; return nullptr;
else else
{ {
iar_generator<false> gen(aut, pairs); iar_generator<false> gen(aut, pairs, pretty_print);
return gen.run(); return gen.run();
} }
else else
{ {
iar_generator<true> gen(aut, pairs); iar_generator<true> gen(aut, pairs, pretty_print);
return gen.run(); return gen.run();
} }
} }
twa_graph_ptr twa_graph_ptr
iar(const const_twa_graph_ptr& aut) iar(const const_twa_graph_ptr& aut, bool pretty_print)
{ {
if (auto res = iar_maybe(aut)) if (auto res = iar_maybe(aut, pretty_print))
return res; return res;
throw std::runtime_error("iar() expects Rabin-like or Streett-like input"); throw std::runtime_error("iar() expects Rabin-like or Streett-like input");
} }

View file

@ -41,7 +41,7 @@ namespace spot
/// Street-like. /// Street-like.
SPOT_API SPOT_API
twa_graph_ptr twa_graph_ptr
iar(const const_twa_graph_ptr& aut); iar(const const_twa_graph_ptr& aut, bool pretty_print = false);
/// \ingroup twa_acc_transform /// \ingroup twa_acc_transform
/// \brief Turn a Rabin-like or Streett-like automaton into a parity automaton /// \brief Turn a Rabin-like or Streett-like automaton into a parity automaton
@ -51,5 +51,5 @@ namespace spot
/// Streett-like, and calls spot::iar() otherwise. /// Streett-like, and calls spot::iar() otherwise.
SPOT_API SPOT_API
twa_graph_ptr twa_graph_ptr
iar_maybe(const const_twa_graph_ptr& aut); iar_maybe(const const_twa_graph_ptr& aut, bool pretty_print = false);
} }