Fixes #495
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:
parent
852abc770f
commit
2298743479
2 changed files with 61 additions and 21 deletions
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue