postproc: add support for -x dpa-simul and simul-trans-pruning
Also have simul-max default to 4096 instead of 512, because it's really simul-trans-pruning that is very slow and need to be limited. * spot/twaalgos/postproc.cc, spot/twaalgos/postproc.hh, spot/twaalgos/simulation.cc, spot/twaalgos/simulation.hh, spot/twaalgos/determinize.cc, spot/twaalgos/determinize.hh: Implement the above options. * bin/spot-x.cc, NEWS: Document them. * tests/core/ltlsynt.test, tests/core/minusx.test, tests/core/sim3.test: Add some test cases.
This commit is contained in:
parent
fca6513604
commit
d32f19f5d0
11 changed files with 210 additions and 101 deletions
|
|
@ -811,7 +811,8 @@ namespace spot
|
|||
tgba_determinize(const const_twa_graph_ptr& a,
|
||||
bool pretty_print, bool use_scc,
|
||||
bool use_simulation, bool use_stutter,
|
||||
const output_aborter* aborter)
|
||||
const output_aborter* aborter,
|
||||
int trans_pruning)
|
||||
{
|
||||
if (!a->is_existential())
|
||||
throw std::runtime_error
|
||||
|
|
@ -829,7 +830,7 @@ namespace spot
|
|||
if (use_simulation)
|
||||
{
|
||||
aut_tmp = spot::scc_filter(aut_tmp);
|
||||
auto aut2 = simulation(aut_tmp, &implications);
|
||||
auto aut2 = simulation(aut_tmp, &implications, trans_pruning);
|
||||
if (pretty_print)
|
||||
aut2->copy_state_names_from(aut_tmp);
|
||||
aut_tmp = aut2;
|
||||
|
|
|
|||
|
|
@ -77,11 +77,16 @@ namespace spot
|
|||
/// \param aborter abort the construction if the constructed
|
||||
/// automaton would be too large. Return nullptr
|
||||
/// in this case.
|
||||
///
|
||||
/// \param trans_pruning when \a use_simulation is true, \a trans_pruning
|
||||
/// is passed to the simulation-based reduction to limit
|
||||
/// the effect of transition pruning.
|
||||
SPOT_API twa_graph_ptr
|
||||
tgba_determinize(const const_twa_graph_ptr& aut,
|
||||
bool pretty_print = false,
|
||||
bool use_scc = true,
|
||||
bool use_simulation = true,
|
||||
bool use_stutter = true,
|
||||
const output_aborter* aborter = nullptr);
|
||||
const output_aborter* aborter = nullptr,
|
||||
int trans_pruning = -1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ namespace spot
|
|||
det_max_edges_ = opt->get("det-max-edges", -1);
|
||||
simul_ = opt->get("simul", -1);
|
||||
simul_method_ = opt->get("simul-method", -1);
|
||||
dpa_simul_ = opt->get("dpa-simul", -1);
|
||||
scc_filter_ = opt->get("scc-filter", -1);
|
||||
ba_simul_ = opt->get("ba-simul", -1);
|
||||
tba_determinisation_ = opt->get("tba-det", 0);
|
||||
|
|
@ -86,8 +87,9 @@ namespace spot
|
|||
state_based_ = opt->get("state-based", 0);
|
||||
wdba_minimize_ = opt->get("wdba-minimize", -1);
|
||||
gen_reduce_parity_ = opt->get("gen-reduce-parity", 1);
|
||||
simul_max_ = opt->get("simul-max", 512);
|
||||
simul_max_ = opt->get("simul-max", 4096);
|
||||
wdba_det_max_ = opt->get("wdba-det-max", 4096);
|
||||
simul_trans_pruning_ = opt->get("simul-trans-pruning", 512);
|
||||
|
||||
if (sat_acc_ && sat_minimize_ == 0)
|
||||
sat_minimize_ = 1; // Dicho.
|
||||
|
|
@ -113,11 +115,10 @@ namespace spot
|
|||
twa_graph_ptr
|
||||
postprocessor::do_simul(const twa_graph_ptr& a, int opt) const
|
||||
{
|
||||
if (simul_max_ > 0 && static_cast<unsigned>(simul_max_) < a->num_states())
|
||||
return a;
|
||||
|
||||
if (opt == 0)
|
||||
return a;
|
||||
if (simul_max_ > 0 && static_cast<unsigned>(simul_max_) < a->num_states())
|
||||
return a;
|
||||
|
||||
static unsigned sim = [&]()
|
||||
{
|
||||
|
|
@ -131,18 +132,18 @@ namespace spot
|
|||
if (sim == 2)
|
||||
opt += 3;
|
||||
|
||||
// FIXME: simulation-based reduction how have work-arounds for
|
||||
// FIXME: simulation-based reduction now have work-arounds for
|
||||
// non-separated sets, so we can probably try them.
|
||||
if (!has_separate_sets(a))
|
||||
return a;
|
||||
switch (opt)
|
||||
{
|
||||
case 1:
|
||||
return simulation(a);
|
||||
return simulation(a, simul_trans_pruning_);
|
||||
case 2:
|
||||
return cosimulation(a);
|
||||
return cosimulation(a, simul_trans_pruning_);
|
||||
case 3:
|
||||
return iterated_simulations(a);
|
||||
return iterated_simulations(a, simul_trans_pruning_);
|
||||
case 4:
|
||||
return reduce_direct_sim(a);
|
||||
case 5:
|
||||
|
|
@ -150,7 +151,7 @@ namespace spot
|
|||
case 6:
|
||||
return reduce_iterated(a);
|
||||
default:
|
||||
return iterated_simulations(a);
|
||||
return iterated_simulations(a, simul_trans_pruning_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,12 +167,12 @@ namespace spot
|
|||
case 0:
|
||||
return a;
|
||||
case 1:
|
||||
return simulation_sba(a);
|
||||
return simulation_sba(a, simul_trans_pruning_);
|
||||
case 2:
|
||||
return cosimulation_sba(a);
|
||||
return cosimulation_sba(a, simul_trans_pruning_);
|
||||
case 3:
|
||||
default:
|
||||
return iterated_simulations_sba(a);
|
||||
return iterated_simulations_sba(a, simul_trans_pruning_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +267,8 @@ namespace spot
|
|||
simul_ = (level_ == Low) ? 1 : 3;
|
||||
if (ba_simul_ < 0)
|
||||
ba_simul_ = (level_ == High) ? 3 : 0;
|
||||
if (dpa_simul_ < 0)
|
||||
dpa_simul_ = (level_ != Low) ? 1 : 0;
|
||||
if (scc_filter_ < 0)
|
||||
scc_filter_ = 1;
|
||||
if (type_ == BA)
|
||||
|
|
@ -551,14 +554,13 @@ namespace spot
|
|||
det_simul = false;
|
||||
dba = tgba_determinize(tba,
|
||||
false, det_scc_, det_simul, det_stutter_,
|
||||
aborter);
|
||||
aborter, simul_trans_pruning_);
|
||||
// Setting det-max-states or det-max-edges may cause tgba_determinize
|
||||
// to fail.
|
||||
|
||||
if (dba)
|
||||
{
|
||||
dba = simplify_acc(dba);
|
||||
if (level_ != Low)
|
||||
dba = simulation(dba);
|
||||
dba = do_simul(simplify_acc(dba), dpa_simul_);
|
||||
sim = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2012-2020 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2012-2021 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -253,6 +253,8 @@ namespace spot
|
|||
int det_max_edges_ = -1;
|
||||
int simul_ = -1;
|
||||
int simul_method_ = -1;
|
||||
int simul_trans_pruning_ = 512;
|
||||
int dpa_simul_ = -1;
|
||||
int scc_filter_ = -1;
|
||||
int ba_simul_ = -1;
|
||||
bool tba_determinisation_ = false;
|
||||
|
|
@ -264,7 +266,7 @@ namespace spot
|
|||
int gen_reduce_parity_ = 1;
|
||||
bool state_based_ = false;
|
||||
int wdba_minimize_ = -1;
|
||||
int simul_max_ = 512;
|
||||
int simul_max_ = 4096;
|
||||
int wdba_det_max_ = 4096;
|
||||
};
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -154,10 +154,12 @@ namespace spot
|
|||
}
|
||||
|
||||
direct_simulation(const const_twa_graph_ptr& in,
|
||||
int trans_pruning,
|
||||
std::vector<bdd>* implications = nullptr)
|
||||
: po_size_(0),
|
||||
all_class_var_(bddtrue),
|
||||
original_(in),
|
||||
trans_pruning_(trans_pruning),
|
||||
record_implications_(implications)
|
||||
{
|
||||
if (!has_separate_sets(in))
|
||||
|
|
@ -467,13 +469,18 @@ namespace spot
|
|||
}
|
||||
|
||||
// Update the partial order.
|
||||
//
|
||||
// Do not compute implication between classes if we have more
|
||||
// classes than trans_pruning_, or if the automaton is
|
||||
// deterministic (in which case want_implications_ was
|
||||
// initialized to false). The number of classes should only
|
||||
// augment, so if we exceed trans_pruning_, it's safe to
|
||||
// disable want_implications_ for good.
|
||||
|
||||
// This loop follows the pattern given by the paper.
|
||||
// foreach class do
|
||||
// | foreach class do
|
||||
// | | update po if needed
|
||||
// | od
|
||||
// od
|
||||
if (want_implications_
|
||||
&& trans_pruning_ >= 0
|
||||
&& static_cast<unsigned>(trans_pruning_) < sz)
|
||||
want_implications_ = false;
|
||||
|
||||
for (unsigned n = 0; n < sz; ++n)
|
||||
{
|
||||
|
|
@ -773,7 +780,7 @@ namespace spot
|
|||
if (!need_another_pass)
|
||||
return res;
|
||||
|
||||
direct_simulation<Cosimulation, Sba> sim(res);
|
||||
direct_simulation<Cosimulation, Sba> sim(res, trans_pruning_);
|
||||
return sim.run();
|
||||
}
|
||||
|
||||
|
|
@ -861,16 +868,16 @@ namespace spot
|
|||
automaton_size stat;
|
||||
|
||||
const const_twa_graph_ptr original_;
|
||||
|
||||
int trans_pruning_;
|
||||
std::vector<bdd>* record_implications_;
|
||||
};
|
||||
|
||||
template<typename Fun, typename Aut>
|
||||
twa_graph_ptr
|
||||
wrap_simul(Fun f, const Aut& a)
|
||||
wrap_simul(Fun f, const Aut& a, int trans_pruning)
|
||||
{
|
||||
if (has_separate_sets(a))
|
||||
return f(a);
|
||||
return f(a, trans_pruning);
|
||||
// If the input has acceptance sets common to Fin and Inf,
|
||||
// separate them before doing the simulation, and merge them
|
||||
// back afterwards. Doing will temporarily introduce more sets
|
||||
|
|
@ -879,62 +886,63 @@ namespace spot
|
|||
// automata sharing Fin/Inf sets.
|
||||
auto b = make_twa_graph(a, twa::prop_set::all());
|
||||
separate_sets_here(b);
|
||||
return simplify_acceptance_here(f(b));
|
||||
return simplify_acceptance_here(f(b, trans_pruning));
|
||||
}
|
||||
|
||||
} // End namespace anonymous.
|
||||
|
||||
|
||||
twa_graph_ptr
|
||||
simulation(const const_twa_graph_ptr& t)
|
||||
simulation(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
return wrap_simul([](const const_twa_graph_ptr& t) {
|
||||
direct_simulation<false, false> simul(t);
|
||||
return simul.run();
|
||||
}, t);
|
||||
return wrap_simul([](const const_twa_graph_ptr& t, int trans_pruning) {
|
||||
direct_simulation<false, false> simul(t, trans_pruning);
|
||||
return simul.run();
|
||||
}, t, trans_pruning);
|
||||
}
|
||||
|
||||
twa_graph_ptr
|
||||
simulation(const const_twa_graph_ptr& t,
|
||||
std::vector<bdd>* implications)
|
||||
std::vector<bdd>* implications, int trans_pruning)
|
||||
{
|
||||
return wrap_simul([implications](const const_twa_graph_ptr& t) {
|
||||
direct_simulation<false, false> simul(t, implications);
|
||||
return simul.run();
|
||||
}, t);
|
||||
return wrap_simul([implications](const const_twa_graph_ptr& t,
|
||||
int trans_pruning) {
|
||||
direct_simulation<false, false> simul(t, trans_pruning, implications);
|
||||
return simul.run();
|
||||
}, t, trans_pruning);
|
||||
}
|
||||
|
||||
twa_graph_ptr
|
||||
simulation_sba(const const_twa_graph_ptr& t)
|
||||
simulation_sba(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
return wrap_simul([](const const_twa_graph_ptr& t) {
|
||||
direct_simulation<false, true> simul(t);
|
||||
return simul.run();
|
||||
}, t);
|
||||
return wrap_simul([](const const_twa_graph_ptr& t, int trans_pruning) {
|
||||
direct_simulation<false, true> simul(t, trans_pruning);
|
||||
return simul.run();
|
||||
}, t, trans_pruning);
|
||||
}
|
||||
|
||||
twa_graph_ptr
|
||||
cosimulation(const const_twa_graph_ptr& t)
|
||||
cosimulation(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
return wrap_simul([](const const_twa_graph_ptr& t) {
|
||||
direct_simulation<true, false> simul(t);
|
||||
return simul.run();
|
||||
}, t);
|
||||
return wrap_simul([](const const_twa_graph_ptr& t, int trans_pruning) {
|
||||
direct_simulation<true, false> simul(t, trans_pruning);
|
||||
return simul.run();
|
||||
}, t, trans_pruning);
|
||||
}
|
||||
|
||||
twa_graph_ptr
|
||||
cosimulation_sba(const const_twa_graph_ptr& t)
|
||||
cosimulation_sba(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
return wrap_simul([](const const_twa_graph_ptr& t) {
|
||||
direct_simulation<true, true> simul(t);
|
||||
return simul.run();
|
||||
}, t);
|
||||
return wrap_simul([](const const_twa_graph_ptr& t, int trans_pruning) {
|
||||
direct_simulation<true, true> simul(t, trans_pruning);
|
||||
return simul.run();
|
||||
}, t, trans_pruning);
|
||||
}
|
||||
|
||||
|
||||
template<bool Sba>
|
||||
twa_graph_ptr
|
||||
iterated_simulations_(const const_twa_graph_ptr& t)
|
||||
iterated_simulations_(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
twa_graph_ptr res = nullptr;
|
||||
automaton_size prev;
|
||||
|
|
@ -943,12 +951,12 @@ namespace spot
|
|||
do
|
||||
{
|
||||
prev = next;
|
||||
direct_simulation<false, Sba> simul(res ? res : t);
|
||||
direct_simulation<false, Sba> simul(res ? res : t, trans_pruning);
|
||||
res = simul.run();
|
||||
if (res->prop_universal())
|
||||
break;
|
||||
|
||||
direct_simulation<true, Sba> cosimul(res);
|
||||
direct_simulation<true, Sba> cosimul(res, trans_pruning);
|
||||
res = cosimul.run();
|
||||
|
||||
if (Sba)
|
||||
|
|
@ -963,15 +971,15 @@ namespace spot
|
|||
}
|
||||
|
||||
twa_graph_ptr
|
||||
iterated_simulations(const const_twa_graph_ptr& t)
|
||||
iterated_simulations(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
return wrap_simul(iterated_simulations_<false>, t);
|
||||
return wrap_simul(iterated_simulations_<false>, t, trans_pruning);
|
||||
}
|
||||
|
||||
twa_graph_ptr
|
||||
iterated_simulations_sba(const const_twa_graph_ptr& t)
|
||||
iterated_simulations_sba(const const_twa_graph_ptr& t, int trans_pruning)
|
||||
{
|
||||
return wrap_simul(iterated_simulations_<true>, t);
|
||||
return wrap_simul(iterated_simulations_<true>, t, trans_pruning);
|
||||
}
|
||||
|
||||
template <bool Cosimulation, bool Sba>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2012-2015, 2017, 2019 Laboratoire de Recherche et
|
||||
// Copyright (C) 2012-2015, 2017, 2019, 2021 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -36,7 +36,8 @@ namespace spot
|
|||
/// described in \cite babiak.13.spin .
|
||||
///
|
||||
/// Our reconstruction of the quotient automaton based on this
|
||||
/// suffix-inclusion relation will also improve determinism.
|
||||
/// suffix-inclusion relation will also improve determinism thanks
|
||||
/// to a kind of transition-pruning.
|
||||
///
|
||||
/// We recommend to call scc_filter() to first simplify the
|
||||
/// automaton that should be reduced by simulation.
|
||||
|
|
@ -47,22 +48,33 @@ namespace spot
|
|||
/// acceptance conditions than necessary, and running scc_filter()
|
||||
/// again afterwards will remove these superfluous conditions.
|
||||
///
|
||||
/// The resulting automaton has a named property "simulated-states", that is a
|
||||
/// vector mapping each state of the input to a state of the output. Note that
|
||||
/// some input states may be mapped to -1, as a by-product of improved
|
||||
/// determinism. Typically, if the language of q1 is included in the language
|
||||
/// of q2, only a transition to q2 will be built.
|
||||
///
|
||||
/// The resulting automaton has a named property "simulated-states",
|
||||
/// that is a vector mapping each state of the input to a state of
|
||||
/// the output. Note that some input states may be mapped to -1, as
|
||||
/// a by-product of transition prunning.
|
||||
///
|
||||
/// \param automaton the automaton to simulate.
|
||||
///
|
||||
/// \param trans_pruning Transition pruning requires a quadratic
|
||||
/// number of BDD implication checks between all equivalence
|
||||
/// classes, so it can be costly on large automata. If \a
|
||||
/// trans_pruning is set to a non-negative integer, only
|
||||
/// (non-deterministic) automata with more states than trans_pruning
|
||||
/// will be simplified.
|
||||
///
|
||||
/// \return a new automaton which is at worst a copy of the received
|
||||
/// one
|
||||
SPOT_API twa_graph_ptr
|
||||
simulation(const const_twa_graph_ptr& automaton);
|
||||
simulation(const const_twa_graph_ptr& automaton,
|
||||
int trans_pruning = -1);
|
||||
SPOT_API twa_graph_ptr
|
||||
simulation(const const_twa_graph_ptr& automaton,
|
||||
std::vector<bdd>* implications);
|
||||
std::vector<bdd>* implications,
|
||||
int trans_pruning = -1);
|
||||
SPOT_API twa_graph_ptr
|
||||
simulation_sba(const const_twa_graph_ptr& automaton);
|
||||
simulation_sba(const const_twa_graph_ptr& automaton,
|
||||
int trans_pruning = -1);
|
||||
/// @}
|
||||
|
||||
/// @{
|
||||
|
|
@ -73,7 +85,8 @@ namespace spot
|
|||
/// state can be merged into the latter. \cite babiak.13.spin .
|
||||
///
|
||||
/// Our reconstruction of the quotient automaton based on this
|
||||
/// prefix-inclusion relation will also improve codeterminism.
|
||||
/// prefix-inclusion relation will also improve codeterminism
|
||||
/// thanks to a kind of transition pruning.
|
||||
///
|
||||
/// We recommend to call scc_filter() to first simplify the
|
||||
/// automaton that should be reduced by cosimulation.
|
||||
|
|
@ -93,12 +106,22 @@ namespace spot
|
|||
/// codeterminism.)
|
||||
///
|
||||
/// \param automaton the automaton to simulate.
|
||||
///
|
||||
/// \param trans_pruning Transition pruning requires a quadratic
|
||||
/// number of BDD implication checks between all equivalence
|
||||
/// classes, so it can be costly on large automata. If \a
|
||||
/// trans_pruning is set to a non-negative integer, only
|
||||
/// (non-deterministic) automata with more states than trans_pruning
|
||||
/// will be simplified.
|
||||
///
|
||||
/// \return a new automaton which is at worst a copy of the received
|
||||
/// one
|
||||
SPOT_API twa_graph_ptr
|
||||
cosimulation(const const_twa_graph_ptr& automaton);
|
||||
cosimulation(const const_twa_graph_ptr& automaton,
|
||||
int trans_pruning = -1);
|
||||
SPOT_API twa_graph_ptr
|
||||
cosimulation_sba(const const_twa_graph_ptr& automaton);
|
||||
cosimulation_sba(const const_twa_graph_ptr& automaton,
|
||||
int trans_pruning = -1);
|
||||
/// @}
|
||||
|
||||
/// @{
|
||||
|
|
@ -117,9 +140,11 @@ namespace spot
|
|||
/// \return a new automaton which is at worst a copy of the received
|
||||
/// one
|
||||
SPOT_API twa_graph_ptr
|
||||
iterated_simulations(const const_twa_graph_ptr& automaton);
|
||||
iterated_simulations(const const_twa_graph_ptr& automaton,
|
||||
int trans_pruning = -1);
|
||||
SPOT_API twa_graph_ptr
|
||||
iterated_simulations_sba(const const_twa_graph_ptr& automaton);
|
||||
iterated_simulations_sba(const const_twa_graph_ptr& automaton,
|
||||
int trans_pruning = -1);
|
||||
/// @}
|
||||
|
||||
/// @{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue