Store membership to acceptance sets using bitsets, not BDDs.
This is a huge patch, that took over a month to complete. The bit sets are currently restricted to what 'unsigned can store', but it should be easy to extend it to 'uint64_t' should we need it. * NEWS: Update. * src/tgba/acc.hh: New file. * src/tgbatest/acc.cc, src/tgbatest/acc.test: Test it. * src/tgba/tgbakvcomplement.cc, src/tgba/tgbakvcomplement.hh, src/tgba/tgbasgba.cc, src/tgba/tgbasgba.hh: Delete. The KV complementation is too slow to be used in practice, and I somehow broke it during the conversion to bitsets. The tgba->sgba conversion was only used for the KV complementation, and should be better redone on tgba_digraph_ptr should it be needed again. * src/bin/ltlcross.cc, src/dstarparse/dra2ba.cc, src/dstarparse/nsa2tgba.cc, src/graphtest/tgbagraph.cc, src/graphtest/tgbagraph.test, src/kripke/fairkripke.cc, src/kripke/fairkripke.hh, src/kripke/kripke.cc, src/kripke/kripke.hh, src/kripke/kripkeexplicit.cc, src/kripke/kripkeexplicit.hh, src/misc/hash.hh, src/neverparse/neverclaimparse.yy, src/priv/accmap.hh, src/ta/ta.cc, src/ta/ta.hh, src/ta/taexplicit.cc, src/ta/taexplicit.hh, src/ta/taproduct.cc, src/ta/taproduct.hh, src/ta/tgta.cc, src/ta/tgta.hh, src/ta/tgtaexplicit.cc, src/ta/tgtaexplicit.hh, src/ta/tgtaproduct.cc, src/ta/tgtaproduct.hh, src/taalgos/dotty.cc, src/taalgos/emptinessta.cc, src/taalgos/minimize.cc, src/taalgos/tgba2ta.cc, src/tgba/Makefile.am, src/tgba/fwd.hh, src/tgba/taatgba.cc, src/tgba/taatgba.hh, src/tgba/tgba.cc, src/tgba/tgba.hh, src/tgba/tgbagraph.cc, src/tgba/tgbagraph.hh, src/tgba/tgbamask.cc, src/tgba/tgbamask.hh, src/tgba/tgbaproduct.cc, src/tgba/tgbaproduct.hh, src/tgba/tgbaproxy.cc, src/tgba/tgbaproxy.hh, src/tgba/tgbasafracomplement.cc, src/tgba/tgbasafracomplement.hh, src/tgbaalgos/bfssteps.cc, src/tgbaalgos/complete.cc, src/tgbaalgos/compsusp.cc, src/tgbaalgos/degen.cc, src/tgbaalgos/dotty.cc, src/tgbaalgos/dtbasat.cc, src/tgbaalgos/dtgbacomp.cc, src/tgbaalgos/dtgbasat.cc, src/tgbaalgos/dupexp.cc, src/tgbaalgos/emptiness.cc, src/tgbaalgos/emptiness.hh, src/tgbaalgos/gtec/ce.cc, src/tgbaalgos/gtec/gtec.cc, src/tgbaalgos/gtec/gtec.hh, src/tgbaalgos/gtec/sccstack.cc, src/tgbaalgos/gtec/sccstack.hh, src/tgbaalgos/gv04.cc, src/tgbaalgos/hoaf.cc, src/tgbaalgos/isweakscc.cc, src/tgbaalgos/lbtt.cc, src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/magic.cc, src/tgbaalgos/ndfs_result.hxx, src/tgbaalgos/neverclaim.cc, src/tgbaalgos/postproc.cc, src/tgbaalgos/powerset.cc, src/tgbaalgos/randomgraph.cc, src/tgbaalgos/randomgraph.hh, src/tgbaalgos/reducerun.cc, src/tgbaalgos/replayrun.cc, src/tgbaalgos/safety.cc, src/tgbaalgos/save.cc, src/tgbaalgos/scc.cc, src/tgbaalgos/scc.hh, src/tgbaalgos/sccfilter.cc, src/tgbaalgos/sccinfo.cc, src/tgbaalgos/sccinfo.hh, src/tgbaalgos/se05.cc, src/tgbaalgos/simulation.cc, src/tgbaalgos/simulation.hh, src/tgbaalgos/stats.cc, src/tgbaalgos/stripacc.cc, src/tgbaalgos/tau03.cc, src/tgbaalgos/tau03opt.cc, src/tgbaalgos/weight.cc, src/tgbaalgos/weight.hh, src/tgbaparse/tgbaparse.yy, src/tgbatest/Makefile.am, src/tgbatest/complementation.cc, src/tgbatest/complementation.test, src/tgbatest/degenlskip.test, src/tgbatest/det.test, src/tgbatest/dstar.test, src/tgbatest/emptchk.cc, src/tgbatest/explpro2.test, src/tgbatest/explpro3.test, src/tgbatest/explpro4.test, src/tgbatest/explprod.test, src/tgbatest/ltl2tgba.cc, src/tgbatest/ltl2tgba.test, src/tgbatest/maskacc.cc, src/tgbatest/maskacc.test, src/tgbatest/neverclaimread.test, src/tgbatest/randtgba.cc, src/tgbatest/readsave.test, src/tgbatest/sim.test, src/tgbatest/sim2.test, src/tgbatest/spotlbtt.test, src/tgbatest/tgbaread.test, src/tgbatest/tripprod.test, iface/dve2/dve2.cc: Adjust or use to the new acceptance interface.
This commit is contained in:
parent
37ece2b878
commit
2c764fb3c7
125 changed files with 1950 additions and 3254 deletions
38
NEWS
38
NEWS
|
|
@ -56,12 +56,35 @@ New in spot 1.99a (not yet released)
|
|||
|
||||
Where the virtual calls to done() and delete have been avoided.
|
||||
|
||||
- tgba::support_variables() and tgba::compute_support_variables()
|
||||
- tgba::succ_iter() now takes only one argument. The optional
|
||||
global_state and global_automaton arguments have been removed.
|
||||
|
||||
- The following methods have been removed from the TGBA interface and
|
||||
all their subclasses:
|
||||
- tgba::support_variables()
|
||||
- tgba::compute_support_variables()
|
||||
- tgba::all_acceptance_conditions() // use acc().accepting(...)
|
||||
- tgba::neg_acceptance_conditions()
|
||||
- tgba::number_of_acceptance_conditions() // use acc().num_sets()
|
||||
methods have been removed from the TGBA interface and all
|
||||
subclasses.
|
||||
|
||||
- tgba::succ_iter() now takes only one argument. The optional
|
||||
global_state and global_automaton arguments have been removed.
|
||||
- Membership to acceptance sets are now stored using bit sets,
|
||||
currently limited to 32 bits. Each TGBA has a acc() method that
|
||||
returns a reference to an acceptance object (of type
|
||||
spot::acc_cond), able to operate on acceptance marks
|
||||
(spot::acc_cond::mark_t).
|
||||
|
||||
Instead of writing
|
||||
i->current_acceptance_conditions() == aut->all_acceptance_conditions()
|
||||
we now write
|
||||
aut->acc().accepting(i->current_acceptance_conditions())
|
||||
|
||||
Similarly,
|
||||
aut->number_of_acceptance_conditions()
|
||||
is now
|
||||
aut->acc().num_sets()
|
||||
|
||||
|
||||
* Removed features
|
||||
|
||||
|
|
@ -87,6 +110,15 @@ New in spot 1.99a (not yet released)
|
|||
automata (when viewed explictely), using the above and non
|
||||
longuer supported tgba_bdd_concrete class.
|
||||
|
||||
- Our implementation of the Kupferman-Vardi complementation has
|
||||
been removed: it was useless in practice beause of the size of
|
||||
the automata built, and it did not survive the conversion of
|
||||
acceptance sets from BDDs to bitsets.
|
||||
|
||||
- Conversion from TGBA to state-based Generalized Büchi automata
|
||||
has been removed too, because it was only used by the KV
|
||||
complementation.
|
||||
|
||||
New in spot 1.2.5a (not yet released)
|
||||
|
||||
* New features:
|
||||
|
|
|
|||
|
|
@ -606,7 +606,8 @@ namespace spot
|
|||
|
||||
dve2_kripke(const dve2_interface* d, const bdd_dict_ptr& dict,
|
||||
const prop_set* ps, const ltl::formula* dead, int compress)
|
||||
: d_(d),
|
||||
: kripke(dict),
|
||||
d_(d),
|
||||
state_size_(d_->get_state_variable_count()),
|
||||
dict_(dict), ps_(ps),
|
||||
compress_(compress == 0 ? 0
|
||||
|
|
|
|||
|
|
@ -1047,7 +1047,7 @@ namespace
|
|||
st->states = s.states;
|
||||
st->edges = s.transitions;
|
||||
st->transitions = s.sub_transitions;
|
||||
st->acc = res->number_of_acceptance_conditions();
|
||||
st->acc = res->acc().num_sets();
|
||||
spot::scc_map m(res);
|
||||
m.build_map();
|
||||
unsigned c = m.scc_count();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "tgbaalgos/reachiter.hh"
|
||||
#include "tgbaalgos/gtec/gtec.hh"
|
||||
#include "tgbaalgos/sccfilter.hh"
|
||||
#include "tgbaalgos/dotty.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -55,7 +56,7 @@ namespace spot
|
|||
{
|
||||
typedef std::list<const state*> state_list;
|
||||
|
||||
// The function that takes aut and dra is first arguments are
|
||||
// The functions that take aut and dra as first arguments are
|
||||
// either called on the main automaton, in which case dra->aut ==
|
||||
// aut, or it is called on a sub-automaton in which case aut is a
|
||||
// masked version of dra->aut. So we should always explore the
|
||||
|
|
@ -293,7 +294,7 @@ namespace spot
|
|||
tgba_digraph_ptr out_;
|
||||
const state_set& final_;
|
||||
size_t num_states_;
|
||||
bdd acc_;
|
||||
acc_cond::mark_t acc_;
|
||||
const scc_map& sm_;
|
||||
const std::vector<bool>& realizable_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ namespace spot
|
|||
for (auto& t: a->out(s.s))
|
||||
{
|
||||
bitvect* pend = 0;
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
if (s.pend)
|
||||
{
|
||||
pend = s.pend->clone();
|
||||
|
|
|
|||
|
|
@ -35,21 +35,20 @@ void f1()
|
|||
auto* f2 = e.require("p2");
|
||||
bdd p1 = bdd_ithvar(d->register_proposition(f1, tg));
|
||||
bdd p2 = bdd_ithvar(d->register_proposition(f2, tg));
|
||||
bdd a1 = bdd_ithvar(d->register_acceptance_variable(f1, tg));
|
||||
bdd a2 = bdd_ithvar(d->register_acceptance_variable(f2, tg));
|
||||
tg->acc().add_sets(2);
|
||||
f1->destroy();
|
||||
f2->destroy();
|
||||
|
||||
auto s1 = tg->new_state();
|
||||
auto s2 = tg->new_state();
|
||||
auto s3 = tg->new_state();
|
||||
tg->new_transition(s1, s1, bddfalse, bddfalse);
|
||||
tg->new_transition(s1, s2, p1, bddfalse);
|
||||
tg->new_transition(s1, s3, p2, (!a1) & a2);
|
||||
tg->new_transition(s2, s3, p1 & p2, a1 & !a2);
|
||||
tg->new_transition(s3, s1, p1 | p2, ((!a1) & a2) | (a1 & !a2));
|
||||
tg->new_transition(s3, s2, p1 >> p2, bddfalse);
|
||||
tg->new_transition(s3, s3, bddtrue, ((!a1) & a2) | (a1 & !a2));
|
||||
tg->new_transition(s1, s1, bddfalse, 0U);
|
||||
tg->new_transition(s1, s2, p1, 0U);
|
||||
tg->new_transition(s1, s3, p2, tg->acc().mark(1));
|
||||
tg->new_transition(s2, s3, p1 & p2, tg->acc().mark(0));
|
||||
tg->new_transition(s3, s1, p1 | p2, tg->acc().marks({0, 1}));
|
||||
tg->new_transition(s3, s2, p1 >> p2, 0U);
|
||||
tg->new_transition(s3, s3, bddtrue, tg->acc().marks({0, 1}));
|
||||
|
||||
spot::dotty_reachable(std::cout, tg);
|
||||
|
||||
|
|
@ -69,9 +68,10 @@ void f1()
|
|||
spot::dotty_reachable(std::cout, tg);
|
||||
}
|
||||
|
||||
tg->new_transition(s3, s1, p1 | p2, ((!a1) & a2) | (a1 & !a2));
|
||||
tg->new_transition(s3, s2, p1 >> p2, bddfalse);
|
||||
tg->new_transition(s3, s1, bddtrue, ((!a1) & a2) | (a1 & !a2));
|
||||
auto all = tg->acc().marks({0, 1});
|
||||
tg->new_transition(s3, s1, p1 | p2, all);
|
||||
tg->new_transition(s3, s2, p1 >> p2, 0U);
|
||||
tg->new_transition(s3, s1, bddtrue, all);
|
||||
|
||||
std::cerr << tg->num_transitions() << '\n';
|
||||
assert(tg->num_transitions() == 7);
|
||||
|
|
|
|||
|
|
@ -37,76 +37,76 @@ digraph G {
|
|||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 1 [label="0\n"]
|
||||
1 -> 2 [label="p1\n"]
|
||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
||||
1 -> 1 [label="0"]
|
||||
1 -> 2 [label="p1"]
|
||||
1 -> 3 [label="p2\n{1}"]
|
||||
2 [label="1"]
|
||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
||||
2 -> 3 [label="p1 & p2\n{0}"]
|
||||
3 [label="2"]
|
||||
3 -> 1 [label="p1 | p2\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 2 [label="!p1 | p2\n"]
|
||||
3 -> 3 [label="1\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 1 [label="p1 | p2\n{0,1}"]
|
||||
3 -> 2 [label="!p1 | p2"]
|
||||
3 -> 3 [label="1\n{0,1}"]
|
||||
}
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 1 [label="0\n"]
|
||||
1 -> 2 [label="p1\n"]
|
||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
||||
1 -> 1 [label="0"]
|
||||
1 -> 2 [label="p1"]
|
||||
1 -> 3 [label="p2\n{1}"]
|
||||
2 [label="1"]
|
||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
||||
2 -> 3 [label="p1 & p2\n{0}"]
|
||||
3 [label="2"]
|
||||
3 -> 1 [label="p1 | p2\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 1 [label="p1 | p2\n{0,1}"]
|
||||
}
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 1 [label="0\n"]
|
||||
1 -> 2 [label="p1\n"]
|
||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
||||
1 -> 1 [label="0"]
|
||||
1 -> 2 [label="p1"]
|
||||
1 -> 3 [label="p2\n{1}"]
|
||||
2 [label="1"]
|
||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
||||
2 -> 3 [label="p1 & p2\n{0}"]
|
||||
3 [label="2"]
|
||||
}
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 1 [label="0\n"]
|
||||
1 -> 2 [label="p1\n"]
|
||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
||||
1 -> 1 [label="0"]
|
||||
1 -> 2 [label="p1"]
|
||||
1 -> 3 [label="p2\n{1}"]
|
||||
2 [label="1"]
|
||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
||||
2 -> 3 [label="p1 & p2\n{0}"]
|
||||
3 [label="2"]
|
||||
3 -> 1 [label="p1 | p2\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 2 [label="!p1 | p2\n"]
|
||||
3 -> 1 [label="1\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 1 [label="p1 | p2\n{0,1}"]
|
||||
3 -> 2 [label="!p1 | p2"]
|
||||
3 -> 1 [label="1\n{0,1}"]
|
||||
}
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 2 [label="p1\n"]
|
||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
||||
1 -> 2 [label="p1"]
|
||||
1 -> 3 [label="p2\n{1}"]
|
||||
2 [label="1"]
|
||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
||||
2 -> 3 [label="p1 & p2\n{0}"]
|
||||
3 [label="2"]
|
||||
3 -> 1 [label="1\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 2 [label="!p1 | p2\n"]
|
||||
3 -> 1 [label="1\n{0,1}"]
|
||||
3 -> 2 [label="!p1 | p2"]
|
||||
}
|
||||
digraph G {
|
||||
0 [label="", style=invis, height=0]
|
||||
0 -> 1
|
||||
1 [label="0"]
|
||||
1 -> 2 [label="p1\n"]
|
||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
||||
1 -> 2 [label="p1"]
|
||||
1 -> 3 [label="p2\n{1}"]
|
||||
2 [label="1"]
|
||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
||||
2 -> 3 [label="p1 & p2\n{0}"]
|
||||
3 [label="2"]
|
||||
3 -> 1 [label="1\n{Acc[p2], Acc[p1]}"]
|
||||
3 -> 2 [label="!p1 | p2\n"]
|
||||
3 -> 1 [label="1\n{0,1}"]
|
||||
3 -> 2 [label="!p1 | p2"]
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
namespace spot
|
||||
{
|
||||
|
||||
fair_kripke_succ_iterator::fair_kripke_succ_iterator(const bdd& cond,
|
||||
const bdd& acc_cond)
|
||||
fair_kripke_succ_iterator::fair_kripke_succ_iterator
|
||||
(const bdd& cond, acc_cond::mark_t acc_cond)
|
||||
: cond_(cond), acc_cond_(acc_cond)
|
||||
{
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ namespace spot
|
|||
return cond_;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
fair_kripke_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
// Do not assert(!done()) here. It is OK to call
|
||||
|
|
|
|||
|
|
@ -52,14 +52,14 @@ namespace spot
|
|||
/// The \a cond and \a acc_cond arguments will be those returned
|
||||
/// by fair_kripke_succ_iterator::current_condition(),
|
||||
/// and fair_kripke_succ_iterator::current_acceptance_conditions().
|
||||
fair_kripke_succ_iterator(const bdd& cond, const bdd& acc_cond);
|
||||
fair_kripke_succ_iterator(const bdd& cond, acc_cond::mark_t acc_cond);
|
||||
virtual ~fair_kripke_succ_iterator();
|
||||
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||
protected:
|
||||
bdd cond_;
|
||||
bdd acc_cond_;
|
||||
acc_cond::mark_t acc_cond_;
|
||||
};
|
||||
|
||||
/// \ingroup kripke
|
||||
|
|
@ -86,16 +86,22 @@ namespace spot
|
|||
/// class and need not be defined.
|
||||
///
|
||||
/// See also spot::fair_kripke_succ_iterator.
|
||||
class SPOT_API fair_kripke : public tgba
|
||||
class SPOT_API fair_kripke: public tgba
|
||||
{
|
||||
public:
|
||||
fair_kripke(const bdd_dict_ptr& d)
|
||||
: tgba(d)
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief The condition that label the state \a s.
|
||||
///
|
||||
/// This should be a conjunction of atomic propositions.
|
||||
virtual bdd state_condition(const state* s) const = 0;
|
||||
|
||||
/// \brief The set of acceptance conditions that label the state \a s.
|
||||
virtual bdd state_acceptance_conditions(const state* s) const = 0;
|
||||
virtual acc_cond::mark_t
|
||||
state_acceptance_conditions(const state* s) const = 0;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* s) const;
|
||||
|
|
|
|||
|
|
@ -34,33 +34,21 @@ namespace spot
|
|||
return cond_;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
kripke_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
// Do not assert(!done()) here. It is OK to call
|
||||
// this function on a state without successor.
|
||||
return bddfalse;
|
||||
return 0U;
|
||||
}
|
||||
|
||||
kripke::~kripke()
|
||||
{
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
kripke::state_acceptance_conditions(const state*) const
|
||||
{
|
||||
return bddtrue;
|
||||
return 0U;
|
||||
}
|
||||
|
||||
bdd kripke::all_acceptance_conditions() const
|
||||
{
|
||||
// There is no acceptance conditions.
|
||||
return bddfalse;
|
||||
}
|
||||
|
||||
bdd kripke::neg_acceptance_conditions() const
|
||||
{
|
||||
return bddtrue;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace spot
|
|||
virtual ~kripke_succ_iterator();
|
||||
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||
protected:
|
||||
bdd cond_;
|
||||
};
|
||||
|
|
@ -92,11 +92,15 @@ namespace spot
|
|||
class SPOT_API kripke: public fair_kripke
|
||||
{
|
||||
public:
|
||||
kripke(const bdd_dict_ptr& d)
|
||||
: fair_kripke(d)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~kripke();
|
||||
|
||||
virtual bdd state_acceptance_conditions(const state*) const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t state_acceptance_conditions(const state*) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ namespace spot
|
|||
|
||||
kripke_explicit::kripke_explicit(const bdd_dict_ptr& dict,
|
||||
state_kripke* init)
|
||||
: dict_(dict),
|
||||
init_ (init)
|
||||
: kripke(dict),
|
||||
init_(init)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ namespace spot
|
|||
|
||||
kripke_explicit::~kripke_explicit()
|
||||
{
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
std::map<const std::string, state_kripke*>::iterator it;
|
||||
for (it = ns_nodes_.begin(); it != ns_nodes_.end(); ++it)
|
||||
{
|
||||
|
|
@ -163,12 +163,6 @@ namespace spot
|
|||
return init_;
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
kripke_explicit::get_dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
// FIXME: Change the bddtrue.
|
||||
kripke_explicit_succ_iterator*
|
||||
kripke_explicit::succ_iter(const spot::state* st) const
|
||||
|
|
@ -269,7 +263,7 @@ namespace spot
|
|||
void kripke_explicit::add_condition(const ltl::formula* f,
|
||||
std::string on_me)
|
||||
{
|
||||
add_conditions(formula_to_bdd(f, dict_, this), on_me);
|
||||
add_conditions(formula_to_bdd(f, get_dict(), this), on_me);
|
||||
f->destroy();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,6 @@ namespace spot
|
|||
kripke_explicit(const bdd_dict_ptr&, state_kripke* = nullptr);
|
||||
~kripke_explicit();
|
||||
|
||||
bdd_dict_ptr get_dict() const;
|
||||
state_kripke* get_init_state() const;
|
||||
|
||||
/// \brief Allow to get an iterator on the state we passed in
|
||||
|
|
@ -174,7 +173,6 @@ namespace spot
|
|||
void add_transition(state_kripke* source,
|
||||
const state_kripke* dest);
|
||||
|
||||
bdd_dict_ptr dict_;
|
||||
state_kripke* init_;
|
||||
std::map<const std::string, state_kripke*> ns_nodes_;
|
||||
std::map<const state_kripke*, std::string> sn_nodes_;
|
||||
|
|
|
|||
|
|
@ -82,8 +82,11 @@ namespace spot
|
|||
template<typename T, typename U>
|
||||
std::size_t operator()(const std::pair<T, U> &p) const
|
||||
{
|
||||
return wang32_hash(static_cast<size_t>(p.first) ^
|
||||
static_cast<size_t>(p.second));
|
||||
std::hash<T> th;
|
||||
std::hash<U> uh;
|
||||
|
||||
return wang32_hash(static_cast<size_t>(th(p.first)) ^
|
||||
static_cast<size_t>(uh(p.second)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -169,17 +169,16 @@ state:
|
|||
|
||||
namer->new_transition(*$1, *$1, bddtrue,
|
||||
!strncmp("accept", $1->c_str(), 6) ?
|
||||
result->all_acceptance_conditions() :
|
||||
static_cast<const bdd>(bddfalse));
|
||||
result->acc().all_sets() :
|
||||
spot::acc_cond::mark_t(0U));
|
||||
delete $1;
|
||||
}
|
||||
| ident_list { delete $1; }
|
||||
| ident_list "false" { delete $1; }
|
||||
| ident_list transition_block
|
||||
{
|
||||
bdd acc = !strncmp("accept", $1->c_str(), 6) ?
|
||||
result->all_acceptance_conditions() :
|
||||
static_cast<const bdd>(bddfalse);
|
||||
auto acc = !strncmp("accept", $1->c_str(), 6) ?
|
||||
result->acc().all_sets() : spot::acc_cond::mark_t(0U);
|
||||
for (auto& p: *$2)
|
||||
namer->new_transition(*$1, *p.second, *p.first, acc);
|
||||
// Free the list
|
||||
|
|
|
|||
|
|
@ -34,10 +34,9 @@ namespace spot
|
|||
bdd_dict_ptr dict_;
|
||||
tgba_digraph_ptr aut_;
|
||||
ltl::environment& env_;
|
||||
bdd neg_;
|
||||
|
||||
acc_mapper_common(const tgba_digraph_ptr& aut, ltl::environment& env)
|
||||
: dict_(aut->get_dict()), aut_(aut), env_(env), neg_(bddtrue)
|
||||
: dict_(aut->get_dict()), aut_(aut), env_(env)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -46,17 +45,11 @@ namespace spot
|
|||
{
|
||||
return env_;
|
||||
}
|
||||
|
||||
// Commit all acceptance set to the automaton.
|
||||
void commit()
|
||||
{
|
||||
aut_->set_acceptance_conditions(neg_);
|
||||
}
|
||||
};
|
||||
|
||||
class acc_mapper_string: public acc_mapper_common
|
||||
{
|
||||
std::unordered_map<std::string, int> map_;
|
||||
std::unordered_map<std::string, unsigned> map_;
|
||||
|
||||
public:
|
||||
acc_mapper_string(const tgba_digraph_ptr& aut,
|
||||
|
|
@ -72,24 +65,17 @@ namespace spot
|
|||
auto i = map_.find(name);
|
||||
if (i != map_.end())
|
||||
return true;
|
||||
auto f = env_.require(name);
|
||||
if (!f)
|
||||
return false;
|
||||
int v = dict_->register_acceptance_variable(f, aut_);
|
||||
f->destroy();
|
||||
auto v = aut_->acc().add_set();
|
||||
map_[name] = v;
|
||||
neg_ &= bdd_nithvar(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<bool, bdd> lookup(std::string name) const
|
||||
std::pair<bool, acc_cond::mark_t> lookup(std::string name) const
|
||||
{
|
||||
auto p = map_.find(name);
|
||||
if (p == map_.end())
|
||||
return std::make_pair(false, bddfalse);
|
||||
return std::make_pair(true, bdd_compose(neg_,
|
||||
bdd_nithvar(p->second),
|
||||
p->second));
|
||||
return std::make_pair(false, 0U);
|
||||
return std::make_pair(true, aut_->acc().marks({p->second}));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -97,42 +83,23 @@ namespace spot
|
|||
// The acceptance sets are named using count consecutive integers.
|
||||
class acc_mapper_consecutive_int: public acc_mapper_common
|
||||
{
|
||||
protected:
|
||||
std::vector<bdd> vec_;
|
||||
std::map<int, bdd> map_;
|
||||
|
||||
public:
|
||||
acc_mapper_consecutive_int(const tgba_digraph_ptr& aut,
|
||||
unsigned count,
|
||||
ltl::environment& env =
|
||||
ltl::default_environment::instance())
|
||||
: acc_mapper_common(aut, env), vec_(count)
|
||||
: acc_mapper_common(aut, env)
|
||||
{
|
||||
std::vector<int> vmap(count);
|
||||
for (unsigned n = 0; n < count; ++n)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << n;
|
||||
auto f = env.require(s.str());
|
||||
int v = dict_->register_acceptance_variable(f, aut_);
|
||||
f->destroy();
|
||||
vmap[n] = v;
|
||||
neg_ &= bdd_nithvar(v);
|
||||
}
|
||||
for (unsigned n = 0; n < count; ++n)
|
||||
{
|
||||
int v = vmap[n];
|
||||
vec_[n] = bdd_compose(neg_, bdd_nithvar(v), v);
|
||||
}
|
||||
commit();
|
||||
std::vector<unsigned> vmap(count);
|
||||
aut->acc().add_sets(count);
|
||||
}
|
||||
|
||||
std::pair<bool, bdd> lookup(unsigned n)
|
||||
std::pair<bool, acc_cond::mark_t> lookup(unsigned n)
|
||||
{
|
||||
if (n < vec_.size())
|
||||
return std::make_pair(true, vec_[n]);
|
||||
if (n < aut_->acc().num_sets())
|
||||
return std::make_pair(true, aut_->acc().marks({n}));
|
||||
else
|
||||
return std::make_pair(false, bddfalse);
|
||||
return std::make_pair(false, 0U);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -141,7 +108,7 @@ namespace spot
|
|||
class acc_mapper_int: public acc_mapper_consecutive_int
|
||||
{
|
||||
unsigned used_;
|
||||
std::map<int, bdd> map_;
|
||||
std::map<unsigned, acc_cond::mark_t> map_;
|
||||
|
||||
public:
|
||||
acc_mapper_int(const tgba_digraph_ptr& aut,
|
||||
|
|
@ -152,18 +119,18 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
std::pair<bool, bdd> lookup(unsigned n)
|
||||
std::pair<bool, acc_cond::mark_t> lookup(unsigned n)
|
||||
{
|
||||
auto p = map_.find(n);
|
||||
if (p != map_.end())
|
||||
return std::make_pair(true, p->second);
|
||||
if (used_ < vec_.size())
|
||||
if (used_ < aut_->acc().num_sets())
|
||||
{
|
||||
bdd res = vec_[used_++];
|
||||
auto res = aut_->acc().marks({used_++});
|
||||
map_[n] = res;
|
||||
return std::make_pair(true, res);
|
||||
}
|
||||
return std::make_pair(false, bddfalse);
|
||||
return std::make_pair(false, 0U);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace spot
|
|||
{
|
||||
index = i;
|
||||
is_accepting = false;
|
||||
condition = bddfalse;
|
||||
condition = 0U;
|
||||
}
|
||||
|
||||
scc_stack_ta::connected_component&
|
||||
|
|
|
|||
39
src/ta/ta.hh
39
src/ta/ta.hh
|
|
@ -76,8 +76,15 @@ namespace spot
|
|||
|
||||
class SPOT_API ta
|
||||
{
|
||||
protected:
|
||||
acc_cond acc_;
|
||||
|
||||
public:
|
||||
ta(const bdd_dict_ptr& d)
|
||||
: acc_(d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~ta()
|
||||
{
|
||||
|
|
@ -128,8 +135,11 @@ namespace spot
|
|||
/// This is useful when dealing with several automata (which
|
||||
/// may use the same BDD variable for different formula),
|
||||
/// or simply when printing.
|
||||
virtual bdd_dict_ptr
|
||||
get_dict() const = 0;
|
||||
bdd_dict_ptr
|
||||
get_dict() const
|
||||
{
|
||||
return acc_.get_dict();
|
||||
}
|
||||
|
||||
/// \brief Format the state as a string for printing.
|
||||
///
|
||||
|
|
@ -160,17 +170,16 @@ namespace spot
|
|||
virtual void
|
||||
free_state(const spot::state* s) const = 0;
|
||||
|
||||
/// \brief Return the set of all acceptance conditions used
|
||||
/// by this automaton
|
||||
/// (for Generalized form: Transition-based Generalized Testing Automata).
|
||||
///
|
||||
/// The goal of the emptiness check is to ensure that
|
||||
/// a strongly connected component walks through each
|
||||
/// of these acceptiong conditions. I.e., the union
|
||||
/// of the acceptiong conditions of all transition in
|
||||
/// the SCC should be equal to the result of this function.
|
||||
virtual bdd
|
||||
all_acceptance_conditions() const = 0;
|
||||
|
||||
const acc_cond& acc() const
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
acc_cond& acc()
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -206,7 +215,7 @@ namespace spot
|
|||
virtual bdd
|
||||
current_condition() const = 0;
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
current_acceptance_conditions() const = 0;
|
||||
|
||||
};
|
||||
|
|
@ -228,7 +237,7 @@ namespace spot
|
|||
|
||||
/// The bdd condition is the union of all acceptance conditions of
|
||||
/// transitions which connect the states of the connected component.
|
||||
bdd condition;
|
||||
acc_cond::mark_t condition;
|
||||
|
||||
std::list<state*> rem;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace spot
|
|||
return (*i_)->condition;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
ta_explicit_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
|
|
@ -352,13 +352,14 @@ namespace spot
|
|||
|
||||
|
||||
ta_explicit::ta_explicit(const const_tgba_ptr& tgba,
|
||||
bdd all_acceptance_conditions,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state):
|
||||
ta(tgba->get_dict()),
|
||||
tgba_(tgba),
|
||||
all_acceptance_conditions_(all_acceptance_conditions),
|
||||
artificial_initial_state_(artificial_initial_state)
|
||||
{
|
||||
get_dict()->register_all_variables_of(&tgba_, this);
|
||||
acc().add_sets(n_acc);
|
||||
if (artificial_initial_state != 0)
|
||||
{
|
||||
state_ta_explicit* is = add_state(artificial_initial_state);
|
||||
|
|
@ -403,7 +404,7 @@ namespace spot
|
|||
{
|
||||
state_ta_explicit* i =
|
||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
||||
create_transition(i, condition, bddfalse, s);
|
||||
create_transition(i, condition, 0U, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -420,7 +421,7 @@ namespace spot
|
|||
|
||||
void
|
||||
ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
|
||||
bdd acceptance_conditions,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
state_ta_explicit* dest, bool add_at_beginning)
|
||||
{
|
||||
state_ta_explicit::transition* t = new state_ta_explicit::transition;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ namespace spot
|
|||
class SPOT_API ta_explicit : public ta
|
||||
{
|
||||
public:
|
||||
ta_explicit(const const_tgba_ptr& tgba, bdd all_acceptance_conditions,
|
||||
ta_explicit(const const_tgba_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = 0);
|
||||
|
||||
const_tgba_ptr
|
||||
|
|
@ -55,7 +56,8 @@ namespace spot
|
|||
|
||||
void
|
||||
create_transition(state_ta_explicit* source, bdd condition,
|
||||
bdd acceptance_conditions, state_ta_explicit* dest,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
state_ta_explicit* dest,
|
||||
bool add_at_beginning = false);
|
||||
|
||||
void
|
||||
|
|
@ -115,27 +117,12 @@ namespace spot
|
|||
return states_set_;
|
||||
}
|
||||
|
||||
/// \brief Return the set of all acceptance conditions used
|
||||
/// by this automaton.
|
||||
///
|
||||
/// The goal of the emptiness check is to ensure that
|
||||
/// a strongly connected component walks through each
|
||||
/// of these acceptiong conditions. I.e., the union
|
||||
/// of the acceptiong conditions of all transition in
|
||||
/// the SCC should be equal to the result of this function.
|
||||
bdd
|
||||
all_acceptance_conditions() const
|
||||
{
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copy.
|
||||
ta_explicit(const ta_explicit& other) SPOT_DELETED;
|
||||
ta_explicit& operator=(const ta_explicit& other) SPOT_DELETED;
|
||||
|
||||
const_tgba_ptr tgba_;
|
||||
bdd all_acceptance_conditions_;
|
||||
state_ta_explicit* artificial_initial_state_;
|
||||
ta::states_set_t states_set_;
|
||||
ta::states_set_t initial_states_set_;
|
||||
|
|
@ -152,7 +139,7 @@ namespace spot
|
|||
struct transition
|
||||
{
|
||||
bdd condition;
|
||||
bdd acceptance_conditions;
|
||||
acc_cond::mark_t acceptance_conditions;
|
||||
state_ta_explicit* dest;
|
||||
};
|
||||
|
||||
|
|
@ -255,7 +242,7 @@ namespace spot
|
|||
virtual bdd
|
||||
current_condition() const;
|
||||
|
||||
virtual bdd
|
||||
virtual acc_cond::mark_t
|
||||
current_acceptance_conditions() const;
|
||||
|
||||
private:
|
||||
|
|
@ -267,13 +254,11 @@ namespace spot
|
|||
typedef std::shared_ptr<const ta_explicit> const_ta_explicit_ptr;
|
||||
|
||||
inline ta_explicit_ptr make_ta_explicit(const const_tgba_ptr& tgba,
|
||||
bdd all_acceptance_conditions,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit*
|
||||
artificial_initial_state = 0)
|
||||
{
|
||||
return std::make_shared<ta_explicit>(tgba,
|
||||
all_acceptance_conditions,
|
||||
artificial_initial_state);
|
||||
return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ namespace spot
|
|||
//if stuttering transition, the TA automata stays in the same state
|
||||
current_state_ = new state_ta_product(source_->get_ta_state(),
|
||||
kripke_current_dest_state->clone());
|
||||
current_acceptance_conditions_ = bddfalse;
|
||||
current_acceptance_conditions_ = 0U;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ namespace spot
|
|||
return current_condition_;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
ta_succ_iterator_product::current_acceptance_conditions() const
|
||||
{
|
||||
return current_acceptance_conditions_;
|
||||
|
|
@ -244,6 +244,7 @@ namespace spot
|
|||
|
||||
ta_product::ta_product(const const_ta_ptr& testing_automata,
|
||||
const const_kripke_ptr& kripke_structure):
|
||||
ta(testing_automata->get_dict()),
|
||||
dict_(testing_automata->get_dict()),
|
||||
ta_(testing_automata),
|
||||
kripke_(kripke_structure)
|
||||
|
|
@ -387,12 +388,6 @@ namespace spot
|
|||
return is_hole_state;
|
||||
}
|
||||
|
||||
bdd
|
||||
ta_product::all_acceptance_conditions() const
|
||||
{
|
||||
return get_ta()->all_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
ta_product::get_state_condition(const spot::state* s) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ namespace spot
|
|||
bdd
|
||||
current_condition() const;
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
current_acceptance_conditions() const;
|
||||
|
||||
/// \brief Return true if the changeset of the current transition is empty
|
||||
|
|
@ -120,7 +120,7 @@ namespace spot
|
|||
tgba_succ_iterator* kripke_succ_it_;
|
||||
state_ta_product* current_state_;
|
||||
bdd current_condition_;
|
||||
bdd current_acceptance_conditions_;
|
||||
acc_cond::mark_t current_acceptance_conditions_;
|
||||
bool is_stuttering_transition_;
|
||||
bdd kripke_source_condition;
|
||||
state * kripke_current_dest_state;
|
||||
|
|
@ -174,9 +174,6 @@ namespace spot
|
|||
virtual bdd
|
||||
get_state_condition(const spot::state* s) const;
|
||||
|
||||
virtual bdd
|
||||
all_acceptance_conditions() const;
|
||||
|
||||
virtual void
|
||||
free_state(const spot::state* s) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2012, 2013 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2012, 2013, 2014 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -22,11 +22,9 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
tgta::tgta()
|
||||
tgta::tgta(const bdd_dict_ptr& d)
|
||||
: tgba(d)
|
||||
{};
|
||||
tgta::~tgta()
|
||||
{};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ namespace spot
|
|||
{
|
||||
|
||||
protected:
|
||||
tgta();
|
||||
public:
|
||||
tgta(const bdd_dict_ptr& d);
|
||||
|
||||
public:
|
||||
virtual
|
||||
~tgta();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ namespace spot
|
|||
{
|
||||
|
||||
tgta_explicit::tgta_explicit(const const_tgba_ptr& tgba,
|
||||
bdd all_acceptance_conditions,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state) :
|
||||
ta_(make_ta_explicit(tgba, all_acceptance_conditions,
|
||||
artificial_initial_state))
|
||||
tgta(tgba->get_dict()),
|
||||
ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -63,18 +63,6 @@ namespace spot
|
|||
return ta_->get_dict();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgta_explicit::all_acceptance_conditions() const
|
||||
{
|
||||
return ta_->all_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgta_explicit::neg_acceptance_conditions() const
|
||||
{
|
||||
return ta_->get_tgba()->neg_acceptance_conditions();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgta_explicit::format_state(const spot::state* s) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
tgta_explicit(const const_tgba_ptr& tgba,
|
||||
bdd all_acceptance_conditions,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state);
|
||||
|
||||
// tgba interface
|
||||
|
|
@ -54,9 +54,6 @@ namespace spot
|
|||
const_ta_explicit_ptr get_ta() const { return ta_; }
|
||||
ta_explicit_ptr get_ta() { return ta_; }
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
virtual std::string format_state(const spot::state* s) const;
|
||||
|
||||
virtual tgba_succ_iterator*
|
||||
|
|
@ -71,12 +68,11 @@ namespace spot
|
|||
typedef std::shared_ptr<const tgta_explicit> const_tgta_explicit_ptr;
|
||||
|
||||
inline tgta_explicit_ptr make_tgta_explicit(const const_tgba_ptr& tgba,
|
||||
bdd all_acceptance_conditions,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit*
|
||||
artificial_initial_state = 0)
|
||||
{
|
||||
return std::make_shared<tgta_explicit>(tgba,
|
||||
all_acceptance_conditions,
|
||||
return std::make_shared<tgta_explicit>(tgba, n_acc,
|
||||
artificial_initial_state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ namespace spot
|
|||
return current_condition_;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
tgta_succ_iterator_product::current_acceptance_conditions() const
|
||||
{
|
||||
return current_acceptance_conditions_;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ namespace spot
|
|||
bdd
|
||||
current_condition() const;
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
current_acceptance_conditions() const;
|
||||
|
||||
private:
|
||||
|
|
@ -96,7 +96,7 @@ namespace spot
|
|||
tgba_succ_iterator* kripke_succ_it_;
|
||||
state_product* current_state_;
|
||||
bdd current_condition_;
|
||||
bdd current_acceptance_conditions_;
|
||||
acc_cond::mark_t current_acceptance_conditions_;
|
||||
bdd kripke_source_condition;
|
||||
state* kripke_current_dest_state;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -106,9 +106,8 @@ namespace spot
|
|||
if (label.empty())
|
||||
label = "{}";
|
||||
|
||||
label += ("\n" +
|
||||
bdd_format_accset(d, si->current_acceptance_conditions()));
|
||||
|
||||
label += "\n";
|
||||
label += t_automata_->acc().format(si->current_acceptance_conditions());
|
||||
|
||||
os_ << " " << in << " -> " << out << " [label=\"";
|
||||
escape_str(os_, label);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ namespace spot
|
|||
// * scc: (attribute) a stack of strongly connected components (SCC)
|
||||
|
||||
// * arc, a stack of acceptance conditions between each of these SCC,
|
||||
std::stack<bdd> arc;
|
||||
std::stack<acc_cond::mark_t> arc;
|
||||
|
||||
// * h: a hash of all visited nodes, with their order,
|
||||
// (it is called "Hash" in Couvreur's paper)
|
||||
|
|
@ -113,7 +113,7 @@ namespace spot
|
|||
}
|
||||
|
||||
scc.push(++num);
|
||||
arc.push(bddfalse);
|
||||
arc.push(0U);
|
||||
|
||||
ta_succ_iterator_product* iter = a_->succ_iter(init);
|
||||
iter->first();
|
||||
|
|
@ -194,7 +194,7 @@ namespace spot
|
|||
// Fetch the values destination state we are interested in...
|
||||
state* dest = succ->current_state();
|
||||
|
||||
bdd acc_cond = succ->current_acceptance_conditions();
|
||||
auto acc_cond = succ->current_acceptance_conditions();
|
||||
|
||||
bool curr_is_livelock_hole_state_in_ta_component =
|
||||
(a_->is_hole_state_in_ta_component(curr))
|
||||
|
|
@ -284,8 +284,8 @@ namespace spot
|
|||
scc.top().condition |= acc_cond;
|
||||
|
||||
scc.rem().splice(scc.rem().end(), rem);
|
||||
bool is_accepting_sscc = (scc.top().is_accepting)
|
||||
|| (scc.top().condition == a_->all_acceptance_conditions());
|
||||
bool is_accepting_sscc = scc.top().is_accepting
|
||||
|| a_->acc().accepting(scc.top().condition);
|
||||
|
||||
if (is_accepting_sscc)
|
||||
{
|
||||
|
|
@ -294,25 +294,14 @@ namespace spot
|
|||
<< a_->is_livelock_accepting_state(curr) << '\n';
|
||||
trace
|
||||
<< "PASS 1: scc.top().condition : "
|
||||
<< bdd_format_accset(a_->get_dict(), scc.top().condition)
|
||||
<< '\n';
|
||||
<< scc.top().condition << '\n';
|
||||
trace
|
||||
<< "PASS 1: a_->all_acceptance_conditions() : "
|
||||
<< (a_->all_acceptance_conditions()) << '\n';
|
||||
<< "PASS 1: a_->acc().all_sets() : "
|
||||
<< (a_->acc().all_sets()) << '\n';
|
||||
trace
|
||||
<< ("PASS 1 CYCLE and (scc.top().condition == "
|
||||
"a_->all_acceptance_conditions()) : ")
|
||||
<< (scc.top().condition
|
||||
== a_->all_acceptance_conditions()) << std::endl;
|
||||
|
||||
trace
|
||||
<< "PASS 1: bddtrue: " << (a_->all_acceptance_conditions()
|
||||
== bddtrue) << '\n';
|
||||
|
||||
trace
|
||||
<< "PASS 1: bddfalse: " << (a_->all_acceptance_conditions()
|
||||
== bddfalse) << '\n';
|
||||
|
||||
<< ("PASS 1 CYCLE and accepting? ")
|
||||
<< a_->acc().accepting(scc.top().condition)
|
||||
<< std::endl;
|
||||
clear(h, todo, ta_init_it_);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,8 @@ namespace spot
|
|||
a->is_livelock_accepting_state(dst);
|
||||
|
||||
state_ta_explicit* new_dst =
|
||||
new state_ta_explicit(result_tgba->state_from_number(i->second),
|
||||
new state_ta_explicit
|
||||
(result_tgba->state_from_number(i->second),
|
||||
tgba_condition, is_initial_state,
|
||||
is_accepting_state,
|
||||
is_livelock_accepting_state);
|
||||
|
|
@ -174,7 +175,8 @@ namespace spot
|
|||
else if (is_initial_state)
|
||||
result->add_to_initial_states_set(new_dst);
|
||||
|
||||
result->create_transition(ta_src, succit->current_condition(),
|
||||
result->create_transition
|
||||
(ta_src, succit->current_condition(),
|
||||
succit->current_acceptance_conditions(),
|
||||
ta_dst);
|
||||
}
|
||||
|
|
@ -185,6 +187,26 @@ namespace spot
|
|||
static partition_t
|
||||
build_partition(const const_ta_ptr& ta_)
|
||||
{
|
||||
unsigned num_sets = ta_->acc().num_sets();
|
||||
std::map<acc_cond::mark_t, bdd> m2b;
|
||||
int acc_vars = ta_->get_dict()->register_anonymous_variables(num_sets,
|
||||
&m2b);
|
||||
auto mark_to_bdd = [&](acc_cond::mark_t m) -> bdd
|
||||
{
|
||||
auto i = m2b.find(m);
|
||||
if (i != m2b.end())
|
||||
return i->second;
|
||||
|
||||
bdd res = bddtrue;
|
||||
for (unsigned n = 0; n < num_sets; ++n)
|
||||
if (m.has(n))
|
||||
res &= bdd_ithvar(acc_vars + n);
|
||||
else
|
||||
res &= bdd_nithvar(acc_vars + n);
|
||||
m2b.emplace_hint(i, m, res);
|
||||
return res;
|
||||
};
|
||||
|
||||
partition_t cur_run;
|
||||
partition_t next_run;
|
||||
|
||||
|
|
@ -237,7 +259,7 @@ namespace spot
|
|||
// Use bdd variables to number sets. set_num is the first variable
|
||||
// available.
|
||||
unsigned set_num =
|
||||
ta_->get_dict()->register_anonymous_variables(size, ta_);
|
||||
ta_->get_dict()->register_anonymous_variables(size, &m2b);
|
||||
|
||||
std::set<int> free_var;
|
||||
for (unsigned i = set_num; i < set_num + size; ++i)
|
||||
|
|
@ -335,6 +357,7 @@ namespace spot
|
|||
delete S;
|
||||
}
|
||||
|
||||
|
||||
// A bdd_states_map is a list of formulae (in a BDD form)
|
||||
// associated with a destination set of states.
|
||||
typedef std::map<bdd, hash_set*, bdd_less_than> bdd_states_map;
|
||||
|
|
@ -372,13 +395,10 @@ namespace spot
|
|||
hash_map::const_iterator i = state_set_map.find(dst);
|
||||
|
||||
assert(i != state_set_map.end());
|
||||
bdd current_acceptance_conditions =
|
||||
si->current_acceptance_conditions();
|
||||
if (current_acceptance_conditions == bddfalse)
|
||||
current_acceptance_conditions
|
||||
= bdd_false_acceptance_condition;
|
||||
f |= (bdd_ithvar(i->second) & si->current_condition()
|
||||
& current_acceptance_conditions);
|
||||
auto curacc =
|
||||
mark_to_bdd(si->current_acceptance_conditions());
|
||||
f |= (bdd_ithvar(i->second)
|
||||
& si->current_condition() & curacc);
|
||||
trace
|
||||
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
||||
<< "\n -bdd_ithvar(i->second): "
|
||||
|
|
@ -388,8 +408,7 @@ namespace spot
|
|||
<< bdd_format_accset(ta_->get_dict(),
|
||||
si->current_condition())
|
||||
<< "\n -current_acceptance_conditions: "
|
||||
<< bdd_format_accset(ta_->get_dict(),
|
||||
current_acceptance_conditions)
|
||||
<< si->current_acceptance_conditions()
|
||||
<< std::endl;
|
||||
}
|
||||
delete si;
|
||||
|
|
@ -480,6 +499,7 @@ namespace spot
|
|||
trace << std::endl;
|
||||
#endif
|
||||
|
||||
ta_->get_dict()->unregister_all_my_variables(&m2b);
|
||||
return done;
|
||||
}
|
||||
}
|
||||
|
|
@ -489,7 +509,7 @@ namespace spot
|
|||
{
|
||||
|
||||
auto tgba = make_tgba_digraph(ta_->get_dict());
|
||||
auto res = make_ta_explicit(tgba, ta_->all_acceptance_conditions(), 0);
|
||||
auto res = make_ta_explicit(tgba, ta_->acc().num_sets(), 0);
|
||||
|
||||
partition_t partition = build_partition(ta_);
|
||||
|
||||
|
|
@ -509,7 +529,7 @@ namespace spot
|
|||
{
|
||||
|
||||
auto tgba = make_tgba_digraph(tgta_->get_dict());
|
||||
auto res = make_tgta_explicit(tgba, tgta_->all_acceptance_conditions(), 0);
|
||||
auto res = make_tgta_explicit(tgba, tgta_->acc().num_sets(), 0);
|
||||
|
||||
auto ta = tgta_->get_ta();
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ namespace spot
|
|||
}
|
||||
|
||||
static void
|
||||
compute_livelock_acceptance_states(const ta_explicit_ptr& testing_automata,
|
||||
compute_livelock_acceptance_states(const ta_explicit_ptr& testing_aut,
|
||||
bool single_pass_emptiness_check,
|
||||
state_ta_explicit*
|
||||
artificial_livelock_acc_state)
|
||||
|
|
@ -158,7 +158,7 @@ namespace spot
|
|||
scc_stack_ta sscc;
|
||||
|
||||
// * arc, a stack of acceptance conditions between each of these SCC,
|
||||
std::stack<bdd> arc;
|
||||
std::stack<acc_cond::mark_t> arc;
|
||||
|
||||
// * h: a hash of all visited nodes, with their order,
|
||||
// (it is called "Hash" in Couvreur's paper)
|
||||
|
|
@ -180,7 +180,7 @@ namespace spot
|
|||
// * init: the set of the depth-first search initial states
|
||||
std::stack<state*> init_set;
|
||||
|
||||
for (state* s: testing_automata->get_initial_states_set())
|
||||
for (state* s: testing_aut->get_initial_states_set())
|
||||
init_set.push(s);
|
||||
|
||||
while (!init_set.empty())
|
||||
|
|
@ -199,10 +199,10 @@ namespace spot
|
|||
}
|
||||
|
||||
sscc.push(++num);
|
||||
arc.push(bddfalse);
|
||||
arc.push(0U);
|
||||
sscc.top().is_accepting
|
||||
= testing_automata->is_accepting_state(init);
|
||||
tgba_succ_iterator* iter = testing_automata->succ_iter(init);
|
||||
= testing_aut->is_accepting_state(init);
|
||||
tgba_succ_iterator* iter = testing_aut->succ_iter(init);
|
||||
iter->first();
|
||||
todo.emplace(init, iter);
|
||||
}
|
||||
|
|
@ -243,10 +243,9 @@ namespace spot
|
|||
// removing states
|
||||
std::list<state*>::iterator i;
|
||||
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
||||
&& ((sscc.top().is_accepting)
|
||||
|| (sscc.top().condition ==
|
||||
testing_automata->all_acceptance_conditions()));
|
||||
|
||||
&& ((sscc.top().is_accepting) ||
|
||||
(testing_aut->acc().
|
||||
accepting(sscc.top().condition)));
|
||||
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
||||
for (auto j: sscc.rem())
|
||||
{
|
||||
|
|
@ -257,7 +256,7 @@ namespace spot
|
|||
// if it is an accepting sscc add the state to
|
||||
// G (=the livelock-accepting states set)
|
||||
trace << "*** sscc.size() > 1: states: ***"
|
||||
<< testing_automata->format_state(j)
|
||||
<< testing_aut->format_state(j)
|
||||
<< '\n';
|
||||
state_ta_explicit* livelock_accepting_state =
|
||||
down_cast<state_ta_explicit*>(j);
|
||||
|
|
@ -283,7 +282,7 @@ namespace spot
|
|||
}
|
||||
|
||||
// automata reduction
|
||||
testing_automata->delete_stuttering_and_hole_successors(curr);
|
||||
testing_aut->delete_stuttering_and_hole_successors(curr);
|
||||
|
||||
delete succ;
|
||||
// Do not delete CURR: it is a key in H.
|
||||
|
|
@ -293,7 +292,7 @@ namespace spot
|
|||
// Fetch the values destination state we are interested in...
|
||||
state* dest = succ->current_state();
|
||||
|
||||
bdd acc_cond = succ->current_acceptance_conditions();
|
||||
auto acc_cond = succ->current_acceptance_conditions();
|
||||
// ... and point the iterator to the next successor, for
|
||||
// the next iteration.
|
||||
succ->next();
|
||||
|
|
@ -301,8 +300,8 @@ namespace spot
|
|||
|
||||
// Are we going to a new state through a stuttering transition?
|
||||
bool is_stuttering_transition =
|
||||
testing_automata->get_state_condition(curr)
|
||||
== testing_automata->get_state_condition(dest);
|
||||
testing_aut->get_state_condition(curr)
|
||||
== testing_aut->get_state_condition(dest);
|
||||
auto id = h.find(dest);
|
||||
|
||||
// Is this a new state?
|
||||
|
|
@ -321,9 +320,9 @@ namespace spot
|
|||
sscc.push(num);
|
||||
arc.push(acc_cond);
|
||||
sscc.top().is_accepting =
|
||||
testing_automata->is_accepting_state(dest);
|
||||
testing_aut->is_accepting_state(dest);
|
||||
|
||||
tgba_succ_iterator* iter = testing_automata->succ_iter(dest);
|
||||
tgba_succ_iterator* iter = testing_aut->succ_iter(dest);
|
||||
iter->first();
|
||||
todo.emplace(dest, iter);
|
||||
continue;
|
||||
|
|
@ -342,9 +341,8 @@ namespace spot
|
|||
down_cast<state_ta_explicit*> (curr);
|
||||
assert(self_loop_state);
|
||||
|
||||
if (testing_automata->is_accepting_state(self_loop_state)
|
||||
|| (acc_cond
|
||||
== testing_automata->all_acceptance_conditions()))
|
||||
if (testing_aut->is_accepting_state(self_loop_state)
|
||||
|| (testing_aut->acc().accepting(acc_cond)))
|
||||
{
|
||||
self_loop_state->set_livelock_accepting_state(true);
|
||||
if (single_pass_emptiness_check)
|
||||
|
|
@ -404,7 +402,7 @@ namespace spot
|
|||
|
||||
if ((artificial_livelock_acc_state != 0)
|
||||
|| single_pass_emptiness_check)
|
||||
transform_to_single_pass_automaton(testing_automata,
|
||||
transform_to_single_pass_automaton(testing_aut,
|
||||
artificial_livelock_acc_state);
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +427,7 @@ namespace spot
|
|||
tgba_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->current_acceptance_conditions() != bddfalse;
|
||||
is_acc = it->current_acceptance_conditions() != 0U;
|
||||
delete it;
|
||||
}
|
||||
|
||||
|
|
@ -462,7 +460,7 @@ namespace spot
|
|||
{
|
||||
const state* tgba_state = tgba_succ_it->current_state();
|
||||
bdd tgba_condition = tgba_succ_it->current_condition();
|
||||
bdd tgba_acceptance_conditions =
|
||||
acc_cond::mark_t tgba_acceptance_conditions =
|
||||
tgba_succ_it->current_acceptance_conditions();
|
||||
bdd satone_tgba_condition;
|
||||
while ((satone_tgba_condition =
|
||||
|
|
@ -481,7 +479,7 @@ namespace spot
|
|||
tgba_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
||||
it->first();
|
||||
if (!it->done())
|
||||
is_acc = it->current_acceptance_conditions() != bddfalse;
|
||||
is_acc = it->current_acceptance_conditions() != 0U;
|
||||
delete it;
|
||||
}
|
||||
|
||||
|
|
@ -554,12 +552,12 @@ namespace spot
|
|||
state_ta_explicit* artificial_init_state =
|
||||
new state_ta_explicit(tgba_init_state->clone(), bddfalse, true);
|
||||
|
||||
ta = make_ta_explicit(tgba_, tgba_->all_acceptance_conditions(),
|
||||
ta = make_ta_explicit(tgba_, tgba_->acc().num_sets(),
|
||||
artificial_init_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
ta = make_ta_explicit(tgba_, tgba_->all_acceptance_conditions());
|
||||
ta = make_ta_explicit(tgba_, tgba_->acc().num_sets());
|
||||
}
|
||||
tgba_init_state->destroy();
|
||||
|
||||
|
|
@ -586,10 +584,7 @@ namespace spot
|
|||
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();
|
||||
++it_trans)
|
||||
{
|
||||
(*it_trans)->acceptance_conditions
|
||||
= ta->all_acceptance_conditions();
|
||||
}
|
||||
(*it_trans)->acceptance_conditions = ta->acc().all_sets();
|
||||
|
||||
state->set_accepting_state(false);
|
||||
}
|
||||
|
|
@ -606,7 +601,7 @@ namespace spot
|
|||
bddfalse, true);
|
||||
tgba_init_state->destroy();
|
||||
|
||||
auto tgta = make_tgta_explicit(tgba_, tgba_->all_acceptance_conditions(),
|
||||
auto tgta = make_tgta_explicit(tgba_, tgba_->acc().num_sets(),
|
||||
artificial_init_state);
|
||||
|
||||
// build a Generalized TA automaton involving a single_pass_emptiness_check
|
||||
|
|
@ -644,13 +639,13 @@ namespace spot
|
|||
if (trans_empty || state->is_accepting_state())
|
||||
{
|
||||
ta->create_transition(state, bdd_stutering_transition,
|
||||
ta->all_acceptance_conditions(), state);
|
||||
ta->acc().all_sets(), state);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->compare(ta->get_artificial_initial_state()))
|
||||
ta->create_transition(state, bdd_stutering_transition,
|
||||
bddfalse, state);
|
||||
0U, state);
|
||||
|
||||
state->set_livelock_accepting_state(false);
|
||||
state->set_accepting_state(false);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
|||
tgbadir = $(pkgincludedir)/tgba
|
||||
|
||||
tgba_HEADERS = \
|
||||
acc.hh \
|
||||
bdddict.hh \
|
||||
bddprint.hh \
|
||||
formula2bdd.hh \
|
||||
|
|
@ -33,11 +34,9 @@ tgba_HEADERS = \
|
|||
taatgba.hh \
|
||||
tgba.hh \
|
||||
tgbagraph.hh \
|
||||
tgbakvcomplement.hh \
|
||||
tgbamask.hh \
|
||||
tgbaproxy.hh \
|
||||
tgbaproduct.hh \
|
||||
tgbasgba.hh \
|
||||
tgbasafracomplement.hh
|
||||
|
||||
noinst_LTLIBRARIES = libtgba.la
|
||||
|
|
@ -48,9 +47,7 @@ libtgba_la_SOURCES = \
|
|||
taatgba.cc \
|
||||
tgba.cc \
|
||||
tgbagraph.cc \
|
||||
tgbakvcomplement.cc \
|
||||
tgbaproduct.cc \
|
||||
tgbamask.cc \
|
||||
tgbaproxy.cc \
|
||||
tgbasafracomplement.cc \
|
||||
tgbasgba.cc
|
||||
tgbasafracomplement.cc
|
||||
|
|
|
|||
433
src/tgba/acc.hh
Normal file
433
src/tgba/acc.hh
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2014 Laboratoire de Recherche et Développement de
|
||||
// l'Epita.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_TGBA_ACC_HH
|
||||
# define SPOT_TGBA_ACC_HH
|
||||
|
||||
# include <functional>
|
||||
# include <unordered_map>
|
||||
# include <sstream>
|
||||
# include "bdddict.hh"
|
||||
# include "ltlenv/defaultenv.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
class acc_cond
|
||||
{
|
||||
public:
|
||||
struct mark_t
|
||||
{
|
||||
typedef unsigned value_t;
|
||||
value_t id;
|
||||
|
||||
mark_t() = default;
|
||||
|
||||
mark_t(value_t id)
|
||||
: id(id)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(unsigned o) const
|
||||
{
|
||||
assert(o == 0U);
|
||||
return id == o;
|
||||
}
|
||||
|
||||
bool operator!=(unsigned o) const
|
||||
{
|
||||
assert(o == 0U);
|
||||
return id != o;
|
||||
}
|
||||
|
||||
bool operator==(mark_t o) const
|
||||
{
|
||||
return id == o.id;
|
||||
}
|
||||
|
||||
bool operator!=(mark_t o) const
|
||||
{
|
||||
return id != o.id;
|
||||
}
|
||||
|
||||
bool operator<(mark_t o) const
|
||||
{
|
||||
return id < o.id;
|
||||
}
|
||||
|
||||
bool operator<=(mark_t o) const
|
||||
{
|
||||
return id <= o.id;
|
||||
}
|
||||
|
||||
bool operator>(mark_t o) const
|
||||
{
|
||||
return id > o.id;
|
||||
}
|
||||
|
||||
bool operator>=(mark_t o) const
|
||||
{
|
||||
return id >= o.id;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return id != 0;
|
||||
}
|
||||
|
||||
|
||||
bool has(unsigned u) const
|
||||
{
|
||||
return id & (1U << u);
|
||||
}
|
||||
|
||||
mark_t& operator&=(mark_t r)
|
||||
{
|
||||
id &= r.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mark_t& operator|=(mark_t r)
|
||||
{
|
||||
id |= r.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mark_t& operator-=(mark_t r)
|
||||
{
|
||||
id &= ~r.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mark_t operator&(mark_t r) const
|
||||
{
|
||||
return id & r.id;
|
||||
}
|
||||
|
||||
mark_t operator|(mark_t r) const
|
||||
{
|
||||
return id | r.id;
|
||||
}
|
||||
|
||||
mark_t operator-(mark_t r) const
|
||||
{
|
||||
return id & ~r.id;
|
||||
}
|
||||
|
||||
// Number of bits sets.
|
||||
unsigned count() const
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_popcount(id);
|
||||
#else
|
||||
unsigned c = 0U;
|
||||
auto v = id;
|
||||
while (v)
|
||||
{
|
||||
++c;
|
||||
v &= v - 1;
|
||||
}
|
||||
return c;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remove n bits that where set
|
||||
mark_t& remove_some(unsigned n)
|
||||
{
|
||||
while (n--)
|
||||
id &= id - 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, mark_t m)
|
||||
{
|
||||
auto a = m.id;
|
||||
os << '{';
|
||||
unsigned level = 0;
|
||||
const char* comma = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << comma << level;
|
||||
comma = ",";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
os << '}';
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
acc_cond(const bdd_dict_ptr& dict, unsigned n_sets = 0)
|
||||
: d_(dict), num_(0U), all_(0U)
|
||||
{
|
||||
add_sets(n_sets);
|
||||
}
|
||||
|
||||
acc_cond(const acc_cond& o)
|
||||
: num_(o.num_), all_(o.all_)
|
||||
{
|
||||
}
|
||||
|
||||
~acc_cond()
|
||||
{
|
||||
}
|
||||
|
||||
const bdd_dict_ptr& get_dict() const
|
||||
{
|
||||
return d_;
|
||||
}
|
||||
|
||||
unsigned add_sets(unsigned num)
|
||||
{
|
||||
if (num == 0)
|
||||
return -1U;
|
||||
unsigned j = num_;
|
||||
num_ += num;
|
||||
if (num_ > 8 * sizeof(mark_t::id))
|
||||
throw std::runtime_error("Too many acceptance sets used.");
|
||||
all_ = all_sets_();
|
||||
return j;
|
||||
}
|
||||
|
||||
unsigned add_set()
|
||||
{
|
||||
return add_sets(1);
|
||||
}
|
||||
|
||||
mark_t mark(unsigned u) const
|
||||
{
|
||||
return out(mark_(u));
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
mark_t marks(const iterator& begin, const iterator& end) const
|
||||
{
|
||||
mark_t::value_t res = 0U;
|
||||
for (iterator i = begin; i != end; ++i)
|
||||
res |= mark_(*i);
|
||||
return out(res);
|
||||
}
|
||||
|
||||
mark_t marks(std::initializer_list<unsigned> vals) const
|
||||
{
|
||||
return marks(vals.begin(), vals.end());
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
void fill_from(mark_t m, iterator here) const
|
||||
{
|
||||
auto a = in(m);
|
||||
unsigned level = 0;
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
*here++ = level;
|
||||
++level;
|
||||
a >>= 1;
|
||||
}
|
||||
assert(level <= num_sets());
|
||||
}
|
||||
|
||||
// FIXME: Return some iterable object without building a vector.
|
||||
std::vector<unsigned> sets(mark_t m) const
|
||||
{
|
||||
std::vector<unsigned> res;
|
||||
fill_from(m, std::back_inserter(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
// whether m contains u
|
||||
bool has(mark_t m, unsigned u) const
|
||||
{
|
||||
return m.has(u);
|
||||
}
|
||||
|
||||
mark_t cup(mark_t l, mark_t r) const
|
||||
{
|
||||
return l | r;
|
||||
}
|
||||
|
||||
mark_t cap(mark_t l, mark_t r) const
|
||||
{
|
||||
return l & r;
|
||||
}
|
||||
|
||||
mark_t set_minus(mark_t l, mark_t r) const
|
||||
{
|
||||
return l - r;
|
||||
}
|
||||
|
||||
mark_t join(const acc_cond& la, mark_t lm,
|
||||
const acc_cond& ra, mark_t rm) const
|
||||
{
|
||||
assert(la.num_sets() + ra.num_sets() == num_sets());
|
||||
return la.in(lm) | (ra.in(rm) << la.num_sets());
|
||||
}
|
||||
|
||||
mark_t comp(mark_t l) const
|
||||
{
|
||||
return out(all_ ^ in(l));
|
||||
}
|
||||
|
||||
mark_t all_sets() const
|
||||
{
|
||||
return out(all_);
|
||||
}
|
||||
|
||||
bool accepting(mark_t inf) const
|
||||
{
|
||||
return in(inf) == all_;
|
||||
}
|
||||
|
||||
std::ostream& format_quoted(std::ostream& os, mark_t m) const
|
||||
{
|
||||
auto a = in(m);
|
||||
if (a == 0U)
|
||||
return os;
|
||||
unsigned level = 0;
|
||||
const char* space = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << space << '"' << level << '"';
|
||||
space = " ";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& format(std::ostream& os, mark_t m) const
|
||||
{
|
||||
auto a = in(m);
|
||||
if (a == 0U)
|
||||
return os;
|
||||
return os << m;
|
||||
}
|
||||
|
||||
std::string format(mark_t m) const
|
||||
{
|
||||
std::ostringstream os;
|
||||
format(os, m);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
unsigned num_sets() const
|
||||
{
|
||||
return num_;
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
mark_t useless(iterator begin, iterator end) const
|
||||
{
|
||||
mark_t::value_t u = 0U; // The set of useless marks.
|
||||
for (unsigned x = 0; x < num_; ++x)
|
||||
{
|
||||
// Skip marks that are already known to be useless.
|
||||
if (u & (1 << x))
|
||||
continue;
|
||||
unsigned all = all_ ^ (u | (1 << x));
|
||||
for (iterator y = begin; y != end; ++y)
|
||||
{
|
||||
auto v = in(*y);
|
||||
if (v & (1 << x))
|
||||
{
|
||||
all &= v;
|
||||
if (!all)
|
||||
break;
|
||||
}
|
||||
}
|
||||
u |= all;
|
||||
}
|
||||
return out(u);
|
||||
}
|
||||
|
||||
mark_t strip(mark_t x, mark_t y) const
|
||||
{
|
||||
// strip every bit of x that is marked in y
|
||||
// strip(100101110100,
|
||||
// 001011001000)
|
||||
// == 10 1 11 100
|
||||
// == 10111100
|
||||
|
||||
auto xv = in(x); // 100101110100
|
||||
auto yv = in(y); // 001011001000
|
||||
|
||||
while (yv && xv)
|
||||
{
|
||||
// Mask for everything after the last 1 in y
|
||||
auto rm = (~yv) & (yv - 1); // 000000000111
|
||||
// Mask for everything before the last 1 in y
|
||||
auto lm = ~(yv ^ (yv - 1)); // 111111110000
|
||||
xv = ((xv & lm) >> 1) | (xv & rm);
|
||||
yv = (yv & lm) >> 1;
|
||||
}
|
||||
|
||||
return out(xv);
|
||||
}
|
||||
|
||||
protected:
|
||||
mark_t::value_t mark_(unsigned u) const
|
||||
{
|
||||
assert(u < num_sets());
|
||||
return 1U << u;
|
||||
}
|
||||
|
||||
mark_t::value_t all_sets_() const
|
||||
{
|
||||
if (num_ == 0)
|
||||
return 0;
|
||||
return -1U >> (8 * sizeof(mark_t::value_t) - num_);
|
||||
}
|
||||
|
||||
mark_t::value_t in(mark_t m) const
|
||||
{
|
||||
return m.id;
|
||||
}
|
||||
|
||||
mark_t out(mark_t::value_t r) const
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
bdd_dict_ptr d_;
|
||||
unsigned num_;
|
||||
mark_t::value_t all_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<spot::acc_cond::mark_t>
|
||||
{
|
||||
size_t operator()(spot::acc_cond::mark_t m) const
|
||||
{
|
||||
std::hash<decltype(m.id)> h;
|
||||
return h(m.id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SPOT_TGBA_ACC_HH
|
||||
|
|
@ -35,10 +35,6 @@ namespace spot
|
|||
class tgba_product;
|
||||
typedef std::shared_ptr<const tgba_product> const_tgba_product_ptr;
|
||||
typedef std::shared_ptr<tgba_product> tgba_product_ptr;
|
||||
|
||||
class tgba_sgba_proxy;
|
||||
typedef std::shared_ptr<const tgba_sgba_proxy> const_tgba_sgba_proxy_ptr;
|
||||
typedef std::shared_ptr<tgba_sgba_proxy> tgba_sgba_proxy_ptr;
|
||||
}
|
||||
|
||||
#endif // SPOT_TGBA_FWD_HH
|
||||
|
|
|
|||
|
|
@ -34,10 +34,7 @@ namespace spot
|
|||
`--------*/
|
||||
|
||||
taa_tgba::taa_tgba(const bdd_dict_ptr& dict)
|
||||
: dict_(dict),
|
||||
all_acceptance_conditions_(bddfalse),
|
||||
all_acceptance_conditions_computed_(false),
|
||||
neg_acceptance_conditions_(bddtrue),
|
||||
: tgba(dict),
|
||||
init_(0), state_set_vec_()
|
||||
{
|
||||
}
|
||||
|
|
@ -47,13 +44,13 @@ namespace spot
|
|||
ss_vec::iterator j;
|
||||
for (j = state_set_vec_.begin(); j != state_set_vec_.end(); ++j)
|
||||
delete *j;
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
void
|
||||
taa_tgba::add_condition(transition* t, const ltl::formula* f)
|
||||
{
|
||||
t->condition &= formula_to_bdd(f, dict_, this);
|
||||
t->condition &= formula_to_bdd(f, get_dict(), this);
|
||||
f->destroy();
|
||||
}
|
||||
|
||||
|
|
@ -69,31 +66,7 @@ namespace spot
|
|||
{
|
||||
const spot::set_state* s = down_cast<const spot::set_state*>(state);
|
||||
assert(s);
|
||||
return new taa_succ_iterator(s->get_state(), all_acceptance_conditions());
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
taa_tgba::get_dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
bdd
|
||||
taa_tgba::all_acceptance_conditions() const
|
||||
{
|
||||
if (!all_acceptance_conditions_computed_)
|
||||
{
|
||||
all_acceptance_conditions_ =
|
||||
compute_all_acceptance_conditions(neg_acceptance_conditions_);
|
||||
all_acceptance_conditions_computed_ = true;
|
||||
}
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
bdd
|
||||
taa_tgba::neg_acceptance_conditions() const
|
||||
{
|
||||
return neg_acceptance_conditions_;
|
||||
return new taa_succ_iterator(s->get_state(), acc_);
|
||||
}
|
||||
|
||||
bdd
|
||||
|
|
@ -172,14 +145,14 @@ namespace spot
|
|||
`--------------*/
|
||||
|
||||
taa_succ_iterator::taa_succ_iterator(const taa_tgba::state_set* s,
|
||||
bdd all_acc)
|
||||
: all_acceptance_conditions_(all_acc), seen_()
|
||||
const acc_cond& acc)
|
||||
: seen_(), acc_(acc)
|
||||
{
|
||||
if (s->empty())
|
||||
{
|
||||
taa_tgba::transition* t = new taa_tgba::transition;
|
||||
t->condition = bddtrue;
|
||||
t->acceptance_conditions = bddfalse;
|
||||
t->acceptance_conditions = 0U;
|
||||
t->dst = new taa_tgba::state_set;
|
||||
succ_.push_back(t);
|
||||
return;
|
||||
|
|
@ -202,7 +175,7 @@ namespace spot
|
|||
{
|
||||
taa_tgba::transition* t = new taa_tgba::transition;
|
||||
t->condition = bddtrue;
|
||||
t->acceptance_conditions = bddfalse;
|
||||
t->acceptance_conditions = 0U;
|
||||
taa_tgba::state_set* ss = new taa_tgba::state_set;
|
||||
|
||||
unsigned p;
|
||||
|
|
@ -330,12 +303,11 @@ namespace spot
|
|||
return (*i_)->condition;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
taa_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
return all_acceptance_conditions_ -
|
||||
((*i_)->acceptance_conditions & all_acceptance_conditions_);
|
||||
return acc_.comp((*i_)->acceptance_conditions);
|
||||
}
|
||||
|
||||
/*----------------.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "ltlast/formula.hh"
|
||||
#include "bdddict.hh"
|
||||
#include "tgba.hh"
|
||||
#include "ltlvisit/tostring.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -45,7 +46,7 @@ namespace spot
|
|||
struct transition
|
||||
{
|
||||
bdd condition;
|
||||
bdd acceptance_conditions;
|
||||
acc_cond::mark_t acceptance_conditions;
|
||||
const state_set* dst;
|
||||
};
|
||||
|
||||
|
|
@ -55,23 +56,19 @@ namespace spot
|
|||
virtual ~taa_tgba();
|
||||
virtual spot::state* get_init_state() const;
|
||||
virtual tgba_succ_iterator* succ_iter(const spot::state* state) const;
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
virtual std::string format_state(const spot::state* state) const = 0;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const spot::state* state) const;
|
||||
|
||||
typedef std::vector<taa_tgba::state_set*> ss_vec;
|
||||
|
||||
bdd_dict_ptr dict_;
|
||||
mutable bdd all_acceptance_conditions_;
|
||||
mutable bool all_acceptance_conditions_computed_;
|
||||
bdd neg_acceptance_conditions_;
|
||||
taa_tgba::state_set* init_;
|
||||
ss_vec state_set_vec_;
|
||||
|
||||
std::map<const ltl::formula*, acc_cond::mark_t,
|
||||
ltl::formula_ptr_less_than> acc_map_;
|
||||
|
||||
private:
|
||||
// Disallow copy.
|
||||
taa_tgba(const taa_tgba& other) SPOT_DELETED;
|
||||
|
|
@ -106,7 +103,7 @@ namespace spot
|
|||
class SPOT_API taa_succ_iterator : public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
taa_succ_iterator(const taa_tgba::state_set* s, bdd all_acc);
|
||||
taa_succ_iterator(const taa_tgba::state_set* s, const acc_cond& acc);
|
||||
virtual ~taa_succ_iterator();
|
||||
|
||||
virtual bool first();
|
||||
|
|
@ -115,7 +112,7 @@ namespace spot
|
|||
|
||||
virtual set_state* current_state() const;
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||
|
||||
private:
|
||||
/// Those typedefs are used to generate all possible successors in
|
||||
|
|
@ -141,8 +138,8 @@ namespace spot
|
|||
|
||||
std::vector<taa_tgba::transition*>::const_iterator i_;
|
||||
std::vector<taa_tgba::transition*> succ_;
|
||||
bdd all_acceptance_conditions_;
|
||||
seen_map seen_;
|
||||
const acc_cond& acc_;
|
||||
};
|
||||
|
||||
/// A taa_tgba instance with states labeled by a given type.
|
||||
|
|
@ -153,6 +150,13 @@ namespace spot
|
|||
public:
|
||||
taa_tgba_labelled(const bdd_dict_ptr& dict) : taa_tgba(dict) {};
|
||||
|
||||
~taa_tgba_labelled()
|
||||
{
|
||||
auto i = acc_map_.begin();
|
||||
while (i != acc_map_.end())
|
||||
(i++)->first->destroy();
|
||||
}
|
||||
|
||||
void set_init_state(const label& s)
|
||||
{
|
||||
std::vector<label> v(1);
|
||||
|
|
@ -173,10 +177,11 @@ namespace spot
|
|||
transition* t = new transition;
|
||||
t->dst = dst;
|
||||
t->condition = bddtrue;
|
||||
t->acceptance_conditions = bddfalse;
|
||||
t->acceptance_conditions = 0U;
|
||||
src->push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
transition*
|
||||
create_transition(const label& s, const label& d)
|
||||
{
|
||||
|
|
@ -187,29 +192,12 @@ namespace spot
|
|||
|
||||
void add_acceptance_condition(transition* t, const ltl::formula* f)
|
||||
{
|
||||
if (dict_->acc_map.find(f) == dict_->acc_map.end())
|
||||
{
|
||||
int v = dict_->register_acceptance_variable(f, this);
|
||||
bdd neg = bdd_nithvar(v);
|
||||
neg_acceptance_conditions_ &= neg;
|
||||
|
||||
// Append neg to all acceptance conditions.
|
||||
typename ns_map::iterator i;
|
||||
for (i = name_state_map_.begin(); i != name_state_map_.end(); ++i)
|
||||
{
|
||||
taa_tgba::state::iterator i2;
|
||||
for (i2 = i->second->begin(); i2 != i->second->end(); ++i2)
|
||||
(*i2)->acceptance_conditions &= neg;
|
||||
}
|
||||
|
||||
all_acceptance_conditions_computed_ = false;
|
||||
}
|
||||
|
||||
bdd_dict::fv_map::iterator i = dict_->acc_map.find(f);
|
||||
assert(i != dict_->acc_map.end());
|
||||
auto p = acc_map_.emplace(f, 0);
|
||||
if (p.second)
|
||||
p.first->second = acc_.marks({acc_.add_set()});
|
||||
else
|
||||
f->destroy();
|
||||
bdd v = bdd_ithvar(i->second);
|
||||
t->acceptance_conditions |= v & bdd_exist(neg_acceptance_conditions_, v);
|
||||
t->acceptance_conditions |= p.first->second;
|
||||
}
|
||||
|
||||
/// \brief Format the state as a string for printing.
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
tgba::tgba()
|
||||
tgba::tgba(const bdd_dict_ptr& d)
|
||||
: iter_cache_(nullptr),
|
||||
last_support_conditions_input_(0),
|
||||
num_acc_(-1)
|
||||
acc_(d),
|
||||
last_support_conditions_input_(0)
|
||||
{
|
||||
props = 0U;
|
||||
}
|
||||
|
|
@ -69,23 +69,6 @@ namespace spot
|
|||
return "";
|
||||
}
|
||||
|
||||
unsigned int
|
||||
tgba::number_of_acceptance_conditions() const
|
||||
{
|
||||
if (num_acc_ < 0)
|
||||
{
|
||||
bdd all = all_acceptance_conditions();
|
||||
unsigned int n = 0;
|
||||
while (all != bddfalse)
|
||||
{
|
||||
++n;
|
||||
all -= bdd_satone(all);
|
||||
}
|
||||
num_acc_ = n;
|
||||
}
|
||||
return num_acc_;
|
||||
}
|
||||
|
||||
bool
|
||||
tgba::is_empty() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
#ifndef SPOT_TGBA_TGBA_HH
|
||||
# define SPOT_TGBA_TGBA_HH
|
||||
|
||||
#include "bdddict.hh"
|
||||
#include "fwd.hh"
|
||||
#include "acc.hh"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include "misc/casts.hh"
|
||||
|
|
@ -387,7 +387,7 @@ namespace spot
|
|||
virtual bdd current_condition() const = 0;
|
||||
/// \brief Get the acceptance conditions on the transition leading
|
||||
/// to this successor.
|
||||
virtual bdd current_acceptance_conditions() const = 0;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const = 0;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
|
@ -467,7 +467,7 @@ namespace spot
|
|||
class SPOT_API tgba: public std::enable_shared_from_this<tgba>
|
||||
{
|
||||
protected:
|
||||
tgba();
|
||||
tgba(const bdd_dict_ptr& d);
|
||||
// Any iterator returned via release_iter.
|
||||
mutable tgba_succ_iterator* iter_cache_;
|
||||
|
||||
|
|
@ -572,7 +572,10 @@ namespace spot
|
|||
/// formulae, and vice versa. This is useful when dealing with
|
||||
/// several automata (which may use the same BDD variable for
|
||||
/// different formula), or simply when printing.
|
||||
virtual bdd_dict_ptr get_dict() const = 0;
|
||||
bdd_dict_ptr get_dict() const
|
||||
{
|
||||
return acc_.get_dict();
|
||||
}
|
||||
|
||||
/// \brief Format the state as a string for printing.
|
||||
///
|
||||
|
|
@ -615,40 +618,27 @@ namespace spot
|
|||
virtual state* project_state(const state* s,
|
||||
const const_tgba_ptr& t) const;
|
||||
|
||||
/// \brief Return the set of all acceptance conditions used
|
||||
/// by this automaton.
|
||||
///
|
||||
/// The goal of the emptiness check is to ensure that
|
||||
/// a strongly connected component walks through each
|
||||
/// of these acceptiong conditions. I.e., the union
|
||||
/// of the acceptiong conditions of all transition in
|
||||
/// the SCC should be equal to the result of this function.
|
||||
virtual bdd all_acceptance_conditions() const = 0;
|
||||
|
||||
/// The number of acceptance conditions.
|
||||
virtual unsigned int number_of_acceptance_conditions() const;
|
||||
const acc_cond& acc() const
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
/// \brief Return the conjuction of all negated acceptance
|
||||
/// variables.
|
||||
///
|
||||
/// For instance if the automaton uses variables <tt>Acc[a]</tt>,
|
||||
/// <tt>Acc[b]</tt> and <tt>Acc[c]</tt> to describe acceptance sets,
|
||||
/// this function should return <tt>!Acc[a]\&!Acc[b]\&!Acc[c]</tt>.
|
||||
///
|
||||
/// This is useful when making products: each operand's condition
|
||||
/// set should be augmented with the neg_acceptance_conditions() of
|
||||
/// the other operand.
|
||||
virtual bdd neg_acceptance_conditions() const = 0;
|
||||
acc_cond& acc()
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
virtual bool is_empty() const;
|
||||
|
||||
protected:
|
||||
acc_cond acc_;
|
||||
|
||||
/// Do the actual computation of tgba::support_conditions().
|
||||
virtual bdd compute_support_conditions(const state* state) const = 0;
|
||||
mutable const state* last_support_conditions_input_;
|
||||
private:
|
||||
mutable bdd last_support_conditions_output_;
|
||||
mutable int num_acc_;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -23,41 +23,6 @@
|
|||
namespace spot
|
||||
{
|
||||
|
||||
void tgba_digraph::set_acceptance_conditions(bdd all)
|
||||
{
|
||||
if (all_acceptance_conditions_ != bddfalse)
|
||||
dict_->unregister_all_typed_variables(bdd_dict::acc, this);
|
||||
|
||||
bdd sup = bdd_support(all);
|
||||
dict_->register_acceptance_variables(sup, this);
|
||||
neg_acceptance_conditions_ = bddtrue;
|
||||
while (sup != bddtrue)
|
||||
{
|
||||
neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
|
||||
sup = bdd_high(sup);
|
||||
}
|
||||
all_acceptance_conditions_ =
|
||||
compute_all_acceptance_conditions(neg_acceptance_conditions_);
|
||||
|
||||
prop_single_acc_set(number_of_acceptance_conditions() == 1);
|
||||
}
|
||||
|
||||
bdd tgba_digraph::set_single_acceptance_set()
|
||||
{
|
||||
if (all_acceptance_conditions_ != bddfalse)
|
||||
dict_->unregister_all_typed_variables(bdd_dict::acc, this);
|
||||
|
||||
prop_single_acc_set();
|
||||
|
||||
int accvar =
|
||||
dict_->register_acceptance_variable(ltl::constant::true_instance(),
|
||||
this);
|
||||
bdd degen_acc = bdd_ithvar(accvar);
|
||||
all_acceptance_conditions_ = degen_acc;
|
||||
neg_acceptance_conditions_ = bdd_nithvar(accvar);
|
||||
return degen_acc;
|
||||
}
|
||||
|
||||
void tgba_digraph::merge_transitions()
|
||||
{
|
||||
for (auto& s: g_.states())
|
||||
|
|
@ -65,7 +30,7 @@ namespace spot
|
|||
// Map a pair (dest state, acc) to the first transition seen
|
||||
// with such characteristic.
|
||||
|
||||
typedef std::pair<graph_t::state, int> key_t;
|
||||
typedef std::pair<graph_t::state, acc_cond::mark_t> key_t;
|
||||
std::unordered_map<key_t, graph_t::transition, pair_hash> trmap;
|
||||
|
||||
auto t = g_.out_iteraser(s);
|
||||
|
|
@ -78,7 +43,7 @@ namespace spot
|
|||
continue;
|
||||
}
|
||||
|
||||
key_t k(t->dst, t->acc.id());
|
||||
key_t k(t->dst, t->acc);
|
||||
auto p = trmap.emplace(k, t.trans());
|
||||
if (!p.second)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,14 +76,14 @@ namespace spot
|
|||
struct SPOT_API tgba_graph_trans_data
|
||||
{
|
||||
bdd cond;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
|
||||
explicit tgba_graph_trans_data()
|
||||
: cond(bddfalse), acc(bddfalse)
|
||||
: cond(bddfalse), acc(0)
|
||||
{
|
||||
}
|
||||
|
||||
tgba_graph_trans_data(bdd cond, bdd acc = bddfalse)
|
||||
tgba_graph_trans_data(bdd cond, acc_cond::mark_t acc = 0U)
|
||||
: cond(cond), acc(acc)
|
||||
{
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ namespace spot
|
|||
return g_->trans_data(p_).cond;
|
||||
}
|
||||
|
||||
virtual bdd current_acceptance_conditions() const
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
return g_->trans_data(p_).acc;
|
||||
|
|
@ -161,23 +161,18 @@ namespace spot
|
|||
|
||||
protected:
|
||||
graph_t g_;
|
||||
bdd_dict_ptr dict_;
|
||||
bdd all_acceptance_conditions_;
|
||||
bdd neg_acceptance_conditions_;
|
||||
mutable unsigned init_number_;
|
||||
|
||||
public:
|
||||
tgba_digraph(const bdd_dict_ptr& dict)
|
||||
: dict_(dict),
|
||||
all_acceptance_conditions_(bddfalse),
|
||||
neg_acceptance_conditions_(bddtrue),
|
||||
: tgba(dict),
|
||||
init_number_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~tgba_digraph()
|
||||
{
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
// Prevent this state from being destroyed by ~tgba(),
|
||||
// as the state will be destroyed when g_ is destroyed.
|
||||
last_support_conditions_input_ = 0;
|
||||
|
|
@ -212,11 +207,6 @@ namespace spot
|
|||
return g_;
|
||||
}
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const
|
||||
{
|
||||
return this->dict_;
|
||||
}
|
||||
|
||||
unsigned num_states() const
|
||||
{
|
||||
return g_.num_states();
|
||||
|
|
@ -314,8 +304,22 @@ namespace spot
|
|||
return g_.trans_data(t);
|
||||
}
|
||||
|
||||
void set_acceptance_conditions(bdd all);
|
||||
bdd set_single_acceptance_set();
|
||||
void set_acceptance_conditions(unsigned num)
|
||||
{
|
||||
if (num < acc_.num_sets())
|
||||
{
|
||||
acc_.~acc_cond();
|
||||
new (&acc_) acc_cond(get_dict());
|
||||
}
|
||||
acc_.add_sets(num - acc_.num_sets());
|
||||
prop_single_acc_set(num == 1);
|
||||
}
|
||||
|
||||
acc_cond::mark_t set_single_acceptance_set()
|
||||
{
|
||||
set_acceptance_conditions(1);
|
||||
return acc_.mark(0);
|
||||
}
|
||||
|
||||
unsigned new_state()
|
||||
{
|
||||
|
|
@ -328,7 +332,7 @@ namespace spot
|
|||
}
|
||||
|
||||
unsigned new_transition(unsigned src, unsigned dst,
|
||||
bdd cond, bdd acc = bddfalse)
|
||||
bdd cond, acc_cond::mark_t acc = 0U)
|
||||
{
|
||||
return g_.new_transition(src, dst, cond, acc);
|
||||
}
|
||||
|
|
@ -337,7 +341,7 @@ namespace spot
|
|||
bdd cond, bool acc = true)
|
||||
{
|
||||
if (acc)
|
||||
return g_.new_transition(src, dst, cond, all_acceptance_conditions_);
|
||||
return g_.new_transition(src, dst, cond, acc_.all_sets());
|
||||
else
|
||||
return g_.new_transition(src, dst, cond);
|
||||
}
|
||||
|
|
@ -364,22 +368,13 @@ namespace spot
|
|||
/// \brief Copy the acceptance conditions of another tgba.
|
||||
void copy_acceptance_conditions_of(const const_tgba_ptr& a)
|
||||
{
|
||||
set_acceptance_conditions(a->neg_acceptance_conditions());
|
||||
assert(acc_.num_sets() == 0);
|
||||
acc_.add_sets(a->acc().num_sets());
|
||||
}
|
||||
|
||||
void copy_ap_of(const const_tgba_ptr& a)
|
||||
{
|
||||
dict_->register_all_propositions_of(a, this);
|
||||
}
|
||||
|
||||
virtual bdd all_acceptance_conditions() const
|
||||
{
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
virtual bdd neg_acceptance_conditions() const
|
||||
{
|
||||
return neg_acceptance_conditions_;
|
||||
get_dict()->register_all_propositions_of(a, this);
|
||||
}
|
||||
|
||||
virtual bdd compute_support_conditions(const state* s) const
|
||||
|
|
@ -400,7 +395,7 @@ namespace spot
|
|||
for (auto& t: g_.out(s))
|
||||
// Stop at the first transition, since the remaining should be
|
||||
// labeled identically.
|
||||
return t.acc == all_acceptance_conditions_;
|
||||
return acc_.accepting(t.acc);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,685 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2010, 2011, 2013, 2014 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include "bdd.h"
|
||||
#include "bddprint.hh"
|
||||
#include "tgba.hh"
|
||||
#include "tgbakvcomplement.hh"
|
||||
#include "misc/hash.hh"
|
||||
#include "tgbaalgos/bfssteps.hh"
|
||||
#include "misc/hashfunc.hh"
|
||||
#include "ltlast/formula.hh"
|
||||
#include "ltlast/constant.hh"
|
||||
#include "priv/countstates.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// rank
|
||||
|
||||
/// \brief A rank structure, one of the main structure of the algorithm.
|
||||
///
|
||||
/// A rank has a number (\a rank) that refers to the depth in the DAG of
|
||||
/// the current word. When the rank is odd, a \a condition is associated
|
||||
/// to this rank.
|
||||
struct rank_t
|
||||
{
|
||||
mutable unsigned rank;
|
||||
mutable bdd_ordered condition;
|
||||
|
||||
bool operator<(const rank_t& other) const
|
||||
{
|
||||
return rank < other.rank ||
|
||||
condition.order() < other.condition.order();
|
||||
}
|
||||
|
||||
unsigned get_rank() const
|
||||
{
|
||||
return rank;
|
||||
}
|
||||
|
||||
bdd_ordered get_condition() const
|
||||
{
|
||||
return condition;
|
||||
}
|
||||
|
||||
size_t hash() const
|
||||
{
|
||||
size_t hash = wang32_hash(rank);
|
||||
if (rank & 1)
|
||||
hash ^= wang32_hash(condition.order());
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string format(const bdd_dict_ptr& d) const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "{rank: " << rank;
|
||||
if (rank & 1)
|
||||
{
|
||||
ss << ", bdd: {" << condition.order() << ", "
|
||||
<< bdd_format_accset(d, condition.get_bdd())
|
||||
<< "} ";
|
||||
}
|
||||
ss << '}';
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
// typedefs.
|
||||
typedef std::unordered_map<shared_state, rank_t,
|
||||
state_shared_ptr_hash,
|
||||
state_shared_ptr_equal> state_rank_map;
|
||||
|
||||
////////////////////////////////////////
|
||||
// state_kv_complement
|
||||
|
||||
/// States used by spot::tgba_kv_complement.
|
||||
/// A state has a map of states associated to ranks, and a set
|
||||
/// of filtered states.
|
||||
/// \ingroup tgba_representation
|
||||
class state_kv_complement : public state
|
||||
{
|
||||
public:
|
||||
state_kv_complement();
|
||||
state_kv_complement(state_rank_map state_map,
|
||||
shared_state_set state_filter);
|
||||
virtual ~state_kv_complement() {}
|
||||
|
||||
virtual int compare(const state* other) const;
|
||||
virtual size_t hash() const;
|
||||
virtual state_kv_complement* clone() const;
|
||||
|
||||
void add(shared_state state, const rank_t& rank);
|
||||
const state_rank_map& get_state_map() const;
|
||||
const shared_state_set& get_filter_set() const;
|
||||
bool accepting() const;
|
||||
private:
|
||||
state_rank_map state_map_;
|
||||
shared_state_set state_filter_;
|
||||
};
|
||||
|
||||
state_kv_complement::state_kv_complement()
|
||||
{
|
||||
}
|
||||
|
||||
state_kv_complement::state_kv_complement(state_rank_map state_map,
|
||||
shared_state_set state_filter)
|
||||
: state_map_(state_map), state_filter_(state_filter)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
state_kv_complement::compare(const state* o) const
|
||||
{
|
||||
const state_kv_complement* other =
|
||||
down_cast<const state_kv_complement*>(o);
|
||||
|
||||
if (other == 0)
|
||||
return 1;
|
||||
|
||||
if (state_map_.size() < other->state_map_.size())
|
||||
return -1;
|
||||
else if (state_map_.size() > other->state_map_.size())
|
||||
return 1;
|
||||
|
||||
if (state_filter_.size() < other->state_filter_.size())
|
||||
return -1;
|
||||
else if (state_filter_.size() > other->state_filter_.size())
|
||||
return 1;
|
||||
|
||||
{
|
||||
state_rank_map::const_iterator i = state_map_.begin();
|
||||
state_rank_map::const_iterator j = other->state_map_.begin();
|
||||
while (i != state_map_.end() && j != other->state_map_.end())
|
||||
{
|
||||
int result = i->first->compare(j->first.get());
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (i->second < j->second)
|
||||
return -1;
|
||||
if (j->second < i->second)
|
||||
return 1;
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
shared_state_set::const_iterator i = state_filter_.begin();
|
||||
shared_state_set::const_iterator j = other->state_filter_.begin();
|
||||
while (i != state_filter_.end() && j != other->state_filter_.end())
|
||||
{
|
||||
int result = (*i)->compare(j->get());
|
||||
if (result != 0)
|
||||
return result;
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
state_kv_complement::hash() const
|
||||
{
|
||||
size_t hash = 0;
|
||||
|
||||
{
|
||||
state_rank_map::const_iterator i = state_map_.begin();
|
||||
while (i != state_map_.end())
|
||||
{
|
||||
hash ^= i->first->hash();
|
||||
hash ^= i->second.hash();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
shared_state_set::const_iterator i = state_filter_.begin();
|
||||
while (i != state_filter_.end())
|
||||
{
|
||||
hash ^= (*i)->hash();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
state_kv_complement*
|
||||
state_kv_complement::clone() const
|
||||
{
|
||||
return new state_kv_complement(*this);
|
||||
}
|
||||
|
||||
void
|
||||
state_kv_complement::add(shared_state state,
|
||||
const rank_t& rank)
|
||||
{
|
||||
state_map_[state] = rank;
|
||||
}
|
||||
|
||||
const state_rank_map&
|
||||
state_kv_complement::get_state_map() const
|
||||
{
|
||||
return state_map_;
|
||||
}
|
||||
|
||||
const shared_state_set&
|
||||
state_kv_complement::get_filter_set() const
|
||||
{
|
||||
return state_filter_;
|
||||
}
|
||||
|
||||
bool
|
||||
state_kv_complement::accepting() const
|
||||
{
|
||||
return state_filter_.empty();
|
||||
}
|
||||
|
||||
/// Successor iterators used by spot::tgba_kv_complement.
|
||||
/// \ingroup tgba_representation
|
||||
///
|
||||
/// Since the algorithm works on-the-fly, the key components of the
|
||||
/// algorithm are implemented in this class.
|
||||
///
|
||||
///
|
||||
class tgba_kv_complement_succ_iterator: public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::list<bdd> bdd_list_t;
|
||||
|
||||
tgba_kv_complement_succ_iterator(const tgba_sgba_proxy* automaton,
|
||||
bdd the_acceptance_cond,
|
||||
const acc_list_t& acc_list,
|
||||
const state_kv_complement* origin);
|
||||
virtual ~tgba_kv_complement_succ_iterator() {};
|
||||
|
||||
virtual bool first();
|
||||
virtual bool next();
|
||||
virtual bool done() const;
|
||||
virtual state_kv_complement* current_state() const;
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
private:
|
||||
/// \brief Create the highest rank of \a origin_ as origin and
|
||||
/// \a condition as successor condition.
|
||||
void successor_highest_rank(bdd condition);
|
||||
void get_atomics(std::set<int>& list, bdd c);
|
||||
void get_conj_list();
|
||||
bool is_valid_rank() const;
|
||||
bool next_valid_rank();
|
||||
|
||||
const tgba_sgba_proxy* automaton_;
|
||||
bdd the_acceptance_cond_;
|
||||
const acc_list_t& acc_list_;
|
||||
const state_kv_complement* origin_;
|
||||
bdd_list_t condition_list_;
|
||||
bdd_list_t::const_iterator current_condition_;
|
||||
state_rank_map highest_current_ranks_;
|
||||
state_rank_map current_ranks_;
|
||||
shared_state_set highest_state_set_;
|
||||
};
|
||||
|
||||
tgba_kv_complement_succ_iterator::
|
||||
tgba_kv_complement_succ_iterator(const tgba_sgba_proxy* automaton,
|
||||
bdd the_acceptance_cond,
|
||||
const acc_list_t& acc_list,
|
||||
const state_kv_complement* origin)
|
||||
: automaton_(automaton), the_acceptance_cond_(the_acceptance_cond),
|
||||
acc_list_(acc_list), origin_(origin)
|
||||
{
|
||||
get_conj_list();
|
||||
}
|
||||
|
||||
/// Insert in \a list atomic properties of the formula \a c.
|
||||
void
|
||||
tgba_kv_complement_succ_iterator::get_atomics(std::set<int>& list, bdd c)
|
||||
{
|
||||
bdd current = bdd_satone(c);
|
||||
while (current != bddtrue && current != bddfalse)
|
||||
{
|
||||
list.insert(bdd_var(current));
|
||||
bdd high = bdd_high(current);
|
||||
if (high == bddfalse)
|
||||
current = bdd_low(current);
|
||||
else
|
||||
current = high;
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the conjunction of all the atomic properties from
|
||||
/// the successors of the current state.
|
||||
void
|
||||
tgba_kv_complement_succ_iterator::get_conj_list()
|
||||
{
|
||||
std::set<int> atomics;
|
||||
condition_list_.clear();
|
||||
state_rank_map sr_map = origin_->get_state_map();
|
||||
|
||||
// Retrieve all the atomics in acceptance conditions.
|
||||
for (state_rank_map::const_iterator i = sr_map.begin();
|
||||
i != sr_map.end();
|
||||
++i)
|
||||
{
|
||||
for (auto iterator: automaton_->succ(i->first.get()))
|
||||
{
|
||||
bdd c = iterator->current_condition();
|
||||
get_atomics(atomics, c);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the conjunction of all those atomic properties.
|
||||
unsigned atomics_size = atomics.size();
|
||||
|
||||
assert(atomics_size < 32);
|
||||
for (unsigned i = 1; i <= static_cast<unsigned>(1 << atomics_size); ++i)
|
||||
{
|
||||
bdd result = bddtrue;
|
||||
unsigned position = 1;
|
||||
for (std::set<int>::const_iterator a_it = atomics.begin();
|
||||
a_it != atomics.end();
|
||||
++a_it, position <<= 1)
|
||||
{
|
||||
bdd this_atomic;
|
||||
if (position & i)
|
||||
this_atomic = bdd_ithvar(*a_it);
|
||||
else
|
||||
this_atomic = bdd_nithvar(*a_it);
|
||||
result = bdd_apply(result, this_atomic, bddop_and);
|
||||
}
|
||||
condition_list_.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether \a current_ranks_ is a valid rank.
|
||||
/// For each odd rank, its condition associated must not
|
||||
/// be present in its tracked state.
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::is_valid_rank() const
|
||||
{
|
||||
for (state_rank_map::const_iterator i = current_ranks_.begin();
|
||||
i != current_ranks_.end();
|
||||
++i)
|
||||
{
|
||||
if (i->second.rank & 1)
|
||||
{
|
||||
if ((automaton_->state_acceptance_conditions(i->first.get()) &
|
||||
i->second.condition.get_bdd()) != bddfalse)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Decrease \a current_ranks_ and produces a valid rank.
|
||||
/// \a current_ranks_ is a map of states to a rank.
|
||||
/// A rank for a state is valid if it is inferior than the rank of its
|
||||
/// predecessor.
|
||||
/// When the rank is odd, its has an acceptance condition associated that
|
||||
/// must not be in its associated state.
|
||||
/// \return false if there is not valid rank as successor.
|
||||
bool tgba_kv_complement_succ_iterator::next_valid_rank()
|
||||
{
|
||||
state_rank_map::const_iterator i;
|
||||
do
|
||||
{
|
||||
for (i = current_ranks_.begin(); i != current_ranks_.end(); ++i)
|
||||
{
|
||||
if (i->second.rank != 0)
|
||||
{
|
||||
if (i->second.rank & 1)
|
||||
{
|
||||
if (i->second.condition.order() == 0)
|
||||
--i->second.rank;
|
||||
else
|
||||
i->second.condition =
|
||||
acc_list_[i->second.condition.order() - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
--i->second.rank;
|
||||
i->second.condition = acc_list_[acc_list_.size() - 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_ranks_[i->first] = highest_current_ranks_[i->first];
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((i != current_ranks_.end()) && !is_valid_rank());
|
||||
|
||||
return i != current_ranks_.end();
|
||||
}
|
||||
|
||||
/// \brief Create the highest rank of \a origin_ as origin and
|
||||
/// \a condition as successor condition.
|
||||
void
|
||||
tgba_kv_complement_succ_iterator::successor_highest_rank(bdd condition)
|
||||
{
|
||||
// Highest rank for bdd.
|
||||
state_rank_map sr_map = origin_->get_state_map();
|
||||
highest_current_ranks_.clear();
|
||||
|
||||
for (state_rank_map::const_iterator i = sr_map.begin();
|
||||
i != sr_map.end();
|
||||
++i)
|
||||
{
|
||||
for (auto iterator: automaton_->succ(i->first.get()))
|
||||
{
|
||||
bdd c = iterator->current_condition();
|
||||
if ((c & condition) != bddfalse)
|
||||
{
|
||||
shared_state s(iterator->current_state(), shared_state_deleter);
|
||||
if (highest_current_ranks_.find(s) != highest_current_ranks_.end())
|
||||
{
|
||||
if (i->second < highest_current_ranks_[s])
|
||||
highest_current_ranks_[s] = i->second;
|
||||
}
|
||||
else
|
||||
highest_current_ranks_[s] = i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Highest $O$ set of the algorithm.
|
||||
shared_state_set s_set = origin_->get_filter_set();
|
||||
highest_state_set_.clear();
|
||||
|
||||
for (shared_state_set::const_iterator i = s_set.begin();
|
||||
i != s_set.end();
|
||||
++i)
|
||||
{
|
||||
for (auto iterator: automaton_->succ(i->get()))
|
||||
{
|
||||
bdd c = iterator->current_condition();
|
||||
if ((c & condition) != bddfalse)
|
||||
{
|
||||
shared_state s(iterator->current_state(), shared_state_deleter);
|
||||
highest_state_set_.insert(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current_ranks_ = highest_current_ranks_;
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::first()
|
||||
{
|
||||
current_condition_ = condition_list_.begin();
|
||||
if (current_condition_ == condition_list_.end())
|
||||
return false;
|
||||
|
||||
successor_highest_rank(*current_condition_);
|
||||
|
||||
if (!is_valid_rank())
|
||||
next_valid_rank();
|
||||
return current_condition_ != condition_list_.end();
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::next()
|
||||
{
|
||||
if (current_condition_ == condition_list_.end())
|
||||
return false;
|
||||
|
||||
if (!next_valid_rank())
|
||||
{
|
||||
++current_condition_;
|
||||
if (!done())
|
||||
{
|
||||
successor_highest_rank(*current_condition_);
|
||||
if (!is_valid_rank())
|
||||
next_valid_rank();
|
||||
}
|
||||
}
|
||||
return current_condition_ != condition_list_.end();
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::done() const
|
||||
{
|
||||
return current_condition_ == condition_list_.end();
|
||||
}
|
||||
|
||||
state_kv_complement*
|
||||
tgba_kv_complement_succ_iterator::current_state() const
|
||||
{
|
||||
if (done())
|
||||
return 0;
|
||||
|
||||
// If the filter set is empty, all the states of the map
|
||||
// that are associated to an even rank create the new filter set.
|
||||
shared_state_set filter;
|
||||
if (origin_->get_filter_set().empty())
|
||||
{
|
||||
for (state_rank_map::const_iterator i = current_ranks_.begin();
|
||||
i != current_ranks_.end();
|
||||
++i)
|
||||
if (!(i->second.rank & 1))
|
||||
filter.insert(i->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It the filter set is non-empty, we delete from this set states
|
||||
// that are now associated to an odd rank.
|
||||
for (shared_state_set::const_iterator i = highest_state_set_.begin();
|
||||
i != highest_state_set_.end();
|
||||
++i)
|
||||
{
|
||||
state_rank_map::const_iterator s(current_ranks_.find(*i));
|
||||
assert(s != current_ranks_.end());
|
||||
|
||||
if (!(s->second.get_rank() & 1))
|
||||
filter.insert(*i);
|
||||
}
|
||||
}
|
||||
|
||||
return new state_kv_complement(current_ranks_, filter);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement_succ_iterator::current_condition() const
|
||||
{
|
||||
if (done())
|
||||
return bddfalse;
|
||||
return *current_condition_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
if (done())
|
||||
return bddfalse;
|
||||
|
||||
// This algorithm doesn't generalized acceptance conditions.
|
||||
if (origin_->accepting())
|
||||
return the_acceptance_cond_;
|
||||
else
|
||||
return bddfalse;
|
||||
}
|
||||
|
||||
} // end namespace anonymous.
|
||||
|
||||
/// Retrieve all the atomic acceptance conditions of the automaton.
|
||||
/// They are inserted into \a acc_list_.
|
||||
void
|
||||
tgba_kv_complement::get_acc_list()
|
||||
{
|
||||
bdd c = automaton_->all_acceptance_conditions();
|
||||
bdd current = bdd_satone(c);
|
||||
unsigned i = 0;
|
||||
while (current != bddtrue && current != bddfalse)
|
||||
{
|
||||
acc_list_.push_back(bdd_ordered(bdd_var(current), i));
|
||||
++i;
|
||||
bdd high = bdd_high(current);
|
||||
if (high == bddfalse)
|
||||
current = bdd_low(current);
|
||||
else
|
||||
current = high;
|
||||
}
|
||||
}
|
||||
|
||||
tgba_kv_complement::tgba_kv_complement(const const_tgba_ptr& a)
|
||||
: automaton_(make_sgba(a))
|
||||
{
|
||||
get_dict()->register_all_variables_of(automaton_, this);
|
||||
int v = get_dict()
|
||||
->register_acceptance_variable(ltl::constant::true_instance(), this);
|
||||
the_acceptance_cond_ = bdd_ithvar(v);
|
||||
nb_states_ = count_states(automaton_);
|
||||
get_acc_list();
|
||||
}
|
||||
|
||||
tgba_kv_complement::~tgba_kv_complement()
|
||||
{
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
state*
|
||||
tgba_kv_complement::get_init_state() const
|
||||
{
|
||||
state_kv_complement* init = new state_kv_complement();
|
||||
rank_t r = {2 * nb_states_, bdd_ordered()};
|
||||
init->add(shared_state(automaton_->get_init_state(), shared_state_deleter),
|
||||
r);
|
||||
return init;
|
||||
}
|
||||
|
||||
tgba_succ_iterator*
|
||||
tgba_kv_complement::succ_iter(const state* state) const
|
||||
{
|
||||
const state_kv_complement* s =
|
||||
down_cast<const state_kv_complement*>(state);
|
||||
assert(s);
|
||||
|
||||
return new tgba_kv_complement_succ_iterator(automaton_.get(),
|
||||
the_acceptance_cond_,
|
||||
acc_list_, s);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_kv_complement::get_dict() const
|
||||
{
|
||||
return automaton_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_kv_complement::format_state(const state* state) const
|
||||
{
|
||||
const state_kv_complement* s =
|
||||
down_cast<const state_kv_complement*>(state);
|
||||
assert(s);
|
||||
std::ostringstream ss;
|
||||
ss << "{ set: {" << std::endl;
|
||||
|
||||
const state_rank_map& state_map = s->get_state_map();
|
||||
const shared_state_set& state_filter = s->get_filter_set();
|
||||
|
||||
for (state_rank_map::const_iterator i = state_map.begin();
|
||||
i != state_map.end();
|
||||
++i)
|
||||
{
|
||||
ss << " {" << automaton_->format_state(i->first.get())
|
||||
<< ", " << i->second.format(get_dict()) << "}\n";
|
||||
}
|
||||
ss << "} odd-less: {";
|
||||
|
||||
for (shared_state_set::const_iterator i = state_filter.begin();
|
||||
i != state_filter.end();
|
||||
++i)
|
||||
ss << " " << automaton_->format_state(i->get()) << '\n';
|
||||
ss << "} }";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement::all_acceptance_conditions() const
|
||||
{
|
||||
return the_acceptance_cond_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement::neg_acceptance_conditions() const
|
||||
{
|
||||
return !the_acceptance_cond_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement::compute_support_conditions(const state* state) const
|
||||
{
|
||||
bdd result = bddfalse;
|
||||
for (auto i: succ(state))
|
||||
result |= i->current_condition();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace spot.
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2010, 2012, 2013, 2014 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_TGBA_TGBAKVCOMPLEMENT_HH
|
||||
#define SPOT_TGBA_TGBAKVCOMPLEMENT_HH
|
||||
|
||||
#include <vector>
|
||||
#include "bdd.h"
|
||||
#include "tgba.hh"
|
||||
#include "tgba/tgbasgba.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
class SPOT_API bdd_ordered
|
||||
{
|
||||
public:
|
||||
bdd_ordered()
|
||||
: bdd_(0), order_(0)
|
||||
{};
|
||||
|
||||
bdd_ordered(int bdd_, unsigned order_)
|
||||
: bdd_(bdd_), order_(order_)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned order() const
|
||||
{
|
||||
return order_;
|
||||
}
|
||||
|
||||
unsigned& order()
|
||||
{
|
||||
return order_;
|
||||
}
|
||||
|
||||
bdd get_bdd() const
|
||||
{
|
||||
return bdd_ithvar(bdd_);
|
||||
}
|
||||
private:
|
||||
int bdd_;
|
||||
unsigned order_;
|
||||
};
|
||||
|
||||
typedef std::vector<bdd_ordered> acc_list_t;
|
||||
|
||||
/// \ingroup tgba_on_the_fly_algorithms
|
||||
/// \brief Build a complemented automaton.
|
||||
///
|
||||
/// The construction comes from:
|
||||
/** \verbatim
|
||||
@Article{ kupferman.05.tcs,
|
||||
title = {From complementation to certification},
|
||||
author = {Kupferman, O. and Vardi, M.Y.},
|
||||
journal = {Theoretical Computer Science},
|
||||
volume = {345},
|
||||
number = {1},
|
||||
pages = {83--100},
|
||||
year = {2005},
|
||||
publisher = {Elsevier}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
/// The original automaton is used as a States-based Generalized
|
||||
/// Büchi Automaton.
|
||||
///
|
||||
/// The construction is done on-the-fly, by the
|
||||
/// \c tgba_kv_complement_succ_iterator class.
|
||||
/// \see tgba_kv_complement_succ_iterator
|
||||
class SPOT_API tgba_kv_complement : public tgba
|
||||
{
|
||||
public:
|
||||
tgba_kv_complement(const const_tgba_ptr& a);
|
||||
virtual ~tgba_kv_complement();
|
||||
|
||||
// tgba interface
|
||||
virtual state* get_init_state() const;
|
||||
virtual tgba_succ_iterator* succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
virtual std::string format_state(const state* state) const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
private:
|
||||
/// Retrieve all the atomic acceptance conditions of the automaton.
|
||||
/// They are inserted into \a acc_list_.
|
||||
void get_acc_list();
|
||||
private:
|
||||
const_tgba_sgba_proxy_ptr automaton_;
|
||||
bdd the_acceptance_cond_;
|
||||
unsigned nb_states_;
|
||||
acc_list_t acc_list_;
|
||||
}; // end class tgba_kv_complement.
|
||||
|
||||
typedef std::shared_ptr<tgba_kv_complement> tgba_kv_complement_ptr;
|
||||
typedef std::shared_ptr<const tgba_kv_complement>
|
||||
const_tgba_kv_complement_ptr;
|
||||
inline tgba_kv_complement_ptr
|
||||
make_kv_complement(const const_tgba_ptr& a)
|
||||
{
|
||||
return std::make_shared<tgba_kv_complement>(a);
|
||||
}
|
||||
} // end namespace spot.
|
||||
|
||||
|
||||
#endif // !SPOT_TGBA_TGBAKVCOMPLEMENT_HH
|
||||
|
|
@ -28,7 +28,7 @@ namespace spot
|
|||
{
|
||||
const state* dest;
|
||||
bdd cond;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
};
|
||||
typedef std::vector<transition> transitions;
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ namespace spot
|
|||
return it_->cond;
|
||||
}
|
||||
|
||||
bdd current_acceptance_conditions() const
|
||||
acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
return it_->acc;
|
||||
}
|
||||
|
|
@ -128,19 +128,19 @@ namespace spot
|
|||
for (auto it: original_->succ(local_state))
|
||||
{
|
||||
const spot::state* s = it->current_state();
|
||||
bdd acc = it->current_acceptance_conditions();
|
||||
auto acc = it->current_acceptance_conditions();
|
||||
if (!wanted(s, acc))
|
||||
{
|
||||
s->destroy();
|
||||
continue;
|
||||
}
|
||||
res->trans_.emplace_back(transition {s, it->current_condition(),
|
||||
acc});
|
||||
res->trans_.emplace_back
|
||||
(transition {s, it->current_condition(), acc});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual bool wanted(const state* s, const bdd& acc) const = 0;
|
||||
virtual bool wanted(const state* s, acc_cond::mark_t acc) const = 0;
|
||||
|
||||
protected:
|
||||
const state* init_;
|
||||
|
|
@ -158,7 +158,7 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
bool wanted(const state* s, const bdd&) const
|
||||
bool wanted(const state* s, const acc_cond::mark_t) const
|
||||
{
|
||||
state_set::const_iterator i = mask_.find(s);
|
||||
return i != mask_.end();
|
||||
|
|
@ -177,7 +177,7 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
bool wanted(const state* s, const bdd&) const
|
||||
bool wanted(const state* s, const acc_cond::mark_t) const
|
||||
{
|
||||
state_set::const_iterator i = mask_.find(s);
|
||||
return i == mask_.end();
|
||||
|
|
@ -186,19 +186,19 @@ namespace spot
|
|||
|
||||
class tgba_mask_acc_ignore: public tgba_mask
|
||||
{
|
||||
const bdd& mask_;
|
||||
unsigned mask_;
|
||||
public:
|
||||
tgba_mask_acc_ignore(const const_tgba_ptr& masked,
|
||||
const bdd& mask,
|
||||
unsigned mask,
|
||||
const state* init)
|
||||
: tgba_mask(masked, init),
|
||||
mask_(mask)
|
||||
{
|
||||
}
|
||||
|
||||
bool wanted(const state*, const bdd& acc) const
|
||||
bool wanted(const state*, const acc_cond::mark_t acc) const
|
||||
{
|
||||
return (acc & mask_) == bddfalse;
|
||||
return !acc.has(mask_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ namespace spot
|
|||
|
||||
const_tgba_ptr
|
||||
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
||||
const bdd to_ignore,
|
||||
unsigned to_ignore,
|
||||
const state* init)
|
||||
{
|
||||
return std::make_shared<tgba_mask_acc_ignore>(to_mask, to_ignore, init);
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ namespace spot
|
|||
/// \ingroup tgba_on_the_fly_algorithms
|
||||
/// \brief Mask a TGBA, rejecting some acceptance set of transitions.
|
||||
///
|
||||
/// This will ignore all transitions labeled by the acceptance ACC
|
||||
/// such that ACC & TO_IGNORE != bddfalse. The initial state can
|
||||
/// optionally be reset to \a init.
|
||||
/// This will ignore all transitions that have the TO_IGNORE
|
||||
/// acceptance mark. The initial state can optionally be reset to
|
||||
/// \a init.
|
||||
///
|
||||
/// Note that the acceptance condition of the automaton (i.e. the
|
||||
/// set of all acceptance set) is not changed, because so far this
|
||||
|
|
@ -62,7 +62,7 @@ namespace spot
|
|||
/// all_acceptance_conditions().
|
||||
SPOT_API const_tgba_ptr
|
||||
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
||||
const bdd to_ignore,
|
||||
unsigned to_ignore,
|
||||
const state* init = 0);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,9 @@ namespace spot
|
|||
public:
|
||||
tgba_succ_iterator_product_common(tgba_succ_iterator* left,
|
||||
tgba_succ_iterator* right,
|
||||
const tgba_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: left_(left), right_(right), pool_(pool)
|
||||
: left_(left), right_(right), prod_(prod), pool_(pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +140,7 @@ namespace spot
|
|||
protected:
|
||||
tgba_succ_iterator* left_;
|
||||
tgba_succ_iterator* right_;
|
||||
const tgba_product* prod_;
|
||||
fixed_size_pool* pool_;
|
||||
friend class spot::tgba_product;
|
||||
};
|
||||
|
|
@ -150,13 +152,9 @@ namespace spot
|
|||
public:
|
||||
tgba_succ_iterator_product(tgba_succ_iterator* left,
|
||||
tgba_succ_iterator* right,
|
||||
bdd left_neg, bdd right_neg,
|
||||
bddPair* right_common_acc,
|
||||
const tgba_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: tgba_succ_iterator_product_common(left, right, pool),
|
||||
left_neg_(left_neg),
|
||||
right_neg_(right_neg),
|
||||
right_common_acc_(right_common_acc)
|
||||
: tgba_succ_iterator_product_common(left, right, prod, pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -203,18 +201,17 @@ namespace spot
|
|||
return current_cond_;
|
||||
}
|
||||
|
||||
bdd current_acceptance_conditions() const
|
||||
acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
return ((left_->current_acceptance_conditions() & right_neg_)
|
||||
| (bdd_replace(right_->current_acceptance_conditions(),
|
||||
right_common_acc_) & left_neg_));
|
||||
return
|
||||
prod_->acc().join(prod_->left_acc(),
|
||||
left_->current_acceptance_conditions(),
|
||||
prod_->right_acc(),
|
||||
right_->current_acceptance_conditions());
|
||||
}
|
||||
|
||||
protected:
|
||||
bdd current_cond_;
|
||||
bdd left_neg_;
|
||||
bdd right_neg_;
|
||||
bddPair* right_common_acc_;
|
||||
};
|
||||
|
||||
/// Iterate over the successors of a product computed on the fly.
|
||||
|
|
@ -225,8 +222,9 @@ namespace spot
|
|||
public:
|
||||
tgba_succ_iterator_product_kripke(tgba_succ_iterator* left,
|
||||
tgba_succ_iterator* right,
|
||||
const tgba_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: tgba_succ_iterator_product_common(left, right, pool)
|
||||
: tgba_succ_iterator_product_common(left, right, prod, pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +268,7 @@ namespace spot
|
|||
return current_cond_;
|
||||
}
|
||||
|
||||
bdd current_acceptance_conditions() const
|
||||
acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
return right_->current_acceptance_conditions();
|
||||
}
|
||||
|
|
@ -286,10 +284,10 @@ namespace spot
|
|||
|
||||
tgba_product::tgba_product(const const_tgba_ptr& left,
|
||||
const const_tgba_ptr& right)
|
||||
: dict_(left->get_dict()), left_(left), right_(right),
|
||||
: tgba(left->get_dict()), left_(left), right_(right),
|
||||
pool_(sizeof(state_product))
|
||||
{
|
||||
assert(dict_ == right_->get_dict());
|
||||
assert(get_dict() == right_->get_dict());
|
||||
|
||||
// If one of the side is a Kripke structure, it is easier to deal
|
||||
// with (we don't have to fix the acceptance conditions, and
|
||||
|
|
@ -308,55 +306,17 @@ namespace spot
|
|||
left_kripke_ = false;
|
||||
}
|
||||
|
||||
dict_->register_all_variables_of(&left_, this);
|
||||
dict_->register_all_variables_of(&right_, this);
|
||||
auto d = get_dict();
|
||||
d->register_all_propositions_of(&left_, this);
|
||||
d->register_all_propositions_of(&right_, this);
|
||||
|
||||
if (left_kripke_)
|
||||
{
|
||||
all_acceptance_conditions_ = right_->all_acceptance_conditions();
|
||||
neg_acceptance_conditions_ = right_->neg_acceptance_conditions();
|
||||
return;
|
||||
}
|
||||
|
||||
bdd lna = left_->neg_acceptance_conditions();
|
||||
bdd rna = right_->neg_acceptance_conditions();
|
||||
|
||||
right_common_acc_ = bdd_newpair();
|
||||
|
||||
bdd tmp = lna;
|
||||
while (tmp != bddtrue)
|
||||
{
|
||||
assert(bdd_high(tmp) == bddfalse);
|
||||
int var = bdd_var(tmp);
|
||||
if (bdd_implies(rna, bdd_nithvar(var)))
|
||||
{
|
||||
int varclone = dict_->register_clone_acc(var, this);
|
||||
bdd_setpair(right_common_acc_, var, varclone);
|
||||
}
|
||||
tmp = bdd_low(tmp);
|
||||
}
|
||||
|
||||
bdd lac = left_->all_acceptance_conditions();
|
||||
bdd rac = right_->all_acceptance_conditions();
|
||||
|
||||
rna = bdd_replace(rna, right_common_acc_);
|
||||
rac = bdd_replace(rac, right_common_acc_);
|
||||
|
||||
left_acc_complement_ = lna;
|
||||
assert(bdd_exist(lna, rna) == lna);
|
||||
right_acc_complement_ = rna;
|
||||
assert(bdd_exist(rna, lna) == rna);
|
||||
|
||||
all_acceptance_conditions_ = ((lac & right_acc_complement_)
|
||||
| (rac & left_acc_complement_));
|
||||
neg_acceptance_conditions_ = lna & rna;
|
||||
assert(acc_.num_sets() == 0);
|
||||
acc_.add_sets(left->acc().num_sets() + right->acc().num_sets());
|
||||
}
|
||||
|
||||
tgba_product::~tgba_product()
|
||||
{
|
||||
if (!left_kripke_)
|
||||
bdd_freepair(right_common_acc_);
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
// Prevent these states from being destroyed by ~tgba(): they
|
||||
// will be destroyed before when the pool is destructed.
|
||||
if (last_support_conditions_input_)
|
||||
|
|
@ -393,13 +353,9 @@ namespace spot
|
|||
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
||||
if (left_kripke_)
|
||||
return new tgba_succ_iterator_product_kripke(li, ri, p);
|
||||
return new tgba_succ_iterator_product_kripke(li, ri, this, p);
|
||||
else
|
||||
return new tgba_succ_iterator_product(li, ri,
|
||||
left_acc_complement_,
|
||||
right_acc_complement_,
|
||||
right_common_acc_,
|
||||
p);
|
||||
return new tgba_succ_iterator_product(li, ri, this, p);
|
||||
}
|
||||
|
||||
bdd
|
||||
|
|
@ -412,10 +368,14 @@ namespace spot
|
|||
return lsc & rsc;
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_product::get_dict() const
|
||||
const acc_cond& tgba_product::left_acc() const
|
||||
{
|
||||
return dict_;
|
||||
return left_->acc();
|
||||
}
|
||||
|
||||
const acc_cond& tgba_product::right_acc() const
|
||||
{
|
||||
return right_->acc();
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
@ -441,18 +401,6 @@ namespace spot
|
|||
return right_->project_state(s2->right(), t);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_product::all_acceptance_conditions() const
|
||||
{
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_product::neg_acceptance_conditions() const
|
||||
{
|
||||
return neg_acceptance_conditions_;
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_product::transition_annotation(const tgba_succ_iterator* t) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ namespace spot
|
|||
virtual tgba_succ_iterator*
|
||||
succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
|
||||
virtual std::string format_state(const state* state) const;
|
||||
|
||||
virtual std::string
|
||||
|
|
@ -103,22 +101,16 @@ namespace spot
|
|||
|
||||
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
const acc_cond& left_acc() const;
|
||||
const acc_cond& right_acc() const;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
|
||||
protected:
|
||||
bdd_dict_ptr dict_;
|
||||
const_tgba_ptr left_;
|
||||
const_tgba_ptr right_;
|
||||
bool left_kripke_;
|
||||
bdd left_acc_complement_;
|
||||
bdd right_acc_complement_;
|
||||
bdd all_acceptance_conditions_;
|
||||
bdd neg_acceptance_conditions_;
|
||||
bddPair* right_common_acc_;
|
||||
fixed_size_pool pool_;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -22,9 +22,10 @@
|
|||
namespace spot
|
||||
{
|
||||
tgba_proxy::tgba_proxy(const const_tgba_ptr& original)
|
||||
: original_(original)
|
||||
: tgba(original->get_dict()), original_(original)
|
||||
{
|
||||
get_dict()->register_all_variables_of(original, this);
|
||||
acc_.add_sets(original->acc().num_sets());
|
||||
}
|
||||
|
||||
tgba_proxy::~tgba_proxy()
|
||||
|
|
@ -48,12 +49,6 @@ namespace spot
|
|||
return original_->succ_iter(state);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_proxy::get_dict() const
|
||||
{
|
||||
return original_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_proxy::format_state(const state* state) const
|
||||
{
|
||||
|
|
@ -72,18 +67,6 @@ namespace spot
|
|||
return original_->project_state(s, t);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_proxy::all_acceptance_conditions() const
|
||||
{
|
||||
return original_->all_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_proxy::neg_acceptance_conditions() const
|
||||
{
|
||||
return original_->neg_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_proxy::compute_support_conditions(const state* state) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ namespace spot
|
|||
virtual tgba_succ_iterator*
|
||||
succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
|
||||
virtual std::string format_state(const state* state) const;
|
||||
|
||||
virtual std::string
|
||||
|
|
@ -55,10 +53,6 @@ namespace spot
|
|||
|
||||
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
const_tgba_ptr original_;
|
||||
|
|
|
|||
|
|
@ -962,7 +962,7 @@ namespace spot
|
|||
typedef std::multimap<bdd, state_complement*, bdd_less_than> succ_list_t;
|
||||
|
||||
tgba_safra_complement_succ_iterator(const succ_list_t& list,
|
||||
bdd the_acceptance_cond)
|
||||
acc_cond::mark_t the_acceptance_cond)
|
||||
: list_(list), the_acceptance_cond_(the_acceptance_cond)
|
||||
{
|
||||
}
|
||||
|
|
@ -979,10 +979,10 @@ namespace spot
|
|||
virtual bool done() const;
|
||||
virtual state_complement* current_state() const;
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||
private:
|
||||
succ_list_t list_;
|
||||
bdd the_acceptance_cond_;
|
||||
acc_cond::mark_t the_acceptance_cond_;
|
||||
succ_list_t::const_iterator it_;
|
||||
};
|
||||
|
||||
|
|
@ -1020,7 +1020,7 @@ namespace spot
|
|||
return it_->first;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
tgba_safra_complement_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
|
|
@ -1075,38 +1075,22 @@ namespace spot
|
|||
//////////////////////////
|
||||
|
||||
tgba_safra_complement::tgba_safra_complement(const const_tgba_ptr& a)
|
||||
: automaton_(a), safra_(safra_determinisation::create_safra_automaton(a))
|
||||
: tgba(a->get_dict()), automaton_(a),
|
||||
safra_(safra_determinisation::create_safra_automaton(a))
|
||||
{
|
||||
assert(safra_ || !"safra construction fails");
|
||||
|
||||
// We will use one acceptance condition for this automata.
|
||||
// Let's call it Acc[True].
|
||||
int v = get_dict()
|
||||
->register_acceptance_variable(ltl::constant::true_instance(), safra_);
|
||||
|
||||
#if TRANSFORM_TO_TBA
|
||||
the_acceptance_cond_ = bdd_ithvar(v);
|
||||
the_acceptance_cond_ = acc_.mark(acc_.add_set());
|
||||
#endif
|
||||
|
||||
#if TRANSFORM_TO_TGBA
|
||||
unsigned nb_acc =
|
||||
static_cast<safra_tree_automaton*>(safra_)->get_nb_acceptance_pairs();
|
||||
all_acceptance_cond_ = bddfalse;
|
||||
neg_acceptance_cond_ = bddtrue;
|
||||
|
||||
acceptance_cond_vec_.reserve(nb_acc);
|
||||
for (unsigned i = 0; i < nb_acc; ++i)
|
||||
{
|
||||
int r = get_dict()->register_clone_acc(v, safra_);
|
||||
all_acceptance_cond_ &= bdd_nithvar(r);
|
||||
all_acceptance_cond_ |= bdd_ithvar(r) & neg_acceptance_cond_;
|
||||
neg_acceptance_cond_ &= bdd_nithvar(r);
|
||||
acceptance_cond_vec_.push_back(bdd_ithvar(r));
|
||||
}
|
||||
for (unsigned i = 0; i < nb_acc; ++i)
|
||||
{
|
||||
bdd c = acceptance_cond_vec_[i];
|
||||
acceptance_cond_vec_[i] = bdd_exist(neg_acceptance_cond_, c) & c;
|
||||
}
|
||||
acceptance_cond_vec_.push_back(acc_.mark(acc_.add_set()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1171,7 +1155,7 @@ namespace spot
|
|||
|
||||
assert(tr != a->automaton.end());
|
||||
|
||||
bdd condition = bddfalse;
|
||||
acc_cond::mark_t condition = 0U;
|
||||
tgba_safra_complement_succ_iterator::succ_list_t succ_list;
|
||||
int nb_acceptance_pairs = a->get_nb_acceptance_pairs();
|
||||
bitvect* e = make_bitvect(nb_acceptance_pairs);
|
||||
|
|
@ -1249,12 +1233,6 @@ namespace spot
|
|||
return new tgba_safra_complement_succ_iterator(succ_list, condition);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_safra_complement::get_dict() const
|
||||
{
|
||||
return automaton_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_safra_complement::format_state(const state* state) const
|
||||
{
|
||||
|
|
@ -1264,26 +1242,6 @@ namespace spot
|
|||
return s->to_string();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_safra_complement::all_acceptance_conditions() const
|
||||
{
|
||||
#if TRANSFORM_TO_TBA
|
||||
return the_acceptance_cond_;
|
||||
#else
|
||||
return all_acceptance_cond_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_safra_complement::neg_acceptance_conditions() const
|
||||
{
|
||||
#if TRANSFORM_TO_TBA
|
||||
return !the_acceptance_cond_;
|
||||
#else
|
||||
return neg_acceptance_cond_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_safra_complement::compute_support_conditions(const state* state) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,10 +57,7 @@ namespace spot
|
|||
virtual state* get_init_state() const;
|
||||
virtual tgba_succ_iterator* succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
virtual std::string format_state(const state* state) const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
void* get_safra() const
|
||||
{
|
||||
|
|
@ -73,13 +70,11 @@ namespace spot
|
|||
const_tgba_ptr automaton_;
|
||||
void* safra_;
|
||||
#if TRANSFORM_TO_TBA
|
||||
bdd the_acceptance_cond_;
|
||||
acc_cond::mark_t the_acceptance_cond_;
|
||||
#endif
|
||||
#if TRANSFORM_TO_TGBA
|
||||
bdd all_acceptance_cond_;
|
||||
bdd neg_acceptance_cond_;
|
||||
// Map to i the i-th acceptance condition of the final automaton.
|
||||
std::vector<bdd> acceptance_cond_vec_;
|
||||
std::vector<acc_cond::mark_t> acceptance_cond_vec_;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,262 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2011, 2012, 2014 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <cassert>
|
||||
#include "tgbasgba.hh"
|
||||
#include "bddprint.hh"
|
||||
#include "ltlast/constant.hh"
|
||||
#include "misc/hashfunc.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/// \brief A state for spot::tgba_sgba_proxy.
|
||||
class state_sgba_proxy: public state
|
||||
{
|
||||
public:
|
||||
state_sgba_proxy(state* s, bdd acc)
|
||||
: s_(s), acc_(acc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
state_sgba_proxy(const state_sgba_proxy& o)
|
||||
: state(),
|
||||
s_(o.real_state()->clone()),
|
||||
acc_(o.acc_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~state_sgba_proxy()
|
||||
{
|
||||
s_->destroy();
|
||||
}
|
||||
|
||||
state*
|
||||
real_state() const
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
bdd
|
||||
acceptance_cond() const
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
virtual int
|
||||
compare(const state* other) const
|
||||
{
|
||||
const state_sgba_proxy* o =
|
||||
down_cast<const state_sgba_proxy*>(other);
|
||||
assert(o);
|
||||
int res = s_->compare(o->real_state());
|
||||
if (res != 0)
|
||||
return res;
|
||||
return acc_.id() - o->acc_.id();
|
||||
}
|
||||
|
||||
virtual size_t
|
||||
hash() const
|
||||
{
|
||||
return wang32_hash(s_->hash()) ^ wang32_hash(acc_.id());
|
||||
}
|
||||
|
||||
virtual
|
||||
state_sgba_proxy* clone() const
|
||||
{
|
||||
return new state_sgba_proxy(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
state* s_;
|
||||
bdd acc_;
|
||||
};
|
||||
|
||||
/// \brief Iterate over the successors of tgba_sgba_proxy computed
|
||||
/// on the fly.
|
||||
class tgba_sgba_proxy_succ_iterator: public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
tgba_sgba_proxy_succ_iterator(tgba_succ_iterator* it)
|
||||
: it_(it), emulate_acc_cond_(false)
|
||||
{
|
||||
}
|
||||
|
||||
tgba_sgba_proxy_succ_iterator(tgba_succ_iterator* it, bdd acc)
|
||||
: it_(it), emulate_acc_cond_(true), acceptance_condition_(acc)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~tgba_sgba_proxy_succ_iterator()
|
||||
{
|
||||
delete it_;
|
||||
}
|
||||
|
||||
// iteration
|
||||
|
||||
bool
|
||||
first()
|
||||
{
|
||||
return it_->first();
|
||||
}
|
||||
|
||||
bool
|
||||
next()
|
||||
{
|
||||
return it_->next();
|
||||
}
|
||||
|
||||
bool
|
||||
done() const
|
||||
{
|
||||
return it_->done();
|
||||
}
|
||||
|
||||
// inspection
|
||||
|
||||
state_sgba_proxy*
|
||||
current_state() const
|
||||
{
|
||||
return new state_sgba_proxy(it_->current_state(),
|
||||
it_->current_acceptance_conditions());
|
||||
}
|
||||
|
||||
bdd
|
||||
current_condition() const
|
||||
{
|
||||
return it_->current_condition();
|
||||
}
|
||||
|
||||
bdd
|
||||
current_acceptance_conditions() const
|
||||
{
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return it_->current_acceptance_conditions();
|
||||
}
|
||||
|
||||
protected:
|
||||
tgba_succ_iterator* it_;
|
||||
// If the automaton has no acceptance condition,
|
||||
// every state is accepting.
|
||||
bool emulate_acc_cond_;
|
||||
bdd acceptance_condition_;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
tgba_sgba_proxy::tgba_sgba_proxy(const const_tgba_ptr& a,
|
||||
bool no_zero_acc)
|
||||
: a_(a), emulate_acc_cond_(false)
|
||||
{
|
||||
if (no_zero_acc && a_->number_of_acceptance_conditions() == 0)
|
||||
{
|
||||
emulate_acc_cond_ = true;
|
||||
int v = get_dict()
|
||||
->register_acceptance_variable(ltl::constant::true_instance(), this);
|
||||
acceptance_condition_ = bdd_ithvar(v);
|
||||
}
|
||||
|
||||
get_dict()->register_all_variables_of(a, this);
|
||||
}
|
||||
|
||||
tgba_sgba_proxy::~tgba_sgba_proxy()
|
||||
{
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
state*
|
||||
tgba_sgba_proxy::get_init_state() const
|
||||
{
|
||||
return new state_sgba_proxy(a_->get_init_state(), bddfalse);
|
||||
}
|
||||
|
||||
tgba_succ_iterator*
|
||||
tgba_sgba_proxy::succ_iter(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s = down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
tgba_succ_iterator* it = a_->succ_iter(s->real_state());
|
||||
return new tgba_sgba_proxy_succ_iterator(it);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_sgba_proxy::get_dict() const
|
||||
{
|
||||
return a_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_sgba_proxy::format_state(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s = down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
std::string a;
|
||||
if (!emulate_acc_cond_)
|
||||
a = bdd_format_accset(get_dict(), s->acceptance_cond());
|
||||
else
|
||||
a = bdd_format_accset(get_dict(), acceptance_condition_);
|
||||
if (a != "")
|
||||
a = " " + a;
|
||||
return a_->format_state(s->real_state()) + a;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::all_acceptance_conditions() const
|
||||
{
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return a_->all_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::neg_acceptance_conditions() const
|
||||
{
|
||||
if (emulate_acc_cond_)
|
||||
return bdd_nithvar(bdd_var(acceptance_condition_));
|
||||
return a_->neg_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::state_acceptance_conditions(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s =
|
||||
down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return s->acceptance_cond();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::compute_support_conditions(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s =
|
||||
down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return a_->support_conditions(s->real_state());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2013, 2014 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_TGBA_TGBASGBA_HH
|
||||
# define SPOT_TGBA_TGBASGBA_HH
|
||||
|
||||
#include "tgba.hh"
|
||||
#include "misc/bddlt.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// \ingroup tgba_on_the_fly_algorithms
|
||||
/// \brief Change the labeling-mode of spot::tgba on the fly, producing a
|
||||
/// state-based generalized Büchi automaton.
|
||||
///
|
||||
/// This class acts as a proxy in front of a spot::tgba, that should
|
||||
/// label on states on-the-fly. The result is still a spot::tgba,
|
||||
/// but acceptances conditions are also on states.
|
||||
class SPOT_API tgba_sgba_proxy : public tgba
|
||||
{
|
||||
public:
|
||||
tgba_sgba_proxy(const const_tgba_ptr& a, bool no_zero_acc = true);
|
||||
|
||||
virtual ~tgba_sgba_proxy();
|
||||
|
||||
virtual state* get_init_state() const;
|
||||
|
||||
virtual tgba_succ_iterator* succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
|
||||
virtual std::string format_state(const state* state) const;
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
/// \brief Retrieve the acceptance condition of a state.
|
||||
bdd state_acceptance_conditions(const state* state) const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
|
||||
private:
|
||||
const_tgba_ptr a_;
|
||||
// If the automaton has no acceptance condition,
|
||||
// every state is accepting.
|
||||
bool emulate_acc_cond_;
|
||||
bdd acceptance_condition_;
|
||||
// Disallow copy.
|
||||
tgba_sgba_proxy(const tgba_sgba_proxy&) SPOT_DELETED;
|
||||
tgba_sgba_proxy& operator=(const tgba_sgba_proxy&) SPOT_DELETED;
|
||||
};
|
||||
|
||||
inline tgba_sgba_proxy_ptr make_sgba(const const_tgba_ptr& a,
|
||||
bool no_zero_acc = true)
|
||||
{
|
||||
return std::make_shared<tgba_sgba_proxy>(a, no_zero_acc);
|
||||
}
|
||||
}
|
||||
#endif // SPOT_TGBA_TGBASGBA_HH
|
||||
|
|
@ -80,7 +80,7 @@ namespace spot
|
|||
continue;
|
||||
|
||||
bdd cond = i->current_condition();
|
||||
bdd acc = i->current_acceptance_conditions();
|
||||
acc_cond::mark_t acc = i->current_acceptance_conditions();
|
||||
tgba_run::step s = { src, cond, acc };
|
||||
|
||||
if (match(s, dest))
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ namespace spot
|
|||
{
|
||||
unsigned n = aut->num_states();
|
||||
unsigned sink = -1U;
|
||||
bdd allacc = aut->all_acceptance_conditions();
|
||||
if (allacc == bddfalse)
|
||||
acc_cond::mark_t allacc = aut->acc().all_sets();
|
||||
if (allacc == 0U)
|
||||
{
|
||||
// We cannot safely complete an automaton if it has no
|
||||
// acceptance set as the added sink would become accepting.
|
||||
|
|
@ -44,7 +44,7 @@ namespace spot
|
|||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
bool selfloop = true;
|
||||
bdd accsum = bddfalse;
|
||||
acc_cond::mark_t accsum = 0U;
|
||||
for (auto& t: aut->out(i))
|
||||
{
|
||||
if (t.dst != i) // Not a self-loop
|
||||
|
|
@ -66,7 +66,7 @@ namespace spot
|
|||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
bdd missingcond = bddtrue;
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
for (auto& t: aut->out(i))
|
||||
{
|
||||
missingcond -= t.cond;
|
||||
|
|
|
|||
|
|
@ -225,35 +225,11 @@ namespace spot
|
|||
dict->register_all_variables_of(right, res);
|
||||
dict->unregister_variable(bdd_var(v), res);
|
||||
|
||||
// The left and right automata might have acceptance marker in
|
||||
// common.
|
||||
// For the example, assume left has acceptance conditions A,B,C,D
|
||||
// while right has acceptance condition C,D,E,F.
|
||||
const acc_cond& la = left->acc();
|
||||
const acc_cond& ra = right->acc();
|
||||
res->set_acceptance_conditions(la.num_sets() + ra.num_sets());
|
||||
|
||||
// Negative acceptance variables...
|
||||
// !A&!B&!C&!D
|
||||
bdd lna = left->neg_acceptance_conditions();
|
||||
// !C&!D&!E&!F
|
||||
bdd rna = right->neg_acceptance_conditions();
|
||||
|
||||
// Missing acceptance variables...
|
||||
// !E&!F
|
||||
bdd lma = bdd_exist(rna, bdd_support(lna));
|
||||
// !A&!B
|
||||
bdd rma = bdd_exist(lna, bdd_support(rna));
|
||||
|
||||
// (A&!B&!C&!D + ... + !A&!B&!C&D) & !E&!F
|
||||
bdd lac = left->all_acceptance_conditions() & lma;
|
||||
// (C&!D&!E&!F + ... + !C&!D&!E&F) & !A&!B
|
||||
bdd rac = right->all_acceptance_conditions() & rma;
|
||||
bdd allacc = lac | rac;
|
||||
res->set_acceptance_conditions(allacc);
|
||||
|
||||
// Acceptance condition to add to all transitions
|
||||
// of the left automaton.
|
||||
// !A&!B&!C&!D&E&!F | !A&!B&!C&!D&!E&F
|
||||
bdd ladd = rac - lma;
|
||||
bdd radd = lac - rma;
|
||||
acc_cond::mark_t radd = ra.all_sets();
|
||||
|
||||
pair_map seen;
|
||||
pair_queue todo;
|
||||
|
|
@ -300,7 +276,7 @@ namespace spot
|
|||
while (!ri || !ri->done())
|
||||
{
|
||||
bdd cond = lc;
|
||||
bdd ra = allacc;
|
||||
acc_cond::mark_t racc = radd;
|
||||
if (ri)
|
||||
{
|
||||
cond = lc & ri->current_condition();
|
||||
|
|
@ -311,7 +287,7 @@ namespace spot
|
|||
continue;
|
||||
}
|
||||
d.second = ri->current_state();
|
||||
ra = (ri->current_acceptance_conditions() & rma) | radd;
|
||||
racc = ri->current_acceptance_conditions();
|
||||
}
|
||||
|
||||
int dest;
|
||||
|
|
@ -327,8 +303,10 @@ namespace spot
|
|||
todo.push_back(d);
|
||||
}
|
||||
|
||||
bdd la = (li->current_acceptance_conditions() & lma) | ladd;
|
||||
res->new_transition(src, dest, bdd_exist(cond, v), ra & la);
|
||||
acc_cond::mark_t a =
|
||||
res->acc().join(la, li->current_acceptance_conditions(),
|
||||
ra, racc);
|
||||
res->new_transition(src, dest, bdd_exist(cond, v), a);
|
||||
|
||||
if (ri)
|
||||
ri->next();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <deque>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include "tgbaalgos/scc.hh"
|
||||
#include "tgba/bddprint.hh"
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ namespace spot
|
|||
class outgoing_acc
|
||||
{
|
||||
const_tgba_ptr a_;
|
||||
typedef std::pair<bdd, bdd> cache_entry;
|
||||
typedef std::pair<acc_cond::mark_t, acc_cond::mark_t> cache_entry;
|
||||
typedef std::unordered_map<const state*, cache_entry,
|
||||
state_ptr_hash, state_ptr_equal> cache_t;
|
||||
cache_t cache_;
|
||||
|
|
@ -86,8 +87,8 @@ namespace spot
|
|||
cache_t::const_iterator fill_cache(const state* s)
|
||||
{
|
||||
unsigned s1 = sm_ ? sm_->scc_of_state(s) : 0;
|
||||
bdd common = a_->all_acceptance_conditions();
|
||||
bdd union_ = bddfalse;
|
||||
acc_cond::mark_t common = a_->acc().all_sets();
|
||||
acc_cond::mark_t union_ = 0U;
|
||||
for (auto it: a_->succ(s))
|
||||
{
|
||||
// Ignore transitions that leave the SCC of s.
|
||||
|
|
@ -97,7 +98,7 @@ namespace spot
|
|||
if (s2 != s1)
|
||||
continue;
|
||||
|
||||
bdd set = it->current_acceptance_conditions();
|
||||
acc_cond::mark_t set = it->current_acceptance_conditions();
|
||||
common &= set;
|
||||
union_ |= set;
|
||||
}
|
||||
|
|
@ -106,7 +107,7 @@ namespace spot
|
|||
}
|
||||
|
||||
// Intersection of all outgoing acceptance sets
|
||||
bdd common_acc(const state* s)
|
||||
acc_cond::mark_t common_acc(const state* s)
|
||||
{
|
||||
cache_t::const_iterator i = cache_.find(s);
|
||||
if (i == cache_.end())
|
||||
|
|
@ -115,7 +116,7 @@ namespace spot
|
|||
}
|
||||
|
||||
// Union of all outgoing acceptance sets
|
||||
bdd union_acc(const state* s)
|
||||
acc_cond::mark_t union_acc(const state* s)
|
||||
{
|
||||
cache_t::const_iterator i = cache_.find(s);
|
||||
if (i == cache_.end())
|
||||
|
|
@ -146,11 +147,10 @@ namespace spot
|
|||
auto p = cache_.emplace(s, false);
|
||||
if (p.second)
|
||||
{
|
||||
bdd all = a_->all_acceptance_conditions();
|
||||
for (auto it: a_->succ(s))
|
||||
{
|
||||
// Look only for transitions that are accepting.
|
||||
if (all != it->current_acceptance_conditions())
|
||||
if (!a_->acc().accepting(it->current_acceptance_conditions()))
|
||||
continue;
|
||||
// Look only for self-loops.
|
||||
const state* dest = uniq_(it->current_state());
|
||||
|
|
@ -168,37 +168,23 @@ namespace spot
|
|||
// Order of accepting sets (for one SCC)
|
||||
class acc_order
|
||||
{
|
||||
std::vector<bdd> order_;
|
||||
bdd found_;
|
||||
std::vector<unsigned> order_;
|
||||
acc_cond::mark_t found_;
|
||||
|
||||
public:
|
||||
unsigned
|
||||
next_level(bdd all, int slevel, bdd acc, bool skip_levels)
|
||||
next_level(const acc_cond& acc, int slevel,
|
||||
acc_cond::mark_t set, bool skip_levels)
|
||||
{
|
||||
bdd temp = acc;
|
||||
if (all != found_)
|
||||
// Update the order with any new set we discover
|
||||
if (auto newsets = set - found_)
|
||||
{
|
||||
// Check for new conditions in acc
|
||||
if ((acc & found_) != acc)
|
||||
{
|
||||
bdd acc_t = acc;
|
||||
while (acc_t != bddfalse)
|
||||
{
|
||||
bdd next = bdd_satone(acc_t);
|
||||
acc_t -= next;
|
||||
// Add new condition
|
||||
if ((next & found_) != next)
|
||||
{
|
||||
order_.push_back(next);
|
||||
found_ |= next;
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.fill_from(newsets, std::back_inserter(order_));
|
||||
found_ |= newsets;
|
||||
}
|
||||
|
||||
acc = temp;
|
||||
unsigned next = slevel;
|
||||
while (next < order_.size() && bdd_implies(order_[next], acc))
|
||||
while (next < order_.size() && set.has(order_[next]))
|
||||
{
|
||||
++next;
|
||||
if (!skip_levels)
|
||||
|
|
@ -208,44 +194,41 @@ namespace spot
|
|||
}
|
||||
|
||||
void
|
||||
print(int scc, const bdd_dict_ptr dict)
|
||||
print(int scc)
|
||||
{
|
||||
std::vector<bdd>::iterator i;
|
||||
std::cout << "Order_" << scc << ":\t";
|
||||
for (i = order_.begin(); i != order_.end(); i++)
|
||||
{
|
||||
bdd_print_acc(std::cout, dict, *i);
|
||||
std::cout << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
for (auto i: order_)
|
||||
std::cout << i << ", ";
|
||||
std::cout << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
// Accepting order for each SCC
|
||||
class scc_orders
|
||||
{
|
||||
bdd all_;
|
||||
const acc_cond& acc_;
|
||||
std::map<int, acc_order> orders_;
|
||||
bool skip_levels_;
|
||||
|
||||
public:
|
||||
scc_orders(bdd all, bool skip_levels):
|
||||
all_(all), skip_levels_(skip_levels)
|
||||
scc_orders(const acc_cond& acc, bool skip_levels):
|
||||
acc_(acc), skip_levels_(skip_levels)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
next_level(int scc, int slevel, bdd acc)
|
||||
next_level(int scc, int slevel, acc_cond::mark_t set)
|
||||
{
|
||||
return orders_[scc].next_level(all_, slevel, acc, skip_levels_);
|
||||
return orders_[scc].next_level(acc_, slevel, set, skip_levels_);
|
||||
}
|
||||
|
||||
void
|
||||
print(const bdd_dict_ptr dict)
|
||||
print()
|
||||
{
|
||||
std::map<int, acc_order>::iterator i;
|
||||
for (i = orders_.begin(); i != orders_.end(); i++)
|
||||
i->second.print(i->first, dict);
|
||||
i->second.print(i->first);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -273,26 +256,23 @@ namespace spot
|
|||
// be used as a level in degen_state to indicate the next expected
|
||||
// acceptance set. Level order.size() is a special level used to
|
||||
// denote accepting states.
|
||||
std::vector<bdd> order;
|
||||
std::vector<unsigned> order;
|
||||
{
|
||||
// FIXME: revisit this comment once everything compiles again.
|
||||
//
|
||||
// The order is arbitrary, but it turns out that using push_back
|
||||
// instead of push_front often gives better results because
|
||||
// acceptance sets at the beginning if the cycle are more often
|
||||
// used in the automaton. (This surprising fact is probably
|
||||
// related to the order in which we declare the BDD variables
|
||||
// during the translation.)
|
||||
bdd all = a->all_acceptance_conditions();
|
||||
while (all != bddfalse)
|
||||
{
|
||||
bdd next = bdd_satone(all);
|
||||
all -= next;
|
||||
order.push_back(next);
|
||||
}
|
||||
unsigned n = a->acc().num_sets();
|
||||
for (unsigned i = n; i > 0; --i)
|
||||
order.push_back(i - 1);
|
||||
}
|
||||
|
||||
// Initialize scc_orders
|
||||
bdd allacc = a->all_acceptance_conditions();
|
||||
scc_orders orders(a->all_acceptance_conditions(), skip_levels);
|
||||
scc_orders orders(a->acc(), skip_levels);
|
||||
|
||||
// Make sure we always use the same pointer for identical states
|
||||
// from the input automaton.
|
||||
|
|
@ -340,11 +320,12 @@ namespace spot
|
|||
// start on the associated level.
|
||||
if (s.second == 0)
|
||||
{
|
||||
bdd acc = outgoing.common_acc(s.first);
|
||||
auto set = outgoing.common_acc(s.first);
|
||||
if (use_cust_acc_orders)
|
||||
s.second = orders.next_level(m.initial(), s.second, acc);
|
||||
s.second = orders.next_level(m.initial(), s.second, set);
|
||||
else
|
||||
while (s.second < order.size() && bdd_implies(order[s.second], acc))
|
||||
while (s.second < order.size()
|
||||
&& set.has(order[s.second]))
|
||||
{
|
||||
++s.second;
|
||||
if (!skip_levels)
|
||||
|
|
@ -405,13 +386,13 @@ namespace spot
|
|||
}
|
||||
|
||||
// The old level is slevel. What should be the new one?
|
||||
bdd acc = i->current_acceptance_conditions();
|
||||
bdd otheracc = outgoing.common_acc(d.first);
|
||||
auto acc = i->current_acceptance_conditions();
|
||||
auto otheracc = outgoing.common_acc(d.first);
|
||||
|
||||
if (want_sba && is_acc)
|
||||
{
|
||||
// Ignore the last expected acceptance set (the value of
|
||||
// *prev below) if it is common to all other outgoing
|
||||
// prev below) if it is common to all other outgoing
|
||||
// transitions (of the current state) AND if it is not
|
||||
// used by any outgoing transition of the destination
|
||||
// state.
|
||||
|
|
@ -447,12 +428,12 @@ namespace spot
|
|||
if (!order.empty())
|
||||
{
|
||||
unsigned prev = order.size() - 1;
|
||||
bdd common = outgoing.common_acc(s.first);
|
||||
if (bdd_implies(order[prev], common))
|
||||
auto common = outgoing.common_acc(s.first);
|
||||
if (common.has(order[prev]))
|
||||
{
|
||||
bdd u = outgoing.union_acc(d.first);
|
||||
if (!bdd_implies(order[prev], u))
|
||||
acc -= order[prev];
|
||||
auto u = outgoing.union_acc(d.first);
|
||||
if (!u.has(order[prev]))
|
||||
acc -= a->acc().mark(order[prev]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -523,7 +504,7 @@ namespace spot
|
|||
// are not skipping levels.
|
||||
if (skip_levels || !is_acc)
|
||||
while (next < order.size()
|
||||
&& bdd_implies(order[next], acc))
|
||||
&& acc.has(order[next]))
|
||||
{
|
||||
++next;
|
||||
if (!skip_levels)
|
||||
|
|
@ -545,7 +526,7 @@ namespace spot
|
|||
{
|
||||
d.second = 0; // Make it go to the first level.
|
||||
// Skip levels as much as possible.
|
||||
if (acc != allacc && !skip_levels)
|
||||
if (!a->acc().accepting(acc) && !skip_levels)
|
||||
{
|
||||
if (use_cust_acc_orders)
|
||||
{
|
||||
|
|
@ -554,7 +535,7 @@ namespace spot
|
|||
else
|
||||
{
|
||||
while (d.second < order.size() &&
|
||||
bdd_implies(order[d.second], acc))
|
||||
acc.has(order[d.second]))
|
||||
++d.second;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,9 +73,8 @@ namespace spot
|
|||
else
|
||||
{
|
||||
si->first();
|
||||
accepting = ((!si->done())
|
||||
&& (si->current_acceptance_conditions() ==
|
||||
aut_->all_acceptance_conditions()));
|
||||
auto a = si->current_acceptance_conditions();
|
||||
accepting = !si->done() && aut_->acc().accepting(a);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -96,10 +95,13 @@ namespace spot
|
|||
{
|
||||
std::string label =
|
||||
bdd_format_formula(aut_->get_dict(),
|
||||
si->current_condition())
|
||||
+ "\n"
|
||||
+ bdd_format_accset(aut_->get_dict(),
|
||||
si->current_acceptance_conditions());
|
||||
si->current_condition());
|
||||
auto a = si->current_acceptance_conditions();
|
||||
if (a)
|
||||
{
|
||||
label += "\n";
|
||||
label += aut_->acc().format(a);
|
||||
}
|
||||
|
||||
std::string s = aut_->transition_annotation(si);
|
||||
if (!s.empty())
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ namespace spot
|
|||
}
|
||||
}
|
||||
|
||||
bdd all_acc = ref->all_acceptance_conditions();
|
||||
const acc_cond& ra = ref->acc();
|
||||
|
||||
// construction of contraints (4,5) : all loops in the product
|
||||
// where no accepting run is detected in the ref. automaton,
|
||||
|
|
@ -477,7 +477,7 @@ namespace spot
|
|||
if (sm.scc_of(dp) != q1p_scc)
|
||||
continue;
|
||||
|
||||
if (tr.acc == all_acc)
|
||||
if (ra.accepting(tr.acc))
|
||||
continue;
|
||||
for (unsigned q3 = 0; q3 < d.cand_size; ++q3)
|
||||
{
|
||||
|
|
@ -574,7 +574,7 @@ namespace spot
|
|||
{
|
||||
// We only care about the looping case if
|
||||
// it is accepting in the reference.
|
||||
if (tr.acc != all_acc)
|
||||
if (!ra.accepting(tr.acc))
|
||||
continue;
|
||||
bdd all = tr.cond;
|
||||
while (all != bddfalse)
|
||||
|
|
@ -636,7 +636,7 @@ namespace spot
|
|||
auto autdict = aut->get_dict();
|
||||
auto a = make_tgba_digraph(autdict);
|
||||
a->copy_ap_of(aut);
|
||||
bdd acc = a->set_single_acceptance_set();
|
||||
acc_cond::mark_t acc = a->set_single_acceptance_set();
|
||||
a->new_states(satdict.cand_size);
|
||||
|
||||
unsigned last_aut_trans = -1U;
|
||||
|
|
|
|||
|
|
@ -28,18 +28,20 @@ namespace spot
|
|||
// Clone the original automaton.
|
||||
tgba_digraph_ptr res = tgba_dupexp_dfs(aut);
|
||||
|
||||
bdd oldaccs = aut->all_acceptance_conditions();
|
||||
bdd oldnegs = aut->neg_acceptance_conditions();
|
||||
|
||||
// Copy the old acceptance condition before we replace it.
|
||||
acc_cond oldacc = aut->acc(); // Copy it!
|
||||
|
||||
// We will modify res in place, and the resulting
|
||||
// automaton will only have one acceptance set.
|
||||
// This changes aut->acc();
|
||||
res->set_single_acceptance_set();
|
||||
|
||||
unsigned num_acc = aut->number_of_acceptance_conditions();
|
||||
unsigned num_sets = oldacc.num_sets();
|
||||
unsigned n = res->num_states();
|
||||
// We will duplicate the automaton as many times as we have
|
||||
// acceptance sets, and we need one extra sink state.
|
||||
res->new_states(num_acc * n + 1);
|
||||
res->new_states(num_sets * n + 1);
|
||||
unsigned sink = res->num_states() - 1;
|
||||
// The sink state has an accepting self-loop.
|
||||
res->new_acc_transition(sink, sink, bddtrue);
|
||||
|
|
@ -54,29 +56,26 @@ namespace spot
|
|||
if (t.dst >= n) // Ignore transitions we added.
|
||||
break;
|
||||
missingcond -= t.cond;
|
||||
bdd curacc = t.acc;
|
||||
acc_cond::mark_t curacc = t.acc;
|
||||
// The original transition must not accept anymore.
|
||||
t.acc = bddfalse;
|
||||
t.acc = 0U;
|
||||
|
||||
// Transition that were fully accepting are never cloned.
|
||||
if (curacc == oldaccs)
|
||||
if (oldacc.accepting(curacc))
|
||||
continue;
|
||||
// Save t.cond and t.dst as the reference to t
|
||||
// is invalided by calls to new_transition().
|
||||
unsigned dst = t.dst;
|
||||
bdd cond = t.cond;
|
||||
// We want all acceptance bdd variable to appear in curacc.
|
||||
if (curacc == bddfalse)
|
||||
curacc = oldnegs;
|
||||
|
||||
// Iterate over all the acceptance conditions in 'curacc',
|
||||
// an duplicate it each each clone for which it does not
|
||||
// an duplicate it for each clone for which it does not
|
||||
// belong to the acceptance set.
|
||||
unsigned add = 0;
|
||||
while (curacc != bddtrue)
|
||||
for (unsigned set = 0; set < num_sets; ++set)
|
||||
{
|
||||
add += n;
|
||||
bdd h = bdd_high(curacc);
|
||||
if (h == bddfalse)
|
||||
if (!oldacc.has(curacc, set))
|
||||
{
|
||||
// Clone the transition
|
||||
res->new_acc_transition(src + add, dst + add, cond);
|
||||
|
|
@ -93,26 +92,9 @@ namespace spot
|
|||
// arc set would be better.
|
||||
if (dst <= src)
|
||||
res->new_transition(src, dst + add, cond);
|
||||
curacc = bdd_low(curacc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We know that only one variable can be positive
|
||||
// on any branch, so since we have just seen such
|
||||
// a variable, we want to go to explore its LOW
|
||||
// branch for more positive variables. The only
|
||||
// case where we will not do that is if the LOW
|
||||
// branch is false. In that case we take the HIGH
|
||||
// branch to enumerate all the remaining negated
|
||||
// variables.
|
||||
bdd tmp = bdd_low(curacc);
|
||||
if (tmp != bddfalse)
|
||||
curacc = tmp;
|
||||
else
|
||||
curacc = h;
|
||||
}
|
||||
}
|
||||
assert(add == num_acc * n);
|
||||
assert(add == num_sets * n);
|
||||
}
|
||||
// Complete the original automaton.
|
||||
if (missingcond != bddfalse)
|
||||
|
|
@ -134,21 +116,18 @@ namespace spot
|
|||
true, // inherently_weak
|
||||
true); // deterministic
|
||||
|
||||
bdd oldaccs = aut->all_acceptance_conditions();
|
||||
bdd oldnegs = aut->neg_acceptance_conditions();
|
||||
|
||||
scc_info si(res);
|
||||
|
||||
// We will modify res in place, and the resulting
|
||||
// automaton will only have one acceptance set.
|
||||
bdd all_acc = res->set_single_acceptance_set();
|
||||
acc_cond::mark_t all_acc = res->set_single_acceptance_set();
|
||||
res->prop_state_based_acc();
|
||||
|
||||
unsigned sink = res->num_states();
|
||||
|
||||
for (unsigned src = 0; src < sink; ++src)
|
||||
{
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
unsigned scc = si.scc_of(src);
|
||||
if (!si.is_accepting_scc(scc) && !si.is_trivial(scc))
|
||||
acc = all_acc;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ namespace spot
|
|||
namespace
|
||||
{
|
||||
static bdd_dict_ptr debug_dict = 0;
|
||||
static const acc_cond* debug_ref_acc = 0;
|
||||
static const acc_cond* debug_cand_acc = 0;
|
||||
|
||||
struct transition
|
||||
{
|
||||
|
|
@ -120,10 +122,10 @@ namespace spot
|
|||
{
|
||||
unsigned src;
|
||||
bdd cond;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
unsigned dst;
|
||||
|
||||
transition_acc(int src, bdd cond, bdd acc, int dst)
|
||||
transition_acc(int src, bdd cond, acc_cond::mark_t acc, int dst)
|
||||
: src(src), cond(cond), acc(acc), dst(dst)
|
||||
{
|
||||
}
|
||||
|
|
@ -142,7 +144,7 @@ namespace spot
|
|||
return true;
|
||||
if (this->cond.id() > other.cond.id())
|
||||
return false;
|
||||
return this->acc.id() < other.acc.id();
|
||||
return this->acc < other.acc;
|
||||
}
|
||||
|
||||
bool operator==(const transition_acc& other) const
|
||||
|
|
@ -150,7 +152,7 @@ namespace spot
|
|||
return (this->src == other.src
|
||||
&& this->dst == other.dst
|
||||
&& this->cond.id() == other.cond.id()
|
||||
&& this->acc.id() == other.acc.id());
|
||||
&& this->acc == other.acc);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -160,19 +162,19 @@ namespace spot
|
|||
unsigned src_ref;
|
||||
unsigned dst_cand;
|
||||
unsigned dst_ref;
|
||||
bdd acc_cand;
|
||||
bdd acc_ref;
|
||||
acc_cond::mark_t acc_cand;
|
||||
acc_cond::mark_t acc_ref;
|
||||
|
||||
path(unsigned src_cand, unsigned src_ref)
|
||||
: src_cand(src_cand), src_ref(src_ref),
|
||||
dst_cand(src_cand), dst_ref(src_ref),
|
||||
acc_cand(bddfalse), acc_ref(bddfalse)
|
||||
acc_cand(0U), acc_ref(0U)
|
||||
{
|
||||
}
|
||||
|
||||
path(unsigned src_cand, unsigned src_ref,
|
||||
unsigned dst_cand, unsigned dst_ref,
|
||||
bdd acc_cand, bdd acc_ref)
|
||||
acc_cond::mark_t acc_cand, acc_cond::mark_t acc_ref)
|
||||
: src_cand(src_cand), src_ref(src_ref),
|
||||
dst_cand(dst_cand), dst_ref(dst_ref),
|
||||
acc_cand(acc_cand), acc_ref(acc_ref)
|
||||
|
|
@ -197,13 +199,13 @@ namespace spot
|
|||
return true;
|
||||
if (this->dst_ref > other.dst_ref)
|
||||
return false;
|
||||
if (this->acc_ref.id() < other.acc_ref.id())
|
||||
if (this->acc_ref < other.acc_ref)
|
||||
return true;
|
||||
if (this->acc_ref.id() > other.acc_ref.id())
|
||||
if (this->acc_ref > other.acc_ref)
|
||||
return false;
|
||||
if (this->acc_cand.id() < other.acc_cand.id())
|
||||
if (this->acc_cand < other.acc_cand)
|
||||
return true;
|
||||
if (this->acc_cand.id() > other.acc_cand.id())
|
||||
if (this->acc_cand > other.acc_cand)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
|
|
@ -224,7 +226,7 @@ namespace spot
|
|||
{
|
||||
os << '<' << t.src << ','
|
||||
<< bdd_format_formula(debug_dict, t.cond) << ','
|
||||
<< bdd_format_accset(debug_dict, t.acc)
|
||||
<< debug_cand_acc->format(t.acc)
|
||||
<< ',' << t.dst << '>';
|
||||
return os;
|
||||
}
|
||||
|
|
@ -236,15 +238,15 @@ namespace spot
|
|||
<< p.src_ref << ','
|
||||
<< p.dst_cand << ','
|
||||
<< p.dst_ref << ", "
|
||||
<< bdd_format_accset(debug_dict, p.acc_cand) << ", "
|
||||
<< bdd_format_accset(debug_dict, p.acc_ref) << '>';
|
||||
<< debug_cand_acc->format(p.acc_cand) << ", "
|
||||
<< debug_ref_acc->format(p.acc_ref) << '>';
|
||||
return os;
|
||||
}
|
||||
|
||||
struct dict
|
||||
{
|
||||
dict(const const_tgba_ptr& a)
|
||||
: aut(a)
|
||||
: aut(a), cacc(a->get_dict())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -267,16 +269,15 @@ namespace spot
|
|||
// int_map int_to_state;
|
||||
unsigned cand_size;
|
||||
unsigned int cand_nacc;
|
||||
std::vector<bdd> cand_acc; // size cand_nacc
|
||||
std::vector<acc_cond::mark_t> cand_acc; // size cand_nacc
|
||||
|
||||
std::vector<bdd> all_cand_acc;
|
||||
std::vector<bdd> all_ref_acc;
|
||||
|
||||
bdd cand_all_acc;
|
||||
bdd ref_all_acc;
|
||||
std::vector<acc_cond::mark_t> all_cand_acc;
|
||||
std::vector<acc_cond::mark_t> all_ref_acc;
|
||||
|
||||
std::vector<bool> is_weak_scc;
|
||||
|
||||
acc_cond cacc;
|
||||
|
||||
~dict()
|
||||
{
|
||||
aut->get_dict()->unregister_all_my_variables(this);
|
||||
|
|
@ -288,48 +289,27 @@ namespace spot
|
|||
dict& d, bdd ap, bool state_based, scc_info& sm)
|
||||
{
|
||||
bdd_dict_ptr bd = aut->get_dict();
|
||||
ltl::default_environment& env = ltl::default_environment::instance();
|
||||
|
||||
d.cand_acc.resize(d.cand_nacc);
|
||||
d.all_cand_acc.push_back(bddfalse);
|
||||
|
||||
bdd allneg = bddtrue;
|
||||
d.cacc.add_sets(d.cand_nacc);
|
||||
d.all_cand_acc.push_back(0U);
|
||||
for (unsigned n = 0; n < d.cand_nacc; ++n)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << n;
|
||||
const ltl::formula* af = env.require(s.str());
|
||||
int v = bd->register_acceptance_variable(af, &d);
|
||||
af->destroy();
|
||||
d.cand_acc[n] = bdd_ithvar(v);
|
||||
allneg &= bdd_nithvar(v);
|
||||
}
|
||||
for (unsigned n = 0; n < d.cand_nacc; ++n)
|
||||
{
|
||||
bdd c = bdd_exist(allneg, d.cand_acc[n]) & d.cand_acc[n];
|
||||
auto c = d.cacc.mark(n);
|
||||
d.cand_acc[n] = c;
|
||||
|
||||
size_t s = d.all_cand_acc.size();
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
d.all_cand_acc.push_back(d.all_cand_acc[i] | c);
|
||||
}
|
||||
d.cand_all_acc = bdd_support(allneg);
|
||||
d.ref_all_acc = bdd_support(aut->all_acceptance_conditions());
|
||||
|
||||
bdd refall = d.ref_all_acc;
|
||||
bdd refnegall = aut->neg_acceptance_conditions();
|
||||
|
||||
d.all_ref_acc.push_back(bddfalse);
|
||||
while (refall != bddtrue)
|
||||
d.all_ref_acc.push_back(0U);
|
||||
unsigned ref_nacc = aut->acc().num_sets();
|
||||
for (unsigned n = 0; n < ref_nacc; ++n)
|
||||
{
|
||||
bdd v = bdd_ithvar(bdd_var(refall));
|
||||
bdd c = bdd_exist(refnegall, v) & v;
|
||||
|
||||
auto c = aut->acc().mark(n);
|
||||
size_t s = d.all_ref_acc.size();
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
d.all_ref_acc.push_back(d.all_ref_acc[i] | c);
|
||||
|
||||
refall = bdd_high(refall);
|
||||
}
|
||||
|
||||
unsigned ref_size = aut->num_states();
|
||||
|
|
@ -485,9 +465,12 @@ namespace spot
|
|||
|
||||
#if DEBUG
|
||||
debug_dict = ref->get_dict();
|
||||
debug_ref_acc = &ref->acc();
|
||||
debug_cand_acc = &d.cacc;
|
||||
dout << "ref_size: " << ref_size << '\n';
|
||||
dout << "cand_size: " << d.cand_size << '\n';
|
||||
#endif
|
||||
auto& racc = ref->acc();
|
||||
|
||||
dout << "symmetry-breaking clauses\n";
|
||||
int j = 0;
|
||||
|
|
@ -586,8 +569,6 @@ namespace spot
|
|||
}
|
||||
}
|
||||
|
||||
bdd all_acc = ref->all_acceptance_conditions();
|
||||
|
||||
// construction of constraints (11,12,13)
|
||||
for (unsigned q1p = 0; q1p < ref_size; ++q1p)
|
||||
{
|
||||
|
|
@ -630,7 +611,7 @@ namespace spot
|
|||
for (unsigned q3 = 0; q3 < d.cand_size; ++q3)
|
||||
{
|
||||
bdd all = tr.cond;
|
||||
bdd curacc = tr.acc;
|
||||
acc_cond::mark_t curacc = tr.acc;
|
||||
while (all != bddfalse)
|
||||
{
|
||||
bdd l = bdd_satoneset(all, ap, bddfalse);
|
||||
|
|
@ -643,23 +624,22 @@ namespace spot
|
|||
{
|
||||
if ((!is_acc) ||
|
||||
(!is_weak &&
|
||||
(curacc |
|
||||
d.all_ref_acc[fp]) != all_acc))
|
||||
!racc.accepting
|
||||
(curacc | d.all_ref_acc[fp])))
|
||||
{
|
||||
#if DEBUG
|
||||
dout << "(11) " << p << " ∧ "
|
||||
<< t << "δ → ¬(";
|
||||
|
||||
bdd all_ = d.all_cand_acc.back();
|
||||
all_ -= d.all_cand_acc[f];
|
||||
bool notfirst = false;
|
||||
while (all_ != bddfalse)
|
||||
acc_cond::mark_t all_ =
|
||||
d.all_cand_acc.back() -
|
||||
d.all_cand_acc[f];
|
||||
for (auto m: d.cacc.sets(all_))
|
||||
{
|
||||
bdd one = bdd_satone(all_);
|
||||
all_ -= one;
|
||||
|
||||
transition_acc ta(q2, l,
|
||||
one, q1);
|
||||
transition_acc
|
||||
ta(q2, l,
|
||||
d.cacc.mark(m), q1);
|
||||
if (notfirst)
|
||||
out << " ∧ ";
|
||||
else
|
||||
|
|
@ -671,15 +651,14 @@ namespace spot
|
|||
out << -pid << ' ' << -ti;
|
||||
|
||||
// 11
|
||||
bdd all_f = d.all_cand_acc.back();
|
||||
all_f -= d.all_cand_acc[f];
|
||||
while (all_f != bddfalse)
|
||||
acc_cond::mark_t all_f =
|
||||
d.all_cand_acc.back() -
|
||||
d.all_cand_acc[f];
|
||||
for (auto m: d.cacc.sets(all_f))
|
||||
{
|
||||
bdd one = bdd_satone(all_f);
|
||||
all_f -= one;
|
||||
|
||||
transition_acc ta(q2, l,
|
||||
one, q1);
|
||||
transition_acc
|
||||
ta(q2, l,
|
||||
d.cacc.mark(m), q1);
|
||||
int tai = d.transaccid[ta];
|
||||
assert(tai != 0);
|
||||
out << ' ' << -tai;
|
||||
|
|
@ -692,17 +671,15 @@ namespace spot
|
|||
#if DEBUG
|
||||
dout << "(12) " << p << " ∧ "
|
||||
<< t << "δ → (";
|
||||
|
||||
bdd all_ = d.all_cand_acc.back();
|
||||
all_ -= d.all_cand_acc[f];
|
||||
bool notfirst = false;
|
||||
while (all_ != bddfalse)
|
||||
// 11
|
||||
acc_cond::mark_t all_ =
|
||||
d.cacc.comp(d.all_cand_acc[f]);
|
||||
for (auto m: d.cacc.sets(all_))
|
||||
{
|
||||
bdd one = bdd_satone(all_);
|
||||
all_ -= one;
|
||||
|
||||
transition_acc ta(q2, l,
|
||||
one, q1);
|
||||
transition_acc
|
||||
ta(q2, l,
|
||||
d.cacc.mark(m), q1);
|
||||
if (notfirst)
|
||||
out << " ∧ ";
|
||||
else
|
||||
|
|
@ -712,15 +689,13 @@ namespace spot
|
|||
out << ")\n";
|
||||
#endif // DEBUG
|
||||
// 12
|
||||
bdd all_f = d.all_cand_acc.back();
|
||||
all_f -= d.all_cand_acc[f];
|
||||
while (all_f != bddfalse)
|
||||
acc_cond::mark_t all_f =
|
||||
d.cacc.comp(d.all_cand_acc[f]);
|
||||
for (auto m: d.cacc.sets(all_f))
|
||||
{
|
||||
bdd one = bdd_satone(all_f);
|
||||
all_f -= one;
|
||||
|
||||
transition_acc ta(q2, l,
|
||||
one, q1);
|
||||
transition_acc
|
||||
ta(q2, l,
|
||||
d.cacc.mark(m), q1);
|
||||
int tai = d.transaccid[ta];
|
||||
assert(tai != 0);
|
||||
|
||||
|
|
@ -735,10 +710,9 @@ namespace spot
|
|||
size_t sf = d.all_cand_acc.size();
|
||||
for (size_t f = 0; f < sf; ++f)
|
||||
{
|
||||
|
||||
bdd f2 = p.acc_cand |
|
||||
d.all_cand_acc[f];
|
||||
bdd f2p = bddfalse;
|
||||
acc_cond::mark_t f2 =
|
||||
p.acc_cand | d.all_cand_acc[f];
|
||||
acc_cond::mark_t f2p = 0U;
|
||||
if (!is_weak)
|
||||
f2p = p.acc_ref | curacc;
|
||||
|
||||
|
|
@ -751,47 +725,34 @@ namespace spot
|
|||
dout << "(13) " << p << " ∧ "
|
||||
<< t << "δ ";
|
||||
|
||||
bdd biga_ = d.all_cand_acc[f];
|
||||
while (biga_ != bddfalse)
|
||||
auto biga_ = d.all_cand_acc[f];
|
||||
for (unsigned m = 0;
|
||||
m < d.cand_nacc; ++m)
|
||||
{
|
||||
bdd a = bdd_satone(biga_);
|
||||
biga_ -= a;
|
||||
|
||||
transition_acc ta(q2, l, a, q3);
|
||||
out << " ∧ " << ta << "FC";
|
||||
}
|
||||
biga_ = d.all_cand_acc.back()
|
||||
- d.all_cand_acc[f];
|
||||
while (biga_ != bddfalse)
|
||||
{
|
||||
bdd a = bdd_satone(biga_);
|
||||
biga_ -= a;
|
||||
|
||||
transition_acc ta(q2, l, a, q3);
|
||||
out << " ∧ ¬" << ta << "FC";
|
||||
transition_acc
|
||||
ta(q2, l,
|
||||
d.cacc.mark(m), q3);
|
||||
int tai = d.transaccid[ta];
|
||||
const char* not_ = "¬";
|
||||
if (d.cacc.has(biga_, m))
|
||||
not_ = "";
|
||||
out << tai << ' ';
|
||||
out << " ∧ " << not_
|
||||
<< ta << "FC";
|
||||
}
|
||||
out << " → " << p2 << '\n';
|
||||
#endif
|
||||
out << -pid << ' ' << -ti << ' ';
|
||||
bdd biga = d.all_cand_acc[f];
|
||||
while (biga != bddfalse)
|
||||
auto biga = d.all_cand_acc[f];
|
||||
for (unsigned m = 0;
|
||||
m < d.cand_nacc; ++m)
|
||||
{
|
||||
bdd a = bdd_satone(biga);
|
||||
biga -= a;
|
||||
|
||||
transition_acc ta(q2, l, a, q3);
|
||||
int tai = d.transaccid[ta];
|
||||
out << -tai << ' ';
|
||||
}
|
||||
biga = d.all_cand_acc.back()
|
||||
- d.all_cand_acc[f];
|
||||
while (biga != bddfalse)
|
||||
{
|
||||
bdd a = bdd_satone(biga);
|
||||
biga -= a;
|
||||
|
||||
transition_acc ta(q2, l, a, q3);
|
||||
transition_acc
|
||||
ta(q2, l,
|
||||
d.cacc.mark(m), q3);
|
||||
int tai = d.transaccid[ta];
|
||||
if (d.cacc.has(biga, m))
|
||||
tai = -tai;
|
||||
out << tai << ' ';
|
||||
}
|
||||
|
||||
|
|
@ -818,7 +779,7 @@ namespace spot
|
|||
auto autdict = aut->get_dict();
|
||||
auto a = make_tgba_digraph(autdict);
|
||||
a->copy_ap_of(aut);
|
||||
a->set_acceptance_conditions(satdict.all_cand_acc.back());
|
||||
a->set_acceptance_conditions(satdict.cand_nacc);
|
||||
|
||||
a->new_states(satdict.cand_size);
|
||||
|
||||
|
|
@ -835,7 +796,7 @@ namespace spot
|
|||
#endif
|
||||
|
||||
dout << "--- transition variables ---\n";
|
||||
std::map<int, bdd> state_acc;
|
||||
std::map<int, acc_cond::mark_t> state_acc;
|
||||
std::set<src_cond> seen_trans;
|
||||
for (int v: solution)
|
||||
{
|
||||
|
|
@ -854,7 +815,7 @@ namespace spot
|
|||
if (seen_trans.insert(src_cond(t->second.src,
|
||||
t->second.cond)).second)
|
||||
{
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
if (state_based)
|
||||
{
|
||||
auto i = state_acc.find(t->second.src);
|
||||
|
|
@ -887,11 +848,13 @@ namespace spot
|
|||
ta->second.dst == last_sat_trans->dst)
|
||||
{
|
||||
assert(!state_based);
|
||||
a->trans_data(last_aut_trans).acc |= ta->second.acc;
|
||||
auto& v = a->trans_data(last_aut_trans).acc;
|
||||
v |= ta->second.acc;
|
||||
}
|
||||
else if (state_based)
|
||||
{
|
||||
state_acc[ta->second.src] |= ta->second.acc;
|
||||
auto& v = state_acc[ta->second.src];
|
||||
v |= ta->second.acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ namespace spot
|
|||
const state*, int out,
|
||||
const tgba_succ_iterator* si)
|
||||
{
|
||||
out_->new_transition(in - 1, out - 1,
|
||||
si->current_condition(),
|
||||
out_->new_transition
|
||||
(in - 1, out - 1, si->current_condition(),
|
||||
si->current_acceptance_conditions());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ namespace spot
|
|||
os << " | ";
|
||||
bdd_print_formula(os, d, i->label);
|
||||
os << '\t';
|
||||
bdd_print_accset(os, d, i->acc);
|
||||
os << a->acc().format(i->acc);
|
||||
os << std::endl;
|
||||
}
|
||||
os << "Cycle:" << std::endl;
|
||||
|
|
@ -100,7 +100,7 @@ namespace spot
|
|||
os << " | ";
|
||||
bdd_print_formula(os, d, i->label);
|
||||
os << '\t';
|
||||
bdd_print_accset(os, d, i->acc);
|
||||
os << a->acc().format(i->acc);
|
||||
os << '\n';
|
||||
}
|
||||
return os;
|
||||
|
|
@ -302,7 +302,7 @@ namespace spot
|
|||
unsigned src;
|
||||
unsigned dst;
|
||||
const tgba_run::steps* l;
|
||||
bdd seen_acc = bddfalse;
|
||||
acc_cond::mark_t seen_acc = 0U;
|
||||
|
||||
typedef std::unordered_map<const state*, unsigned,
|
||||
state_ptr_hash, state_ptr_equal> state_map;
|
||||
|
|
@ -323,7 +323,7 @@ namespace spot
|
|||
{
|
||||
// expected outgoing transition
|
||||
bdd label = i->label;
|
||||
bdd acc = i->acc;
|
||||
acc_cond::mark_t acc = i->acc;
|
||||
|
||||
// compute the next expected state
|
||||
const state* next;
|
||||
|
|
@ -379,7 +379,7 @@ namespace spot
|
|||
|
||||
s->destroy();
|
||||
|
||||
assert(seen_acc == a->all_acceptance_conditions());
|
||||
assert(a->acc().accepting(seen_acc));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ namespace spot
|
|||
struct step {
|
||||
const state* s;
|
||||
bdd label;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
};
|
||||
|
||||
typedef std::list<step> steps;
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ namespace spot
|
|||
void
|
||||
couvreur99_check_result::accepting_cycle()
|
||||
{
|
||||
bdd acc_to_traverse = ecs_->aut->all_acceptance_conditions();
|
||||
acc_cond::mark_t acc_to_traverse = ecs_->aut->acc().all_sets();
|
||||
// Compute an accepting cycle using successive BFS that are
|
||||
// restarted from the point reached after we have discovered a
|
||||
// transition with a new acceptance conditions.
|
||||
|
|
@ -173,11 +173,11 @@ namespace spot
|
|||
{
|
||||
const couvreur99_check_status* ecs;
|
||||
couvreur99_check_result* r;
|
||||
bdd& acc_to_traverse;
|
||||
acc_cond::mark_t& acc_to_traverse;
|
||||
int scc_root;
|
||||
|
||||
scc_bfs(const couvreur99_check_status* ecs,
|
||||
couvreur99_check_result* r, bdd& acc_to_traverse)
|
||||
couvreur99_check_result* r, acc_cond::mark_t& acc_to_traverse)
|
||||
: bfs_steps(ecs->aut), ecs(ecs), r(r),
|
||||
acc_to_traverse(acc_to_traverse),
|
||||
scc_root(ecs->root.top().index)
|
||||
|
|
@ -202,9 +202,10 @@ namespace spot
|
|||
virtual bool
|
||||
match(tgba_run::step& st, const state* s)
|
||||
{
|
||||
bdd less_acc = acc_to_traverse - st.acc;
|
||||
acc_cond::mark_t less_acc =
|
||||
acc_to_traverse - st.acc;
|
||||
if (less_acc != acc_to_traverse
|
||||
|| (acc_to_traverse == bddfalse
|
||||
|| (acc_to_traverse == 0U
|
||||
&& s == ecs->cycle_seed))
|
||||
{
|
||||
acc_to_traverse = less_acc;
|
||||
|
|
@ -218,7 +219,7 @@ namespace spot
|
|||
substart = b.search(substart, run_->cycle);
|
||||
assert(substart);
|
||||
}
|
||||
while (acc_to_traverse != bddfalse || substart != ecs_->cycle_seed);
|
||||
while (acc_to_traverse != 0U || substart != ecs_->cycle_seed);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ namespace spot
|
|||
// * couvreur99_check::h, a hash of all visited nodes, with their order,
|
||||
// (it is called "Hash" in Couvreur's paper)
|
||||
// * arc, a stack of acceptance conditions between each of these SCC,
|
||||
std::stack<bdd> arc;
|
||||
std::stack<acc_cond::mark_t> arc;
|
||||
// * num, the number of visited nodes. Used to set the order of each
|
||||
// visited node,
|
||||
int num = 1;
|
||||
|
|
@ -152,7 +152,7 @@ namespace spot
|
|||
state* init = ecs_->aut->get_init_state();
|
||||
ecs_->h[init] = 1;
|
||||
ecs_->root.push(1);
|
||||
arc.push(bddfalse);
|
||||
arc.push(0U);
|
||||
tgba_succ_iterator* iter = ecs_->aut->succ_iter(init);
|
||||
iter->first();
|
||||
todo.emplace(init, iter);
|
||||
|
|
@ -207,7 +207,7 @@ namespace spot
|
|||
// Fetch the values (destination state, acceptance conditions
|
||||
// of the arc) we are interested in...
|
||||
const state* dest = succ->current_state();
|
||||
bdd acc = succ->current_acceptance_conditions();
|
||||
acc_cond::mark_t acc = succ->current_acceptance_conditions();
|
||||
// ... and point the iterator to the next successor, for
|
||||
// the next iteration.
|
||||
succ->next();
|
||||
|
|
@ -265,8 +265,7 @@ namespace spot
|
|||
ecs_->root.top().condition |= acc;
|
||||
ecs_->root.rem().splice(ecs_->root.rem().end(), rem);
|
||||
|
||||
if (ecs_->root.top().condition
|
||||
== ecs_->aut->all_acceptance_conditions())
|
||||
if (ecs_->aut->acc().accepting(ecs_->root.top().condition))
|
||||
{
|
||||
// We have found an accepting SCC.
|
||||
// Release all iterators in TODO.
|
||||
|
|
@ -521,7 +520,7 @@ namespace spot
|
|||
// (called the "threshold").
|
||||
int threshold = i->second;
|
||||
std::list<const state*> rem;
|
||||
bdd acc = succ.acc;
|
||||
acc_cond::mark_t acc = succ.acc;
|
||||
while (threshold < ecs_->root.top().index)
|
||||
{
|
||||
assert(!ecs_->root.empty());
|
||||
|
|
@ -543,8 +542,7 @@ namespace spot
|
|||
ecs_->root.rem().splice(ecs_->root.rem().end(), rem);
|
||||
|
||||
// Have we found all acceptance conditions?
|
||||
if (ecs_->root.top().condition
|
||||
== ecs_->aut->all_acceptance_conditions())
|
||||
if (ecs_->aut->acc().accepting(ecs_->root.top().condition))
|
||||
{
|
||||
// Use this state to start the computation of an accepting
|
||||
// cycle.
|
||||
|
|
|
|||
|
|
@ -195,9 +195,9 @@ namespace spot
|
|||
|
||||
protected:
|
||||
struct successor {
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
const spot::state* s;
|
||||
successor(bdd acc, const spot::state* s): acc(acc), s(s) {}
|
||||
successor(acc_cond::mark_t acc, const spot::state* s): acc(acc), s(s) {}
|
||||
};
|
||||
|
||||
// We use five main data in this algorithm:
|
||||
|
|
@ -205,7 +205,7 @@ namespace spot
|
|||
// * couvreur99_check::h, a hash of all visited nodes, with their order,
|
||||
// (it is called "Hash" in Couvreur's paper)
|
||||
// * arc, a stack of acceptance conditions between each of these SCC,
|
||||
std::stack<bdd> arc;
|
||||
std::stack<acc_cond::mark_t> arc;
|
||||
// * num, the number of visited nodes. Used to set the order of each
|
||||
// visited node,
|
||||
int num;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace spot
|
|||
scc_stack::connected_component::connected_component(int i)
|
||||
{
|
||||
index = i;
|
||||
condition = bddfalse;
|
||||
condition = 0U;
|
||||
}
|
||||
|
||||
scc_stack::connected_component&
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ namespace spot
|
|||
|
||||
/// Index of the SCC.
|
||||
int index;
|
||||
/// The bdd condition is the union of all acceptance conditions of
|
||||
/// transitions which connect the states of the connected component.
|
||||
bdd condition;
|
||||
/// The union of all acceptance marks of transitions the
|
||||
/// connected component.
|
||||
acc_cond::mark_t condition;
|
||||
|
||||
std::list<const state*> rem;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,10 +54,6 @@ namespace spot
|
|||
|
||||
struct gv04: public emptiness_check, public ec_statistics
|
||||
{
|
||||
// The unique acceptance condition of the automaton \a a,
|
||||
// or bddfalse if there is no.
|
||||
bdd accepting;
|
||||
|
||||
// Map of visited states.
|
||||
typedef std::unordered_map<const state*, size_t,
|
||||
state_ptr_hash, state_ptr_equal> hash_type;
|
||||
|
|
@ -72,9 +68,9 @@ namespace spot
|
|||
bool violation; // Whether an accepting run was found.
|
||||
|
||||
gv04(const const_tgba_ptr& a, option_map o)
|
||||
: emptiness_check(a, o), accepting(a->all_acceptance_conditions())
|
||||
: emptiness_check(a, o)
|
||||
{
|
||||
assert(a->number_of_acceptance_conditions() <= 1);
|
||||
assert(a->acc().num_sets() <= 1);
|
||||
}
|
||||
|
||||
~gv04()
|
||||
|
|
@ -125,7 +121,8 @@ namespace spot
|
|||
else
|
||||
{
|
||||
const state* s_prime = iter->current_state();
|
||||
bool acc = iter->current_acceptance_conditions() == accepting;
|
||||
bool acc =
|
||||
a_->acc().accepting(iter->current_acceptance_conditions());
|
||||
inc_transitions();
|
||||
|
||||
trace << " Next successor: s_prime = "
|
||||
|
|
@ -365,7 +362,7 @@ namespace spot
|
|||
virtual bool
|
||||
match(tgba_run::step& step, const state*)
|
||||
{
|
||||
return step.acc != bddfalse;
|
||||
return step.acc != 0U;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -386,7 +383,7 @@ namespace spot
|
|||
|
||||
const state* bfs_start = data.stack[scc_root].s;
|
||||
const state* bfs_end = bfs_start;
|
||||
if (data.accepting != bddfalse)
|
||||
if (a_->acc().num_sets() > 0)
|
||||
{
|
||||
first_bfs b1(this, scc_root);
|
||||
bfs_start = b1.search(bfs_start, res->cycle);
|
||||
|
|
|
|||
|
|
@ -44,10 +44,6 @@ namespace spot
|
|||
typedef std::vector<int> vap_t;
|
||||
vap_t vap;
|
||||
|
||||
// Assign a number to each acceptance condition.
|
||||
typedef std::map<bdd, unsigned, bdd_less_than> acc_map;
|
||||
acc_map acc;
|
||||
|
||||
// Map each state to a number.
|
||||
typedef std::unordered_map<const state*, unsigned,
|
||||
state_ptr_hash, state_ptr_equal> state_map;
|
||||
|
|
@ -69,40 +65,27 @@ namespace spot
|
|||
metadata(const const_tgba_ptr& aut)
|
||||
: state_acc(true), is_complete(true), is_deterministic(true)
|
||||
{
|
||||
number_all_acc(aut);
|
||||
number_all_states_and_fill_sup(aut);
|
||||
number_all_ap();
|
||||
}
|
||||
|
||||
void number_all_acc(const const_tgba_ptr& aut)
|
||||
{
|
||||
bdd all_acc = aut->all_acceptance_conditions();
|
||||
unsigned count = 0;
|
||||
while (all_acc != bddfalse)
|
||||
{
|
||||
bdd one = bdd_satone(all_acc);
|
||||
all_acc -= one;
|
||||
acc[one] = count++;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
emit_acc(std::ostream& os, bdd b)
|
||||
emit_acc(std::ostream& os,
|
||||
const const_tgba_ptr& aut,
|
||||
acc_cond::mark_t b)
|
||||
{
|
||||
// FIXME: We could use a cache for this.
|
||||
if (b == bddfalse)
|
||||
if (b == 0U)
|
||||
return os;
|
||||
os << " {";
|
||||
bool notfirst = false;
|
||||
while (b != bddfalse)
|
||||
for (auto v: aut->acc().sets(b))
|
||||
{
|
||||
bdd one = bdd_satone(b);
|
||||
b -= one;
|
||||
if (notfirst)
|
||||
os << ' ';
|
||||
else
|
||||
notfirst = true;
|
||||
os << acc[one];
|
||||
os << v;
|
||||
}
|
||||
os << '}';
|
||||
return os;
|
||||
|
|
@ -124,7 +107,7 @@ namespace spot
|
|||
{
|
||||
auto src = todo.front();
|
||||
todo.pop_front();
|
||||
bdd prev = bddtrue;
|
||||
acc_cond::mark_t prev = -1U;
|
||||
bool st_acc = true;
|
||||
bdd sum = bddfalse;
|
||||
bdd available = bddtrue;
|
||||
|
|
@ -153,8 +136,8 @@ namespace spot
|
|||
}
|
||||
if (st_acc)
|
||||
{
|
||||
bdd acc = i->current_acceptance_conditions();
|
||||
if (prev != bddtrue && prev != acc)
|
||||
acc_cond::mark_t acc = i->current_acceptance_conditions();
|
||||
if (prev != -1U && prev != acc)
|
||||
st_acc = false;
|
||||
else
|
||||
prev = acc;
|
||||
|
|
@ -265,7 +248,7 @@ namespace spot
|
|||
i != md.vap.end(); ++i)
|
||||
escape_str(os << " \"", to_string(d->bdd_map[*i].f)) << '"';
|
||||
os << nl;
|
||||
unsigned num_acc = md.acc.size();
|
||||
unsigned num_acc = aut->acc().num_sets();
|
||||
if (num_acc == 0)
|
||||
os << "acc-name: all";
|
||||
else if (num_acc == 1)
|
||||
|
|
@ -309,7 +292,7 @@ namespace spot
|
|||
|
||||
os << "State: " << i;
|
||||
if (this_acc == Hoaf_Acceptance_States && !j->done())
|
||||
md.emit_acc(os, j->current_acceptance_conditions());
|
||||
md.emit_acc(os, aut, j->current_acceptance_conditions());
|
||||
os << nl;
|
||||
|
||||
for (; !j->done(); j->next())
|
||||
|
|
@ -317,7 +300,7 @@ namespace spot
|
|||
const state* dst = j->current_state();
|
||||
os << '[' << md.sup[j->current_condition()] << "] " << md.sm[dst];
|
||||
if (this_acc == Hoaf_Acceptance_Transitions)
|
||||
md.emit_acc(os, j->current_acceptance_conditions());
|
||||
md.emit_acc(os, aut, j->current_acceptance_conditions());
|
||||
os << nl;
|
||||
dst->destroy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace spot
|
|||
cycle_found(const state* start)
|
||||
{
|
||||
dfs_stack::const_reverse_iterator i = dfs_.rbegin();
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
for (;;)
|
||||
{
|
||||
acc |= i->succ->current_acceptance_conditions();
|
||||
|
|
@ -51,7 +51,7 @@ namespace spot
|
|||
// At least version 4.0 needs it.
|
||||
assert(i != const_cast<const dfs_stack&>(dfs_).rend());
|
||||
}
|
||||
if (acc != aut_->all_acceptance_conditions())
|
||||
if (!aut_->acc().accepting(acc))
|
||||
{
|
||||
// We have found an non-accepting cycle, so the SCC is not
|
||||
// weak.
|
||||
|
|
@ -83,9 +83,8 @@ namespace spot
|
|||
// If no cycle is accepting, the SCC is weak.
|
||||
if (!map.accepting(scc))
|
||||
return true;
|
||||
// If all transitions use all acceptance conditions, the SCC is weak.
|
||||
return (map.useful_acc_of(scc)
|
||||
== bdd_support(map.get_aut()->neg_acceptance_conditions()));
|
||||
// If all transitions use the same acceptance set, the SCC is weak.
|
||||
return map.useful_acc_of(scc).size() == 1;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -128,8 +127,8 @@ namespace spot
|
|||
is_terminal_scc(scc_map& map, unsigned scc)
|
||||
{
|
||||
// If all transitions use all acceptance conditions, the SCC is weak.
|
||||
return ((map.useful_acc_of(scc) ==
|
||||
bdd_support(map.get_aut()->neg_acceptance_conditions()))
|
||||
return (map.accepting(scc)
|
||||
&& map.useful_acc_of(scc).size() == 1
|
||||
&& is_complete_scc(map, scc));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,49 +35,12 @@ namespace spot
|
|||
{
|
||||
namespace
|
||||
{
|
||||
// At some point we'll need to print an acceptance set into LBTT's
|
||||
// format. LBTT expects numbered acceptance sets, so first we'll
|
||||
// number each acceptance condition, and later when we have to print
|
||||
// them we'll just have to look up each of them.
|
||||
class acceptance_cond_splitter
|
||||
{
|
||||
public:
|
||||
acceptance_cond_splitter(bdd all_acc)
|
||||
{
|
||||
unsigned count = 0;
|
||||
while (all_acc != bddfalse)
|
||||
{
|
||||
bdd acc = bdd_satone(all_acc);
|
||||
all_acc -= acc;
|
||||
sm[acc] = count++;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
split(std::ostream& os, bdd b)
|
||||
{
|
||||
while (b != bddfalse)
|
||||
{
|
||||
bdd acc = bdd_satone(b);
|
||||
b -= acc;
|
||||
os << sm[acc] << ' ';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<bdd, unsigned, bdd_less_than> split_map;
|
||||
split_map sm;
|
||||
};
|
||||
|
||||
class lbtt_bfs : public tgba_reachable_iterator_breadth_first
|
||||
{
|
||||
public:
|
||||
lbtt_bfs(const const_tgba_ptr& a, std::ostream& os, bool sba_format)
|
||||
: tgba_reachable_iterator_breadth_first(a),
|
||||
os_(os),
|
||||
all_acc_conds_(a->all_acceptance_conditions()),
|
||||
acs_(all_acc_conds_),
|
||||
sba_format_(sba_format),
|
||||
sba_(nullptr)
|
||||
{
|
||||
|
|
@ -104,7 +67,7 @@ namespace spot
|
|||
// iterator.
|
||||
tgba_succ_iterator* it = aut_->succ_iter(s);
|
||||
bool accepting = it->first()
|
||||
&& it->current_acceptance_conditions() == all_acc_conds_;
|
||||
&& aut_->acc().accepting(it->current_acceptance_conditions());
|
||||
aut_->release_iter(it);
|
||||
return accepting;
|
||||
}
|
||||
|
|
@ -138,7 +101,8 @@ namespace spot
|
|||
body_ << out - 1 << ' ';
|
||||
if (!sba_format_)
|
||||
{
|
||||
acs_.split(body_, si->current_acceptance_conditions());
|
||||
for (auto s: aut_->acc().sets(si->current_acceptance_conditions()))
|
||||
body_ << s << ' ';
|
||||
body_ << "-1 ";
|
||||
}
|
||||
const ltl::formula* f = bdd_to_formula(si->current_condition(),
|
||||
|
|
@ -155,7 +119,7 @@ namespace spot
|
|||
if (sba_format_)
|
||||
os_ << '1';
|
||||
else
|
||||
os_ << aut_->number_of_acceptance_conditions() << 't';
|
||||
os_ << aut_->acc().num_sets() << 't';
|
||||
os_ << '\n' << body_.str() << "-1" << std::endl;
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +127,6 @@ namespace spot
|
|||
std::ostream& os_;
|
||||
std::ostringstream body_;
|
||||
bdd all_acc_conds_;
|
||||
acceptance_cond_splitter acs_;
|
||||
bool sba_format_;
|
||||
const_tgba_digraph_ptr sba_;
|
||||
};
|
||||
|
|
@ -196,7 +159,7 @@ namespace spot
|
|||
break;
|
||||
|
||||
// Read the acceptance conditions.
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
for (;;)
|
||||
{
|
||||
int acc_n = 0;
|
||||
|
|
@ -254,7 +217,7 @@ namespace spot
|
|||
aut->set_init_state(src_state);
|
||||
|
||||
// Read the acceptance conditions.
|
||||
bdd acc = bddfalse;
|
||||
acc_cond::mark_t acc = 0U;
|
||||
for (;;)
|
||||
{
|
||||
int acc_n = 0;
|
||||
|
|
|
|||
|
|
@ -141,7 +141,9 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
|
||||
translate_dict(const bdd_dict_ptr& dict, ltl_simplifier* ls, bool exprop,
|
||||
translate_dict(const bdd_dict_ptr& dict,
|
||||
acc_cond& acc,
|
||||
ltl_simplifier* ls, bool exprop,
|
||||
bool single_acc)
|
||||
: dict(dict),
|
||||
ls(ls),
|
||||
|
|
@ -150,7 +152,8 @@ namespace spot
|
|||
next_set(bddtrue),
|
||||
transdfa(*this),
|
||||
exprop(exprop),
|
||||
single_acc(single_acc)
|
||||
single_acc(single_acc),
|
||||
acc(acc)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -184,6 +187,9 @@ namespace spot
|
|||
ratexp_to_dfa transdfa;
|
||||
bool exprop;
|
||||
bool single_acc;
|
||||
acc_cond& acc;
|
||||
// Map BDD variables to acceptance marks.
|
||||
std::map<int, unsigned> bm;
|
||||
|
||||
enum translate_flags
|
||||
{
|
||||
|
|
@ -231,6 +237,7 @@ namespace spot
|
|||
|
||||
public:
|
||||
|
||||
|
||||
int
|
||||
register_proposition(const formula* f)
|
||||
{
|
||||
|
|
@ -239,6 +246,30 @@ namespace spot
|
|||
return num;
|
||||
}
|
||||
|
||||
acc_cond::mark_t
|
||||
bdd_to_mark(bdd a)
|
||||
{
|
||||
bdd o = a;
|
||||
if (a == bddtrue)
|
||||
return 0U;
|
||||
assert(a != bddfalse);
|
||||
std::vector<unsigned> t;
|
||||
do
|
||||
{
|
||||
int v = bdd_var(a);
|
||||
bdd h = bdd_high(a);
|
||||
a = bdd_low(a);
|
||||
if (h != bddfalse)
|
||||
{
|
||||
t.push_back(bm[v]);
|
||||
if (a == bddfalse)
|
||||
a = h;
|
||||
}
|
||||
}
|
||||
while (a != bddtrue);
|
||||
return acc.marks(t.begin(), t.end());
|
||||
}
|
||||
|
||||
int
|
||||
register_a_variable(const formula* f)
|
||||
{
|
||||
|
|
@ -247,6 +278,10 @@ namespace spot
|
|||
int num = dict->register_acceptance_variable
|
||||
(ltl::constant::true_instance(), this);
|
||||
a_set &= bdd_ithvar(num);
|
||||
|
||||
auto p = bm.emplace(num, 0U);
|
||||
if (p.second)
|
||||
p.first->second = acc.add_set();
|
||||
return num;
|
||||
}
|
||||
// A promise of 'x', noted P(x) is pretty much like the F(x)
|
||||
|
|
@ -297,6 +332,11 @@ namespace spot
|
|||
int num = dict->register_acceptance_variable(g, this);
|
||||
a_set &= bdd_ithvar(num);
|
||||
g->destroy();
|
||||
|
||||
auto p = bm.emplace(num, 0U);
|
||||
if (p.second)
|
||||
p.first->second = acc.add_set();
|
||||
|
||||
return num;
|
||||
}
|
||||
else
|
||||
|
|
@ -316,6 +356,11 @@ namespace spot
|
|||
}
|
||||
int num = dict->register_acceptance_variable(f, this);
|
||||
a_set &= bdd_ithvar(num);
|
||||
|
||||
auto p = bm.emplace(num, 0U);
|
||||
if (p.second)
|
||||
p.first->second = acc.add_set();
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
|
@ -2105,7 +2150,10 @@ namespace spot
|
|||
|
||||
assert(dict == s->get_dict());
|
||||
|
||||
translate_dict d(dict, s, exprop, f->is_syntactic_persistence());
|
||||
tgba_digraph_ptr a = make_tgba_digraph(dict);
|
||||
auto namer = a->create_namer<const formula*, formula_ptr_hash>();
|
||||
|
||||
translate_dict d(dict, a->acc(), s, exprop, f->is_syntactic_persistence());
|
||||
|
||||
// Compute the set of all promises that can possibly occur
|
||||
// inside the formula.
|
||||
|
|
@ -2154,8 +2202,6 @@ namespace spot
|
|||
bdd all_events = observable_events | unobservable_events;
|
||||
|
||||
|
||||
tgba_digraph_ptr a = make_tgba_digraph(dict);
|
||||
auto namer = a->create_namer<const formula*, formula_ptr_hash>();
|
||||
|
||||
// This is in case the initial state is equivalent to true...
|
||||
if (symb_merge)
|
||||
|
|
@ -2341,7 +2387,7 @@ namespace spot
|
|||
formulae_to_translate.insert(truef);
|
||||
namer->new_state(truef);
|
||||
}
|
||||
namer->new_transition(now, truef, cond_for_true, bddtrue);
|
||||
namer->new_transition(now, truef, cond_for_true, 0U);
|
||||
}
|
||||
// Register other transitions.
|
||||
for (i = dests.begin(); i != dests.end(); ++i)
|
||||
|
|
@ -2365,7 +2411,7 @@ namespace spot
|
|||
if (!reachable && !seen)
|
||||
namer->new_state(dest);
|
||||
reachable = true;
|
||||
namer->new_transition(now, dest, cond, j.first);
|
||||
namer->new_transition(now, dest, cond, d.bdd_to_mark(j.first));
|
||||
}
|
||||
|
||||
if (reachable && !seen)
|
||||
|
|
@ -2380,21 +2426,15 @@ namespace spot
|
|||
delete namer;
|
||||
|
||||
dict->register_propositions(fc.used_vars(), a);
|
||||
a->set_acceptance_conditions(d.a_set);
|
||||
// Turn all promises into real acceptance conditions.
|
||||
acc_compl ac(a->all_acceptance_conditions(),
|
||||
a->neg_acceptance_conditions());
|
||||
|
||||
unsigned ns = a->num_states();
|
||||
for (unsigned s = 0; s < ns; ++s)
|
||||
for (auto& t: a->out(s))
|
||||
t.acc = ac.reverse_complement(t.acc);
|
||||
|
||||
t.acc = a->acc().comp(t.acc);
|
||||
|
||||
if (!simplifier)
|
||||
// This should not be deleted before we have registered all propositions.
|
||||
delete s;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,10 +57,9 @@ namespace spot
|
|||
magic_search_(const const_tgba_ptr& a, size_t size,
|
||||
option_map o = option_map())
|
||||
: emptiness_check(a, o),
|
||||
h(size),
|
||||
all_cond(a->all_acceptance_conditions())
|
||||
h(size)
|
||||
{
|
||||
assert(a->number_of_acceptance_conditions() <= 1);
|
||||
assert(a->acc().num_sets() <= 1);
|
||||
}
|
||||
|
||||
virtual ~magic_search_()
|
||||
|
|
@ -98,7 +97,7 @@ namespace spot
|
|||
const state* s0 = a_->get_init_state();
|
||||
inc_states();
|
||||
h.add_new_state(s0, BLUE);
|
||||
push(st_blue, s0, bddfalse, bddfalse);
|
||||
push(st_blue, s0, bddfalse, 0U);
|
||||
if (dfs_blue())
|
||||
return std::make_shared<magic_search_result>(t, options());
|
||||
}
|
||||
|
|
@ -151,7 +150,7 @@ namespace spot
|
|||
private:
|
||||
|
||||
void push(stack_type& st, const state* s,
|
||||
const bdd& label, const bdd& acc)
|
||||
const bdd& label, acc_cond::mark_t acc)
|
||||
{
|
||||
inc_depth();
|
||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||
|
|
@ -179,9 +178,6 @@ namespace spot
|
|||
/// State targeted by the red dfs.
|
||||
const state* target;
|
||||
|
||||
/// The unique acceptance condition of the automaton \a a.
|
||||
bdd all_cond;
|
||||
|
||||
bool dfs_blue()
|
||||
{
|
||||
while (!st_blue.empty())
|
||||
|
|
@ -194,7 +190,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
@ -208,7 +204,7 @@ namespace spot
|
|||
}
|
||||
else
|
||||
{
|
||||
if (acc == all_cond && c.get_color() != RED)
|
||||
if (a_->acc().accepting(acc) && c.get_color() != RED)
|
||||
{
|
||||
// the test 'c.get_color() != RED' is added to limit
|
||||
// the number of runs reported by successive
|
||||
|
|
@ -239,7 +235,7 @@ namespace spot
|
|||
typename heap::color_ref c = h.get_color_ref(f_dest.s);
|
||||
assert(!c.is_white());
|
||||
if (!st_blue.empty() &&
|
||||
f_dest.acc == all_cond && c.get_color() != RED)
|
||||
a_->acc().accepting(f_dest.acc) && c.get_color() != RED)
|
||||
{
|
||||
// the test 'c.get_color() != RED' is added to limit
|
||||
// the number of runs reported by successive
|
||||
|
|
@ -281,7 +277,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace spot
|
|||
{
|
||||
struct stack_item
|
||||
{
|
||||
stack_item(const state* n, tgba_succ_iterator* i, bdd l, bdd a)
|
||||
stack_item(const state* n, tgba_succ_iterator* i, bdd l, acc_cond::mark_t a)
|
||||
: s(n), it(i), label(l), acc(a) {};
|
||||
/// The visited state.
|
||||
const state* s;
|
||||
|
|
@ -57,7 +57,7 @@ namespace spot
|
|||
bdd label;
|
||||
/// The acceptance set of the transition traversed to reach \a s
|
||||
/// (false for the first one).
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
};
|
||||
|
||||
typedef std::list<stack_item> stack_type;
|
||||
|
|
@ -112,7 +112,7 @@ namespace spot
|
|||
|
||||
assert(!stb.empty());
|
||||
|
||||
bdd covered_acc = bddfalse;
|
||||
acc_cond::mark_t covered_acc = 0U;
|
||||
accepting_transitions_list acc_trans;
|
||||
|
||||
const state* start;
|
||||
|
|
@ -120,7 +120,7 @@ namespace spot
|
|||
start = stb.front().s->clone();
|
||||
if (!str.empty())
|
||||
{
|
||||
if (a_->number_of_acceptance_conditions() == 0)
|
||||
if (a_->acc().num_sets() == 0)
|
||||
{
|
||||
// take arbitrarily the last transition on the red stack
|
||||
stack_type::const_iterator i, j;
|
||||
|
|
@ -184,7 +184,7 @@ namespace spot
|
|||
}
|
||||
}
|
||||
|
||||
if (a_->all_acceptance_conditions() != covered_acc)
|
||||
if (!a_->acc().accepting(covered_acc))
|
||||
{
|
||||
bool b = dfs(start, acc_trans, covered_acc);
|
||||
assert(b);
|
||||
|
|
@ -222,7 +222,7 @@ namespace spot
|
|||
struct transition {
|
||||
const state* source;
|
||||
bdd label;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
const state* dest;
|
||||
};
|
||||
typedef std::list<transition> accepting_transitions_list;
|
||||
|
|
@ -253,7 +253,7 @@ namespace spot
|
|||
}
|
||||
|
||||
bool dfs(const state* target, accepting_transitions_list& acc_trans,
|
||||
bdd& covered_acc)
|
||||
acc_cond::mark_t& covered_acc)
|
||||
{
|
||||
assert(h_.has_been_visited(target));
|
||||
stack_type st1;
|
||||
|
|
@ -264,7 +264,7 @@ namespace spot
|
|||
seen.insert(start);
|
||||
tgba_succ_iterator* i = a_->succ_iter(start);
|
||||
i->first();
|
||||
st1.emplace_front(start, i, bddfalse, bddfalse);
|
||||
st1.emplace_front(start, i, bddfalse, 0U);
|
||||
|
||||
while (!st1.empty())
|
||||
{
|
||||
|
|
@ -277,7 +277,7 @@ namespace spot
|
|||
ndfsr_trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
f.it->next();
|
||||
if (h_.has_been_visited(s_prime))
|
||||
{
|
||||
|
|
@ -308,7 +308,7 @@ namespace spot
|
|||
assert(h_.has_been_visited(t.dest));
|
||||
acc_trans.push_back(t);
|
||||
covered_acc |= acc;
|
||||
if (covered_acc == a_->all_acceptance_conditions())
|
||||
if (a_->acc().accepting(covered_acc))
|
||||
{
|
||||
clean(a_, st1, seen, dead);
|
||||
s_prime->destroy();
|
||||
|
|
@ -337,7 +337,7 @@ namespace spot
|
|||
stack_item f_dest(f);
|
||||
a_->release_iter(st1.front().it);
|
||||
st1.pop_front();
|
||||
if (!st1.empty() && (f_dest.acc & covered_acc) != f_dest.acc)
|
||||
if (!st1.empty() && ((f_dest.acc & covered_acc) != f_dest.acc))
|
||||
{
|
||||
ndfsr_trace << " a propagation is needed, start a search"
|
||||
<< std::endl;
|
||||
|
|
@ -350,7 +350,7 @@ namespace spot
|
|||
assert(h_.has_been_visited(t.dest));
|
||||
acc_trans.push_back(t);
|
||||
covered_acc |= f_dest.acc;
|
||||
if (covered_acc == a_->all_acceptance_conditions())
|
||||
if (a_->acc().accepting(covered_acc))
|
||||
{
|
||||
clean(a_, st1, seen, dead);
|
||||
return true;
|
||||
|
|
@ -607,6 +607,7 @@ namespace spot
|
|||
<< a_->format_state(begin) << std::endl;
|
||||
transition tmp;
|
||||
tmp.source = tmp.dest = 0; // Initialize to please GCC 4.0.1 (Darwin).
|
||||
tmp.acc = 0U;
|
||||
target.emplace(begin, tmp);
|
||||
min_path<true> s(this, a_, target, h_);
|
||||
const state* res = s.search(current.dest->clone(), run->cycle);
|
||||
|
|
@ -621,6 +622,7 @@ namespace spot
|
|||
m_source_trans target;
|
||||
transition tmp;
|
||||
tmp.source = tmp.dest = 0; // Initialize to please GCC 4.0.
|
||||
tmp.acc = 0U;
|
||||
|
||||
// Register all states from the cycle as target of the BFS.
|
||||
for (tgba_run::steps::const_iterator i = run->cycle.begin();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace spot
|
|||
const ltl::formula* f, bool comments)
|
||||
: tgba_reachable_iterator_breadth_first(a),
|
||||
os_(os), f_(f), accept_all_(-1), fi_needed_(false),
|
||||
comments_(comments), all_acc_conds_(a->all_acceptance_conditions()),
|
||||
comments_(comments),
|
||||
sba_(std::dynamic_pointer_cast<const tgba_digraph>(a))
|
||||
{
|
||||
assert(!sba_ || sba_->has_state_based_acc());
|
||||
|
|
@ -87,8 +87,8 @@ namespace spot
|
|||
// is not terribly efficient since we have to create the
|
||||
// iterator.
|
||||
tgba_succ_iterator* it = aut_->succ_iter(s);
|
||||
bool accepting =
|
||||
it->first() && it->current_acceptance_conditions() == all_acc_conds_;
|
||||
bool accepting = it->first()
|
||||
&& aut_->acc().accepting(it->current_acceptance_conditions());
|
||||
aut_->release_iter(it);
|
||||
return accepting;
|
||||
}
|
||||
|
|
@ -193,7 +193,6 @@ namespace spot
|
|||
bool fi_needed_;
|
||||
state* init_;
|
||||
bool comments_;
|
||||
bdd all_acc_conds_;
|
||||
const_tgba_digraph_ptr sba_;
|
||||
};
|
||||
} // anonymous
|
||||
|
|
@ -202,7 +201,7 @@ namespace spot
|
|||
never_claim_reachable(std::ostream& os, const const_tgba_ptr& g,
|
||||
const ltl::formula* f, bool comments)
|
||||
{
|
||||
assert(g->number_of_acceptance_conditions() <= 1);
|
||||
assert(g->acc().num_sets() <= 1);
|
||||
never_claim_bfs n(g, os, f, comments);
|
||||
n.run();
|
||||
return os;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ namespace spot
|
|||
if (type_ == BA)
|
||||
state_based_ = true;
|
||||
|
||||
int original_acc = a->number_of_acceptance_conditions();
|
||||
int original_acc = a->acc().num_sets();
|
||||
|
||||
// Remove useless SCCs.
|
||||
if (type_ == Monitor)
|
||||
|
|
@ -237,7 +237,7 @@ namespace spot
|
|||
if (PREF_ == Deterministic
|
||||
&& f
|
||||
&& f->is_syntactic_recurrence()
|
||||
&& sim->number_of_acceptance_conditions() > 1)
|
||||
&& sim->acc().num_sets() > 1)
|
||||
tmpd = degeneralize_tba(sim);
|
||||
|
||||
auto in = tmpd ? tmpd : sim;
|
||||
|
|
@ -306,7 +306,7 @@ namespace spot
|
|||
// because the input TBA might be smaller.
|
||||
if (state_based_)
|
||||
in = degeneralize(dba);
|
||||
else if (dba->number_of_acceptance_conditions() != 1)
|
||||
else if (dba->acc().num_sets() != 1)
|
||||
in = degeneralize_tba(dba);
|
||||
else
|
||||
in = dba;
|
||||
|
|
@ -354,8 +354,7 @@ namespace spot
|
|||
// Degeneralize the dba resulting from tba-determinization or
|
||||
// sat-minimization (which is a TBA) if requested and needed.
|
||||
if (dba && !dba_is_wdba && type_ == BA
|
||||
&& !(dba_is_minimal && state_based_
|
||||
&& dba->number_of_acceptance_conditions() == 1))
|
||||
&& !(dba_is_minimal && state_based_ && dba->acc().num_sets() == 1))
|
||||
dba = degeneralize(dba);
|
||||
|
||||
if (dba && sim)
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ namespace spot
|
|||
// print_set(std::cerr, *j) << '\n';
|
||||
// }
|
||||
|
||||
bdd acc = aut_->all_acceptance_conditions();
|
||||
auto acc = aut_->acc().all_sets();
|
||||
for (auto i: all_)
|
||||
i->acc = acc;
|
||||
return threshold_ != 0 && cycles_left_ == 0;
|
||||
|
|
@ -316,7 +316,7 @@ namespace spot
|
|||
{
|
||||
if (f == 0 && neg_aut == 0)
|
||||
return 0;
|
||||
if (aut->number_of_acceptance_conditions() > 1)
|
||||
if (aut->acc().num_sets() > 1)
|
||||
return 0;
|
||||
|
||||
auto det = tba_determinize(aut, threshold_states, threshold_cycles);
|
||||
|
|
|
|||
|
|
@ -35,20 +35,12 @@ namespace spot
|
|||
|
||||
namespace
|
||||
{
|
||||
std::string
|
||||
acc(int n)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << n;
|
||||
return "a" + s.str();
|
||||
}
|
||||
|
||||
void
|
||||
random_labels(tgba_digraph_ptr aut,
|
||||
unsigned src,
|
||||
unsigned dest,
|
||||
int* props, int props_n, float t,
|
||||
const std::list<bdd>& accs, float a)
|
||||
unsigned n_accs, float a)
|
||||
{
|
||||
int val = 0;
|
||||
int size = 0;
|
||||
|
|
@ -70,21 +62,18 @@ namespace spot
|
|||
if (size > 0)
|
||||
p &= bdd_ibuildcube(val, size, props);
|
||||
|
||||
bdd ac = bddfalse;
|
||||
for (std::list<bdd>::const_iterator i = accs.begin();
|
||||
i != accs.end(); ++i)
|
||||
acc_cond::mark_t m = 0U;
|
||||
for (unsigned i = 0U; i < n_accs; ++i)
|
||||
if (drand() < a)
|
||||
ac |= *i;
|
||||
|
||||
aut->new_transition(src, dest, p, ac);
|
||||
m |= aut->acc().mark(i);
|
||||
aut->new_transition(src, dest, p, m);
|
||||
}
|
||||
}
|
||||
|
||||
tgba_digraph_ptr
|
||||
random_graph(int n, float d,
|
||||
const ltl::atomic_prop_set* ap, const bdd_dict_ptr& dict,
|
||||
int n_acc, float a, float t,
|
||||
ltl::environment* env)
|
||||
unsigned n_accs, float a, float t)
|
||||
{
|
||||
assert(n > 0);
|
||||
auto res = make_tgba_digraph(dict);
|
||||
|
|
@ -96,20 +85,7 @@ namespace spot
|
|||
for (auto i: *ap)
|
||||
props[pi++] = dict->register_proposition(i, res);
|
||||
|
||||
std::list<bdd> accs;
|
||||
bdd allneg = bddtrue;
|
||||
for (int i = 0; i < n_acc; ++i)
|
||||
{
|
||||
const ltl::formula* f = env->require(acc(i));
|
||||
int v = dict->register_acceptance_variable(f, res);
|
||||
f->destroy();
|
||||
bdd b = bdd_nithvar(v);
|
||||
allneg &= b;
|
||||
accs.push_back(b);
|
||||
}
|
||||
res->set_acceptance_conditions(allneg);
|
||||
for (auto& i: accs)
|
||||
i = bdd_compose(allneg, i, bdd_var(i));
|
||||
res->set_acceptance_conditions(n_accs);
|
||||
|
||||
// Using std::unordered_set instead of std::set for these sets is 3
|
||||
// times slower (tested on a 50000 nodes example).
|
||||
|
|
@ -162,7 +138,7 @@ namespace spot
|
|||
std::advance(i, index);
|
||||
|
||||
// Link it from src.
|
||||
random_labels(res, src, *i, props, props_n, t, accs, a);
|
||||
random_labels(res, src, *i, props, props_n, t, n_accs, a);
|
||||
nodes_to_process.insert(*i);
|
||||
unreachable_nodes.erase(i);
|
||||
break;
|
||||
|
|
@ -178,7 +154,7 @@ namespace spot
|
|||
state_randomizer[index] = state_randomizer[possibilities];
|
||||
state_randomizer[possibilities] = x;
|
||||
|
||||
random_labels(res, src, x, props, props_n, t, accs, a);
|
||||
random_labels(res, src, x, props, props_n, t, n_accs, a);
|
||||
|
||||
auto j = unreachable_nodes.find(x);
|
||||
if (j != unreachable_nodes.end())
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace spot
|
|||
/// A density of 1 means all states will be connected to each other.
|
||||
/// \param ap The list of atomic property that should label the transition.
|
||||
/// \param dict The bdd_dict to used for this automata.
|
||||
/// \param n_acc The number of acceptance sets to use.
|
||||
/// \param n_accs The number of acceptance sets to use.
|
||||
/// If this number is non null, then there is no guarantee
|
||||
/// that the generated graph contains an accepting cycle (raise
|
||||
/// the value of \a a to improve the chances).
|
||||
|
|
@ -49,7 +49,6 @@ namespace spot
|
|||
/// to an acceptance set.
|
||||
/// \param t The probability (between 0.0 and 1.0) that an atomic proposition
|
||||
/// is true.
|
||||
/// \param env The environment in which to declare the acceptance conditions.
|
||||
///
|
||||
/// This algorithms is adapted from the one in Fig 6.2 page 48 of
|
||||
/** \verbatim
|
||||
|
|
@ -79,8 +78,7 @@ namespace spot
|
|||
SPOT_API tgba_digraph_ptr
|
||||
random_graph(int n, float d,
|
||||
const ltl::atomic_prop_set* ap, const bdd_dict_ptr& dict,
|
||||
int n_acc = 0, float a = 0.1, float t = 0.5,
|
||||
ltl::environment* env = <l::default_environment::instance());
|
||||
unsigned n_accs = 0, float a = 0.1, float t = 0.5);
|
||||
}
|
||||
|
||||
#endif // SPOT_TGBAALGOS_RANDOMGRAPH_HH
|
||||
|
|
|
|||
|
|
@ -102,9 +102,8 @@ namespace spot
|
|||
const state* segment_next; // The state immediately after the segment.
|
||||
|
||||
// Start from the end of the original cycle, and rewind until all
|
||||
// acceptance conditions have been seen.
|
||||
bdd seen_acc = bddfalse;
|
||||
bdd all_acc = a->all_acceptance_conditions();
|
||||
// acceptance sets have been seen.
|
||||
acc_cond::mark_t seen_acc = 0U;
|
||||
tgba_run::steps::const_iterator seg = org->cycle.end();
|
||||
do
|
||||
{
|
||||
|
|
@ -112,12 +111,12 @@ namespace spot
|
|||
--seg;
|
||||
seen_acc |= seg->acc;
|
||||
}
|
||||
while (seen_acc != all_acc);
|
||||
while (!a->acc().accepting(seen_acc));
|
||||
segment_start = seg->s;
|
||||
|
||||
// Now go forward and ends the segment as soon as we have seen all
|
||||
// acceptance conditions, cloning it in our result along the way.
|
||||
seen_acc = bddfalse;
|
||||
// acceptance sets, cloning it in our result along the way.
|
||||
seen_acc = 0U;
|
||||
do
|
||||
{
|
||||
assert(seg != org->cycle.end());
|
||||
|
|
@ -128,7 +127,7 @@ namespace spot
|
|||
|
||||
++seg;
|
||||
}
|
||||
while (seen_acc != all_acc);
|
||||
while (!a->acc().accepting(seen_acc));
|
||||
segment_next = seg == org->cycle.end() ? org->cycle.front().s : seg->s;
|
||||
|
||||
// Close this cycle if needed, that is, compute a cycle going
|
||||
|
|
|
|||
|
|
@ -51,8 +51,7 @@ namespace spot
|
|||
int serial = 1;
|
||||
const tgba_run::steps* l;
|
||||
std::string in;
|
||||
bdd all_acc = bddfalse;
|
||||
bdd expected_all_acc = a->all_acceptance_conditions();
|
||||
acc_cond::mark_t all_acc = 0U;
|
||||
bool all_acc_seen = false;
|
||||
typedef std::unordered_map<const state*, std::set<int>,
|
||||
state_ptr_hash, state_ptr_equal> state_map;
|
||||
|
|
@ -116,7 +115,7 @@ namespace spot
|
|||
|
||||
// expected outgoing transition
|
||||
bdd label = i->label;
|
||||
bdd acc = i->acc;
|
||||
acc_cond::mark_t acc = i->acc;
|
||||
|
||||
// compute the next expected state
|
||||
const state* next;
|
||||
|
|
@ -170,7 +169,7 @@ namespace spot
|
|||
{
|
||||
os << "ERROR: no transition with label="
|
||||
<< bdd_format_formula(a->get_dict(), label)
|
||||
<< " and acc=" << bdd_format_accset(a->get_dict(), acc)
|
||||
<< " and acc=" << a->acc().format(acc)
|
||||
<< " leaving state " << serial
|
||||
<< " for state " << a->format_state(next) << '\n'
|
||||
<< "The following transitions leave state " << serial
|
||||
|
|
@ -185,9 +184,7 @@ namespace spot
|
|||
<< bdd_format_formula(a->get_dict(),
|
||||
j->current_condition())
|
||||
<< " and acc="
|
||||
<< (bdd_format_accset
|
||||
(a->get_dict(),
|
||||
j->current_acceptance_conditions()))
|
||||
<< a->acc().format(j->current_acceptance_conditions())
|
||||
<< " going to " << a->format_state(s2) << '\n';
|
||||
s2->destroy();
|
||||
}
|
||||
|
|
@ -203,7 +200,7 @@ namespace spot
|
|||
print_annotation(os, a, j);
|
||||
os << " with label="
|
||||
<< bdd_format_formula(a->get_dict(), label)
|
||||
<< " and acc=" << bdd_format_accset(a->get_dict(), acc)
|
||||
<< " and acc=" << a->acc().format(acc)
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
|
|
@ -212,7 +209,7 @@ namespace spot
|
|||
print_annotation(os, a, j);
|
||||
bdd_print_formula(os, a->get_dict(), label);
|
||||
os << '\t';
|
||||
bdd_print_accset(os, a->get_dict(), acc);
|
||||
a->acc().format(acc);
|
||||
os << std::endl;
|
||||
}
|
||||
a->release_iter(j);
|
||||
|
|
@ -226,24 +223,24 @@ namespace spot
|
|||
if (l == &run->cycle && i != l->begin())
|
||||
{
|
||||
all_acc |= acc;
|
||||
if (!all_acc_seen && all_acc == expected_all_acc)
|
||||
if (!all_acc_seen && a->acc().accepting(all_acc))
|
||||
{
|
||||
all_acc_seen = true;
|
||||
if (debug)
|
||||
os << "all acceptance conditions ("
|
||||
<< bdd_format_accset(a->get_dict(), all_acc)
|
||||
<< a->acc().format(all_acc)
|
||||
<< ") have been seen\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
s->destroy();
|
||||
if (all_acc != expected_all_acc)
|
||||
if (!a->acc().accepting(all_acc))
|
||||
{
|
||||
if (debug)
|
||||
os << "ERROR: The cycle's acceptance conditions ("
|
||||
<< bdd_format_accset(a->get_dict(), all_acc)
|
||||
<< a->acc().format(all_acc)
|
||||
<< ") do not\nmatch those of the automaton ("
|
||||
<< bdd_format_accset(a->get_dict(), expected_all_acc)
|
||||
<< a->acc().format(a->acc().all_sets())
|
||||
<< ")\n";
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,6 @@ namespace spot
|
|||
|
||||
todo.push_back(seen(aut->get_init_state()));
|
||||
|
||||
bdd all_acc = aut->all_acceptance_conditions();
|
||||
|
||||
bool all_accepting = true;
|
||||
while (all_accepting && !todo.empty())
|
||||
{
|
||||
|
|
@ -86,8 +84,8 @@ namespace spot
|
|||
|
||||
for (auto it: aut->succ(s))
|
||||
{
|
||||
bdd acc = it->current_acceptance_conditions();
|
||||
if (acc != all_acc)
|
||||
auto acc = it->current_acceptance_conditions();
|
||||
if (!aut->acc().accepting(acc))
|
||||
{
|
||||
all_accepting = false;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -43,8 +43,9 @@ namespace spot
|
|||
void
|
||||
start()
|
||||
{
|
||||
os_ << "acc =";
|
||||
print_acc(aut_->all_acceptance_conditions()) << ";\n";
|
||||
os_ << "acc = ";
|
||||
aut_->acc().format_quoted(os_, aut_->acc().all_sets())
|
||||
<< ";\n";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -61,7 +62,10 @@ namespace spot
|
|||
os_ << "\", \"";
|
||||
escape_str(os_, bdd_format_formula(d, si->current_condition()));
|
||||
os_ << "\",";
|
||||
print_acc(si->current_acceptance_conditions()) << ";\n";
|
||||
if (si->current_acceptance_conditions())
|
||||
aut_->acc().format_quoted(os_ << ' ',
|
||||
si->current_acceptance_conditions());
|
||||
os_ << ";\n";
|
||||
dest->destroy();
|
||||
}
|
||||
while (si->next());
|
||||
|
|
@ -69,28 +73,6 @@ namespace spot
|
|||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
|
||||
std::ostream&
|
||||
print_acc(bdd acc)
|
||||
{
|
||||
const bdd_dict_ptr d = aut_->get_dict();
|
||||
while (acc != bddfalse)
|
||||
{
|
||||
bdd cube = bdd_satone(acc);
|
||||
acc -= cube;
|
||||
const ltl::formula* f = d->oneacc_to_formula(cube);
|
||||
std::string s = ltl::to_string(f);
|
||||
if (is_atomic_prop(f) && s[0] == '"')
|
||||
{
|
||||
// Unquote atomic propositions.
|
||||
s.erase(s.begin());
|
||||
s.resize(s.size() - 1);
|
||||
}
|
||||
os_ << " \"";
|
||||
escape_str(os_, s) << '"';
|
||||
}
|
||||
return os_;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ namespace spot
|
|||
{
|
||||
if (scc_map_[n].trivial)
|
||||
return false;
|
||||
return acc_set_of(n) == aut_->all_acceptance_conditions();
|
||||
return aut_->acc().accepting(acc_set_of(n));
|
||||
}
|
||||
|
||||
const_tgba_ptr
|
||||
|
|
@ -139,8 +139,6 @@ namespace spot
|
|||
void
|
||||
scc_map::build_map()
|
||||
{
|
||||
acceptance_convertor conv(aut_->neg_acceptance_conditions());
|
||||
|
||||
// Setup depth-first search from the initial state.
|
||||
{
|
||||
self_loops_ = 0;
|
||||
|
|
@ -148,7 +146,7 @@ namespace spot
|
|||
num_ = -1;
|
||||
h_.emplace(init, num_);
|
||||
root_.emplace_front(num_);
|
||||
arc_acc_.push(bddfalse);
|
||||
arc_acc_.push(0U);
|
||||
arc_cond_.push(bddfalse);
|
||||
tgba_succ_iterator* iter = aut_->succ_iter(init);
|
||||
iter->first();
|
||||
|
|
@ -209,7 +207,7 @@ namespace spot
|
|||
const state* dest = succ->current_state();
|
||||
if (!dest->compare(todo_.top().first))
|
||||
++self_loops_;
|
||||
bdd acc = succ->current_acceptance_conditions();
|
||||
auto acc = succ->current_acceptance_conditions();
|
||||
bdd cond = succ->current_condition();
|
||||
root_.front().supp &= bdd_support(cond);
|
||||
// ... and point the iterator to the next successor, for
|
||||
|
|
@ -268,17 +266,18 @@ namespace spot
|
|||
cond_set conds;
|
||||
conds.insert(cond);
|
||||
bdd supp = bddtrue;
|
||||
bdd all = aut_->all_acceptance_conditions();
|
||||
bdd useful = conv.as_full_product(acc);
|
||||
std::set<acc_cond::mark_t> used_acc = { acc };
|
||||
while (threshold > root_.front().index)
|
||||
{
|
||||
assert(!root_.empty());
|
||||
assert(!arc_acc_.empty());
|
||||
assert(arc_acc_.size() == arc_cond_.size());
|
||||
acc |= root_.front().acc;
|
||||
bdd lacc = arc_acc_.top();
|
||||
auto lacc = arc_acc_.top();
|
||||
acc |= lacc;
|
||||
useful |= conv.as_full_product(lacc) | root_.front().useful_acc;
|
||||
used_acc.insert(lacc);
|
||||
used_acc.insert(root_.front().useful_acc.begin(),
|
||||
root_.front().useful_acc.end());
|
||||
states.splice(states.end(), root_.front().states);
|
||||
succs.insert(root_.front().succ.begin(),
|
||||
root_.front().succ.end());
|
||||
|
|
@ -305,7 +304,8 @@ namespace spot
|
|||
root_.front().supp &= supp;
|
||||
// This SCC is no longer trivial.
|
||||
root_.front().trivial = false;
|
||||
root_.front().useful_acc |= useful;
|
||||
assert(!used_acc.empty());
|
||||
root_.front().useful_acc.insert(used_acc.begin(), used_acc.end());
|
||||
}
|
||||
|
||||
// recursively update supp_rec
|
||||
|
|
@ -339,7 +339,7 @@ namespace spot
|
|||
}
|
||||
|
||||
|
||||
bdd scc_map::acc_set_of(unsigned n) const
|
||||
acc_cond::mark_t scc_map::acc_set_of(unsigned n) const
|
||||
{
|
||||
assert(scc_map_.size() > n);
|
||||
return scc_map_[n].acc;
|
||||
|
|
@ -367,7 +367,7 @@ namespace spot
|
|||
return scc_map_.size();
|
||||
}
|
||||
|
||||
bdd
|
||||
const std::set<acc_cond::mark_t>&
|
||||
scc_map::useful_acc_of(unsigned n) const
|
||||
{
|
||||
assert(scc_map_.size() > n);
|
||||
|
|
@ -449,12 +449,14 @@ namespace spot
|
|||
res.dead_paths = d.dead_paths[init];
|
||||
|
||||
res.useless_scc_map.reserve(res.scc_total);
|
||||
res.useful_acc = bddfalse;
|
||||
for (unsigned n = 0; n < res.scc_total; ++n)
|
||||
{
|
||||
res.useless_scc_map[n] = !d.acc_paths[n];
|
||||
if (m.accepting(n))
|
||||
res.useful_acc |= m.useful_acc_of(n);
|
||||
{
|
||||
auto& c = m.useful_acc_of(n);
|
||||
res.useful_acc.insert(c.begin(), c.end());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -495,8 +497,7 @@ namespace spot
|
|||
if (n > 1)
|
||||
ostr << 's';
|
||||
ostr << ")\\naccs=";
|
||||
escape_str(ostr, bdd_format_accset(m.get_aut()->get_dict(),
|
||||
m.acc_set_of(state)));
|
||||
escape_str(ostr, m.get_aut()->acc().format(m.acc_set_of(state)));
|
||||
ostr << "\\nconds=[";
|
||||
for (scc_map::cond_set::const_iterator i = cs.begin();
|
||||
i != cs.end(); ++i)
|
||||
|
|
@ -514,8 +515,9 @@ namespace spot
|
|||
escape_str(ostr, bdd_format_sat(m.get_aut()->get_dict(),
|
||||
m.aprec_set_of(state)));
|
||||
ostr << "]\\n useful=[";
|
||||
escape_str(ostr, bdd_format_accset(m.get_aut()->get_dict(),
|
||||
m.useful_acc_of(state))) << ']';
|
||||
for (auto a: m.useful_acc_of(state))
|
||||
m.get_aut()->acc().format(a);
|
||||
ostr << ']';
|
||||
}
|
||||
|
||||
out << " " << state << " [shape=box,"
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace spot
|
|||
/// The set of useful acceptance conditions (i.e. acceptance
|
||||
/// conditions that are not always implied by other acceptance
|
||||
/// conditions).
|
||||
bdd useful_acc;
|
||||
std::set<acc_cond::mark_t> useful_acc;
|
||||
|
||||
std::ostream& dump(std::ostream& out) const;
|
||||
};
|
||||
|
|
@ -144,13 +144,13 @@ namespace spot
|
|||
/// \brief Return the set of acceptance conditions occurring in an SCC.
|
||||
///
|
||||
/// \pre This should only be called once build_map() has run.
|
||||
bdd acc_set_of(unsigned n) const;
|
||||
acc_cond::mark_t acc_set_of(unsigned n) const;
|
||||
|
||||
/// \brief Return the set of useful acceptance conditions of SCC \a n.
|
||||
///
|
||||
/// Useless acceptances conditions are always implied by other acceptances
|
||||
/// conditions. This returns all the other acceptance conditions.
|
||||
bdd useful_acc_of(unsigned n) const;
|
||||
const std::set<acc_cond::mark_t>& useful_acc_of(unsigned n) const;
|
||||
|
||||
/// \brief Return the set of states of an SCC.
|
||||
///
|
||||
|
|
@ -183,14 +183,14 @@ namespace spot
|
|||
struct scc
|
||||
{
|
||||
public:
|
||||
scc(int index) : index(index), acc(bddfalse),
|
||||
scc(int index) : index(index), acc(0U),
|
||||
supp(bddtrue), supp_rec(bddfalse),
|
||||
trivial(true), useful_acc(bddfalse) {};
|
||||
trivial(true) {};
|
||||
/// Index of the SCC.
|
||||
int index;
|
||||
/// The union of all acceptance conditions of transitions which
|
||||
/// connect the states of the connected component.
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
/// States of the component.
|
||||
std::list<const state*> states;
|
||||
/// Set of conditions used in the SCC.
|
||||
|
|
@ -204,22 +204,13 @@ namespace spot
|
|||
/// Trivial SCC have one state and no self-loops.
|
||||
bool trivial;
|
||||
/// \brief Set of acceptance combinations used in the SCC.
|
||||
///
|
||||
/// Note that the encoding used here differs from the
|
||||
/// encoding used in automata.
|
||||
/// If some transitions of the automaton are labeled by
|
||||
/// Acc[a]&!Acc[b]&!Acc[c] | !Acc[a]&Acc[b]&!Acc[c]
|
||||
/// an other transitions are labeled by
|
||||
/// !Acc[a]&Acc[b]&!Acc[c] | !Acc[a]&!Acc[b]&Acc[c]
|
||||
/// then useful_acc will contain
|
||||
/// Acc[a]&Acc[b]&!Acc[c] | !Acc[a]&Acc[b]&Acc[c]
|
||||
bdd useful_acc;
|
||||
std::set<acc_cond::mark_t> useful_acc;
|
||||
};
|
||||
|
||||
const_tgba_ptr aut_; // Automata to decompose.
|
||||
typedef std::list<scc> stack_type;
|
||||
stack_type root_; // Stack of SCC roots.
|
||||
std::stack<bdd> arc_acc_; // A stack of acceptance conditions
|
||||
std::stack<acc_cond::mark_t> arc_acc_; // A stack of acceptance conditions
|
||||
// between each of these SCC.
|
||||
std::stack<bdd> arc_cond_; // A stack of conditions
|
||||
// between each of these SCC.
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ namespace spot
|
|||
typedef std::map<int, unsigned> accremap_t;
|
||||
typedef std::vector<accremap_t> remap_table_t;
|
||||
|
||||
typedef std::tuple<bool, bdd, bdd> filtered_trans;
|
||||
typedef std::pair<bdd, bdd> acc_pair;
|
||||
typedef std::tuple<bool, bdd, acc_cond::mark_t> filtered_trans;
|
||||
|
||||
|
||||
// SCC filters are objects with two methods:
|
||||
|
|
@ -53,13 +52,13 @@ namespace spot
|
|||
return true;
|
||||
}
|
||||
|
||||
acc_pair accsets(bdd all, bdd all_neg)
|
||||
unsigned accsets(unsigned n)
|
||||
{
|
||||
return acc_pair(all, all_neg);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Accept all transitions, unmodified
|
||||
filtered_trans trans(unsigned, unsigned, bdd cond, bdd acc)
|
||||
filtered_trans trans(unsigned, unsigned, bdd cond, acc_cond::mark_t acc)
|
||||
{
|
||||
return filtered_trans{true, cond, acc};
|
||||
}
|
||||
|
|
@ -101,7 +100,7 @@ namespace spot
|
|||
}
|
||||
|
||||
filtered_trans trans(unsigned src, unsigned dst,
|
||||
bdd cond, bdd acc)
|
||||
bdd cond, acc_cond::mark_t acc)
|
||||
{
|
||||
bool keep;
|
||||
std::tie(keep, cond, acc) =
|
||||
|
|
@ -137,7 +136,7 @@ namespace spot
|
|||
}
|
||||
|
||||
filtered_trans trans(unsigned src, unsigned dst,
|
||||
bdd cond, bdd acc)
|
||||
bdd cond, acc_cond::mark_t acc)
|
||||
{
|
||||
bool keep;
|
||||
std::tie(keep, cond, acc) =
|
||||
|
|
@ -149,7 +148,7 @@ namespace spot
|
|||
// If the transition is between two SCCs, or in a
|
||||
// non-accepting SCC. Remove the acceptance sets.
|
||||
if (!this->si->is_accepting_scc(u) || u != this->si->scc_of(dst))
|
||||
acc = bddfalse;
|
||||
acc = 0U;
|
||||
}
|
||||
|
||||
return filtered_trans(keep, cond, acc);
|
||||
|
|
@ -168,14 +167,14 @@ namespace spot
|
|||
}
|
||||
|
||||
filtered_trans trans(unsigned src, unsigned dst,
|
||||
bdd cond, bdd acc)
|
||||
bdd cond, acc_cond::mark_t acc)
|
||||
{
|
||||
bool keep;
|
||||
std::tie(keep, cond, acc) =
|
||||
this->next_filter::trans(src, dst, cond, acc);
|
||||
|
||||
if (!this->si->is_accepting_scc(this->si->scc_of(dst)))
|
||||
acc = bddfalse;
|
||||
acc = 0U;
|
||||
return filtered_trans(keep, cond, acc);
|
||||
}
|
||||
};
|
||||
|
|
@ -184,10 +183,8 @@ namespace spot
|
|||
template <class next_filter = id_filter>
|
||||
struct acc_filter_simplify: next_filter
|
||||
{
|
||||
std::vector<bdd> acc_;
|
||||
typedef std::map<int, bdd> map_t;
|
||||
typedef std::vector<map_t> remap_t;
|
||||
remap_t remap_;
|
||||
// Acceptance sets to strip in each SCC.
|
||||
std::vector<acc_cond::mark_t> strip_;
|
||||
|
||||
template<typename... Args>
|
||||
acc_filter_simplify(scc_info* si, Args&&... args)
|
||||
|
|
@ -195,118 +192,27 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
acc_pair accsets(bdd in_all, bdd in_all_neg)
|
||||
unsigned accsets(unsigned n)
|
||||
{
|
||||
std::tie(in_all, in_all_neg) =
|
||||
this->next_filter::accsets(in_all, in_all_neg);
|
||||
|
||||
unsigned scc_count = this->si->scc_count();
|
||||
remap_table_t remap_table(scc_count);
|
||||
std::vector<unsigned> max_table(scc_count);
|
||||
std::vector<bdd> useful_table(scc_count);
|
||||
std::vector<bdd> useless_table(scc_count);
|
||||
unsigned max_num = 1;
|
||||
const_tgba_digraph_ptr aut = this->si->get_aut();
|
||||
|
||||
std::vector<bdd> used_acc = this->si->used_acc();
|
||||
auto& acc = this->si->get_aut()->acc();
|
||||
assert(n == acc.num_sets());
|
||||
(void) n;
|
||||
|
||||
auto used_acc = this->si->used_acc();
|
||||
assert(used_acc.size() == scc_count);
|
||||
strip_.resize(scc_count);
|
||||
std::vector<unsigned> cnt(scc_count); // # of useful sets in each SCC
|
||||
unsigned max = 0; // Max number of useful sets
|
||||
for (unsigned n = 0; n < scc_count; ++n)
|
||||
{
|
||||
if (!this->si->is_accepting_scc(n))
|
||||
continue;
|
||||
bdd all = used_acc[n];
|
||||
|
||||
//std::cerr << "SCC #" << n << "; used = " << all << std::endl;
|
||||
|
||||
// Compute a set of useless acceptance sets.
|
||||
// If the acceptance combinations occurring in
|
||||
// the automata are { a, ab, abc, bd }, then
|
||||
// ALL contains (a&!b&!c&!d)|(a&b&!c&!d)|(a&b&c&!d)|(!a&b&!c&d)
|
||||
// and we want to find that 'a' and 'b' are useless because
|
||||
// they always occur with 'c'.
|
||||
// The way we check if 'a' is useless is to look whether ALL
|
||||
// implications (x -> a) for some other acceptance set x.
|
||||
//
|
||||
// The two while() loops in the code perform the equivalent of
|
||||
// for all a in allconds_a:
|
||||
// for all x in allconds_x:
|
||||
// check whether x -> a
|
||||
// ...
|
||||
//
|
||||
// Initially allconds_a = allconds_x contains all acceptance
|
||||
// sets. However when an acceptance set 'a' is determined to
|
||||
// be useless, it can be removed from allconds_x from future
|
||||
// iterations.
|
||||
bdd allconds_a = bdd_support(in_all_neg);
|
||||
bdd allconds_x = allconds_a;
|
||||
bdd useless = bddtrue;
|
||||
while (allconds_a != bddtrue)
|
||||
{
|
||||
// Speed-up the computation of implied acceptance sets by
|
||||
// removing those that are always present. We detect
|
||||
// those that appear as conjunction of positive variables
|
||||
// at the start of ALL.
|
||||
bdd prefix = bdd_satprefix(all);
|
||||
if (prefix != bddtrue)
|
||||
{
|
||||
assert(prefix == bdd_support(prefix));
|
||||
allconds_a = bdd_exist(allconds_a, prefix);
|
||||
if (allconds_a != bddtrue)
|
||||
{
|
||||
useless &= prefix;
|
||||
strip_[n] = acc.useless(used_acc[n].begin(), used_acc[n].end());
|
||||
cnt[n] = acc.num_sets() - strip_[n].count();
|
||||
if (cnt[n] > max)
|
||||
max = cnt[n];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Never erase all conditions: at least keep one.
|
||||
useless &= bdd_high(prefix);
|
||||
break;
|
||||
}
|
||||
allconds_x = bdd_exist(allconds_x, prefix);
|
||||
}
|
||||
|
||||
// Pick an acceptance set 'a'.
|
||||
bdd a = bdd_ithvar(bdd_var(allconds_a));
|
||||
// For all acceptance sets 'x' that are not already
|
||||
// useless...
|
||||
bdd others = allconds_x;
|
||||
while (others != bddtrue)
|
||||
{
|
||||
bdd x = bdd_ithvar(bdd_var(others));
|
||||
// ... check whether 'x' always implies 'a'.
|
||||
if (x != a && bdd_implies(all, x >> a))
|
||||
{
|
||||
// If so, 'a' is useless.
|
||||
all = bdd_exist(all, a);
|
||||
useless &= a;
|
||||
allconds_x = bdd_exist(allconds_x, a);
|
||||
break;
|
||||
}
|
||||
others = bdd_high(others);
|
||||
}
|
||||
allconds_a = bdd_high(allconds_a);
|
||||
}
|
||||
|
||||
// We never remove ALL acceptance marks.
|
||||
assert(in_all_neg == bddtrue || useless != bdd_support(in_all_neg));
|
||||
|
||||
useless_table[n] = useless;
|
||||
bdd useful = bdd_exist(in_all_neg, useless);
|
||||
|
||||
//std::cerr << "SCC #" << n << "; useful = " << useful << std::endl;
|
||||
|
||||
// Go over all useful sets of acceptance marks, and give them
|
||||
// a number.
|
||||
unsigned num = 1;
|
||||
// First compute the number of acceptance conditions used.
|
||||
for (BDD c = useful.id(); c != 1; c = bdd_low(c))
|
||||
++num;
|
||||
max_table[n] = num;
|
||||
if (num > max_num)
|
||||
max_num = num;
|
||||
|
||||
useful_table[n] = useful;
|
||||
}
|
||||
|
||||
// Now that we know about the max number of acceptance
|
||||
// conditions, add extra acceptance conditions to those SCC
|
||||
// that do not have enough.
|
||||
|
|
@ -314,118 +220,30 @@ namespace spot
|
|||
{
|
||||
if (!this->si->is_accepting_scc(n))
|
||||
continue;
|
||||
//std::cerr << "SCC " << n << '\n';
|
||||
bdd useful = useful_table[n];
|
||||
|
||||
int missing = max_num - max_table[n];
|
||||
bdd useless = useless_table[n];
|
||||
while (missing--)
|
||||
{
|
||||
//std::cerr << useful << " : " << useless << std::endl;
|
||||
useful &= bdd_nithvar(bdd_var(useless));
|
||||
useless = bdd_high(useless);
|
||||
if (cnt[n] < max)
|
||||
strip_[n].remove_some(max - cnt[n]);
|
||||
}
|
||||
int num = max_num;
|
||||
// Then number all of these acceptance conditions in the
|
||||
// reverse order. This makes sure that the associated number
|
||||
// varies in the same direction as the bdd variables, which in
|
||||
// turn makes sure we preserve the acceptance condition
|
||||
// ordering (which matters for degeneralization).
|
||||
for (BDD c = useful.id(); c != 1; c = bdd_low(c))
|
||||
remap_table[n].emplace(bdd_var(c), --num);
|
||||
|
||||
max_table[n] = max_num;
|
||||
return max;
|
||||
}
|
||||
|
||||
acc_.resize(max_num);
|
||||
acc_[0] = bddfalse;
|
||||
bdd tmp = in_all;
|
||||
assert(aut->number_of_acceptance_conditions() >= max_num - 1);
|
||||
|
||||
bdd all = bddfalse;
|
||||
bdd all_neg = bddtrue;
|
||||
|
||||
if (tmp != bddfalse)
|
||||
{
|
||||
for (unsigned n = max_num - 1; n > 0; --n)
|
||||
{
|
||||
assert(tmp != bddfalse);
|
||||
int v = bdd_var(tmp);
|
||||
bdd vn = bdd_nithvar(v);
|
||||
all = (all & vn) | (all_neg & bdd_ithvar(v));
|
||||
all_neg &= vn;
|
||||
tmp = bdd_low(tmp);
|
||||
}
|
||||
tmp = in_all;
|
||||
for (unsigned n = max_num - 1; n > 0; --n)
|
||||
{
|
||||
int v = bdd_var(tmp);
|
||||
acc_[n] = bdd_compose(all_neg, bdd_nithvar(v), v);
|
||||
tmp = bdd_low(tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(max_num == 1);
|
||||
}
|
||||
|
||||
remap_.resize(scc_count);
|
||||
bdd all_orig_neg = in_all_neg;
|
||||
bdd all_sup = bdd_support(all_orig_neg);
|
||||
|
||||
for (unsigned n = 0; n < scc_count; ++n)
|
||||
{
|
||||
//std::cerr << "SCC #" << n << '\n';
|
||||
if (!this->si->is_accepting_scc(n))
|
||||
continue;
|
||||
|
||||
bdd all = used_acc[n];
|
||||
while (all != bddfalse)
|
||||
{
|
||||
bdd one = bdd_satoneset(all, all_sup, bddtrue);
|
||||
all -= one;
|
||||
bdd res = bddfalse;
|
||||
bdd resacc = bddfalse;
|
||||
while (one != bddtrue)
|
||||
{
|
||||
if (bdd_high(one) == bddfalse)
|
||||
{
|
||||
one = bdd_low(one);
|
||||
continue;
|
||||
}
|
||||
int vn = bdd_var(one);
|
||||
bdd v = bdd_ithvar(vn);
|
||||
resacc |= bdd_exist(all_orig_neg, v) & v;
|
||||
res |= acc_[remap_table[n][vn]];
|
||||
one = bdd_high(one);
|
||||
}
|
||||
int id = resacc.id();
|
||||
//std::cerr << resacc << " -> " << res << '\n';
|
||||
remap_[n][id] = res;
|
||||
}
|
||||
}
|
||||
return acc_pair{all, all_neg};
|
||||
}
|
||||
|
||||
filtered_trans trans(unsigned src, unsigned dst, bdd cond, bdd acc)
|
||||
filtered_trans trans(unsigned src, unsigned dst, bdd cond,
|
||||
acc_cond::mark_t acc)
|
||||
{
|
||||
bool keep;
|
||||
std::tie(keep, cond, acc) =
|
||||
this->next_filter::trans(src, dst, cond, acc);
|
||||
|
||||
if (keep && acc != bddfalse)
|
||||
if (keep && acc)
|
||||
{
|
||||
unsigned u = this->si->scc_of(dst);
|
||||
|
||||
auto i = remap_[u].find(acc.id());
|
||||
if (i != remap_[u].end())
|
||||
acc = i->second;
|
||||
if (!this->si->is_accepting_scc(u))
|
||||
acc = 0U;
|
||||
else
|
||||
acc = bddfalse;
|
||||
acc = this->si->get_aut()->acc().strip(acc, strip_[u]);
|
||||
}
|
||||
return filtered_trans{keep, cond, acc};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -456,11 +274,8 @@ namespace spot
|
|||
else
|
||||
inout.push_back(-1U);
|
||||
|
||||
{
|
||||
bdd all = aut->all_acceptance_conditions();
|
||||
bdd neg = aut->neg_acceptance_conditions();
|
||||
filtered->set_acceptance_conditions(filter.accsets(all, neg).first);
|
||||
}
|
||||
filtered->
|
||||
set_acceptance_conditions(filter.accsets(aut->acc().num_sets()));
|
||||
filtered->new_states(out_n);
|
||||
for (unsigned isrc = 0; isrc < in_n; ++isrc)
|
||||
{
|
||||
|
|
@ -474,7 +289,7 @@ namespace spot
|
|||
continue;
|
||||
bool want;
|
||||
bdd cond;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
std::tie(want, cond, acc) =
|
||||
filter.trans(isrc, t.dst, t.cond, t.acc);
|
||||
if (want)
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ namespace spot
|
|||
struct scc
|
||||
{
|
||||
public:
|
||||
scc(int index, bdd in_cond, bdd in_acc):
|
||||
scc(int index, bdd in_cond, acc_cond::mark_t in_acc):
|
||||
index(index), in_cond(in_cond), in_acc(in_acc)
|
||||
{
|
||||
}
|
||||
|
||||
int index; // Index of the SCC
|
||||
bdd in_cond; // Condition on incoming transition
|
||||
bdd in_acc; // Acceptance sets on the incoming transition
|
||||
acc_cond::mark_t in_acc; // Acceptance sets on the incoming transition
|
||||
scc_info::scc_node node;
|
||||
};
|
||||
}
|
||||
|
|
@ -50,7 +50,6 @@ namespace spot
|
|||
{
|
||||
unsigned n = aut->num_states();
|
||||
sccof_.resize(n, -1U);
|
||||
bdd all_acc = aut->all_acceptance_conditions();
|
||||
|
||||
typedef std::list<scc> stack_type;
|
||||
stack_type root_; // Stack of SCC roots.
|
||||
|
|
@ -81,7 +80,7 @@ namespace spot
|
|||
unsigned init = aut->get_init_state_number();
|
||||
num_ = -1;
|
||||
h_[init] = num_;
|
||||
root_.emplace_front(num_, bddfalse, bddfalse);
|
||||
root_.emplace_front(num_, bddfalse, 0U);
|
||||
todo_.emplace(init, aut->out(init).begin());
|
||||
}
|
||||
|
||||
|
|
@ -117,12 +116,12 @@ namespace spot
|
|||
h_[s] = num + 1;
|
||||
}
|
||||
bdd cond = root_.front().in_cond;
|
||||
bdd acc = root_.front().node.acc;
|
||||
auto acc = root_.front().node.acc;
|
||||
bool triv = root_.front().node.trivial;
|
||||
node_.emplace_back(acc, triv);
|
||||
std::swap(node_.back().succ, root_.front().node.succ);
|
||||
std::swap(node_.back().states, root_.front().node.states);
|
||||
node_.back().accepting = acc == all_acc;
|
||||
node_.back().accepting = aut->acc().accepting(acc);
|
||||
root_.pop_front();
|
||||
// Record the transition between the SCC being popped
|
||||
// and the previous SCC.
|
||||
|
|
@ -135,7 +134,7 @@ namespace spot
|
|||
// We have a successor to look at.
|
||||
// Fetch the values we are interested in...
|
||||
unsigned dest = succ->dst;
|
||||
bdd acc = succ->acc;
|
||||
auto acc = succ->acc;
|
||||
bdd cond = succ->cond;
|
||||
++todo_.top().second;
|
||||
|
||||
|
|
@ -191,7 +190,8 @@ namespace spot
|
|||
while (threshold > root_.front().index)
|
||||
{
|
||||
assert(!root_.empty());
|
||||
acc |= root_.front().node.acc | root_.front().in_acc;
|
||||
acc |= root_.front().node.acc;
|
||||
acc |= root_.front().in_acc;
|
||||
states.splice(states.end(), root_.front().node.states);
|
||||
|
||||
succs.insert(succs.end(),
|
||||
|
|
@ -229,22 +229,22 @@ namespace spot
|
|||
}
|
||||
|
||||
|
||||
std::vector<bdd> scc_info::used_acc() const
|
||||
std::vector<std::set<acc_cond::mark_t>> scc_info::used_acc() const
|
||||
{
|
||||
unsigned n = aut_->num_states();
|
||||
std::vector<bdd> result(scc_count());
|
||||
acceptance_convertor conv(aut_->neg_acceptance_conditions());
|
||||
std::vector<std::set<acc_cond::mark_t>> result(scc_count());
|
||||
|
||||
for (unsigned src = 0; src < n; ++src)
|
||||
{
|
||||
unsigned src_scc = scc_of(src);
|
||||
if (src_scc == -1U || !is_accepting_scc(src_scc))
|
||||
continue;
|
||||
auto& s = result[src_scc];
|
||||
for (auto& t: aut_->out(src))
|
||||
{
|
||||
if (scc_of(t.dst) != src_scc)
|
||||
continue;
|
||||
result[src_scc] |= conv.as_full_product(t.acc);
|
||||
s.insert(t.acc);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -255,9 +255,8 @@ namespace spot
|
|||
unsigned n = scc_count();
|
||||
std::vector<bool> result(scc_count());
|
||||
auto acc = used_acc();
|
||||
bdd all = bdd_support(aut_->neg_acceptance_conditions());
|
||||
for (unsigned s = 0; s < n; ++s)
|
||||
result[s] = !is_accepting_scc(s) || acc[s] == all;
|
||||
result[s] = !is_accepting_scc(s) || acc[s].size() == 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +275,6 @@ namespace spot
|
|||
{
|
||||
scc_info* m = sccinfo ? sccinfo : new scc_info(aut);
|
||||
|
||||
bdd all_acc = aut->all_acceptance_conditions();
|
||||
|
||||
out << "digraph G {\n i [label=\"\", style=invis, height=0]\n";
|
||||
int start = m->scc_of(aut->get_init_state_number());
|
||||
out << " i -> " << start << std::endl;
|
||||
|
|
@ -293,7 +290,7 @@ namespace spot
|
|||
q.pop();
|
||||
|
||||
out << " " << state << " [shape=box,"
|
||||
<< (m->acc(state) == all_acc ? "style=bold," : "")
|
||||
<< (aut->acc().accepting(m->acc(state)) ? "style=bold," : "")
|
||||
<< "label=\"" << state;
|
||||
{
|
||||
size_t n = m->states_of(state).size();
|
||||
|
|
|
|||
|
|
@ -45,17 +45,17 @@ namespace spot
|
|||
struct scc_node
|
||||
{
|
||||
scc_node():
|
||||
acc(bddfalse), trivial(true)
|
||||
acc(0U), trivial(true)
|
||||
{
|
||||
}
|
||||
|
||||
scc_node(bdd acc, bool trivial):
|
||||
scc_node(acc_cond::mark_t acc, bool trivial):
|
||||
acc(acc), trivial(trivial)
|
||||
{
|
||||
}
|
||||
|
||||
scc_succs succ;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
std::list<unsigned> states; // States of the component
|
||||
bool trivial:1;
|
||||
bool accepting:1;
|
||||
|
|
@ -114,7 +114,7 @@ namespace spot
|
|||
return node(scc).trivial;
|
||||
}
|
||||
|
||||
bdd acc(unsigned scc) const
|
||||
acc_cond::mark_t acc(unsigned scc) const
|
||||
{
|
||||
return node(scc).acc;
|
||||
}
|
||||
|
|
@ -136,16 +136,7 @@ namespace spot
|
|||
|
||||
/// \brief Return the set of all used acceptance combinations, for
|
||||
/// each accepting SCC.
|
||||
///
|
||||
/// If SCC #i use {a,b} and {c}, which
|
||||
/// are normally respectively encoded as
|
||||
/// Acc[a]&!Acc[b]&!Acc[c] | !Acc[a]&Acc[b]&!Acc[c]
|
||||
/// and
|
||||
/// !Acc[a]&!Acc[b]&Acc[c]
|
||||
/// then the vector will contain
|
||||
/// Acc[a]&Acc[b] | Acc[c]
|
||||
/// at position #i.
|
||||
std::vector<bdd> used_acc() const;
|
||||
std::vector<std::set<acc_cond::mark_t>> used_acc() const;
|
||||
|
||||
std::vector<bool> weak_sccs() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,10 +57,9 @@ namespace spot
|
|||
se05_search(const const_tgba_ptr a, size_t size,
|
||||
option_map o = option_map())
|
||||
: emptiness_check(a, o),
|
||||
h(size),
|
||||
all_cond(a->all_acceptance_conditions())
|
||||
h(size)
|
||||
{
|
||||
assert(a->number_of_acceptance_conditions() <= 1);
|
||||
assert(a->acc().num_sets() <= 1);
|
||||
}
|
||||
|
||||
virtual ~se05_search()
|
||||
|
|
@ -98,7 +97,7 @@ namespace spot
|
|||
const state* s0 = a_->get_init_state();
|
||||
inc_states();
|
||||
h.add_new_state(s0, CYAN);
|
||||
push(st_blue, s0, bddfalse, bddfalse);
|
||||
push(st_blue, s0, bddfalse, 0U);
|
||||
if (dfs_blue())
|
||||
return std::make_shared<se05_result>(t, options());
|
||||
}
|
||||
|
|
@ -151,7 +150,7 @@ namespace spot
|
|||
private:
|
||||
|
||||
void push(stack_type& st, const state* s,
|
||||
const bdd& label, const bdd& acc)
|
||||
const bdd& label, acc_cond::mark_t acc)
|
||||
{
|
||||
inc_depth();
|
||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||
|
|
@ -176,9 +175,6 @@ namespace spot
|
|||
/// by the last dfs visiting it.
|
||||
heap h;
|
||||
|
||||
/// The unique acceptance condition of the automaton \a a.
|
||||
bdd all_cond;
|
||||
|
||||
bool dfs_blue()
|
||||
{
|
||||
while (!st_blue.empty())
|
||||
|
|
@ -191,7 +187,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
@ -203,8 +199,9 @@ namespace spot
|
|||
h.add_new_state(s_prime, CYAN);
|
||||
push(st_blue, s_prime, label, acc);
|
||||
}
|
||||
else if (c.get_color() == CYAN && (acc == all_cond ||
|
||||
(f.s->compare(s_prime) != 0 && f.acc == all_cond)))
|
||||
else if (c.get_color() == CYAN && (a_->acc().accepting(acc) ||
|
||||
(f.s->compare(s_prime) != 0
|
||||
&& a_->acc().accepting(f.acc))))
|
||||
{
|
||||
trace << " It is cyan and acceptance condition "
|
||||
<< "is reached, report cycle" << std::endl;
|
||||
|
|
@ -212,7 +209,7 @@ namespace spot
|
|||
push(st_red, s_prime, label, acc);
|
||||
return true;
|
||||
}
|
||||
else if (acc == all_cond && c.get_color() != RED)
|
||||
else if (a_->acc().accepting(acc) && c.get_color() != RED)
|
||||
{
|
||||
// the test 'c.get_color() != RED' is added to limit
|
||||
// the number of runs reported by successive
|
||||
|
|
@ -241,7 +238,7 @@ namespace spot
|
|||
typename heap::color_ref c = h.get_color_ref(f_dest.s);
|
||||
assert(!c.is_white());
|
||||
if (!st_blue.empty() &&
|
||||
f_dest.acc == all_cond && c.get_color() != RED)
|
||||
a_->acc().accepting(f_dest.acc) && c.get_color() != RED)
|
||||
{
|
||||
// the test 'c.get_color() != RED' is added to limit
|
||||
// the number of runs reported by successive
|
||||
|
|
@ -281,7 +278,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
|
|||
|
|
@ -215,7 +215,30 @@ namespace spot
|
|||
protected:
|
||||
// Shortcut used in update_po and go_to_next_it.
|
||||
typedef std::map<bdd, bdd, bdd_less_than> map_bdd_bdd;
|
||||
int acc_vars;
|
||||
public:
|
||||
|
||||
bdd mark_to_bdd(acc_cond::mark_t m)
|
||||
{
|
||||
// FIXME: Use a cache.
|
||||
bdd res = bddtrue;
|
||||
for (auto n: a_->acc().sets(m))
|
||||
res &= bdd_ithvar(acc_vars + n);
|
||||
return res;
|
||||
}
|
||||
|
||||
acc_cond::mark_t bdd_to_mark(const tgba_digraph_ptr& aut, bdd b)
|
||||
{
|
||||
// FIXME: Use a cache.
|
||||
std::vector<unsigned> res;
|
||||
while (b != bddtrue)
|
||||
{
|
||||
res.push_back(bdd_var(b) - acc_vars);
|
||||
b = bdd_high(b);
|
||||
}
|
||||
return aut->acc().marks(res.begin(), res.end());
|
||||
}
|
||||
|
||||
direct_simulation(const const_tgba_ptr& t,
|
||||
const map_constraint* map_cst = 0)
|
||||
: a_(0),
|
||||
|
|
@ -234,9 +257,6 @@ namespace spot
|
|||
old_a_ = a_;
|
||||
|
||||
|
||||
acc_compl ac(a_->all_acceptance_conditions(),
|
||||
a_->neg_acceptance_conditions());
|
||||
|
||||
// Replace all the acceptance conditions by their complements.
|
||||
// (In the case of Cosimulation, we also flip the transitions.)
|
||||
{
|
||||
|
|
@ -253,7 +273,7 @@ namespace spot
|
|||
{
|
||||
for (auto& t: old_a_->out(s))
|
||||
{
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
if (Sba && Cosimulation)
|
||||
{
|
||||
// If the acceptance is interpreted as
|
||||
|
|
@ -262,16 +282,16 @@ namespace spot
|
|||
// the destination state on its incoming arcs
|
||||
// (which now become outgoing arcs after
|
||||
// transposition).
|
||||
acc = bddfalse;
|
||||
acc = 0U;
|
||||
for (auto& td: old_a_->out(t.dst))
|
||||
{
|
||||
acc = ac.complement(td.acc);
|
||||
acc = old_a_->acc().comp(td.acc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
acc = ac.complement(t.acc);
|
||||
acc = old_a_->acc().comp(t.acc);
|
||||
}
|
||||
if (Cosimulation)
|
||||
a_->new_transition(t.dst, s, t.cond, acc);
|
||||
|
|
@ -288,8 +308,13 @@ namespace spot
|
|||
unsigned set_num = a_->get_dict()
|
||||
->register_anonymous_variables(size_a_ + 1, this);
|
||||
|
||||
all_acceptance_conditions_ = a_->all_acceptance_conditions();
|
||||
all_proms_ = bdd_support(all_acceptance_conditions_);
|
||||
unsigned n_acc = a_->acc().num_sets();
|
||||
acc_vars = a_->get_dict()
|
||||
->register_anonymous_variables(n_acc, this);
|
||||
|
||||
all_proms_ = bddtrue;
|
||||
for (unsigned v = acc_vars; v < acc_vars + n_acc; ++v)
|
||||
all_proms_ &= bdd_ithvar(v);
|
||||
|
||||
bdd_initial = bdd_ithvar(set_num++);
|
||||
bdd init = bdd_ithvar(set_num++);
|
||||
|
|
@ -397,7 +422,7 @@ namespace spot
|
|||
}
|
||||
else
|
||||
{
|
||||
acc = t.acc;
|
||||
acc = mark_to_bdd(t.acc);
|
||||
}
|
||||
|
||||
// to_add is a conjunction of the acceptance condition,
|
||||
|
|
@ -527,23 +552,14 @@ namespace spot
|
|||
// Build the minimal resulting automaton.
|
||||
tgba_digraph_ptr build_result()
|
||||
{
|
||||
// We have all the a_'s acceptances conditions
|
||||
// complemented. So we need to complement it when adding a
|
||||
// transition. We *must* keep the complemented because it
|
||||
// is easy to know if an acceptance condition is maximal or
|
||||
// not.
|
||||
acc_compl reverser(all_acceptance_conditions_,
|
||||
a_->neg_acceptance_conditions());
|
||||
|
||||
tgba_digraph_ptr res = make_tgba_digraph(a_->get_dict());
|
||||
res->copy_ap_of(a_);
|
||||
res->set_acceptance_conditions(all_acceptance_conditions_);
|
||||
res->copy_acceptance_conditions_of(a_);
|
||||
if (Sba)
|
||||
res->prop_state_based_acc();
|
||||
|
||||
bdd sup_all_acc = bdd_support(all_acceptance_conditions_);
|
||||
// Non atomic propositions variables (= acc and class)
|
||||
bdd nonapvars = sup_all_acc & bdd_support(all_class_var_);
|
||||
bdd nonapvars = all_proms_ & bdd_support(all_class_var_);
|
||||
|
||||
auto* gb = res->create_namer<int>();
|
||||
|
||||
|
|
@ -558,9 +574,9 @@ namespace spot
|
|||
}
|
||||
|
||||
// Acceptance of states. Only used if Sba && Cosimulation.
|
||||
std::vector<bdd> accst;
|
||||
std::vector<acc_cond::mark_t> accst;
|
||||
if (Sba && Cosimulation)
|
||||
accst.resize(res->num_states(), bddfalse);
|
||||
accst.resize(res->num_states(), 0U);
|
||||
|
||||
stat.states = bdd_lstate_.size();
|
||||
stat.transitions = 0;
|
||||
|
|
@ -626,7 +642,8 @@ namespace spot
|
|||
all_class_var_);
|
||||
|
||||
// Keep only ones who are acceptance condition.
|
||||
bdd acc = bdd_existcomp(cond_acc_dest, sup_all_acc);
|
||||
auto acc = bdd_to_mark(res, bdd_existcomp(cond_acc_dest,
|
||||
all_proms_));
|
||||
|
||||
// Keep the other!
|
||||
bdd cond = bdd_existcomp(cond_acc_dest,
|
||||
|
|
@ -635,7 +652,7 @@ namespace spot
|
|||
// Because we have complemented all the acceptance
|
||||
// conditions on the input automaton, we must
|
||||
// revert them to create a new transition.
|
||||
acc = reverser.reverse_complement(acc);
|
||||
acc = res->acc().comp(acc);
|
||||
|
||||
if (Cosimulation)
|
||||
{
|
||||
|
|
@ -647,7 +664,7 @@ namespace spot
|
|||
// can't do this here, store this in a table
|
||||
// so we can fix it later.
|
||||
accst[gb->get_state(src.id())] = acc;
|
||||
acc = bddfalse;
|
||||
acc = 0U;
|
||||
}
|
||||
gb->new_transition(dst.id(), src.id(), cond, acc);
|
||||
}
|
||||
|
|
@ -671,8 +688,8 @@ namespace spot
|
|||
unsigned ns = res->num_states();
|
||||
for (unsigned s = 0; s < ns; ++s)
|
||||
{
|
||||
bdd acc = accst[s];
|
||||
if (acc == bddfalse)
|
||||
acc_cond::mark_t acc = accst[s];
|
||||
if (acc == 0U)
|
||||
continue;
|
||||
for (auto& t: res->out(s))
|
||||
t.acc = acc;
|
||||
|
|
@ -774,8 +791,6 @@ namespace spot
|
|||
const map_constraint* map_cst_;
|
||||
|
||||
const_tgba_ptr original_;
|
||||
|
||||
bdd all_acceptance_conditions_;
|
||||
};
|
||||
|
||||
// For now, we don't try to handle cosimulation.
|
||||
|
|
@ -807,8 +822,7 @@ namespace spot
|
|||
// simulation to run.
|
||||
has_limit_ = false;
|
||||
|
||||
notap = (bdd_support(all_acceptance_conditions_)
|
||||
& all_class_var_ & on_cycle_);
|
||||
notap = bdd_support(all_proms_) & all_class_var_ & on_cycle_;
|
||||
}
|
||||
|
||||
// This function computes the don't care signature of the state
|
||||
|
|
@ -831,13 +845,14 @@ namespace spot
|
|||
if (scc != scc_info_->scc_of(t.dst))
|
||||
acc = !on_cycle_;
|
||||
else if (sccacc)
|
||||
acc = on_cycle_ & t.acc;
|
||||
acc = on_cycle_ & mark_to_bdd(t.acc);
|
||||
else
|
||||
acc = on_cycle_ & all_proms_;
|
||||
|
||||
bdd to_add = acc & t.cond & relation_[cl];
|
||||
res |= to_add;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -864,9 +879,6 @@ namespace spot
|
|||
bool could_imply_aux(bdd f1, bdd g1, bdd left_class,
|
||||
bdd right, bdd right_class)
|
||||
{
|
||||
(void) left_class;
|
||||
(void) right_class;
|
||||
|
||||
bdd f2g2 = bdd_exist(right, on_cycle_);
|
||||
bdd f2g2n = bdd_exist(f2g2, all_proms_);
|
||||
|
||||
|
|
@ -973,8 +985,7 @@ namespace spot
|
|||
bdd b = bdd_exist(right, notap);
|
||||
bdd add = bdd_exist(left & b, bdd_support(b));
|
||||
|
||||
if (add != bddfalse
|
||||
&& bdd_exist(add, all_acceptance_conditions_) == bddtrue)
|
||||
if (add != bddfalse && bdd_exist(add, all_proms_) == bddtrue)
|
||||
{
|
||||
assert(src_right != dst_right);
|
||||
|
||||
|
|
@ -988,8 +999,7 @@ namespace spot
|
|||
bdd b = bdd_exist(left, notap);
|
||||
bdd add = bdd_exist(right & b, bdd_support(b));
|
||||
|
||||
if (add != bddfalse
|
||||
&& bdd_exist(add, all_acceptance_conditions_) == bddtrue)
|
||||
if (add != bddfalse && bdd_exist(add, all_proms_) == bddtrue)
|
||||
{
|
||||
assert(src_left != dst_left);
|
||||
|
||||
|
|
@ -1003,8 +1013,7 @@ namespace spot
|
|||
bdd b = bdd_exist(left, notap);
|
||||
bdd add = bdd_exist(right & b, bdd_support(b));
|
||||
|
||||
if (add != bddfalse
|
||||
&& bdd_exist(add, all_acceptance_conditions_) == bddtrue)
|
||||
if (add != bddfalse && bdd_exist(add, all_proms_) == bddtrue)
|
||||
{
|
||||
assert(src_left != dst_left && src_right != dst_right);
|
||||
// FIXME: cas pas compris.
|
||||
|
|
@ -1174,6 +1183,9 @@ namespace spot
|
|||
}
|
||||
while (diff != bddtrue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (auto& i: class2state)
|
||||
assert(previous_class_[i.second] == i.first);
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@ namespace spot
|
|||
/// @}
|
||||
|
||||
|
||||
|
||||
// FIXME: Remove: dont_care_*_simulation is broken since the move to
|
||||
// bitset acceptance, has never been really used, and really useful
|
||||
// (nor really well tested and understood), so we should remove it.
|
||||
SPOT_API tgba_digraph_ptr
|
||||
dont_care_simulation(const const_tgba_ptr& t, int limit = -1);
|
||||
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ namespace spot
|
|||
}
|
||||
|
||||
if (has('a'))
|
||||
acc_ = aut->number_of_acceptance_conditions();
|
||||
acc_ = aut->acc().num_sets();
|
||||
|
||||
if (has('c') || has('S'))
|
||||
scc_ = scc_info(aut).scc_count();
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace spot
|
|||
unsigned n = a->num_states();
|
||||
for (unsigned s = 0; s < n; ++s)
|
||||
for (auto& t: a->out(s))
|
||||
t.acc = bddfalse;
|
||||
a->set_acceptance_conditions(bddfalse);
|
||||
t.acc = 0U;
|
||||
a->set_acceptance_conditions(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,10 +56,9 @@ namespace spot
|
|||
/// \brief Initialize the search algorithm on the automaton \a a
|
||||
tau03_search(const const_tgba_ptr a, size_t size, option_map o)
|
||||
: emptiness_check(a, o),
|
||||
h(size),
|
||||
all_cond(a->all_acceptance_conditions())
|
||||
h(size)
|
||||
{
|
||||
assert(a->number_of_acceptance_conditions() > 0);
|
||||
assert(a->acc().num_sets() > 0);
|
||||
}
|
||||
|
||||
virtual ~tau03_search()
|
||||
|
|
@ -91,7 +90,7 @@ namespace spot
|
|||
const state* s0 = a_->get_init_state();
|
||||
inc_states();
|
||||
h.add_new_state(s0, BLUE);
|
||||
push(st_blue, s0, bddfalse, bddfalse);
|
||||
push(st_blue, s0, bddfalse, 0U);
|
||||
auto t = std::static_pointer_cast<tau03_search>
|
||||
(this->emptiness_check::shared_from_this());
|
||||
if (dfs_blue())
|
||||
|
|
@ -124,7 +123,7 @@ namespace spot
|
|||
|
||||
private:
|
||||
void push(stack_type& st, const state* s,
|
||||
const bdd& label, const bdd& acc)
|
||||
const bdd& label, acc_cond::mark_t acc)
|
||||
{
|
||||
inc_depth();
|
||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||
|
|
@ -149,9 +148,6 @@ namespace spot
|
|||
/// by the last dfs visiting it.
|
||||
heap h;
|
||||
|
||||
/// The unique acceptance condition of the automaton \a a.
|
||||
bdd all_cond;
|
||||
|
||||
bool dfs_blue()
|
||||
{
|
||||
while (!st_blue.empty())
|
||||
|
|
@ -164,7 +160,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
@ -199,10 +195,10 @@ namespace spot
|
|||
<< a_->format_state(f.s) << " to "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = i->current_condition();
|
||||
bdd acc = i->current_acceptance_conditions();
|
||||
auto acc = i->current_acceptance_conditions();
|
||||
typename heap::color_ref c_prime = h.get_color_ref(s_prime);
|
||||
assert(!c_prime.is_white());
|
||||
bdd acu = acc | c.get_acc();
|
||||
auto acu = acc | c.get_acc();
|
||||
if ((c_prime.get_acc() & acu) != acu)
|
||||
{
|
||||
trace << " a propagation is needed, go down"
|
||||
|
|
@ -212,7 +208,7 @@ namespace spot
|
|||
dfs_red(acu);
|
||||
}
|
||||
}
|
||||
if (c.get_acc() == all_cond)
|
||||
if (a_->acc().accepting(c.get_acc()))
|
||||
{
|
||||
trace << "DFS_BLUE propagation is successful, report a"
|
||||
<< " cycle" << std::endl;
|
||||
|
|
@ -230,7 +226,7 @@ namespace spot
|
|||
return false;
|
||||
}
|
||||
|
||||
void dfs_red(const bdd& acu)
|
||||
void dfs_red(acc_cond::mark_t acu)
|
||||
{
|
||||
assert(!st_red.empty());
|
||||
|
||||
|
|
@ -244,7 +240,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
@ -286,7 +282,7 @@ namespace spot
|
|||
class color_ref
|
||||
{
|
||||
public:
|
||||
color_ref(color* c, bdd* a) :p(c), acc(a)
|
||||
color_ref(color* c, acc_cond::mark_t* a) :p(c), acc(a)
|
||||
{
|
||||
}
|
||||
color get_color() const
|
||||
|
|
@ -298,12 +294,12 @@ namespace spot
|
|||
assert(!is_white());
|
||||
*p = c;
|
||||
}
|
||||
const bdd& get_acc() const
|
||||
acc_cond::mark_t get_acc() const
|
||||
{
|
||||
assert(!is_white());
|
||||
return *acc;
|
||||
}
|
||||
void cumulate_acc(const bdd& a)
|
||||
void cumulate_acc(acc_cond::mark_t a)
|
||||
{
|
||||
assert(!is_white());
|
||||
*acc |= a;
|
||||
|
|
@ -314,7 +310,7 @@ namespace spot
|
|||
}
|
||||
private:
|
||||
color *p;
|
||||
bdd* acc;
|
||||
acc_cond::mark_t* acc;
|
||||
};
|
||||
|
||||
explicit_tau03_search_heap(size_t)
|
||||
|
|
@ -349,7 +345,9 @@ namespace spot
|
|||
void add_new_state(const state* s, color c)
|
||||
{
|
||||
assert(h.find(s) == h.end());
|
||||
h.emplace(s, std::make_pair(c, bddfalse));
|
||||
h.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(s),
|
||||
std::forward_as_tuple(c, 0U));
|
||||
}
|
||||
|
||||
void pop_notify(const state*) const
|
||||
|
|
@ -369,7 +367,8 @@ namespace spot
|
|||
}
|
||||
private:
|
||||
|
||||
typedef std::unordered_map<const state*, std::pair<color, bdd>,
|
||||
typedef std::unordered_map<const state*,
|
||||
std::pair<color, acc_cond::mark_t>,
|
||||
state_ptr_hash, state_ptr_equal> hash_type;
|
||||
hash_type h;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -67,24 +67,13 @@ namespace spot
|
|||
/// \brief Initialize the search algorithm on the automaton \a a
|
||||
tau03_opt_search(const const_tgba_ptr& a, size_t size, option_map o)
|
||||
: emptiness_check(a, o),
|
||||
current_weight(a->neg_acceptance_conditions()),
|
||||
current_weight(a->acc()),
|
||||
h(size),
|
||||
all_acc(a->all_acceptance_conditions()),
|
||||
use_condition_stack(o.get("condstack")),
|
||||
use_ordering(use_condition_stack && o.get("ordering")),
|
||||
use_weights(o.get("weights", 1)),
|
||||
use_red_weights(use_weights && o.get("redweights", 1))
|
||||
{
|
||||
if (use_ordering)
|
||||
{
|
||||
bdd all_conds = all_acc;
|
||||
while (all_conds != bddfalse)
|
||||
{
|
||||
bdd acc = bdd_satone(all_conds);
|
||||
cond.push_back(acc);
|
||||
all_conds -= acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~tau03_opt_search()
|
||||
|
|
@ -116,7 +105,7 @@ namespace spot
|
|||
const state* s0 = a_->get_init_state();
|
||||
inc_states();
|
||||
h.add_new_state(s0, CYAN, current_weight);
|
||||
push(st_blue, s0, bddfalse, bddfalse);
|
||||
push(st_blue, s0, bddfalse, 0U);
|
||||
auto t = std::static_pointer_cast<tau03_opt_search>
|
||||
(this->emptiness_check::shared_from_this());
|
||||
if (dfs_blue())
|
||||
|
|
@ -149,7 +138,7 @@ namespace spot
|
|||
|
||||
private:
|
||||
void push(stack_type& st, const state* s,
|
||||
const bdd& label, const bdd& acc)
|
||||
const bdd& label, acc_cond::mark_t acc)
|
||||
{
|
||||
inc_depth();
|
||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||
|
|
@ -164,14 +153,16 @@ namespace spot
|
|||
st.pop_front();
|
||||
}
|
||||
|
||||
bdd project_acc(bdd acc) const
|
||||
acc_cond::mark_t project_acc(acc_cond::mark_t acc) const
|
||||
{
|
||||
bdd result = bddfalse;
|
||||
for (std::vector<bdd>::const_iterator i = cond.begin();
|
||||
i != cond.end() && (acc & *i) != bddfalse;
|
||||
++i)
|
||||
result |= *i;
|
||||
return result;
|
||||
if (!use_ordering)
|
||||
return acc;
|
||||
// FIXME: This should be improved.
|
||||
std::vector<unsigned> res;
|
||||
unsigned max = a_->acc().num_sets();
|
||||
for (unsigned n = 0; n < max && a_->acc().has(acc, n); ++n)
|
||||
res.push_back(n);
|
||||
return a_->acc().marks(res.begin(), res.end());
|
||||
}
|
||||
|
||||
/// \brief weight of the state on top of the blue stack.
|
||||
|
|
@ -187,9 +178,6 @@ namespace spot
|
|||
/// by the last dfs visiting it.
|
||||
heap h;
|
||||
|
||||
/// The unique acceptance condition of the automaton \a a.
|
||||
bdd all_acc;
|
||||
|
||||
/// Whether to use the "condition stack".
|
||||
bool use_condition_stack;
|
||||
/// Whether to use an ordering between the acceptance conditions.
|
||||
|
|
@ -200,9 +188,6 @@ namespace spot
|
|||
/// Whether to use weights in the red dfs.
|
||||
bool use_red_weights;
|
||||
|
||||
/// Ordering of the acceptance conditions.
|
||||
std::vector<bdd> cond;
|
||||
|
||||
bool dfs_blue()
|
||||
{
|
||||
while (!st_blue.empty())
|
||||
|
|
@ -215,7 +200,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
@ -224,7 +209,7 @@ namespace spot
|
|||
{
|
||||
trace << " It is white, go down" << std::endl;
|
||||
if (use_weights)
|
||||
current_weight += acc;
|
||||
current_weight.add(a_->acc(), acc);
|
||||
inc_states();
|
||||
h.add_new_state(s_prime, CYAN, current_weight);
|
||||
push(st_blue, s_prime, label, acc);
|
||||
|
|
@ -234,22 +219,21 @@ namespace spot
|
|||
typename heap::color_ref c = h.get_color_ref(f.s);
|
||||
assert(!c.is_white());
|
||||
if (c_prime.get_color() == CYAN
|
||||
&& all_acc == ((current_weight - c_prime.get_weight())
|
||||
| c.get_acc()
|
||||
| acc
|
||||
| c_prime.get_acc()))
|
||||
&& a_->acc().accepting
|
||||
(current_weight.diff(a_->acc(), c_prime. get_weight())
|
||||
| c.get_acc() | acc | c_prime.get_acc()))
|
||||
{
|
||||
trace << " It is cyan and acceptance condition "
|
||||
<< "is reached, report cycle" << std::endl;
|
||||
c_prime.cumulate_acc(all_acc);
|
||||
c_prime.cumulate_acc(a_->acc().all_sets());
|
||||
push(st_red, s_prime, label, acc);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace << " It is cyan or blue and";
|
||||
bdd acu = acc | c.get_acc();
|
||||
bdd acp = (use_ordering ? project_acc(acu) : acu);
|
||||
auto acu = acc | c.get_acc();
|
||||
auto acp = project_acc(acu);
|
||||
if ((c_prime.get_acc() & acp) != acp)
|
||||
{
|
||||
trace << " a propagation is needed, "
|
||||
|
|
@ -276,7 +260,7 @@ namespace spot
|
|||
stack_item f_dest(f);
|
||||
pop(st_blue);
|
||||
if (use_weights)
|
||||
current_weight -= f_dest.acc;
|
||||
current_weight.sub(a_->acc(), f_dest.acc);
|
||||
typename heap::color_ref c_prime = h.get_color_ref(f_dest.s);
|
||||
assert(!c_prime.is_white());
|
||||
c_prime.set_color(BLUE);
|
||||
|
|
@ -285,8 +269,8 @@ namespace spot
|
|||
typename heap::color_ref c =
|
||||
h.get_color_ref(st_blue.front().s);
|
||||
assert(!c.is_white());
|
||||
bdd acu = f_dest.acc | c.get_acc();
|
||||
bdd acp = (use_ordering ? project_acc(acu) : acu);
|
||||
auto acu = f_dest.acc | c.get_acc();
|
||||
auto acp = project_acc(acu);
|
||||
if ((c_prime.get_acc() & acp) != acp)
|
||||
{
|
||||
trace << " The arc from "
|
||||
|
|
@ -315,15 +299,15 @@ namespace spot
|
|||
}
|
||||
|
||||
bool
|
||||
dfs_red(bdd acu)
|
||||
dfs_red(acc_cond::mark_t acu)
|
||||
{
|
||||
assert(!st_red.empty());
|
||||
|
||||
// These are useful only when USE_CONDITION_STACK is set.
|
||||
typedef std::pair<bdd, unsigned> cond_level;
|
||||
typedef std::pair<acc_cond::mark_t, unsigned> cond_level;
|
||||
std::stack<cond_level> condition_stack;
|
||||
unsigned depth = 1;
|
||||
condition_stack.emplace(bddfalse, 0);
|
||||
condition_stack.emplace(0U, 0);
|
||||
|
||||
while (!st_red.empty())
|
||||
{
|
||||
|
|
@ -335,7 +319,7 @@ namespace spot
|
|||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
auto acc = f.it->current_acceptance_conditions();
|
||||
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||
f.it->next();
|
||||
inc_transitions();
|
||||
|
|
@ -347,22 +331,23 @@ namespace spot
|
|||
continue;
|
||||
}
|
||||
else if (c_prime.get_color() == CYAN &&
|
||||
(all_acc == ((use_red_weights ?
|
||||
(current_weight - c_prime.get_weight())
|
||||
: bdd_false())
|
||||
| c_prime.get_acc()
|
||||
| acc
|
||||
| acu)))
|
||||
a_->acc().accepting
|
||||
(acc | acu | c_prime.get_acc() |
|
||||
(use_red_weights ?
|
||||
current_weight.diff(a_->acc(),
|
||||
c_prime.
|
||||
get_weight())
|
||||
: acc_cond::mark_t(0U))))
|
||||
{
|
||||
trace << " It is cyan and acceptance condition "
|
||||
<< "is reached, report cycle" << std::endl;
|
||||
c_prime.cumulate_acc(all_acc);
|
||||
c_prime.cumulate_acc(a_->acc().all_sets());
|
||||
push(st_red, s_prime, label, acc);
|
||||
return true;
|
||||
}
|
||||
bdd acp;
|
||||
acc_cond::mark_t acp;
|
||||
if (use_ordering)
|
||||
acp = project_acc(c_prime.get_acc() | acu | acc);
|
||||
acp = project_acc(acu | acc | c_prime.get_acc());
|
||||
else if (use_condition_stack)
|
||||
acp = acu | acc;
|
||||
else
|
||||
|
|
@ -376,7 +361,7 @@ namespace spot
|
|||
push(st_red, s_prime, label, acc);
|
||||
if (use_condition_stack)
|
||||
{
|
||||
bdd old = acu;
|
||||
auto old = acu;
|
||||
acu |= acc;
|
||||
condition_stack.emplace(acu - old, depth);
|
||||
}
|
||||
|
|
@ -412,20 +397,22 @@ namespace spot
|
|||
|
||||
class explicit_tau03_opt_search_heap
|
||||
{
|
||||
typedef std::unordered_map<const state*, std::pair<weight, bdd>,
|
||||
typedef std::unordered_map<const state*, std::pair<weight,
|
||||
acc_cond::mark_t>,
|
||||
state_ptr_hash, state_ptr_equal> hcyan_type;
|
||||
typedef std::unordered_map<const state*, std::pair<color, bdd>,
|
||||
typedef std::unordered_map<const state*, std::pair<color,
|
||||
acc_cond::mark_t>,
|
||||
state_ptr_hash, state_ptr_equal> hash_type;
|
||||
public:
|
||||
class color_ref
|
||||
{
|
||||
public:
|
||||
color_ref(hash_type* h, hcyan_type* hc, const state* s,
|
||||
const weight* w, bdd* a)
|
||||
const weight* w, acc_cond::mark_t* a)
|
||||
: is_cyan(true), w(w), ph(h), phc(hc), ps(s), acc(a)
|
||||
{
|
||||
}
|
||||
color_ref(color* c, bdd* a)
|
||||
color_ref(color* c, acc_cond::mark_t* a)
|
||||
: is_cyan(false), pc(c), acc(a)
|
||||
{
|
||||
}
|
||||
|
|
@ -459,12 +446,12 @@ namespace spot
|
|||
*pc=c;
|
||||
}
|
||||
}
|
||||
const bdd& get_acc() const
|
||||
acc_cond::mark_t get_acc() const
|
||||
{
|
||||
assert(!is_white());
|
||||
return *acc;
|
||||
}
|
||||
void cumulate_acc(const bdd& a)
|
||||
void cumulate_acc(acc_cond::mark_t a)
|
||||
{
|
||||
assert(!is_white());
|
||||
*acc |= a;
|
||||
|
|
@ -480,8 +467,8 @@ namespace spot
|
|||
hcyan_type* phc; // point to the hash table hcyan
|
||||
const state* ps; // point to the state in hcyan
|
||||
color *pc; // point to the color of a state stored in main hash table
|
||||
bdd* acc; // point to the acc set of a state stored in main hash table
|
||||
// or hcyan
|
||||
acc_cond::mark_t* acc; // point to the acc set of a state stored
|
||||
// in main hash table or hcyan
|
||||
};
|
||||
|
||||
explicit_tau03_opt_search_heap(size_t)
|
||||
|
|
@ -540,7 +527,7 @@ namespace spot
|
|||
(void)c;
|
||||
hc.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(s),
|
||||
std::forward_as_tuple(w, bddfalse));
|
||||
std::forward_as_tuple(w, 0U));
|
||||
}
|
||||
|
||||
void pop_notify(const state*) const
|
||||
|
|
|
|||
|
|
@ -26,96 +26,41 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
weight::weight_vector* weight::pm = 0;
|
||||
|
||||
weight::weight(const bdd& neg_all_cond) : neg_all_acc(neg_all_cond)
|
||||
weight::weight(const acc_cond& acc):
|
||||
m(acc.num_sets())
|
||||
{
|
||||
}
|
||||
|
||||
void weight::inc_weight_handler(char* varset, int size)
|
||||
weight& weight::add(const acc_cond& acc, acc_cond::mark_t a)
|
||||
{
|
||||
for (int v = 0; v < size; ++v)
|
||||
if (varset[v] > 0)
|
||||
{
|
||||
weight::weight_vector::iterator it = pm->find(v);
|
||||
if (it == pm->end())
|
||||
pm->emplace(v, 1);
|
||||
else
|
||||
++(it->second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
weight& weight::operator+=(const bdd& acc)
|
||||
{
|
||||
pm = &m;
|
||||
bdd_allsat(acc, inc_weight_handler);
|
||||
for (auto s: acc.sets(a))
|
||||
++m[s];
|
||||
return *this;
|
||||
}
|
||||
|
||||
void weight::dec_weight_handler(char* varset, int size)
|
||||
weight& weight::sub(const acc_cond& acc, acc_cond::mark_t a)
|
||||
{
|
||||
for (int v = 0; v < size; ++v)
|
||||
if (varset[v] > 0)
|
||||
{
|
||||
weight::weight_vector::iterator it = pm->find(v);
|
||||
assert(it != pm->end() && it->second > 0);
|
||||
if (it->second > 1)
|
||||
--(it->second);
|
||||
else
|
||||
pm->erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
weight& weight::operator-=(const bdd& acc)
|
||||
{
|
||||
pm = &m;
|
||||
bdd_allsat(acc, dec_weight_handler);
|
||||
for (auto s: acc.sets(a))
|
||||
if (m[s] > 0)
|
||||
--m[s];
|
||||
return *this;
|
||||
}
|
||||
|
||||
bdd weight::operator-(const weight& w) const
|
||||
acc_cond::mark_t weight::diff(const acc_cond& acc, const weight& w) const
|
||||
{
|
||||
weight_vector::const_iterator itw1 = m.begin(), itw2 = w.m.begin();
|
||||
bdd res = bddfalse;
|
||||
|
||||
while (itw1 != m.end() && itw2 != w.m.end())
|
||||
{
|
||||
assert(itw1->first <= itw2->first);
|
||||
if (itw1->first < itw2->first)
|
||||
{
|
||||
res |= bdd_exist(neg_all_acc, bdd_ithvar(itw1->first)) &
|
||||
bdd_ithvar(itw1->first);
|
||||
++itw1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(itw1->second >= itw2->second);
|
||||
if (itw1->second > itw2->second)
|
||||
{
|
||||
res |= bdd_exist(neg_all_acc, bdd_ithvar(itw1->first)) &
|
||||
bdd_ithvar(itw1->first);
|
||||
}
|
||||
++itw1;
|
||||
++itw2;
|
||||
}
|
||||
}
|
||||
assert(itw2 == w.m.end());
|
||||
while (itw1 != m.end())
|
||||
{
|
||||
res |= bdd_exist(neg_all_acc, bdd_ithvar(itw1->first)) &
|
||||
bdd_ithvar(itw1->first);
|
||||
++itw1;
|
||||
}
|
||||
return res;
|
||||
unsigned max = acc.num_sets();
|
||||
std::vector<unsigned> res;
|
||||
for (unsigned n = 0; n < max; ++n)
|
||||
if (m[n] > w.m[n])
|
||||
res.push_back(n);
|
||||
return acc.marks(res.begin(), res.end());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const weight& w)
|
||||
{
|
||||
weight::weight_vector::const_iterator it;
|
||||
for (it = w.m.begin(); it != w.m.end(); ++it)
|
||||
os << '(' << it->first << ',' << it->second << ')';
|
||||
unsigned s = w.m.size();
|
||||
for (unsigned n = 0; n < s; ++n)
|
||||
os << '(' << n << ',' << w.m[n] << ')';
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// Copyright (C) 2004, 2014 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
//
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <bdd.h>
|
||||
#include "tgba/acc.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -33,29 +34,23 @@ namespace spot
|
|||
{
|
||||
public:
|
||||
/// Construct a empty vector (all counters set to zero).
|
||||
///
|
||||
/// \param neg_all_cond : negation of all the acceptance conditions of
|
||||
/// the automaton (the bdd returned by tgba::neg_acceptance_conditions()).
|
||||
weight(const bdd& neg_all_cond);
|
||||
weight(const acc_cond& acc);
|
||||
/// Increment by one the counters of each acceptance condition in \a acc.
|
||||
weight& operator+=(const bdd& acc);
|
||||
weight& add(const acc_cond& acc, acc_cond::mark_t a);
|
||||
/// Decrement by one the counters of each acceptance condition in \a acc.
|
||||
weight& operator-=(const bdd& acc);
|
||||
weight& sub(const acc_cond& acc, acc_cond::mark_t a);
|
||||
/// Return the set of each acceptance condition such that its counter is
|
||||
/// strictly greatest than the corresponding counter in w.
|
||||
///
|
||||
/// \pre For each acceptance condition, its counter is greatest or equal to
|
||||
/// the corresponding counter in w.
|
||||
bdd operator-(const weight& w) const;
|
||||
friend std::ostream& operator<<(std::ostream& os, const weight& w);
|
||||
acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const;
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const weight& w);
|
||||
|
||||
private:
|
||||
typedef std::map<int, int> weight_vector;
|
||||
typedef std::vector<int> weight_vector;
|
||||
weight_vector m;
|
||||
bdd neg_all_acc;
|
||||
static weight_vector* pm;
|
||||
static void inc_weight_handler(char* varset, int size);
|
||||
static void dec_weight_handler(char* varset, int size);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
int token;
|
||||
std::string* str;
|
||||
const spot::ltl::formula* f;
|
||||
bdd* acc;
|
||||
spot::acc_cond::mark_t acc;
|
||||
}
|
||||
|
||||
%code
|
||||
|
|
@ -80,10 +80,9 @@ typedef std::pair<bool, spot::ltl::formula*> pair;
|
|||
%token ACC_DEF
|
||||
|
||||
%destructor { delete $$; } <str>
|
||||
%destructor { delete $$; } <acc>
|
||||
|
||||
%printer { debug_stream() << *$$; } <str>
|
||||
%printer { debug_stream() << *$$; } <acc>
|
||||
%printer { debug_stream() << $$; } <acc>
|
||||
|
||||
%%
|
||||
tgba: acceptance_decl lines
|
||||
|
|
@ -94,7 +93,8 @@ tgba: acceptance_decl lines
|
|||
{ namer->new_state("0"); };
|
||||
|
||||
acceptance_decl: ACC_DEF acc_decl ';'
|
||||
{ acc_map.commit(); }
|
||||
{
|
||||
}
|
||||
|
||||
/* At least one line. */
|
||||
lines: line
|
||||
|
|
@ -137,11 +137,10 @@ line: strident ',' strident ',' condition ',' acc_list ';'
|
|||
}
|
||||
unsigned s = namer->new_state(*$1);
|
||||
unsigned d = namer->new_state(*$3);
|
||||
namer->graph().new_transition(s, d, cond, *$7);
|
||||
namer->graph().new_transition(s, d, cond, $7);
|
||||
delete $1;
|
||||
delete $3;
|
||||
delete $5;
|
||||
delete $7;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -166,7 +165,7 @@ condition:
|
|||
|
||||
acc_list:
|
||||
{
|
||||
$$ = new bdd(bddfalse);
|
||||
$$ = 0U;
|
||||
}
|
||||
| acc_list strident
|
||||
{
|
||||
|
|
@ -180,7 +179,7 @@ acc_list:
|
|||
// $2 will be destroyed on error recovery.
|
||||
YYERROR;
|
||||
}
|
||||
*$1 |= p.second;
|
||||
$1 |= p.second;
|
||||
}
|
||||
delete $2;
|
||||
$$ = $1;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue