twaalgos: add a match_states variant with a formula argument
This is related to issue #591, reported by Blake C. Rawlings. * spot/twaalgos/ltl2tgba_fm.cc, spot/twaalgos/ltl2tgba_fm.hh (ltl_to_tgba_fm): Add option to keep LTL labels. * spot/twaalgos/matchstates.cc, spot/twaalgos/matchstates.hh (match_states): Add variant with a formula as second argument. * tests/python/matchstates.py: Test it. * NEWS: Mention it. * THANKS: Add reporter.
This commit is contained in:
parent
5f1d00b858
commit
3d3e87948c
7 changed files with 89 additions and 4 deletions
6
NEWS
6
NEWS
|
|
@ -62,6 +62,12 @@ New in spot 2.12.0.dev (not yet released)
|
||||||
and B accept the same language, any word accepted by A from state
|
and B accept the same language, any word accepted by A from state
|
||||||
x can be accepted in B from some state in V[x].
|
x can be accepted in B from some state in V[x].
|
||||||
|
|
||||||
|
That function also has a variant spot::match_states(A, f) where f
|
||||||
|
is an LTL formula. In this case it returns and array of
|
||||||
|
formulas. If f represents a superset of the language of A, then
|
||||||
|
any word accepted by A from state x satisfies V[x]. Related to
|
||||||
|
Issue #591.
|
||||||
|
|
||||||
Bug fixes:
|
Bug fixes:
|
||||||
|
|
||||||
- Generating random formulas without any unary opertor would very
|
- Generating random formulas without any unary opertor would very
|
||||||
|
|
|
||||||
1
THANKS
1
THANKS
|
|
@ -5,6 +5,7 @@ Andreas Tollkötter
|
||||||
Andrew Wells
|
Andrew Wells
|
||||||
Anton Pirogov
|
Anton Pirogov
|
||||||
Ayrat Khalimov
|
Ayrat Khalimov
|
||||||
|
Blake C. Rawlings
|
||||||
Cambridge Yang
|
Cambridge Yang
|
||||||
Caroline Lemieux
|
Caroline Lemieux
|
||||||
Christian Dax
|
Christian Dax
|
||||||
|
|
|
||||||
|
|
@ -1887,7 +1887,7 @@ namespace spot
|
||||||
bool exprop, bool symb_merge, bool branching_postponement,
|
bool exprop, bool symb_merge, bool branching_postponement,
|
||||||
bool fair_loop_approx, const atomic_prop_set* unobs,
|
bool fair_loop_approx, const atomic_prop_set* unobs,
|
||||||
tl_simplifier* simplifier, bool unambiguous,
|
tl_simplifier* simplifier, bool unambiguous,
|
||||||
const output_aborter* aborter)
|
const output_aborter* aborter, bool label_with_ltl)
|
||||||
{
|
{
|
||||||
tl_simplifier* s = simplifier;
|
tl_simplifier* s = simplifier;
|
||||||
|
|
||||||
|
|
@ -2216,8 +2216,9 @@ namespace spot
|
||||||
if (orig_f.is_syntactic_guarantee())
|
if (orig_f.is_syntactic_guarantee())
|
||||||
a->prop_terminal(true);
|
a->prop_terminal(true);
|
||||||
}
|
}
|
||||||
// Set the following to true to preserve state names.
|
|
||||||
a->release_formula_namer(namer, false);
|
// This gives each state a name of label_with_ltl is set.
|
||||||
|
a->release_formula_namer(namer, label_with_ltl);
|
||||||
|
|
||||||
if (!simplifier)
|
if (!simplifier)
|
||||||
// This should not be deleted before we have registered all propositions.
|
// This should not be deleted before we have registered all propositions.
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,10 @@ namespace spot
|
||||||
/// constructed automaton would become larger than specified by the
|
/// constructed automaton would become larger than specified by the
|
||||||
/// output_aborter.
|
/// output_aborter.
|
||||||
///
|
///
|
||||||
|
/// \param label_with_ltl keep one LTL formula equivalent the
|
||||||
|
/// language recognized by each state, and use that to name each
|
||||||
|
/// state.
|
||||||
|
///
|
||||||
/// \return A spot::twa_graph that recognizes the language of \a f.
|
/// \return A spot::twa_graph that recognizes the language of \a f.
|
||||||
SPOT_API twa_graph_ptr
|
SPOT_API twa_graph_ptr
|
||||||
ltl_to_tgba_fm(formula f, const bdd_dict_ptr& dict,
|
ltl_to_tgba_fm(formula f, const bdd_dict_ptr& dict,
|
||||||
|
|
@ -83,5 +87,6 @@ namespace spot
|
||||||
const atomic_prop_set* unobs = nullptr,
|
const atomic_prop_set* unobs = nullptr,
|
||||||
tl_simplifier* simplifier = nullptr,
|
tl_simplifier* simplifier = nullptr,
|
||||||
bool unambiguous = false,
|
bool unambiguous = false,
|
||||||
const output_aborter* aborter = nullptr);
|
const output_aborter* aborter = nullptr,
|
||||||
|
bool label_with_ltl = false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
#include <spot/twaalgos/matchstates.hh>
|
#include <spot/twaalgos/matchstates.hh>
|
||||||
#include <spot/twaalgos/sccinfo.hh>
|
#include <spot/twaalgos/sccinfo.hh>
|
||||||
#include <spot/twaalgos/product.hh>
|
#include <spot/twaalgos/product.hh>
|
||||||
|
#include <spot/twaalgos/ltl2tgba_fm.hh>
|
||||||
|
#include <spot/tl/parse.hh>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -45,6 +47,43 @@ namespace spot
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<formula>
|
||||||
|
match_states(const const_twa_graph_ptr& aut1, formula f)
|
||||||
|
{
|
||||||
|
twa_graph_ptr aut2 = ltl_to_tgba_fm(f, aut1->get_dict(),
|
||||||
|
false /* exprop */,
|
||||||
|
true /* symbolic merge */,
|
||||||
|
false /* branching postponement */,
|
||||||
|
false /* fair loop approx. */,
|
||||||
|
nullptr /* unobs event */,
|
||||||
|
nullptr /* simplifier */,
|
||||||
|
false /* unambiguous */,
|
||||||
|
nullptr /* aborter */,
|
||||||
|
true /* label with LTL */);
|
||||||
|
auto state_names =
|
||||||
|
aut2->get_named_prop<std::vector<std::string>>("state-names");
|
||||||
|
auto v = match_states(aut1, aut2);
|
||||||
|
unsigned sz1 = aut1->num_states();
|
||||||
|
unsigned sz2 = aut2->num_states();
|
||||||
|
|
||||||
|
// State are labeled with strings, but we know those strings to
|
||||||
|
// represent LTL formulas, so convert those.
|
||||||
|
std::vector<formula> state_formulas;
|
||||||
|
state_formulas.reserve(sz2);
|
||||||
|
for (unsigned i = 0; i < sz2; ++i)
|
||||||
|
state_formulas.push_back(parse_formula((*state_names)[i]));
|
||||||
|
|
||||||
|
std::vector<formula> res;
|
||||||
|
res.reserve(sz1);
|
||||||
|
|
||||||
|
std::vector<formula> disjuncts;
|
||||||
|
for (unsigned i = 0; i < sz1; ++i)
|
||||||
|
{
|
||||||
|
disjuncts.clear();
|
||||||
|
for (unsigned j: v[i])
|
||||||
|
disjuncts.push_back(state_formulas[j]);
|
||||||
|
res.push_back(formula::Or(disjuncts));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <spot/misc/common.hh>
|
#include <spot/misc/common.hh>
|
||||||
#include <spot/twa/fwd.hh>
|
#include <spot/twa/fwd.hh>
|
||||||
|
#include <spot/tl/formula.hh>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
|
|
@ -37,4 +38,21 @@ namespace spot
|
||||||
SPOT_API std::vector<std::vector<unsigned>>
|
SPOT_API std::vector<std::vector<unsigned>>
|
||||||
match_states(const const_twa_graph_ptr& aut1,
|
match_states(const const_twa_graph_ptr& aut1,
|
||||||
const const_twa_graph_ptr& aut2);
|
const const_twa_graph_ptr& aut2);
|
||||||
|
|
||||||
|
/// \ingroup twa_algorithms \brief match the states of \a aut with
|
||||||
|
/// formulas "reachable" from \a f.
|
||||||
|
///
|
||||||
|
/// The returned vector V assigns each state `x` of \a aut to a
|
||||||
|
/// formula `V[x]`.
|
||||||
|
///
|
||||||
|
/// This translates \a f as an automaton B in which states are labeled
|
||||||
|
/// by formulas, match the states of \a aut with the states of B, and
|
||||||
|
/// use that to find formulas associated to each state of \a aut.
|
||||||
|
///
|
||||||
|
/// In particular, if the language of \a f is a superset of the
|
||||||
|
/// language of \a aut, then every word accepted in \a aut from
|
||||||
|
/// state `x` will satisfy formula `V[x]`. However `V[x]` may
|
||||||
|
/// accept more than the words accepted from `a` in \a aut.
|
||||||
|
SPOT_API std::vector<formula>
|
||||||
|
match_states(const const_twa_graph_ptr& aut, formula f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,3 +60,18 @@ m3 = spot.match_states(a, c)
|
||||||
tc.assertEqual(m3, ((), (), (), ()))
|
tc.assertEqual(m3, ((), (), (), ()))
|
||||||
m4 = spot.match_states(c, a)
|
m4 = spot.match_states(c, a)
|
||||||
tc.assertEqual(m4, ((), ))
|
tc.assertEqual(m4, ((), ))
|
||||||
|
|
||||||
|
f = spot.formula("Ga | Gb | Gc")
|
||||||
|
m5 = spot.match_states(a, f)
|
||||||
|
tc.assertEqual(m5, (f, f, f, f))
|
||||||
|
m6 = spot.match_states(b, f)
|
||||||
|
tc.assertEqual(m6, (spot.formula("Gc"),
|
||||||
|
spot.formula("Gb | Gc"),
|
||||||
|
spot.formula("Gb"),
|
||||||
|
spot.formula("Ga"),
|
||||||
|
spot.formula("Ga | Gc"),
|
||||||
|
spot.formula("Ga | Gb"),
|
||||||
|
spot.formula("Ga | Gb | Gc")))
|
||||||
|
|
||||||
|
m7 = spot.match_states(c, f) # Note that f is not the formula for c
|
||||||
|
tc.assertEqual(m7, (spot.formula("0"),))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue