Remove do_simplify opt from split_2step

Removing this option to guarante that all arenas
are alternating

* spot/twaalgos/synthesis.hh: Here
* spot/twaalgos/synthesis.cc: Here
* spot/twaalgos/mealy_machine.cc: API change
* tests/python/aiger.py: API change
* tests/python/mealy.py: API change
* tests/python/split.py: API change
This commit is contained in:
Philipp Schlehuber 2021-09-22 12:52:03 +02:00
parent ddda68403f
commit 406bc8ed17
6 changed files with 27 additions and 63 deletions

View file

@ -507,7 +507,7 @@ namespace spot
// Split if the initial aut was split // Split if the initial aut was split
if (orig_is_split) if (orig_is_split)
{ {
mmc = split_2step(mmc, outs, false, false); mmc = split_2step(mmc, outs, false);
bool orig_init_player = bool orig_init_player =
mm->get_named_prop<std::vector<bool>>("state-player") mm->get_named_prop<std::vector<bool>>("state-player")
->at(mm->get_init_state_number()); ->at(mm->get_init_state_number());
@ -582,7 +582,7 @@ namespace spot
mm->purge_unreachable_states(); mm->purge_unreachable_states();
if (orig_is_split) if (orig_is_split)
{ {
mm = split_2step(mm, outs, false, false); mm = split_2step(mm, outs, false);
alternate_players(mm, init_player, false); alternate_players(mm, init_player, false);
mm->set_named_prop("synthesis-outputs", new bdd(outs)); mm->set_named_prop("synthesis-outputs", new bdd(outs));
} }

View file

@ -135,8 +135,7 @@ namespace spot
{ {
twa_graph_ptr 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)
bool do_simplify)
{ {
auto split = make_twa_graph(aut->get_dict()); auto split = make_twa_graph(aut->get_dict());
split->copy_ap_of(aut); split->copy_ap_of(aut);
@ -216,25 +215,6 @@ namespace spot
e_cache.clear(); e_cache.clear();
auto out_cont = aut->out(src); auto out_cont = aut->out(src);
// Short-cut if we do not want to
// split the edges of nodes that have
// a single outgoing edge
if (do_simplify
&& (++out_cont.begin()) == out_cont.end())
{
// "copy" the edge
const auto& e = *out_cont.begin();
split->new_edge(src, e.dst, e.cond, e.acc);
// Check if it needs to be completed
if (complete_env)
{
bdd missing = bddtrue - bdd_exist(e.cond, output_bdd);
if (missing != bddfalse)
split->new_edge(src, get_sink_con_state(), missing);
}
// We are done for this state
continue;
}
// Avoid looping over all minterms // Avoid looping over all minterms
// we only loop over the minterms that actually exist // we only loop over the minterms that actually exist
@ -433,9 +413,11 @@ namespace spot
out->copy_acceptance_of(aut); out->copy_acceptance_of(aut);
out->copy_ap_of(aut); out->copy_ap_of(aut);
// split_2step is not guaranteed to produce // split_2step is guaranteed to produce an alternating arena
// states that alternate between env and player do to do_simplify
auto owner = get_state_players(aut); auto owner = get_state_players(aut);
#ifndef NDEGUB
(void) owner;
#endif
std::vector<unsigned> state_map(aut->num_states(), unseen_mark); std::vector<unsigned> state_map(aut->num_states(), unseen_mark);
auto seen = [&](unsigned s){return state_map[s] != unseen_mark; }; auto seen = [&](unsigned s){return state_map[s] != unseen_mark; };
@ -456,30 +438,16 @@ namespace spot
todo.pop_front(); todo.pop_front();
for (const auto& i : aut->out(cur)) for (const auto& i : aut->out(cur))
{ for (const auto& o : aut->out(i.dst))
// if the dst is also owned env {
if (!owner[i.dst]) assert((owner.at(cur) != owner.at(o.src))
{ && (owner.at(cur) == owner.at(o.dst)
// This can only happen if there is only && "Arena is not alternating!"));
// one outgoing edges for cur if (!seen(o.dst))
assert(([&aut, cur]()->bool todo.push_back(o.dst);
{ out->new_edge(cur_m, map_s(o.dst),
auto out_cont = aut->out(cur); i.cond & o.cond, i.acc | o.acc);
return (++(out_cont.begin()) == out_cont.end()); }
})());
if (!seen(i.dst))
todo.push_back(i.dst);
out->new_edge(cur_m, map_s(i.dst), i.cond, i.acc);
continue; // Done with cur
}
for (const auto& o : aut->out(i.dst))
{
if (!seen(o.dst))
todo.push_back(o.dst);
out->new_edge(cur_m, map_s(o.dst),
i.cond & o.cond, i.acc | o.acc);
}
}
} }
out->set_init_state(map_s(aut->get_init_state_number())); out->set_init_state(map_s(aut->get_init_state_number()));
// Try to set outputs // Try to set outputs
@ -952,7 +920,7 @@ namespace spot
<< bv->paritize_time << " seconds\n"; << bv->paritize_time << " seconds\n";
if (bv) if (bv)
sw.start(); sw.start();
dpa = split_2step(tmp, outs, true, false); dpa = split_2step(tmp, outs, true);
colorize_parity_here(dpa, true); colorize_parity_here(dpa, true);
if (bv) if (bv)
bv->split_time += sw.stop(); bv->split_time += sw.stop();
@ -975,7 +943,7 @@ namespace spot
<< " states\n"; << " states\n";
if (bv) if (bv)
sw.start(); sw.start();
dpa = split_2step(aut, outs, true, false); dpa = split_2step(aut, outs, true);
colorize_parity_here(dpa, true); colorize_parity_here(dpa, true);
if (bv) if (bv)
bv->split_time += sw.stop(); bv->split_time += sw.stop();
@ -988,8 +956,7 @@ namespace spot
case solver::SPLIT_DET: case solver::SPLIT_DET:
{ {
sw.start(); sw.start();
auto split = split_2step(aut, outs, auto split = split_2step(aut, outs, true);
true, false);
if (bv) if (bv)
bv->split_time += sw.stop(); bv->split_time += sw.stop();
if (vs) if (vs)
@ -1045,7 +1012,7 @@ namespace spot
if (bv) if (bv)
sw.start(); sw.start();
dpa = split_2step(dpa, outs, true, false); dpa = split_2step(dpa, outs, true);
colorize_parity_here(dpa, true); colorize_parity_here(dpa, true);
if (bv) if (bv)
bv->split_time += sw.stop(); bv->split_time += sw.stop();

View file

@ -25,8 +25,8 @@
namespace spot namespace spot
{ {
/// \brief make each transition (conditionally, see do_simplify) /// \brief make each transition a 2-step transition, transforming
/// a 2-step transition /// the graph into an alternating arena
/// ///
/// Given a set of atomic propositions I, split each transition /// Given a set of atomic propositions I, split each transition
/// p -- cond --> q cond in 2^2^AP /// p -- cond --> q cond in 2^2^AP
@ -45,16 +45,13 @@ namespace spot
/// are treated as inputs /// are treated as inputs
/// \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 I /// environment, i.e. the player of I
/// \param do_simplify If a state has a single outgoing transition
/// we do not necessarily have to split it
/// to solve the game
/// \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 for both env and player
/// then egdes between the sinks will be added /// then egdes between the sinks will be added
/// (assuming that the environnement/player of I) plays first /// (assuming that the environnement/player of I) plays first
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, bool do_simplify); const bdd& output_bdd, bool complete_env);
/// \brief make each transition a 2-step transition. /// \brief make each transition a 2-step transition.

View file

@ -3333,7 +3333,7 @@ for strat_string, (ins_str, outs_str) in strats:
outs &= buddy.bdd_ithvar(strat.register_ap(aout)) outs &= buddy.bdd_ithvar(strat.register_ap(aout))
spot.set_synthesis_outputs(strat, outs) spot.set_synthesis_outputs(strat, outs)
strat_s = spot.split_2step(strat, outs, False, False) strat_s = spot.split_2step(strat, outs, False)
for m in ["isop", "ite", "both"]: for m in ["isop", "ite", "both"]:
for ss in [""] + [f"+sub{ii}" for ii in range(3)]: for ss in [""] + [f"+sub{ii}" for ii in range(3)]:

View file

@ -378,7 +378,7 @@ for (mealy_str, nenv_min) in test_auts:
ins = ins & buddy.bdd_ithvar(mealy.register_ap(aap.ap_name())) ins = ins & buddy.bdd_ithvar(mealy.register_ap(aap.ap_name()))
else: else:
assert("""Aps must start with either "i" or "o".""") assert("""Aps must start with either "i" or "o".""")
mealy_min_us_s = spot.split_2step(mealy_min_us, outs, False, False) mealy_min_us_s = spot.split_2step(mealy_min_us, outs, False)
assert(spot.is_mealy_specialization(mealy, mealy_min_us_s, True)) assert(spot.is_mealy_specialization(mealy, mealy_min_us_s, True))

View file

@ -46,7 +46,7 @@ def do_split(f, out_list):
outputs = spot.buddy.bddtrue outputs = spot.buddy.bddtrue
for a in out_list: for a in out_list:
outputs &= spot.buddy.bdd_ithvar(aut.get_dict().varnum(spot.formula(a))) outputs &= spot.buddy.bdd_ithvar(aut.get_dict().varnum(spot.formula(a)))
s = spot.split_2step(aut, outputs, False, False) s = spot.split_2step(aut, outputs, False)
return aut, s return aut, s
aut, s = do_split('(FG !a) <-> (GF b)', ['b']) aut, s = do_split('(FG !a) <-> (GF b)', ['b'])