Synthesis: rewrite bypass
* spot/twaalgos/synthesis.cc: here * spot/twaalgos/synthesis.hh: introduce a realizability_code * bin/ltlsynt.cc, spot/twaalgos/aiger.cc: use this enum * tests/core/ltlsynt.test: update tests
This commit is contained in:
parent
3be79ea476
commit
8aa9da7fc8
5 changed files with 292 additions and 161 deletions
|
|
@ -359,22 +359,27 @@ namespace
|
||||||
|
|
||||||
for (; sub_f != sub_form.end(); ++sub_f, ++sub_o)
|
for (; sub_f != sub_form.end(); ++sub_f, ++sub_o)
|
||||||
{
|
{
|
||||||
|
spot::strategy_like_t strat
|
||||||
|
{
|
||||||
|
spot::strategy_like_t::realizability_code::UNKNOWN,
|
||||||
|
nullptr,
|
||||||
|
bddfalse
|
||||||
|
};
|
||||||
// If we want to print a game,
|
// If we want to print a game,
|
||||||
// we never use the direct approach
|
// we never use the direct approach
|
||||||
spot::strategy_like_t strat{0, nullptr, bddfalse};
|
|
||||||
if (!want_game)
|
if (!want_game)
|
||||||
strat =
|
strat =
|
||||||
spot::try_create_direct_strategy(*sub_f, *sub_o, *gi);
|
spot::try_create_direct_strategy(*sub_f, *sub_o, *gi);
|
||||||
|
|
||||||
switch (strat.success)
|
switch (strat.success)
|
||||||
{
|
{
|
||||||
case -1:
|
case spot::strategy_like_t::realizability_code::UNREALIZABLE:
|
||||||
{
|
{
|
||||||
std::cout << "UNREALIZABLE" << std::endl;
|
std::cout << "UNREALIZABLE" << std::endl;
|
||||||
safe_tot_time();
|
safe_tot_time();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case 0:
|
case spot::strategy_like_t::realizability_code::UNKNOWN:
|
||||||
{
|
{
|
||||||
auto arena = spot::ltl_to_game(*sub_f, *sub_o, *gi);
|
auto arena = spot::ltl_to_game(*sub_f, *sub_o, *gi);
|
||||||
if (gi->bv)
|
if (gi->bv)
|
||||||
|
|
@ -400,14 +405,15 @@ namespace
|
||||||
if (!opt_real)
|
if (!opt_real)
|
||||||
{
|
{
|
||||||
spot::strategy_like_t sl;
|
spot::strategy_like_t sl;
|
||||||
sl.success = 1;
|
sl.success =
|
||||||
|
spot::strategy_like_t::realizability_code::REALIZABLE_REGULAR;
|
||||||
sl.strat_like = spot::create_strategy(arena, *gi);
|
sl.strat_like = spot::create_strategy(arena, *gi);
|
||||||
sl.glob_cond = bddfalse;
|
sl.glob_cond = bddfalse;
|
||||||
strategies.push_back(sl);
|
strategies.push_back(sl);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case spot::strategy_like_t::realizability_code::REALIZABLE_REGULAR:
|
||||||
{
|
{
|
||||||
// the direct approach yielded a strategy
|
// the direct approach yielded a strategy
|
||||||
// which can now be minimized
|
// which can now be minimized
|
||||||
|
|
@ -439,7 +445,7 @@ namespace
|
||||||
}
|
}
|
||||||
SPOT_FALLTHROUGH;
|
SPOT_FALLTHROUGH;
|
||||||
}
|
}
|
||||||
case 2:
|
case spot::strategy_like_t::realizability_code::REALIZABLE_DTGBA:
|
||||||
if (!opt_real)
|
if (!opt_real)
|
||||||
strategies.push_back(strat);
|
strategies.push_back(strat);
|
||||||
break;
|
break;
|
||||||
|
|
@ -498,8 +504,11 @@ namespace
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(std::all_of(strategies.begin(), strategies.end(),
|
assert(std::all_of(
|
||||||
[](const auto& sl){return sl.success == 1; })
|
strategies.begin(), strategies.end(),
|
||||||
|
[](const auto& sl)
|
||||||
|
{return sl.success ==
|
||||||
|
spot::strategy_like_t::realizability_code::REALIZABLE_REGULAR; })
|
||||||
&& "ltlsynt: Can not handle TGBA as strategy.");
|
&& "ltlsynt: Can not handle TGBA as strategy.");
|
||||||
tot_strat = strategies.front().strat_like;
|
tot_strat = strategies.front().strat_like;
|
||||||
for (size_t i = 1; i < strategies.size(); ++i)
|
for (size_t i = 1; i < strategies.size(); ++i)
|
||||||
|
|
|
||||||
|
|
@ -1956,19 +1956,19 @@ namespace spot
|
||||||
{
|
{
|
||||||
switch (strat_vec[i].success)
|
switch (strat_vec[i].success)
|
||||||
{
|
{
|
||||||
case -1:
|
case strategy_like_t::realizability_code::UNREALIZABLE:
|
||||||
throw std::runtime_error("strategies_to_aig(): Partial strat is "
|
throw std::runtime_error("strategies_to_aig(): Partial strat is "
|
||||||
"not feasible!");
|
"not feasible!");
|
||||||
case 0:
|
case strategy_like_t::realizability_code::UNKNOWN:
|
||||||
throw std::runtime_error("strategies_to_aig(): Partial strat has "
|
throw std::runtime_error("strategies_to_aig(): Partial strat has "
|
||||||
"unknown status!");
|
"unknown status!");
|
||||||
case 1:
|
case strategy_like_t::realizability_code::REALIZABLE_REGULAR:
|
||||||
{
|
{
|
||||||
strategies.push_back(strat_vec[i].strat_like);
|
strategies.push_back(strat_vec[i].strat_like);
|
||||||
outs_used.push_back(outs[i]);
|
outs_used.push_back(outs[i]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case strategy_like_t::realizability_code::REALIZABLE_DTGBA:
|
||||||
throw std::runtime_error("strategies_to_aig(): TGBA not "
|
throw std::runtime_error("strategies_to_aig(): TGBA not "
|
||||||
"yet supported.");
|
"yet supported.");
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -1246,175 +1246,208 @@ namespace spot
|
||||||
const std::vector<std::string>& output_aps,
|
const std::vector<std::string>& output_aps,
|
||||||
synthesis_info &gi)
|
synthesis_info &gi)
|
||||||
{
|
{
|
||||||
formula_2_inout_props form2props(output_aps);
|
|
||||||
auto vs = gi.verbose_stream;
|
auto vs = gi.verbose_stream;
|
||||||
|
auto& bv = gi.bv;
|
||||||
|
|
||||||
if (vs)
|
if (vs)
|
||||||
*vs << "trying to create strategy directly\n";
|
*vs << "trying to create strategy directly for " << f << '\n';
|
||||||
|
|
||||||
auto ret_sol_maybe = [&vs]()
|
auto ret_sol_maybe = [&vs]()
|
||||||
{
|
{
|
||||||
if (vs)
|
if (vs)
|
||||||
*vs << "direct strategy might exist but was not found.\n";
|
*vs << "direct strategy might exist but was not found.\n";
|
||||||
return strategy_like_t{0, nullptr, bddfalse};
|
return strategy_like_t{
|
||||||
};
|
strategy_like_t::realizability_code::UNKNOWN,
|
||||||
|
nullptr,
|
||||||
|
bddfalse};
|
||||||
|
};
|
||||||
auto ret_sol_none = [&vs]()
|
auto ret_sol_none = [&vs]()
|
||||||
{
|
{
|
||||||
if (vs)
|
if (vs)
|
||||||
*vs << "no direct strategy exists.\n";
|
*vs << "no strategy exists.\n";
|
||||||
return strategy_like_t{-1, nullptr, bddfalse};
|
return strategy_like_t{
|
||||||
|
strategy_like_t::realizability_code::UNREALIZABLE,
|
||||||
|
nullptr,
|
||||||
|
bddfalse};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto ret_sol_exists = [&vs](auto strat)
|
auto ret_sol_exists = [&vs](auto strat)
|
||||||
|
{
|
||||||
|
if (vs)
|
||||||
{
|
{
|
||||||
if (vs)
|
*vs << "direct strategy was found.\n"
|
||||||
{
|
<< "direct strat has " << strat->num_states()
|
||||||
*vs << "direct strategy was found.\n"
|
<< " states and " << strat->num_sets() << " colors\n";
|
||||||
<< "direct strat has " << strat->num_states()
|
}
|
||||||
<< " states and " << strat->num_sets() << " colors\n";
|
return strategy_like_t{
|
||||||
}
|
strategy_like_t::realizability_code::REALIZABLE_REGULAR,
|
||||||
return strategy_like_t{1, strat, bddfalse};
|
strat,
|
||||||
};
|
bddfalse};
|
||||||
|
};
|
||||||
|
formula_2_inout_props form2props(output_aps);
|
||||||
|
|
||||||
// We need a lot of look-ups
|
|
||||||
auto output_aps_set = std::set<std::string>(output_aps.begin(),
|
auto output_aps_set = std::set<std::string>(output_aps.begin(),
|
||||||
output_aps.end());
|
output_aps.end());
|
||||||
|
|
||||||
bool is_and = f.is(op::And);
|
formula f_g = formula::tt(), f_left, f_right;
|
||||||
formula f_g, f_equiv;
|
|
||||||
// Rewrite a conjunction as G(…) ∧ …
|
// If we have a formula like G(b₁) ∧ (φ ↔ GFb₂), we extract b₁ and
|
||||||
if (is_and)
|
// continue the construction for (φ ↔ GFb₂).
|
||||||
|
if (f.is(op::And))
|
||||||
|
{
|
||||||
|
if (f.size() != 2)
|
||||||
|
return ret_sol_maybe();
|
||||||
|
if (f[0].is(op::G) && f[0][0].is_boolean())
|
||||||
{
|
{
|
||||||
if (f.size() != 2)
|
|
||||||
return ret_sol_maybe();
|
|
||||||
if (f[1].is(op::G))
|
|
||||||
f = formula::And({f[1], f[0]});
|
|
||||||
f_equiv = f[1];
|
|
||||||
f_g = f[0];
|
f_g = f[0];
|
||||||
|
f = f[1];
|
||||||
}
|
}
|
||||||
else
|
else if (f[1].is(op::G) && f[1][0].is_boolean())
|
||||||
{
|
{
|
||||||
f_equiv = f;
|
f_g = f[1];
|
||||||
f_g = spot::formula::tt();
|
f = f[0];
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return ret_sol_maybe();
|
||||||
|
}
|
||||||
|
if (f.is(op::Equiv))
|
||||||
|
{
|
||||||
|
auto [left_ins, left_outs] = form2props.aps_of(f[0]);
|
||||||
|
auto [right_ins, right_outs] = form2props.aps_of(f[1]);
|
||||||
|
|
||||||
if (!f_equiv.is(op::Equiv) || (!f_g.is_tt() && (!f_g.is(op::G)
|
auto properties_vector = [](const formula& f,
|
||||||
|| !f_g[0].is_boolean())))
|
const std::set<formula>& ins,
|
||||||
return ret_sol_maybe();
|
const std::set<formula>& outs)
|
||||||
// stopwatch sw;
|
{
|
||||||
twa_graph_ptr res;
|
return std::vector<bool>
|
||||||
|
{
|
||||||
formula left = f_equiv[0],
|
f.is({op::G, op::F}) && f[0][0].is_boolean() && ins.empty(),
|
||||||
right = f_equiv[1];
|
f.is_syntactic_recurrence() && outs.empty(),
|
||||||
|
// f is FG(bool)
|
||||||
auto [left_ins, left_outs] = form2props.aps_of(left);
|
f.is({op::F, op::G}) && f[0][0].is_boolean() && ins.empty(),
|
||||||
auto [right_ins, right_outs] = form2props.aps_of(right);
|
f.is_syntactic_persistence() && outs.empty()
|
||||||
|
};
|
||||||
bool has_left_outs = !left_outs.empty();
|
};
|
||||||
bool has_left_ins = !left_ins.empty();
|
// We need to detect
|
||||||
bool has_right_outs = !right_outs.empty();
|
// GF(outs) ↔ recurrence(ins),
|
||||||
bool has_right_ins = !right_ins.empty();
|
// recurrence(ins) ↔ GF(outs),
|
||||||
|
// FG(outs) ↔ persistence(ins),
|
||||||
// Try to rewrite the equivalence as f(b1) <-> f(b2) where b2 has not any
|
// persistence(ins) ↔ FG(outs)
|
||||||
// input
|
const auto left_properties = properties_vector(f[0], left_ins, left_outs),
|
||||||
if (has_right_ins)
|
right_properties = properties_vector(f[1], right_ins, right_outs);
|
||||||
|
unsigned combin = -1U;
|
||||||
|
for (unsigned i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
if (left_properties[i] && right_properties[(i%2) ? (i-1) : (i+1)])
|
||||||
|
{
|
||||||
|
combin = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (combin == -1U)
|
||||||
|
return ret_sol_maybe();
|
||||||
|
|
||||||
|
// left is the recurrence (resp. persistence)
|
||||||
|
// right is GF(outs) (resp. GF(outs))
|
||||||
|
// If f[0] is GF or FG
|
||||||
|
f_left = f[(combin+1)%2];
|
||||||
|
f_right = f[combin%2];
|
||||||
|
if (!(combin%2))
|
||||||
{
|
{
|
||||||
std::swap(left, right);
|
|
||||||
std::swap(has_left_ins, has_right_ins);
|
|
||||||
std::swap(has_left_outs, has_right_outs);
|
|
||||||
std::swap(left_ins, right_ins);
|
std::swap(left_ins, right_ins);
|
||||||
std::swap(left_outs, right_outs);
|
std::swap(left_outs, right_outs);
|
||||||
}
|
}
|
||||||
// We need to have f(inputs) <-> f(outputs)
|
|
||||||
if (has_right_ins || has_left_outs || !has_right_outs)
|
|
||||||
return ret_sol_maybe();
|
|
||||||
|
|
||||||
bool is_gf_bool_right = right.is({op::G, op::F});
|
auto trans = create_translator(gi);
|
||||||
bool is_fg_bool_right = right.is({op::F, op::G});
|
trans.set_type(combin < 2 ? postprocessor::Buchi
|
||||||
|
: postprocessor::CoBuchi);
|
||||||
|
trans.set_pref(postprocessor::Deterministic | postprocessor::Complete);
|
||||||
|
|
||||||
// Now we have to detect if we have persistence(ins) <-> FG(outs)
|
stopwatch sw;
|
||||||
// or Büchi(ins) <-> GF(outs).
|
if (bv)
|
||||||
|
sw.start();
|
||||||
|
auto res = trans.run(f_left);
|
||||||
|
|
||||||
bool is_ok = ((is_gf_bool_right && left.is_syntactic_recurrence())
|
if (bv)
|
||||||
|| (is_fg_bool_right && left.is_syntactic_guarantee()));
|
|
||||||
|
|
||||||
// TODO: synthesis_info not updated
|
|
||||||
// TODO: Verbose
|
|
||||||
auto& bv = gi.bv;
|
|
||||||
stopwatch sw;
|
|
||||||
if (is_ok)
|
|
||||||
{
|
{
|
||||||
bool right_bool = right[0][0].is_boolean();
|
auto delta = sw.stop();
|
||||||
if (!right_bool)
|
bv->trans_time += delta;
|
||||||
return ret_sol_maybe();
|
if (vs)
|
||||||
auto trans = create_translator(gi);
|
*vs << "tanslating formula done in " << delta << " seconds\n";
|
||||||
trans.set_type(postprocessor::Buchi);
|
|
||||||
trans.set_pref(postprocessor::Deterministic | postprocessor::Complete);
|
|
||||||
|
|
||||||
|
|
||||||
auto right_sub = right[0][0];
|
|
||||||
|
|
||||||
if (bv)
|
|
||||||
sw.start();
|
|
||||||
res = trans.run(left);
|
|
||||||
if (bv)
|
|
||||||
{
|
|
||||||
auto delta = sw.stop();
|
|
||||||
bv->trans_time += delta;
|
|
||||||
if (vs)
|
|
||||||
*vs << "tanslating formula done in " << delta << " seconds\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& out : right_outs)
|
|
||||||
res->register_ap(out.ap_name());
|
|
||||||
if (!is_deterministic(res))
|
|
||||||
return ret_sol_maybe();
|
|
||||||
bdd form_bdd = bddtrue;
|
|
||||||
if (is_and)
|
|
||||||
{
|
|
||||||
bdd output_bdd = bddtrue;
|
|
||||||
for (auto &out : output_aps_set)
|
|
||||||
output_bdd &= bdd_ithvar(res->register_ap(out));
|
|
||||||
form_bdd = f_g.is_tt() ? (bdd) bddtrue :
|
|
||||||
formula_to_bdd(f_g[0],
|
|
||||||
res->get_dict(), res);
|
|
||||||
if (bdd_exist(form_bdd, output_bdd) != bddtrue)
|
|
||||||
return ret_sol_maybe();
|
|
||||||
}
|
|
||||||
bdd right_bdd = formula_to_bdd(right_sub, res->get_dict(), res);
|
|
||||||
bdd neg_right_bdd = bdd_not(right_bdd);
|
|
||||||
assert(right_ins.empty());
|
|
||||||
const bool is_true = res->acc().is_t();
|
|
||||||
scc_info si(res, scc_info_options::NONE);
|
|
||||||
for (auto& e : res->edges())
|
|
||||||
{
|
|
||||||
// Here the part describing the outputs is based on the fact that
|
|
||||||
// they must be seen infinitely often. As these edges are seen
|
|
||||||
// finitely often, we can let the minimization choose the value.
|
|
||||||
if (si.scc_of(e.src) == si.scc_of(e.dst))
|
|
||||||
{
|
|
||||||
if (e.acc || is_true)
|
|
||||||
e.cond &= (right_bdd);
|
|
||||||
else
|
|
||||||
e.cond &= (neg_right_bdd);
|
|
||||||
}
|
|
||||||
// form_bdd has to be true all the time. So we cannot only do it
|
|
||||||
// between SCCs.
|
|
||||||
if (!bdd_have_common_assignment(e.cond, form_bdd))
|
|
||||||
return ret_sol_none();
|
|
||||||
e.acc = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bdd output_bdd = bddtrue;
|
|
||||||
for (auto &out : output_aps_set)
|
|
||||||
output_bdd &= bdd_ithvar(res->register_ap(out));
|
|
||||||
|
|
||||||
set_synthesis_outputs(res, output_bdd);
|
|
||||||
res->set_acceptance(acc_cond::acc_code::t());
|
|
||||||
|
|
||||||
res->prop_complete(trival::maybe());
|
|
||||||
return ret_sol_exists(res);
|
|
||||||
}
|
}
|
||||||
return ret_sol_maybe();
|
|
||||||
|
if (!is_deterministic(res))
|
||||||
|
return ret_sol_maybe();
|
||||||
|
for (auto& out : right_outs)
|
||||||
|
res->register_ap(out.ap_name());
|
||||||
|
|
||||||
|
// The BDD that describes the content of the G in a conjunction
|
||||||
|
bdd g_bdd = bddtrue;
|
||||||
|
|
||||||
|
// Convert the set of outputs to a BDD
|
||||||
|
bdd output_bdd = bddtrue;
|
||||||
|
for (auto &out : output_aps_set)
|
||||||
|
output_bdd &= bdd_ithvar(res->register_ap(out));
|
||||||
|
|
||||||
|
if (!f_g.is_tt())
|
||||||
|
{
|
||||||
|
g_bdd = formula_to_bdd(f_g[0], res->get_dict(), res);
|
||||||
|
// If the content of G is not input-complete, a simple strategy for
|
||||||
|
// env is to play this missing value.
|
||||||
|
if (bdd_exist(g_bdd, output_bdd) != bddtrue)
|
||||||
|
{
|
||||||
|
return ret_sol_none();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the GF(outs) (resp. GF(outs)), the content and its negation can be
|
||||||
|
// converted to a BDD.
|
||||||
|
bdd right_bdd, neg_right_bdd;
|
||||||
|
if (combin < 2)
|
||||||
|
{
|
||||||
|
right_bdd = formula_to_bdd(f_right[0][0], res->get_dict(), res);
|
||||||
|
neg_right_bdd = bdd_not(right_bdd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neg_right_bdd = formula_to_bdd(f_right[0][0], res->get_dict(), res);
|
||||||
|
right_bdd = bdd_not(neg_right_bdd);
|
||||||
|
}
|
||||||
|
// Monitor is a special case. As we color accepting transitions, if the
|
||||||
|
// acceptance is true, we cannot say that a transition is accepting if
|
||||||
|
// a color is seen.
|
||||||
|
const bool is_true = res->acc().is_t();
|
||||||
|
scc_info si(res, scc_info_options::NONE);
|
||||||
|
for (auto& e : res->edges())
|
||||||
|
{
|
||||||
|
// Here the part describing the outputs is based on the fact that
|
||||||
|
// they must be seen infinitely often. As these edges are seen
|
||||||
|
// finitely often, we can let the minimization choose the value.
|
||||||
|
if (si.scc_of(e.src) == si.scc_of(e.dst))
|
||||||
|
{
|
||||||
|
if (e.acc || is_true)
|
||||||
|
e.cond &= right_bdd;
|
||||||
|
else
|
||||||
|
e.cond &= neg_right_bdd;
|
||||||
|
}
|
||||||
|
// g_bdd has to be true all the time. So we cannot only do it
|
||||||
|
// between SCCs.
|
||||||
|
e.cond &= g_bdd;
|
||||||
|
if (e.cond == bddfalse)
|
||||||
|
return ret_sol_maybe();
|
||||||
|
// The recurrence is Büchi but the strategy is a monitor. We need
|
||||||
|
// to remove the color.
|
||||||
|
e.acc = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
set_synthesis_outputs(res, output_bdd);
|
||||||
|
res->set_acceptance(acc_cond::acc_code::t());
|
||||||
|
|
||||||
|
res->prop_complete(trival::maybe());
|
||||||
|
return ret_sol_exists(res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ret_sol_maybe();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // spot
|
} // spot
|
||||||
|
|
|
||||||
|
|
@ -224,11 +224,17 @@ namespace spot
|
||||||
struct SPOT_API
|
struct SPOT_API
|
||||||
strategy_like_t
|
strategy_like_t
|
||||||
{
|
{
|
||||||
// -1 : Unrealizable
|
|
||||||
// 0 : Unknown
|
enum class realizability_code
|
||||||
// 1 : Realizable -> regular strat
|
{
|
||||||
// 2 : Realizable -> strat is DTGBA and a glob_cond // todo
|
UNREALIZABLE,
|
||||||
int success;
|
UNKNOWN,
|
||||||
|
REALIZABLE_REGULAR,
|
||||||
|
// strat is DTGBA and a glob_cond
|
||||||
|
REALIZABLE_DTGBA
|
||||||
|
};
|
||||||
|
|
||||||
|
realizability_code success;
|
||||||
twa_graph_ptr strat_like;
|
twa_graph_ptr strat_like;
|
||||||
bdd glob_cond;
|
bdd glob_cond;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ ltlsynt --ins=a --outs=b,c -f 'GFa <-> (GFb & GFc)' \
|
||||||
diff out exp
|
diff out exp
|
||||||
|
|
||||||
cat >exp <<EOF
|
cat >exp <<EOF
|
||||||
trying to create strategy directly
|
trying to create strategy directly for GFa <-> GFb
|
||||||
tanslating formula done in X seconds
|
tanslating formula done in X seconds
|
||||||
direct strategy was found.
|
direct strategy was found.
|
||||||
direct strat has 1 states and 0 colors
|
direct strat has 1 states and 0 colors
|
||||||
|
|
@ -202,7 +202,7 @@ sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
diff outx exp
|
diff outx exp
|
||||||
|
|
||||||
cat >exp <<EOF
|
cat >exp <<EOF
|
||||||
trying to create strategy directly
|
trying to create strategy directly for GFa <-> GFb
|
||||||
tanslating formula done in X seconds
|
tanslating formula done in X seconds
|
||||||
direct strategy was found.
|
direct strategy was found.
|
||||||
direct strat has 1 states and 0 colors
|
direct strat has 1 states and 0 colors
|
||||||
|
|
@ -214,7 +214,7 @@ sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
diff outx exp
|
diff outx exp
|
||||||
|
|
||||||
cat >exp <<EOF
|
cat >exp <<EOF
|
||||||
trying to create strategy directly
|
trying to create strategy directly for (Fa & Fb & Fc & Fd) <-> GFe
|
||||||
tanslating formula done in X seconds
|
tanslating formula done in X seconds
|
||||||
direct strategy was found.
|
direct strategy was found.
|
||||||
direct strat has 16 states and 0 colors
|
direct strat has 16 states and 0 colors
|
||||||
|
|
@ -225,7 +225,7 @@ sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
diff outx exp
|
diff outx exp
|
||||||
|
|
||||||
cat >exp <<EOF
|
cat >exp <<EOF
|
||||||
trying to create strategy directly
|
trying to create strategy directly for G(Fi0 & Fi1 & Fi2) -> G(i1 <-> o0)
|
||||||
direct strategy might exist but was not found.
|
direct strategy might exist but was not found.
|
||||||
translating formula done in X seconds
|
translating formula done in X seconds
|
||||||
automaton has 2 states and 3 colors
|
automaton has 2 states and 3 colors
|
||||||
|
|
@ -551,3 +551,86 @@ grep "both.*but 'b' is unlisted" stderr
|
||||||
ltlsynt -f 'GFa | FGb | GFc' 2>stderr && :
|
ltlsynt -f 'GFa | FGb | GFc' 2>stderr && :
|
||||||
test $? -eq 2
|
test $? -eq 2
|
||||||
grep "one of --ins or --outs" stderr
|
grep "one of --ins or --outs" stderr
|
||||||
|
|
||||||
|
# Try to find a direct strategy for GFa <-> GFb and a direct strategy for
|
||||||
|
# Gc
|
||||||
|
cat >exp <<EOF
|
||||||
|
trying to create strategy directly for GFa <-> GFb
|
||||||
|
tanslating formula done in X seconds
|
||||||
|
direct strategy was found.
|
||||||
|
direct strat has 1 states and 0 colors
|
||||||
|
final strategy has 1 states and 2 edges
|
||||||
|
minimization took X seconds
|
||||||
|
trying to create strategy directly for Gc
|
||||||
|
direct strategy might exist but was not found.
|
||||||
|
translating formula done in X seconds
|
||||||
|
automaton has 1 states and 1 colors
|
||||||
|
LAR construction done in X seconds
|
||||||
|
DPA has 1 states, 2 colors
|
||||||
|
split inputs and outputs done in X seconds
|
||||||
|
automaton has 2 states
|
||||||
|
solving game with acceptance: parity max odd 4
|
||||||
|
game solved in X seconds
|
||||||
|
EOF
|
||||||
|
ltlsynt -f '(GFa <-> GFb) && (Gc)' --outs=b,c --verbose 2> out
|
||||||
|
sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
|
diff outx exp
|
||||||
|
|
||||||
|
# Try to find a direct strategy for (GFa <-> GFb) & Gc. THe order should not
|
||||||
|
# impact the result
|
||||||
|
for f in "(GFa <-> GFb) & Gc" "(GFb <-> GFa) & Gc" \
|
||||||
|
"Gc & (GFa <-> GFb)" "Gc & (GFb <-> GFa)"
|
||||||
|
do
|
||||||
|
cat >exp <<EOF
|
||||||
|
trying to create strategy directly for $f
|
||||||
|
tanslating formula done in X seconds
|
||||||
|
direct strategy was found.
|
||||||
|
direct strat has 1 states and 0 colors
|
||||||
|
final strategy has 1 states and 2 edges
|
||||||
|
minimization took X seconds
|
||||||
|
EOF
|
||||||
|
ltlsynt -f "$f" --outs=b,c --verbose --decompose=0 --verify 2> out
|
||||||
|
sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
|
diff outx exp
|
||||||
|
done
|
||||||
|
|
||||||
|
# # Ltlsynt should be able to detect that G(a&c) is not input-complete so it is
|
||||||
|
# # impossible to find a strategy.
|
||||||
|
cat >exp <<EOF
|
||||||
|
trying to create strategy directly for (GFb <-> GFa) & G(a & c)
|
||||||
|
tanslating formula done in X seconds
|
||||||
|
no strategy exists.
|
||||||
|
EOF
|
||||||
|
ltlsynt -f '(GFb <-> GFa) && G(a&c)' --outs=b,c --verbose\
|
||||||
|
--decompose=0 2> out || true
|
||||||
|
sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
|
diff outx exp
|
||||||
|
|
||||||
|
# # Ltlsynt should be able to create a strategy when the last G
|
||||||
|
# is input-complete.
|
||||||
|
cat >exp <<EOF
|
||||||
|
trying to create strategy directly for (GFb <-> GFa) & G((a & c) | (!a & !c))
|
||||||
|
tanslating formula done in X seconds
|
||||||
|
direct strategy was found.
|
||||||
|
direct strat has 1 states and 0 colors
|
||||||
|
final strategy has 1 states and 2 edges
|
||||||
|
minimization took X seconds
|
||||||
|
EOF
|
||||||
|
ltlsynt -f '(GFb <-> GFa) && (G((a&c)|(!a&!c)))' --outs=b,c --verbose\
|
||||||
|
--verify --decompose=0 2> out
|
||||||
|
sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
|
diff outx exp
|
||||||
|
|
||||||
|
# Direct strategy for persistence
|
||||||
|
|
||||||
|
cat >exp <<EOF
|
||||||
|
trying to create strategy directly for Fa <-> FGb
|
||||||
|
tanslating formula done in X seconds
|
||||||
|
direct strategy was found.
|
||||||
|
direct strat has 2 states and 0 colors
|
||||||
|
final strategy has 2 states and 3 edges
|
||||||
|
minimization took X seconds
|
||||||
|
EOF
|
||||||
|
ltlsynt -f "Fa <-> FGb" --outs=b,c --verbose --decompose=0 --verify 2> out
|
||||||
|
sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx
|
||||||
|
diff outx exp
|
||||||
Loading…
Add table
Add a link
Reference in a new issue