Monitors can now be split AND completed at the same time.
Split can be called on games without providing
"synthesis-outputs" - relying on named prop.

* spot/twaalgos/synthesis.cc,
spot/twaalgos/synthesis.hh: Here
This commit is contained in:
philipp 2022-01-07 09:28:11 +01:00 committed by Alexandre Duret-Lutz
parent 852abc770f
commit 2298743479
2 changed files with 61 additions and 21 deletions

View file

@ -447,16 +447,28 @@ namespace spot
const bdd& output_bdd, bool complete_env) const bdd& output_bdd, bool complete_env)
{ {
auto split = make_twa_graph(aut->get_dict()); auto split = make_twa_graph(aut->get_dict());
auto [has_unsat, unsat_mark] = aut->acc().unsat_mark();
split->copy_ap_of(aut); split->copy_ap_of(aut);
split->copy_acceptance_of(aut);
split->new_states(aut->num_states()); split->new_states(aut->num_states());
split->set_init_state(aut->get_init_state_number()); split->set_init_state(aut->get_init_state_number());
split->set_named_prop<bdd>("synthesis-outputs", new bdd(output_bdd)); set_synthesis_outputs(split, output_bdd);
auto [is_unsat, unsat_mark] = aut->acc().unsat_mark(); const auto use_color = has_unsat;
if (!is_unsat && complete_env) if (has_unsat)
throw std::runtime_error("split_2step(): Cannot complete arena for " split->copy_acceptance_of(aut);
"env as there is no unsat mark."); else
{
if (complete_env)
{
split->set_co_buchi(); // Fin(0)
unsat_mark = acc_cond::mark_t({0});
has_unsat = true;
}
else
split->acc().set_acceptance(acc_cond::acc_code::t());
}
bdd input_bdd = bddtrue; bdd input_bdd = bddtrue;
{ {
@ -504,9 +516,10 @@ namespace spot
unsigned sink_con = -1u; unsigned sink_con = -1u;
unsigned sink_env = -1u; unsigned sink_env = -1u;
auto get_sink_con_state = [&split, &sink_con, &sink_env, auto get_sink_con_state = [&split, &sink_con, &sink_env,
um = unsat_mark] um = unsat_mark, hu = has_unsat]
(bool create = true) (bool create = true)
{ {
assert(hu);
if (SPOT_UNLIKELY((sink_con == -1u) && create)) if (SPOT_UNLIKELY((sink_con == -1u) && create))
{ {
sink_con = split->new_state(); sink_con = split->new_state();
@ -518,7 +531,8 @@ namespace spot
}; };
// Loop over all states // Loop over all states
for (unsigned src = 0; src < aut->num_states(); ++src) const auto n_states = aut->num_states();
for (unsigned src = 0; src < n_states; ++src)
{ {
env_edge_hash.clear(); env_edge_hash.clear();
e_cache.clear(); e_cache.clear();
@ -579,11 +593,16 @@ namespace spot
auto out = split->out(i); auto out = split->out(i);
if (std::equal(out.begin(), out.end(), if (std::equal(out.begin(), out.end(),
dests.begin(), dests.end(), dests.begin(), dests.end(),
[](const twa_graph::edge_storage_t& x, [uc = use_color]
(const twa_graph::edge_storage_t& x,
const e_info_t* y) const e_info_t* y)
{ {
// If there is no unsat -> we do not care
// about color
// todo further optim?
return x.dst == y->dst return x.dst == y->dst
&& x.acc == y->acc && (!uc
|| x.acc == y->acc)
&& x.cond.id() == y->econdout.id(); && x.cond.id() == y->econdout.id();
})) }))
{ {
@ -592,6 +611,7 @@ namespace spot
if (it != env_edge_hash.end()) if (it != env_edge_hash.end())
it->second.second |= one_letter; it->second.second |= one_letter;
else else
// Uncolored
env_edge_hash.emplace(i, env_edge_hash.emplace(i,
eeh_t(split->new_edge(src, i, bddtrue), one_letter)); eeh_t(split->new_edge(src, i, bddtrue), one_letter));
break; break;
@ -605,7 +625,8 @@ namespace spot
env_hash.emplace(h, d); env_hash.emplace(h, d);
env_edge_hash.emplace(d, eeh_t(n_e, one_letter)); env_edge_hash.emplace(d, eeh_t(n_e, one_letter));
for (const auto &t: dests) for (const auto &t: dests)
split->new_edge(d, t->dst, t->econdout, t->acc); split->new_edge(d, t->dst, t->econdout,
use_color ? t->acc : acc_cond::mark_t({}));
} }
} // letters } // letters
// save locally stored condition // save locally stored condition
@ -619,21 +640,34 @@ namespace spot
// The named property // The named property
// compute the owners // compute the owners
// env is equal to false // env is equal to false
std::vector<bool>* owner = auto owner = std::vector<bool>(split->num_states(), false);
new std::vector<bool>(split->num_states(), false);
// All "new" states belong to the player // All "new" states belong to the player
std::fill(owner->begin()+aut->num_states(), owner->end(), true); std::fill(owner.begin()+aut->num_states(), owner.end(), true);
// Check if sinks have been created // Check if sinks have been created
if (sink_env != -1u) if (sink_env != -1u)
owner->at(sink_env) = false; owner.at(sink_env) = false;
split->set_named_prop("state-player", owner);
split->set_named_prop("synthesis-outputs", // !use_color -> all words accepted
new bdd(output_bdd)); // complete_env && sink_env == -1u
// complet. for env demanded but already
// satisfied -> split is also all true
if (complete_env && sink_env == -1u && !use_color)
split->acc() = acc_cond::acc_code::t();
set_state_players(split, std::move(owner));
// Done // Done
return split; return split;
} }
twa_graph_ptr
split_2step(const const_twa_graph_ptr& aut, bool complete_env)
{
return split_2step(aut,
get_synthesis_outputs(aut),
complete_env);
}
twa_graph_ptr twa_graph_ptr
unsplit_2step(const const_twa_graph_ptr& aut) unsplit_2step(const const_twa_graph_ptr& aut)
{ {

View file

@ -52,11 +52,17 @@ namespace spot
/// \param complete_env Whether the automaton should be complete for the /// \param complete_env Whether the automaton should be complete for the
/// environment, i.e. the player of inputs /// environment, i.e. the player of inputs
/// \note This function also computes the state players /// \note This function also computes the state players
/// \note If the automaton is to be completed for both env and player /// \note If the automaton is to be completed, sink states will
/// then egdes between the sinks will be added /// be added for both env and player if necessary
SPOT_API twa_graph_ptr SPOT_API twa_graph_ptr
split_2step(const const_twa_graph_ptr& aut, split_2step(const const_twa_graph_ptr& aut,
const bdd& output_bdd, bool complete_env); const bdd& output_bdd, bool complete_env = true);
/// \ingroup synthesis
/// \brief Like split_2step but relying on the named property
/// 'synthesis-outputs'
SPOT_API twa_graph_ptr
split_2step(const const_twa_graph_ptr& aut, bool complete_env = true);
/// \ingroup synthesis /// \ingroup synthesis
/// \brief the inverse of split_2step /// \brief the inverse of split_2step