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.
|
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
|
methods have been removed from the TGBA interface and all
|
||||||
subclasses.
|
subclasses.
|
||||||
|
|
||||||
- tgba::succ_iter() now takes only one argument. The optional
|
- Membership to acceptance sets are now stored using bit sets,
|
||||||
global_state and global_automaton arguments have been removed.
|
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
|
* Removed features
|
||||||
|
|
||||||
|
|
@ -87,6 +110,15 @@ New in spot 1.99a (not yet released)
|
||||||
automata (when viewed explictely), using the above and non
|
automata (when viewed explictely), using the above and non
|
||||||
longuer supported tgba_bdd_concrete class.
|
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 in spot 1.2.5a (not yet released)
|
||||||
|
|
||||||
* New features:
|
* New features:
|
||||||
|
|
|
||||||
|
|
@ -606,7 +606,8 @@ namespace spot
|
||||||
|
|
||||||
dve2_kripke(const dve2_interface* d, const bdd_dict_ptr& dict,
|
dve2_kripke(const dve2_interface* d, const bdd_dict_ptr& dict,
|
||||||
const prop_set* ps, const ltl::formula* dead, int compress)
|
const prop_set* ps, const ltl::formula* dead, int compress)
|
||||||
: d_(d),
|
: kripke(dict),
|
||||||
|
d_(d),
|
||||||
state_size_(d_->get_state_variable_count()),
|
state_size_(d_->get_state_variable_count()),
|
||||||
dict_(dict), ps_(ps),
|
dict_(dict), ps_(ps),
|
||||||
compress_(compress == 0 ? 0
|
compress_(compress == 0 ? 0
|
||||||
|
|
|
||||||
|
|
@ -1047,7 +1047,7 @@ namespace
|
||||||
st->states = s.states;
|
st->states = s.states;
|
||||||
st->edges = s.transitions;
|
st->edges = s.transitions;
|
||||||
st->transitions = s.sub_transitions;
|
st->transitions = s.sub_transitions;
|
||||||
st->acc = res->number_of_acceptance_conditions();
|
st->acc = res->acc().num_sets();
|
||||||
spot::scc_map m(res);
|
spot::scc_map m(res);
|
||||||
m.build_map();
|
m.build_map();
|
||||||
unsigned c = m.scc_count();
|
unsigned c = m.scc_count();
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "tgbaalgos/reachiter.hh"
|
#include "tgbaalgos/reachiter.hh"
|
||||||
#include "tgbaalgos/gtec/gtec.hh"
|
#include "tgbaalgos/gtec/gtec.hh"
|
||||||
#include "tgbaalgos/sccfilter.hh"
|
#include "tgbaalgos/sccfilter.hh"
|
||||||
|
#include "tgbaalgos/dotty.hh"
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -55,7 +56,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
typedef std::list<const state*> state_list;
|
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 ==
|
// 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
|
// 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
|
// masked version of dra->aut. So we should always explore the
|
||||||
|
|
@ -293,7 +294,7 @@ namespace spot
|
||||||
tgba_digraph_ptr out_;
|
tgba_digraph_ptr out_;
|
||||||
const state_set& final_;
|
const state_set& final_;
|
||||||
size_t num_states_;
|
size_t num_states_;
|
||||||
bdd acc_;
|
acc_cond::mark_t acc_;
|
||||||
const scc_map& sm_;
|
const scc_map& sm_;
|
||||||
const std::vector<bool>& realizable_;
|
const std::vector<bool>& realizable_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ namespace spot
|
||||||
for (auto& t: a->out(s.s))
|
for (auto& t: a->out(s.s))
|
||||||
{
|
{
|
||||||
bitvect* pend = 0;
|
bitvect* pend = 0;
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
if (s.pend)
|
if (s.pend)
|
||||||
{
|
{
|
||||||
pend = s.pend->clone();
|
pend = s.pend->clone();
|
||||||
|
|
|
||||||
|
|
@ -35,21 +35,20 @@ void f1()
|
||||||
auto* f2 = e.require("p2");
|
auto* f2 = e.require("p2");
|
||||||
bdd p1 = bdd_ithvar(d->register_proposition(f1, tg));
|
bdd p1 = bdd_ithvar(d->register_proposition(f1, tg));
|
||||||
bdd p2 = bdd_ithvar(d->register_proposition(f2, tg));
|
bdd p2 = bdd_ithvar(d->register_proposition(f2, tg));
|
||||||
bdd a1 = bdd_ithvar(d->register_acceptance_variable(f1, tg));
|
tg->acc().add_sets(2);
|
||||||
bdd a2 = bdd_ithvar(d->register_acceptance_variable(f2, tg));
|
|
||||||
f1->destroy();
|
f1->destroy();
|
||||||
f2->destroy();
|
f2->destroy();
|
||||||
|
|
||||||
auto s1 = tg->new_state();
|
auto s1 = tg->new_state();
|
||||||
auto s2 = tg->new_state();
|
auto s2 = tg->new_state();
|
||||||
auto s3 = tg->new_state();
|
auto s3 = tg->new_state();
|
||||||
tg->new_transition(s1, s1, bddfalse, bddfalse);
|
tg->new_transition(s1, s1, bddfalse, 0U);
|
||||||
tg->new_transition(s1, s2, p1, bddfalse);
|
tg->new_transition(s1, s2, p1, 0U);
|
||||||
tg->new_transition(s1, s3, p2, (!a1) & a2);
|
tg->new_transition(s1, s3, p2, tg->acc().mark(1));
|
||||||
tg->new_transition(s2, s3, p1 & p2, a1 & !a2);
|
tg->new_transition(s2, s3, p1 & p2, tg->acc().mark(0));
|
||||||
tg->new_transition(s3, s1, p1 | p2, ((!a1) & a2) | (a1 & !a2));
|
tg->new_transition(s3, s1, p1 | p2, tg->acc().marks({0, 1}));
|
||||||
tg->new_transition(s3, s2, p1 >> p2, bddfalse);
|
tg->new_transition(s3, s2, p1 >> p2, 0U);
|
||||||
tg->new_transition(s3, s3, bddtrue, ((!a1) & a2) | (a1 & !a2));
|
tg->new_transition(s3, s3, bddtrue, tg->acc().marks({0, 1}));
|
||||||
|
|
||||||
spot::dotty_reachable(std::cout, tg);
|
spot::dotty_reachable(std::cout, tg);
|
||||||
|
|
||||||
|
|
@ -69,9 +68,10 @@ void f1()
|
||||||
spot::dotty_reachable(std::cout, tg);
|
spot::dotty_reachable(std::cout, tg);
|
||||||
}
|
}
|
||||||
|
|
||||||
tg->new_transition(s3, s1, p1 | p2, ((!a1) & a2) | (a1 & !a2));
|
auto all = tg->acc().marks({0, 1});
|
||||||
tg->new_transition(s3, s2, p1 >> p2, bddfalse);
|
tg->new_transition(s3, s1, p1 | p2, all);
|
||||||
tg->new_transition(s3, s1, bddtrue, ((!a1) & a2) | (a1 & !a2));
|
tg->new_transition(s3, s2, p1 >> p2, 0U);
|
||||||
|
tg->new_transition(s3, s1, bddtrue, all);
|
||||||
|
|
||||||
std::cerr << tg->num_transitions() << '\n';
|
std::cerr << tg->num_transitions() << '\n';
|
||||||
assert(tg->num_transitions() == 7);
|
assert(tg->num_transitions() == 7);
|
||||||
|
|
|
||||||
|
|
@ -37,76 +37,76 @@ digraph G {
|
||||||
0 [label="", style=invis, height=0]
|
0 [label="", style=invis, height=0]
|
||||||
0 -> 1
|
0 -> 1
|
||||||
1 [label="0"]
|
1 [label="0"]
|
||||||
1 -> 1 [label="0\n"]
|
1 -> 1 [label="0"]
|
||||||
1 -> 2 [label="p1\n"]
|
1 -> 2 [label="p1"]
|
||||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
1 -> 3 [label="p2\n{1}"]
|
||||||
2 [label="1"]
|
2 [label="1"]
|
||||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
2 -> 3 [label="p1 & p2\n{0}"]
|
||||||
3 [label="2"]
|
3 [label="2"]
|
||||||
3 -> 1 [label="p1 | p2\n{Acc[p2], Acc[p1]}"]
|
3 -> 1 [label="p1 | p2\n{0,1}"]
|
||||||
3 -> 2 [label="!p1 | p2\n"]
|
3 -> 2 [label="!p1 | p2"]
|
||||||
3 -> 3 [label="1\n{Acc[p2], Acc[p1]}"]
|
3 -> 3 [label="1\n{0,1}"]
|
||||||
}
|
}
|
||||||
digraph G {
|
digraph G {
|
||||||
0 [label="", style=invis, height=0]
|
0 [label="", style=invis, height=0]
|
||||||
0 -> 1
|
0 -> 1
|
||||||
1 [label="0"]
|
1 [label="0"]
|
||||||
1 -> 1 [label="0\n"]
|
1 -> 1 [label="0"]
|
||||||
1 -> 2 [label="p1\n"]
|
1 -> 2 [label="p1"]
|
||||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
1 -> 3 [label="p2\n{1}"]
|
||||||
2 [label="1"]
|
2 [label="1"]
|
||||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
2 -> 3 [label="p1 & p2\n{0}"]
|
||||||
3 [label="2"]
|
3 [label="2"]
|
||||||
3 -> 1 [label="p1 | p2\n{Acc[p2], Acc[p1]}"]
|
3 -> 1 [label="p1 | p2\n{0,1}"]
|
||||||
}
|
}
|
||||||
digraph G {
|
digraph G {
|
||||||
0 [label="", style=invis, height=0]
|
0 [label="", style=invis, height=0]
|
||||||
0 -> 1
|
0 -> 1
|
||||||
1 [label="0"]
|
1 [label="0"]
|
||||||
1 -> 1 [label="0\n"]
|
1 -> 1 [label="0"]
|
||||||
1 -> 2 [label="p1\n"]
|
1 -> 2 [label="p1"]
|
||||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
1 -> 3 [label="p2\n{1}"]
|
||||||
2 [label="1"]
|
2 [label="1"]
|
||||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
2 -> 3 [label="p1 & p2\n{0}"]
|
||||||
3 [label="2"]
|
3 [label="2"]
|
||||||
}
|
}
|
||||||
digraph G {
|
digraph G {
|
||||||
0 [label="", style=invis, height=0]
|
0 [label="", style=invis, height=0]
|
||||||
0 -> 1
|
0 -> 1
|
||||||
1 [label="0"]
|
1 [label="0"]
|
||||||
1 -> 1 [label="0\n"]
|
1 -> 1 [label="0"]
|
||||||
1 -> 2 [label="p1\n"]
|
1 -> 2 [label="p1"]
|
||||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
1 -> 3 [label="p2\n{1}"]
|
||||||
2 [label="1"]
|
2 [label="1"]
|
||||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
2 -> 3 [label="p1 & p2\n{0}"]
|
||||||
3 [label="2"]
|
3 [label="2"]
|
||||||
3 -> 1 [label="p1 | p2\n{Acc[p2], Acc[p1]}"]
|
3 -> 1 [label="p1 | p2\n{0,1}"]
|
||||||
3 -> 2 [label="!p1 | p2\n"]
|
3 -> 2 [label="!p1 | p2"]
|
||||||
3 -> 1 [label="1\n{Acc[p2], Acc[p1]}"]
|
3 -> 1 [label="1\n{0,1}"]
|
||||||
}
|
}
|
||||||
digraph G {
|
digraph G {
|
||||||
0 [label="", style=invis, height=0]
|
0 [label="", style=invis, height=0]
|
||||||
0 -> 1
|
0 -> 1
|
||||||
1 [label="0"]
|
1 [label="0"]
|
||||||
1 -> 2 [label="p1\n"]
|
1 -> 2 [label="p1"]
|
||||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
1 -> 3 [label="p2\n{1}"]
|
||||||
2 [label="1"]
|
2 [label="1"]
|
||||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
2 -> 3 [label="p1 & p2\n{0}"]
|
||||||
3 [label="2"]
|
3 [label="2"]
|
||||||
3 -> 1 [label="1\n{Acc[p2], Acc[p1]}"]
|
3 -> 1 [label="1\n{0,1}"]
|
||||||
3 -> 2 [label="!p1 | p2\n"]
|
3 -> 2 [label="!p1 | p2"]
|
||||||
}
|
}
|
||||||
digraph G {
|
digraph G {
|
||||||
0 [label="", style=invis, height=0]
|
0 [label="", style=invis, height=0]
|
||||||
0 -> 1
|
0 -> 1
|
||||||
1 [label="0"]
|
1 [label="0"]
|
||||||
1 -> 2 [label="p1\n"]
|
1 -> 2 [label="p1"]
|
||||||
1 -> 3 [label="p2\n{Acc[p2]}"]
|
1 -> 3 [label="p2\n{1}"]
|
||||||
2 [label="1"]
|
2 [label="1"]
|
||||||
2 -> 3 [label="p1 & p2\n{Acc[p1]}"]
|
2 -> 3 [label="p1 & p2\n{0}"]
|
||||||
3 [label="2"]
|
3 [label="2"]
|
||||||
3 -> 1 [label="1\n{Acc[p2], Acc[p1]}"]
|
3 -> 1 [label="1\n{0,1}"]
|
||||||
3 -> 2 [label="!p1 | p2\n"]
|
3 -> 2 [label="!p1 | p2"]
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
fair_kripke_succ_iterator::fair_kripke_succ_iterator(const bdd& cond,
|
fair_kripke_succ_iterator::fair_kripke_succ_iterator
|
||||||
const bdd& acc_cond)
|
(const bdd& cond, acc_cond::mark_t acc_cond)
|
||||||
: cond_(cond), acc_cond_(acc_cond)
|
: cond_(cond), acc_cond_(acc_cond)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ namespace spot
|
||||||
return cond_;
|
return cond_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
fair_kripke_succ_iterator::current_acceptance_conditions() const
|
fair_kripke_succ_iterator::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
// Do not assert(!done()) here. It is OK to call
|
// 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
|
/// The \a cond and \a acc_cond arguments will be those returned
|
||||||
/// by fair_kripke_succ_iterator::current_condition(),
|
/// by fair_kripke_succ_iterator::current_condition(),
|
||||||
/// and fair_kripke_succ_iterator::current_acceptance_conditions().
|
/// 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 ~fair_kripke_succ_iterator();
|
||||||
|
|
||||||
virtual bdd current_condition() const;
|
virtual bdd current_condition() const;
|
||||||
virtual bdd current_acceptance_conditions() const;
|
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||||
protected:
|
protected:
|
||||||
bdd cond_;
|
bdd cond_;
|
||||||
bdd acc_cond_;
|
acc_cond::mark_t acc_cond_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \ingroup kripke
|
/// \ingroup kripke
|
||||||
|
|
@ -86,16 +86,22 @@ namespace spot
|
||||||
/// class and need not be defined.
|
/// class and need not be defined.
|
||||||
///
|
///
|
||||||
/// See also spot::fair_kripke_succ_iterator.
|
/// See also spot::fair_kripke_succ_iterator.
|
||||||
class SPOT_API fair_kripke : public tgba
|
class SPOT_API fair_kripke: public tgba
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
fair_kripke(const bdd_dict_ptr& d)
|
||||||
|
: tgba(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief The condition that label the state \a s.
|
/// \brief The condition that label the state \a s.
|
||||||
///
|
///
|
||||||
/// This should be a conjunction of atomic propositions.
|
/// This should be a conjunction of atomic propositions.
|
||||||
virtual bdd state_condition(const state* s) const = 0;
|
virtual bdd state_condition(const state* s) const = 0;
|
||||||
|
|
||||||
/// \brief The set of acceptance conditions that label the state \a s.
|
/// \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:
|
protected:
|
||||||
virtual bdd compute_support_conditions(const state* s) const;
|
virtual bdd compute_support_conditions(const state* s) const;
|
||||||
|
|
|
||||||
|
|
@ -34,33 +34,21 @@ namespace spot
|
||||||
return cond_;
|
return cond_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
kripke_succ_iterator::current_acceptance_conditions() const
|
kripke_succ_iterator::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
// Do not assert(!done()) here. It is OK to call
|
// Do not assert(!done()) here. It is OK to call
|
||||||
// this function on a state without successor.
|
// this function on a state without successor.
|
||||||
return bddfalse;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
kripke::~kripke()
|
kripke::~kripke()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
kripke::state_acceptance_conditions(const state*) const
|
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 ~kripke_succ_iterator();
|
||||||
|
|
||||||
virtual bdd current_condition() const;
|
virtual bdd current_condition() const;
|
||||||
virtual bdd current_acceptance_conditions() const;
|
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||||
protected:
|
protected:
|
||||||
bdd cond_;
|
bdd cond_;
|
||||||
};
|
};
|
||||||
|
|
@ -92,11 +92,15 @@ namespace spot
|
||||||
class SPOT_API kripke: public fair_kripke
|
class SPOT_API kripke: public fair_kripke
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
kripke(const bdd_dict_ptr& d)
|
||||||
|
: fair_kripke(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual ~kripke();
|
virtual ~kripke();
|
||||||
|
|
||||||
virtual bdd state_acceptance_conditions(const state*) const;
|
virtual acc_cond::mark_t state_acceptance_conditions(const state*) const;
|
||||||
virtual bdd neg_acceptance_conditions() const;
|
|
||||||
virtual bdd all_acceptance_conditions() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,8 @@ namespace spot
|
||||||
|
|
||||||
kripke_explicit::kripke_explicit(const bdd_dict_ptr& dict,
|
kripke_explicit::kripke_explicit(const bdd_dict_ptr& dict,
|
||||||
state_kripke* init)
|
state_kripke* init)
|
||||||
: dict_(dict),
|
: kripke(dict),
|
||||||
init_ (init)
|
init_(init)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,7 +148,7 @@ namespace spot
|
||||||
|
|
||||||
kripke_explicit::~kripke_explicit()
|
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;
|
std::map<const std::string, state_kripke*>::iterator it;
|
||||||
for (it = ns_nodes_.begin(); it != ns_nodes_.end(); ++it)
|
for (it = ns_nodes_.begin(); it != ns_nodes_.end(); ++it)
|
||||||
{
|
{
|
||||||
|
|
@ -163,12 +163,6 @@ namespace spot
|
||||||
return init_;
|
return init_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd_dict_ptr
|
|
||||||
kripke_explicit::get_dict() const
|
|
||||||
{
|
|
||||||
return dict_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Change the bddtrue.
|
// FIXME: Change the bddtrue.
|
||||||
kripke_explicit_succ_iterator*
|
kripke_explicit_succ_iterator*
|
||||||
kripke_explicit::succ_iter(const spot::state* st) const
|
kripke_explicit::succ_iter(const spot::state* st) const
|
||||||
|
|
@ -269,7 +263,7 @@ namespace spot
|
||||||
void kripke_explicit::add_condition(const ltl::formula* f,
|
void kripke_explicit::add_condition(const ltl::formula* f,
|
||||||
std::string on_me)
|
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();
|
f->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,6 @@ namespace spot
|
||||||
kripke_explicit(const bdd_dict_ptr&, state_kripke* = nullptr);
|
kripke_explicit(const bdd_dict_ptr&, state_kripke* = nullptr);
|
||||||
~kripke_explicit();
|
~kripke_explicit();
|
||||||
|
|
||||||
bdd_dict_ptr get_dict() const;
|
|
||||||
state_kripke* get_init_state() const;
|
state_kripke* get_init_state() const;
|
||||||
|
|
||||||
/// \brief Allow to get an iterator on the state we passed in
|
/// \brief Allow to get an iterator on the state we passed in
|
||||||
|
|
@ -174,7 +173,6 @@ namespace spot
|
||||||
void add_transition(state_kripke* source,
|
void add_transition(state_kripke* source,
|
||||||
const state_kripke* dest);
|
const state_kripke* dest);
|
||||||
|
|
||||||
bdd_dict_ptr dict_;
|
|
||||||
state_kripke* init_;
|
state_kripke* init_;
|
||||||
std::map<const std::string, state_kripke*> ns_nodes_;
|
std::map<const std::string, state_kripke*> ns_nodes_;
|
||||||
std::map<const state_kripke*, std::string> sn_nodes_;
|
std::map<const state_kripke*, std::string> sn_nodes_;
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,11 @@ namespace spot
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
std::size_t operator()(const std::pair<T, U> &p) const
|
std::size_t operator()(const std::pair<T, U> &p) const
|
||||||
{
|
{
|
||||||
return wang32_hash(static_cast<size_t>(p.first) ^
|
std::hash<T> th;
|
||||||
static_cast<size_t>(p.second));
|
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,
|
namer->new_transition(*$1, *$1, bddtrue,
|
||||||
!strncmp("accept", $1->c_str(), 6) ?
|
!strncmp("accept", $1->c_str(), 6) ?
|
||||||
result->all_acceptance_conditions() :
|
result->acc().all_sets() :
|
||||||
static_cast<const bdd>(bddfalse));
|
spot::acc_cond::mark_t(0U));
|
||||||
delete $1;
|
delete $1;
|
||||||
}
|
}
|
||||||
| ident_list { delete $1; }
|
| ident_list { delete $1; }
|
||||||
| ident_list "false" { delete $1; }
|
| ident_list "false" { delete $1; }
|
||||||
| ident_list transition_block
|
| ident_list transition_block
|
||||||
{
|
{
|
||||||
bdd acc = !strncmp("accept", $1->c_str(), 6) ?
|
auto acc = !strncmp("accept", $1->c_str(), 6) ?
|
||||||
result->all_acceptance_conditions() :
|
result->acc().all_sets() : spot::acc_cond::mark_t(0U);
|
||||||
static_cast<const bdd>(bddfalse);
|
|
||||||
for (auto& p: *$2)
|
for (auto& p: *$2)
|
||||||
namer->new_transition(*$1, *p.second, *p.first, acc);
|
namer->new_transition(*$1, *p.second, *p.first, acc);
|
||||||
// Free the list
|
// Free the list
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,9 @@ namespace spot
|
||||||
bdd_dict_ptr dict_;
|
bdd_dict_ptr dict_;
|
||||||
tgba_digraph_ptr aut_;
|
tgba_digraph_ptr aut_;
|
||||||
ltl::environment& env_;
|
ltl::environment& env_;
|
||||||
bdd neg_;
|
|
||||||
|
|
||||||
acc_mapper_common(const tgba_digraph_ptr& aut, ltl::environment& env)
|
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_;
|
return env_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit all acceptance set to the automaton.
|
|
||||||
void commit()
|
|
||||||
{
|
|
||||||
aut_->set_acceptance_conditions(neg_);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class acc_mapper_string: public acc_mapper_common
|
class acc_mapper_string: public acc_mapper_common
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, int> map_;
|
std::unordered_map<std::string, unsigned> map_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
acc_mapper_string(const tgba_digraph_ptr& aut,
|
acc_mapper_string(const tgba_digraph_ptr& aut,
|
||||||
|
|
@ -72,24 +65,17 @@ namespace spot
|
||||||
auto i = map_.find(name);
|
auto i = map_.find(name);
|
||||||
if (i != map_.end())
|
if (i != map_.end())
|
||||||
return true;
|
return true;
|
||||||
auto f = env_.require(name);
|
auto v = aut_->acc().add_set();
|
||||||
if (!f)
|
|
||||||
return false;
|
|
||||||
int v = dict_->register_acceptance_variable(f, aut_);
|
|
||||||
f->destroy();
|
|
||||||
map_[name] = v;
|
map_[name] = v;
|
||||||
neg_ &= bdd_nithvar(v);
|
|
||||||
return true;
|
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);
|
auto p = map_.find(name);
|
||||||
if (p == map_.end())
|
if (p == map_.end())
|
||||||
return std::make_pair(false, bddfalse);
|
return std::make_pair(false, 0U);
|
||||||
return std::make_pair(true, bdd_compose(neg_,
|
return std::make_pair(true, aut_->acc().marks({p->second}));
|
||||||
bdd_nithvar(p->second),
|
|
||||||
p->second));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -97,42 +83,23 @@ namespace spot
|
||||||
// The acceptance sets are named using count consecutive integers.
|
// The acceptance sets are named using count consecutive integers.
|
||||||
class acc_mapper_consecutive_int: public acc_mapper_common
|
class acc_mapper_consecutive_int: public acc_mapper_common
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
std::vector<bdd> vec_;
|
|
||||||
std::map<int, bdd> map_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
acc_mapper_consecutive_int(const tgba_digraph_ptr& aut,
|
acc_mapper_consecutive_int(const tgba_digraph_ptr& aut,
|
||||||
unsigned count,
|
unsigned count,
|
||||||
ltl::environment& env =
|
ltl::environment& env =
|
||||||
ltl::default_environment::instance())
|
ltl::default_environment::instance())
|
||||||
: acc_mapper_common(aut, env), vec_(count)
|
: acc_mapper_common(aut, env)
|
||||||
{
|
{
|
||||||
std::vector<int> vmap(count);
|
std::vector<unsigned> vmap(count);
|
||||||
for (unsigned n = 0; n < count; ++n)
|
aut->acc().add_sets(count);
|
||||||
{
|
|
||||||
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::pair<bool, bdd> lookup(unsigned n)
|
std::pair<bool, acc_cond::mark_t> lookup(unsigned n)
|
||||||
{
|
{
|
||||||
if (n < vec_.size())
|
if (n < aut_->acc().num_sets())
|
||||||
return std::make_pair(true, vec_[n]);
|
return std::make_pair(true, aut_->acc().marks({n}));
|
||||||
else
|
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
|
class acc_mapper_int: public acc_mapper_consecutive_int
|
||||||
{
|
{
|
||||||
unsigned used_;
|
unsigned used_;
|
||||||
std::map<int, bdd> map_;
|
std::map<unsigned, acc_cond::mark_t> map_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
acc_mapper_int(const tgba_digraph_ptr& aut,
|
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);
|
auto p = map_.find(n);
|
||||||
if (p != map_.end())
|
if (p != map_.end())
|
||||||
return std::make_pair(true, p->second);
|
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;
|
map_[n] = res;
|
||||||
return std::make_pair(true, 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;
|
index = i;
|
||||||
is_accepting = false;
|
is_accepting = false;
|
||||||
condition = bddfalse;
|
condition = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_stack_ta::connected_component&
|
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
|
class SPOT_API ta
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
acc_cond acc_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ta(const bdd_dict_ptr& d)
|
||||||
|
: acc_(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
~ta()
|
~ta()
|
||||||
{
|
{
|
||||||
|
|
@ -128,8 +135,11 @@ namespace spot
|
||||||
/// This is useful when dealing with several automata (which
|
/// This is useful when dealing with several automata (which
|
||||||
/// may use the same BDD variable for different formula),
|
/// may use the same BDD variable for different formula),
|
||||||
/// or simply when printing.
|
/// or simply when printing.
|
||||||
virtual bdd_dict_ptr
|
bdd_dict_ptr
|
||||||
get_dict() const = 0;
|
get_dict() const
|
||||||
|
{
|
||||||
|
return acc_.get_dict();
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Format the state as a string for printing.
|
/// \brief Format the state as a string for printing.
|
||||||
///
|
///
|
||||||
|
|
@ -160,17 +170,16 @@ namespace spot
|
||||||
virtual void
|
virtual void
|
||||||
free_state(const spot::state* s) const = 0;
|
free_state(const spot::state* s) const = 0;
|
||||||
|
|
||||||
/// \brief Return the set of all acceptance conditions used
|
|
||||||
/// by this automaton
|
const acc_cond& acc() const
|
||||||
/// (for Generalized form: Transition-based Generalized Testing Automata).
|
{
|
||||||
///
|
return acc_;
|
||||||
/// 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
|
acc_cond& acc()
|
||||||
/// of the acceptiong conditions of all transition in
|
{
|
||||||
/// the SCC should be equal to the result of this function.
|
return acc_;
|
||||||
virtual bdd
|
}
|
||||||
all_acceptance_conditions() const = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -206,7 +215,7 @@ namespace spot
|
||||||
virtual bdd
|
virtual bdd
|
||||||
current_condition() const = 0;
|
current_condition() const = 0;
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
current_acceptance_conditions() const = 0;
|
current_acceptance_conditions() const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -228,7 +237,7 @@ namespace spot
|
||||||
|
|
||||||
/// The bdd condition is the union of all acceptance conditions of
|
/// The bdd condition is the union of all acceptance conditions of
|
||||||
/// transitions which connect the states of the connected component.
|
/// transitions which connect the states of the connected component.
|
||||||
bdd condition;
|
acc_cond::mark_t condition;
|
||||||
|
|
||||||
std::list<state*> rem;
|
std::list<state*> rem;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ namespace spot
|
||||||
return (*i_)->condition;
|
return (*i_)->condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
ta_explicit_succ_iterator::current_acceptance_conditions() const
|
ta_explicit_succ_iterator::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
assert(!done());
|
assert(!done());
|
||||||
|
|
@ -352,13 +352,14 @@ namespace spot
|
||||||
|
|
||||||
|
|
||||||
ta_explicit::ta_explicit(const const_tgba_ptr& tgba,
|
ta_explicit::ta_explicit(const const_tgba_ptr& tgba,
|
||||||
bdd all_acceptance_conditions,
|
unsigned n_acc,
|
||||||
state_ta_explicit* artificial_initial_state):
|
state_ta_explicit* artificial_initial_state):
|
||||||
|
ta(tgba->get_dict()),
|
||||||
tgba_(tgba),
|
tgba_(tgba),
|
||||||
all_acceptance_conditions_(all_acceptance_conditions),
|
|
||||||
artificial_initial_state_(artificial_initial_state)
|
artificial_initial_state_(artificial_initial_state)
|
||||||
{
|
{
|
||||||
get_dict()->register_all_variables_of(&tgba_, this);
|
get_dict()->register_all_variables_of(&tgba_, this);
|
||||||
|
acc().add_sets(n_acc);
|
||||||
if (artificial_initial_state != 0)
|
if (artificial_initial_state != 0)
|
||||||
{
|
{
|
||||||
state_ta_explicit* is = add_state(artificial_initial_state);
|
state_ta_explicit* is = add_state(artificial_initial_state);
|
||||||
|
|
@ -403,7 +404,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
state_ta_explicit* i =
|
state_ta_explicit* i =
|
||||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
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
|
void
|
||||||
ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
|
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* dest, bool add_at_beginning)
|
||||||
{
|
{
|
||||||
state_ta_explicit::transition* t = new state_ta_explicit::transition;
|
state_ta_explicit::transition* t = new state_ta_explicit::transition;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,8 @@ namespace spot
|
||||||
class SPOT_API ta_explicit : public ta
|
class SPOT_API ta_explicit : public ta
|
||||||
{
|
{
|
||||||
public:
|
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);
|
state_ta_explicit* artificial_initial_state = 0);
|
||||||
|
|
||||||
const_tgba_ptr
|
const_tgba_ptr
|
||||||
|
|
@ -55,8 +56,9 @@ namespace spot
|
||||||
|
|
||||||
void
|
void
|
||||||
create_transition(state_ta_explicit* source, bdd condition,
|
create_transition(state_ta_explicit* source, bdd condition,
|
||||||
bdd acceptance_conditions, state_ta_explicit* dest,
|
acc_cond::mark_t acceptance_conditions,
|
||||||
bool add_at_beginning = false);
|
state_ta_explicit* dest,
|
||||||
|
bool add_at_beginning = false);
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_stuttering_transitions();
|
delete_stuttering_transitions();
|
||||||
|
|
@ -115,27 +117,12 @@ namespace spot
|
||||||
return states_set_;
|
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:
|
private:
|
||||||
// Disallow copy.
|
// Disallow copy.
|
||||||
ta_explicit(const ta_explicit& other) SPOT_DELETED;
|
ta_explicit(const ta_explicit& other) SPOT_DELETED;
|
||||||
ta_explicit& operator=(const ta_explicit& other) SPOT_DELETED;
|
ta_explicit& operator=(const ta_explicit& other) SPOT_DELETED;
|
||||||
|
|
||||||
const_tgba_ptr tgba_;
|
const_tgba_ptr tgba_;
|
||||||
bdd all_acceptance_conditions_;
|
|
||||||
state_ta_explicit* artificial_initial_state_;
|
state_ta_explicit* artificial_initial_state_;
|
||||||
ta::states_set_t states_set_;
|
ta::states_set_t states_set_;
|
||||||
ta::states_set_t initial_states_set_;
|
ta::states_set_t initial_states_set_;
|
||||||
|
|
@ -152,7 +139,7 @@ namespace spot
|
||||||
struct transition
|
struct transition
|
||||||
{
|
{
|
||||||
bdd condition;
|
bdd condition;
|
||||||
bdd acceptance_conditions;
|
acc_cond::mark_t acceptance_conditions;
|
||||||
state_ta_explicit* dest;
|
state_ta_explicit* dest;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -255,7 +242,7 @@ namespace spot
|
||||||
virtual bdd
|
virtual bdd
|
||||||
current_condition() const;
|
current_condition() const;
|
||||||
|
|
||||||
virtual bdd
|
virtual acc_cond::mark_t
|
||||||
current_acceptance_conditions() const;
|
current_acceptance_conditions() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -267,13 +254,11 @@ namespace spot
|
||||||
typedef std::shared_ptr<const ta_explicit> const_ta_explicit_ptr;
|
typedef std::shared_ptr<const ta_explicit> const_ta_explicit_ptr;
|
||||||
|
|
||||||
inline ta_explicit_ptr make_ta_explicit(const const_tgba_ptr& tgba,
|
inline ta_explicit_ptr make_ta_explicit(const const_tgba_ptr& tgba,
|
||||||
bdd all_acceptance_conditions,
|
unsigned n_acc,
|
||||||
state_ta_explicit*
|
state_ta_explicit*
|
||||||
artificial_initial_state = 0)
|
artificial_initial_state = 0)
|
||||||
{
|
{
|
||||||
return std::make_shared<ta_explicit>(tgba,
|
return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state);
|
||||||
all_acceptance_conditions,
|
|
||||||
artificial_initial_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ namespace spot
|
||||||
//if stuttering transition, the TA automata stays in the same state
|
//if stuttering transition, the TA automata stays in the same state
|
||||||
current_state_ = new state_ta_product(source_->get_ta_state(),
|
current_state_ = new state_ta_product(source_->get_ta_state(),
|
||||||
kripke_current_dest_state->clone());
|
kripke_current_dest_state->clone());
|
||||||
current_acceptance_conditions_ = bddfalse;
|
current_acceptance_conditions_ = 0U;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,7 +232,7 @@ namespace spot
|
||||||
return current_condition_;
|
return current_condition_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
ta_succ_iterator_product::current_acceptance_conditions() const
|
ta_succ_iterator_product::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
return current_acceptance_conditions_;
|
return current_acceptance_conditions_;
|
||||||
|
|
@ -244,6 +244,7 @@ namespace spot
|
||||||
|
|
||||||
ta_product::ta_product(const const_ta_ptr& testing_automata,
|
ta_product::ta_product(const const_ta_ptr& testing_automata,
|
||||||
const const_kripke_ptr& kripke_structure):
|
const const_kripke_ptr& kripke_structure):
|
||||||
|
ta(testing_automata->get_dict()),
|
||||||
dict_(testing_automata->get_dict()),
|
dict_(testing_automata->get_dict()),
|
||||||
ta_(testing_automata),
|
ta_(testing_automata),
|
||||||
kripke_(kripke_structure)
|
kripke_(kripke_structure)
|
||||||
|
|
@ -387,12 +388,6 @@ namespace spot
|
||||||
return is_hole_state;
|
return is_hole_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
|
||||||
ta_product::all_acceptance_conditions() const
|
|
||||||
{
|
|
||||||
return get_ta()->all_acceptance_conditions();
|
|
||||||
}
|
|
||||||
|
|
||||||
bdd
|
bdd
|
||||||
ta_product::get_state_condition(const spot::state* s) const
|
ta_product::get_state_condition(const spot::state* s) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ namespace spot
|
||||||
bdd
|
bdd
|
||||||
current_condition() const;
|
current_condition() const;
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
current_acceptance_conditions() const;
|
current_acceptance_conditions() const;
|
||||||
|
|
||||||
/// \brief Return true if the changeset of the current transition is empty
|
/// \brief Return true if the changeset of the current transition is empty
|
||||||
|
|
@ -120,7 +120,7 @@ namespace spot
|
||||||
tgba_succ_iterator* kripke_succ_it_;
|
tgba_succ_iterator* kripke_succ_it_;
|
||||||
state_ta_product* current_state_;
|
state_ta_product* current_state_;
|
||||||
bdd current_condition_;
|
bdd current_condition_;
|
||||||
bdd current_acceptance_conditions_;
|
acc_cond::mark_t current_acceptance_conditions_;
|
||||||
bool is_stuttering_transition_;
|
bool is_stuttering_transition_;
|
||||||
bdd kripke_source_condition;
|
bdd kripke_source_condition;
|
||||||
state * kripke_current_dest_state;
|
state * kripke_current_dest_state;
|
||||||
|
|
@ -174,9 +174,6 @@ namespace spot
|
||||||
virtual bdd
|
virtual bdd
|
||||||
get_state_condition(const spot::state* s) const;
|
get_state_condition(const spot::state* s) const;
|
||||||
|
|
||||||
virtual bdd
|
|
||||||
all_acceptance_conditions() const;
|
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
free_state(const spot::state* s) const;
|
free_state(const spot::state* s) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- 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).
|
// de l'Epita (LRDE).
|
||||||
//
|
//
|
||||||
// This file is part of Spot, a model checking library.
|
// This file is part of Spot, a model checking library.
|
||||||
|
|
@ -22,11 +22,9 @@
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
tgta::tgta(const bdd_dict_ptr& d)
|
||||||
tgta::tgta()
|
: tgba(d)
|
||||||
{};
|
{};
|
||||||
tgta::~tgta()
|
tgta::~tgta()
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,9 @@ namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
tgta();
|
tgta(const bdd_dict_ptr& d);
|
||||||
public:
|
|
||||||
|
|
||||||
|
public:
|
||||||
virtual
|
virtual
|
||||||
~tgta();
|
~tgta();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,10 @@ namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
tgta_explicit::tgta_explicit(const const_tgba_ptr& tgba,
|
tgta_explicit::tgta_explicit(const const_tgba_ptr& tgba,
|
||||||
bdd all_acceptance_conditions,
|
unsigned n_acc,
|
||||||
state_ta_explicit* artificial_initial_state) :
|
state_ta_explicit* artificial_initial_state) :
|
||||||
ta_(make_ta_explicit(tgba, all_acceptance_conditions,
|
tgta(tgba->get_dict()),
|
||||||
artificial_initial_state))
|
ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,18 +63,6 @@ namespace spot
|
||||||
return ta_->get_dict();
|
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
|
std::string
|
||||||
tgta_explicit::format_state(const spot::state* s) const
|
tgta_explicit::format_state(const spot::state* s) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
tgta_explicit(const const_tgba_ptr& tgba,
|
tgta_explicit(const const_tgba_ptr& tgba,
|
||||||
bdd all_acceptance_conditions,
|
unsigned n_acc,
|
||||||
state_ta_explicit* artificial_initial_state);
|
state_ta_explicit* artificial_initial_state);
|
||||||
|
|
||||||
// tgba interface
|
// tgba interface
|
||||||
|
|
@ -54,9 +54,6 @@ namespace spot
|
||||||
const_ta_explicit_ptr get_ta() const { return ta_; }
|
const_ta_explicit_ptr get_ta() const { return ta_; }
|
||||||
ta_explicit_ptr get_ta() { 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 std::string format_state(const spot::state* s) const;
|
||||||
|
|
||||||
virtual tgba_succ_iterator*
|
virtual tgba_succ_iterator*
|
||||||
|
|
@ -71,12 +68,11 @@ namespace spot
|
||||||
typedef std::shared_ptr<const tgta_explicit> const_tgta_explicit_ptr;
|
typedef std::shared_ptr<const tgta_explicit> const_tgta_explicit_ptr;
|
||||||
|
|
||||||
inline tgta_explicit_ptr make_tgta_explicit(const const_tgba_ptr& tgba,
|
inline tgta_explicit_ptr make_tgta_explicit(const const_tgba_ptr& tgba,
|
||||||
bdd all_acceptance_conditions,
|
unsigned n_acc,
|
||||||
state_ta_explicit*
|
state_ta_explicit*
|
||||||
artificial_initial_state = 0)
|
artificial_initial_state = 0)
|
||||||
{
|
{
|
||||||
return std::make_shared<tgta_explicit>(tgba,
|
return std::make_shared<tgta_explicit>(tgba, n_acc,
|
||||||
all_acceptance_conditions,
|
|
||||||
artificial_initial_state);
|
artificial_initial_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ namespace spot
|
||||||
kripke_current_dest_state->clone(),
|
kripke_current_dest_state->clone(),
|
||||||
tgta_succ_it_->current_state(), pool_);
|
tgta_succ_it_->current_state(), pool_);
|
||||||
current_acceptance_conditions_
|
current_acceptance_conditions_
|
||||||
= tgta_succ_it_->current_acceptance_conditions();
|
= tgta_succ_it_->current_acceptance_conditions();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,7 +244,7 @@ namespace spot
|
||||||
return current_condition_;
|
return current_condition_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
tgta_succ_iterator_product::current_acceptance_conditions() const
|
tgta_succ_iterator_product::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
return current_acceptance_conditions_;
|
return current_acceptance_conditions_;
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ namespace spot
|
||||||
bdd
|
bdd
|
||||||
current_condition() const;
|
current_condition() const;
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
current_acceptance_conditions() const;
|
current_acceptance_conditions() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -96,7 +96,7 @@ namespace spot
|
||||||
tgba_succ_iterator* kripke_succ_it_;
|
tgba_succ_iterator* kripke_succ_it_;
|
||||||
state_product* current_state_;
|
state_product* current_state_;
|
||||||
bdd current_condition_;
|
bdd current_condition_;
|
||||||
bdd current_acceptance_conditions_;
|
acc_cond::mark_t current_acceptance_conditions_;
|
||||||
bdd kripke_source_condition;
|
bdd kripke_source_condition;
|
||||||
state* kripke_current_dest_state;
|
state* kripke_current_dest_state;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,8 @@ namespace spot
|
||||||
if (label.empty())
|
if (label.empty())
|
||||||
label = "{}";
|
label = "{}";
|
||||||
|
|
||||||
label += ("\n" +
|
label += "\n";
|
||||||
bdd_format_accset(d, si->current_acceptance_conditions()));
|
label += t_automata_->acc().format(si->current_acceptance_conditions());
|
||||||
|
|
||||||
|
|
||||||
os_ << " " << in << " -> " << out << " [label=\"";
|
os_ << " " << in << " -> " << out << " [label=\"";
|
||||||
escape_str(os_, label);
|
escape_str(os_, label);
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace spot
|
||||||
// * scc: (attribute) a stack of strongly connected components (SCC)
|
// * scc: (attribute) a stack of strongly connected components (SCC)
|
||||||
|
|
||||||
// * arc, a stack of acceptance conditions between each of these 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,
|
// * h: a hash of all visited nodes, with their order,
|
||||||
// (it is called "Hash" in Couvreur's paper)
|
// (it is called "Hash" in Couvreur's paper)
|
||||||
|
|
@ -113,7 +113,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
scc.push(++num);
|
scc.push(++num);
|
||||||
arc.push(bddfalse);
|
arc.push(0U);
|
||||||
|
|
||||||
ta_succ_iterator_product* iter = a_->succ_iter(init);
|
ta_succ_iterator_product* iter = a_->succ_iter(init);
|
||||||
iter->first();
|
iter->first();
|
||||||
|
|
@ -194,7 +194,7 @@ namespace spot
|
||||||
// Fetch the values destination state we are interested in...
|
// Fetch the values destination state we are interested in...
|
||||||
state* dest = succ->current_state();
|
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 =
|
bool curr_is_livelock_hole_state_in_ta_component =
|
||||||
(a_->is_hole_state_in_ta_component(curr))
|
(a_->is_hole_state_in_ta_component(curr))
|
||||||
|
|
@ -284,8 +284,8 @@ namespace spot
|
||||||
scc.top().condition |= acc_cond;
|
scc.top().condition |= acc_cond;
|
||||||
|
|
||||||
scc.rem().splice(scc.rem().end(), rem);
|
scc.rem().splice(scc.rem().end(), rem);
|
||||||
bool is_accepting_sscc = (scc.top().is_accepting)
|
bool is_accepting_sscc = scc.top().is_accepting
|
||||||
|| (scc.top().condition == a_->all_acceptance_conditions());
|
|| a_->acc().accepting(scc.top().condition);
|
||||||
|
|
||||||
if (is_accepting_sscc)
|
if (is_accepting_sscc)
|
||||||
{
|
{
|
||||||
|
|
@ -294,25 +294,14 @@ namespace spot
|
||||||
<< a_->is_livelock_accepting_state(curr) << '\n';
|
<< a_->is_livelock_accepting_state(curr) << '\n';
|
||||||
trace
|
trace
|
||||||
<< "PASS 1: scc.top().condition : "
|
<< "PASS 1: scc.top().condition : "
|
||||||
<< bdd_format_accset(a_->get_dict(), scc.top().condition)
|
<< scc.top().condition << '\n';
|
||||||
<< '\n';
|
|
||||||
trace
|
trace
|
||||||
<< "PASS 1: a_->all_acceptance_conditions() : "
|
<< "PASS 1: a_->acc().all_sets() : "
|
||||||
<< (a_->all_acceptance_conditions()) << '\n';
|
<< (a_->acc().all_sets()) << '\n';
|
||||||
trace
|
trace
|
||||||
<< ("PASS 1 CYCLE and (scc.top().condition == "
|
<< ("PASS 1 CYCLE and accepting? ")
|
||||||
"a_->all_acceptance_conditions()) : ")
|
<< a_->acc().accepting(scc.top().condition)
|
||||||
<< (scc.top().condition
|
<< std::endl;
|
||||||
== 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';
|
|
||||||
|
|
||||||
clear(h, todo, ta_init_it_);
|
clear(h, todo, ta_init_it_);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,127 +64,149 @@ namespace spot
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string
|
static std::string
|
||||||
format_hash_set(const hash_set* hs, const const_ta_ptr& aut)
|
format_hash_set(const hash_set* hs, const const_ta_ptr& aut)
|
||||||
{
|
{
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
dump_hash_set(hs, aut, s);
|
dump_hash_set(hs, aut, s);
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// From the base automaton and the list of sets, build the minimal
|
// From the base automaton and the list of sets, build the minimal
|
||||||
// automaton
|
// automaton
|
||||||
static void
|
static void
|
||||||
build_result(const const_ta_ptr& a, std::list<hash_set*>& sets,
|
build_result(const const_ta_ptr& a, std::list<hash_set*>& sets,
|
||||||
tgba_digraph_ptr result_tgba, const ta_explicit_ptr& result)
|
tgba_digraph_ptr result_tgba, const ta_explicit_ptr& result)
|
||||||
{
|
{
|
||||||
// For each set, create a state in the tgbaulting automaton.
|
// For each set, create a state in the tgbaulting automaton.
|
||||||
// For a state s, state_num[s] is the number of the state in the minimal
|
// For a state s, state_num[s] is the number of the state in the minimal
|
||||||
// automaton.
|
// automaton.
|
||||||
hash_map state_num;
|
hash_map state_num;
|
||||||
std::list<hash_set*>::iterator sit;
|
std::list<hash_set*>::iterator sit;
|
||||||
unsigned num = 0;
|
unsigned num = 0;
|
||||||
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
||||||
{
|
{
|
||||||
hash_set::iterator hit;
|
hash_set::iterator hit;
|
||||||
hash_set* h = *sit;
|
hash_set* h = *sit;
|
||||||
for (hit = h->begin(); hit != h->end(); ++hit)
|
for (hit = h->begin(); hit != h->end(); ++hit)
|
||||||
state_num[*hit] = num;
|
state_num[*hit] = num;
|
||||||
result_tgba->new_state();
|
result_tgba->new_state();
|
||||||
++num;
|
++num;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each transition in the initial automaton, add the corresponding
|
// For each transition in the initial automaton, add the corresponding
|
||||||
// transition in ta.
|
// transition in ta.
|
||||||
|
|
||||||
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
for (sit = sets.begin(); sit != sets.end(); ++sit)
|
||||||
{
|
{
|
||||||
hash_set::iterator hit;
|
hash_set::iterator hit;
|
||||||
hash_set* h = *sit;
|
hash_set* h = *sit;
|
||||||
hit = h->begin();
|
hit = h->begin();
|
||||||
const state* src = *hit;
|
const state* src = *hit;
|
||||||
unsigned src_num = state_num[src];
|
unsigned src_num = state_num[src];
|
||||||
|
|
||||||
bdd tgba_condition = bddtrue;
|
bdd tgba_condition = bddtrue;
|
||||||
bool is_initial_state = a->is_initial_state(src);
|
bool is_initial_state = a->is_initial_state(src);
|
||||||
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
||||||
tgba_condition = a->get_state_condition(src);
|
tgba_condition = a->get_state_condition(src);
|
||||||
bool is_accepting_state = a->is_accepting_state(src);
|
bool is_accepting_state = a->is_accepting_state(src);
|
||||||
bool is_livelock_accepting_state =
|
bool is_livelock_accepting_state =
|
||||||
a->is_livelock_accepting_state(src);
|
a->is_livelock_accepting_state(src);
|
||||||
|
|
||||||
state_ta_explicit* new_src =
|
state_ta_explicit* new_src =
|
||||||
new state_ta_explicit(result_tgba->state_from_number(src_num),
|
new state_ta_explicit(result_tgba->state_from_number(src_num),
|
||||||
tgba_condition, is_initial_state,
|
tgba_condition, is_initial_state,
|
||||||
is_accepting_state,
|
is_accepting_state,
|
||||||
is_livelock_accepting_state);
|
is_livelock_accepting_state);
|
||||||
|
|
||||||
state_ta_explicit* ta_src = result->add_state(new_src);
|
state_ta_explicit* ta_src = result->add_state(new_src);
|
||||||
|
|
||||||
if (ta_src != new_src)
|
if (ta_src != new_src)
|
||||||
{
|
{
|
||||||
delete new_src;
|
delete new_src;
|
||||||
}
|
}
|
||||||
else if (a->get_artificial_initial_state() != 0)
|
else if (a->get_artificial_initial_state() != 0)
|
||||||
{
|
{
|
||||||
if (a->get_artificial_initial_state() == src)
|
if (a->get_artificial_initial_state() == src)
|
||||||
result->set_artificial_initial_state(new_src);
|
result->set_artificial_initial_state(new_src);
|
||||||
}
|
}
|
||||||
else if (is_initial_state)
|
else if (is_initial_state)
|
||||||
{
|
{
|
||||||
result->add_to_initial_states_set(new_src);
|
result->add_to_initial_states_set(new_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
ta_succ_iterator* succit = a->succ_iter(src);
|
ta_succ_iterator* succit = a->succ_iter(src);
|
||||||
|
|
||||||
for (succit->first(); !succit->done(); succit->next())
|
for (succit->first(); !succit->done(); succit->next())
|
||||||
{
|
{
|
||||||
const state* dst = succit->current_state();
|
const state* dst = succit->current_state();
|
||||||
hash_map::const_iterator i = state_num.find(dst);
|
hash_map::const_iterator i = state_num.find(dst);
|
||||||
|
|
||||||
if (i == state_num.end()) // Ignore useless destinations.
|
if (i == state_num.end()) // Ignore useless destinations.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bdd tgba_condition = bddtrue;
|
bdd tgba_condition = bddtrue;
|
||||||
is_initial_state = a->is_initial_state(dst);
|
is_initial_state = a->is_initial_state(dst);
|
||||||
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
if ((a->get_artificial_initial_state() == 0) && is_initial_state)
|
||||||
tgba_condition = a->get_state_condition(dst);
|
tgba_condition = a->get_state_condition(dst);
|
||||||
bool is_accepting_state = a->is_accepting_state(dst);
|
bool is_accepting_state = a->is_accepting_state(dst);
|
||||||
bool is_livelock_accepting_state =
|
bool is_livelock_accepting_state =
|
||||||
a->is_livelock_accepting_state(dst);
|
a->is_livelock_accepting_state(dst);
|
||||||
|
|
||||||
state_ta_explicit* new_dst =
|
state_ta_explicit* new_dst =
|
||||||
new state_ta_explicit(result_tgba->state_from_number(i->second),
|
new state_ta_explicit
|
||||||
tgba_condition, is_initial_state,
|
(result_tgba->state_from_number(i->second),
|
||||||
is_accepting_state,
|
tgba_condition, is_initial_state,
|
||||||
is_livelock_accepting_state);
|
is_accepting_state,
|
||||||
|
is_livelock_accepting_state);
|
||||||
|
|
||||||
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
state_ta_explicit* ta_dst = result->add_state(new_dst);
|
||||||
|
|
||||||
if (ta_dst != new_dst)
|
if (ta_dst != new_dst)
|
||||||
{
|
{
|
||||||
delete new_dst;
|
delete new_dst;
|
||||||
}
|
}
|
||||||
else if (a->get_artificial_initial_state() != 0)
|
else if (a->get_artificial_initial_state() != 0)
|
||||||
{
|
{
|
||||||
if (a->get_artificial_initial_state() == dst)
|
if (a->get_artificial_initial_state() == dst)
|
||||||
result->set_artificial_initial_state(new_dst);
|
result->set_artificial_initial_state(new_dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (is_initial_state)
|
else if (is_initial_state)
|
||||||
result->add_to_initial_states_set(new_dst);
|
result->add_to_initial_states_set(new_dst);
|
||||||
|
|
||||||
result->create_transition(ta_src, succit->current_condition(),
|
result->create_transition
|
||||||
succit->current_acceptance_conditions(),
|
(ta_src, succit->current_condition(),
|
||||||
ta_dst);
|
succit->current_acceptance_conditions(),
|
||||||
}
|
ta_dst);
|
||||||
delete succit;
|
}
|
||||||
}
|
delete succit;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static partition_t
|
static partition_t
|
||||||
build_partition(const const_ta_ptr& ta_)
|
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 cur_run;
|
||||||
partition_t next_run;
|
partition_t next_run;
|
||||||
|
|
||||||
|
|
@ -237,7 +259,7 @@ namespace spot
|
||||||
// Use bdd variables to number sets. set_num is the first variable
|
// Use bdd variables to number sets. set_num is the first variable
|
||||||
// available.
|
// available.
|
||||||
unsigned set_num =
|
unsigned set_num =
|
||||||
ta_->get_dict()->register_anonymous_variables(size, ta_);
|
ta_->get_dict()->register_anonymous_variables(size, &m2b);
|
||||||
|
|
||||||
std::set<int> free_var;
|
std::set<int> free_var;
|
||||||
for (unsigned i = set_num; i < set_num + size; ++i)
|
for (unsigned i = set_num; i < set_num + size; ++i)
|
||||||
|
|
@ -335,6 +357,7 @@ namespace spot
|
||||||
delete S;
|
delete S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// A bdd_states_map is a list of formulae (in a BDD form)
|
// A bdd_states_map is a list of formulae (in a BDD form)
|
||||||
// associated with a destination set of states.
|
// associated with a destination set of states.
|
||||||
typedef std::map<bdd, hash_set*, bdd_less_than> bdd_states_map;
|
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);
|
hash_map::const_iterator i = state_set_map.find(dst);
|
||||||
|
|
||||||
assert(i != state_set_map.end());
|
assert(i != state_set_map.end());
|
||||||
bdd current_acceptance_conditions =
|
auto curacc =
|
||||||
si->current_acceptance_conditions();
|
mark_to_bdd(si->current_acceptance_conditions());
|
||||||
if (current_acceptance_conditions == bddfalse)
|
f |= (bdd_ithvar(i->second)
|
||||||
current_acceptance_conditions
|
& si->current_condition() & curacc);
|
||||||
= bdd_false_acceptance_condition;
|
|
||||||
f |= (bdd_ithvar(i->second) & si->current_condition()
|
|
||||||
& current_acceptance_conditions);
|
|
||||||
trace
|
trace
|
||||||
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
<< "+f: " << bdd_format_accset(ta_->get_dict(), f)
|
||||||
<< "\n -bdd_ithvar(i->second): "
|
<< "\n -bdd_ithvar(i->second): "
|
||||||
|
|
@ -388,9 +408,8 @@ namespace spot
|
||||||
<< bdd_format_accset(ta_->get_dict(),
|
<< bdd_format_accset(ta_->get_dict(),
|
||||||
si->current_condition())
|
si->current_condition())
|
||||||
<< "\n -current_acceptance_conditions: "
|
<< "\n -current_acceptance_conditions: "
|
||||||
<< bdd_format_accset(ta_->get_dict(),
|
<< si->current_acceptance_conditions()
|
||||||
current_acceptance_conditions)
|
<< std::endl;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
delete si;
|
delete si;
|
||||||
|
|
||||||
|
|
@ -480,6 +499,7 @@ namespace spot
|
||||||
trace << std::endl;
|
trace << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ta_->get_dict()->unregister_all_my_variables(&m2b);
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -489,7 +509,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
auto tgba = make_tgba_digraph(ta_->get_dict());
|
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_);
|
partition_t partition = build_partition(ta_);
|
||||||
|
|
||||||
|
|
@ -509,7 +529,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
auto tgba = make_tgba_digraph(tgta_->get_dict());
|
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();
|
auto ta = tgta_->get_ta();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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,
|
bool single_pass_emptiness_check,
|
||||||
state_ta_explicit*
|
state_ta_explicit*
|
||||||
artificial_livelock_acc_state)
|
artificial_livelock_acc_state)
|
||||||
|
|
@ -158,7 +158,7 @@ namespace spot
|
||||||
scc_stack_ta sscc;
|
scc_stack_ta sscc;
|
||||||
|
|
||||||
// * arc, a stack of acceptance conditions between each of these 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,
|
// * h: a hash of all visited nodes, with their order,
|
||||||
// (it is called "Hash" in Couvreur's paper)
|
// (it is called "Hash" in Couvreur's paper)
|
||||||
|
|
@ -180,7 +180,7 @@ namespace spot
|
||||||
// * init: the set of the depth-first search initial states
|
// * init: the set of the depth-first search initial states
|
||||||
std::stack<state*> init_set;
|
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);
|
init_set.push(s);
|
||||||
|
|
||||||
while (!init_set.empty())
|
while (!init_set.empty())
|
||||||
|
|
@ -199,10 +199,10 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
sscc.push(++num);
|
sscc.push(++num);
|
||||||
arc.push(bddfalse);
|
arc.push(0U);
|
||||||
sscc.top().is_accepting
|
sscc.top().is_accepting
|
||||||
= testing_automata->is_accepting_state(init);
|
= testing_aut->is_accepting_state(init);
|
||||||
tgba_succ_iterator* iter = testing_automata->succ_iter(init);
|
tgba_succ_iterator* iter = testing_aut->succ_iter(init);
|
||||||
iter->first();
|
iter->first();
|
||||||
todo.emplace(init, iter);
|
todo.emplace(init, iter);
|
||||||
}
|
}
|
||||||
|
|
@ -243,10 +243,9 @@ namespace spot
|
||||||
// removing states
|
// removing states
|
||||||
std::list<state*>::iterator i;
|
std::list<state*>::iterator i;
|
||||||
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
bool is_livelock_accepting_sscc = (sscc.rem().size() > 1)
|
||||||
&& ((sscc.top().is_accepting)
|
&& ((sscc.top().is_accepting) ||
|
||||||
|| (sscc.top().condition ==
|
(testing_aut->acc().
|
||||||
testing_automata->all_acceptance_conditions()));
|
accepting(sscc.top().condition)));
|
||||||
|
|
||||||
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
trace << "*** sscc.size() = ***" << sscc.size() << '\n';
|
||||||
for (auto j: sscc.rem())
|
for (auto j: sscc.rem())
|
||||||
{
|
{
|
||||||
|
|
@ -257,7 +256,7 @@ namespace spot
|
||||||
// if it is an accepting sscc add the state to
|
// if it is an accepting sscc add the state to
|
||||||
// G (=the livelock-accepting states set)
|
// G (=the livelock-accepting states set)
|
||||||
trace << "*** sscc.size() > 1: states: ***"
|
trace << "*** sscc.size() > 1: states: ***"
|
||||||
<< testing_automata->format_state(j)
|
<< testing_aut->format_state(j)
|
||||||
<< '\n';
|
<< '\n';
|
||||||
state_ta_explicit* livelock_accepting_state =
|
state_ta_explicit* livelock_accepting_state =
|
||||||
down_cast<state_ta_explicit*>(j);
|
down_cast<state_ta_explicit*>(j);
|
||||||
|
|
@ -283,7 +282,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
// automata reduction
|
// automata reduction
|
||||||
testing_automata->delete_stuttering_and_hole_successors(curr);
|
testing_aut->delete_stuttering_and_hole_successors(curr);
|
||||||
|
|
||||||
delete succ;
|
delete succ;
|
||||||
// Do not delete CURR: it is a key in H.
|
// 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...
|
// Fetch the values destination state we are interested in...
|
||||||
state* dest = succ->current_state();
|
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
|
// ... and point the iterator to the next successor, for
|
||||||
// the next iteration.
|
// the next iteration.
|
||||||
succ->next();
|
succ->next();
|
||||||
|
|
@ -301,8 +300,8 @@ namespace spot
|
||||||
|
|
||||||
// Are we going to a new state through a stuttering transition?
|
// Are we going to a new state through a stuttering transition?
|
||||||
bool is_stuttering_transition =
|
bool is_stuttering_transition =
|
||||||
testing_automata->get_state_condition(curr)
|
testing_aut->get_state_condition(curr)
|
||||||
== testing_automata->get_state_condition(dest);
|
== testing_aut->get_state_condition(dest);
|
||||||
auto id = h.find(dest);
|
auto id = h.find(dest);
|
||||||
|
|
||||||
// Is this a new state?
|
// Is this a new state?
|
||||||
|
|
@ -321,9 +320,9 @@ namespace spot
|
||||||
sscc.push(num);
|
sscc.push(num);
|
||||||
arc.push(acc_cond);
|
arc.push(acc_cond);
|
||||||
sscc.top().is_accepting =
|
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();
|
iter->first();
|
||||||
todo.emplace(dest, iter);
|
todo.emplace(dest, iter);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -342,9 +341,8 @@ namespace spot
|
||||||
down_cast<state_ta_explicit*> (curr);
|
down_cast<state_ta_explicit*> (curr);
|
||||||
assert(self_loop_state);
|
assert(self_loop_state);
|
||||||
|
|
||||||
if (testing_automata->is_accepting_state(self_loop_state)
|
if (testing_aut->is_accepting_state(self_loop_state)
|
||||||
|| (acc_cond
|
|| (testing_aut->acc().accepting(acc_cond)))
|
||||||
== testing_automata->all_acceptance_conditions()))
|
|
||||||
{
|
{
|
||||||
self_loop_state->set_livelock_accepting_state(true);
|
self_loop_state->set_livelock_accepting_state(true);
|
||||||
if (single_pass_emptiness_check)
|
if (single_pass_emptiness_check)
|
||||||
|
|
@ -404,7 +402,7 @@ namespace spot
|
||||||
|
|
||||||
if ((artificial_livelock_acc_state != 0)
|
if ((artificial_livelock_acc_state != 0)
|
||||||
|| single_pass_emptiness_check)
|
|| single_pass_emptiness_check)
|
||||||
transform_to_single_pass_automaton(testing_automata,
|
transform_to_single_pass_automaton(testing_aut,
|
||||||
artificial_livelock_acc_state);
|
artificial_livelock_acc_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,7 +427,7 @@ namespace spot
|
||||||
tgba_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
tgba_succ_iterator* it = tgba_->succ_iter(tgba_init_state);
|
||||||
it->first();
|
it->first();
|
||||||
if (!it->done())
|
if (!it->done())
|
||||||
is_acc = it->current_acceptance_conditions() != bddfalse;
|
is_acc = it->current_acceptance_conditions() != 0U;
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -462,7 +460,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
const state* tgba_state = tgba_succ_it->current_state();
|
const state* tgba_state = tgba_succ_it->current_state();
|
||||||
bdd tgba_condition = tgba_succ_it->current_condition();
|
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();
|
tgba_succ_it->current_acceptance_conditions();
|
||||||
bdd satone_tgba_condition;
|
bdd satone_tgba_condition;
|
||||||
while ((satone_tgba_condition =
|
while ((satone_tgba_condition =
|
||||||
|
|
@ -481,7 +479,7 @@ namespace spot
|
||||||
tgba_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
tgba_succ_iterator* it = tgba_->succ_iter(tgba_state);
|
||||||
it->first();
|
it->first();
|
||||||
if (!it->done())
|
if (!it->done())
|
||||||
is_acc = it->current_acceptance_conditions() != bddfalse;
|
is_acc = it->current_acceptance_conditions() != 0U;
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -554,12 +552,12 @@ namespace spot
|
||||||
state_ta_explicit* artificial_init_state =
|
state_ta_explicit* artificial_init_state =
|
||||||
new state_ta_explicit(tgba_init_state->clone(), bddfalse, true);
|
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);
|
artificial_init_state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ta = make_ta_explicit(tgba_, tgba_->all_acceptance_conditions());
|
ta = make_ta_explicit(tgba_, tgba_->acc().num_sets());
|
||||||
}
|
}
|
||||||
tgba_init_state->destroy();
|
tgba_init_state->destroy();
|
||||||
|
|
||||||
|
|
@ -586,10 +584,7 @@ namespace spot
|
||||||
|
|
||||||
for (it_trans = trans->begin(); it_trans != trans->end();
|
for (it_trans = trans->begin(); it_trans != trans->end();
|
||||||
++it_trans)
|
++it_trans)
|
||||||
{
|
(*it_trans)->acceptance_conditions = ta->acc().all_sets();
|
||||||
(*it_trans)->acceptance_conditions
|
|
||||||
= ta->all_acceptance_conditions();
|
|
||||||
}
|
|
||||||
|
|
||||||
state->set_accepting_state(false);
|
state->set_accepting_state(false);
|
||||||
}
|
}
|
||||||
|
|
@ -606,7 +601,7 @@ namespace spot
|
||||||
bddfalse, true);
|
bddfalse, true);
|
||||||
tgba_init_state->destroy();
|
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);
|
artificial_init_state);
|
||||||
|
|
||||||
// build a Generalized TA automaton involving a single_pass_emptiness_check
|
// build a Generalized TA automaton involving a single_pass_emptiness_check
|
||||||
|
|
@ -644,13 +639,13 @@ namespace spot
|
||||||
if (trans_empty || state->is_accepting_state())
|
if (trans_empty || state->is_accepting_state())
|
||||||
{
|
{
|
||||||
ta->create_transition(state, bdd_stutering_transition,
|
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()))
|
if (state->compare(ta->get_artificial_initial_state()))
|
||||||
ta->create_transition(state, bdd_stutering_transition,
|
ta->create_transition(state, bdd_stutering_transition,
|
||||||
bddfalse, state);
|
0U, state);
|
||||||
|
|
||||||
state->set_livelock_accepting_state(false);
|
state->set_livelock_accepting_state(false);
|
||||||
state->set_accepting_state(false);
|
state->set_accepting_state(false);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
||||||
tgbadir = $(pkgincludedir)/tgba
|
tgbadir = $(pkgincludedir)/tgba
|
||||||
|
|
||||||
tgba_HEADERS = \
|
tgba_HEADERS = \
|
||||||
|
acc.hh \
|
||||||
bdddict.hh \
|
bdddict.hh \
|
||||||
bddprint.hh \
|
bddprint.hh \
|
||||||
formula2bdd.hh \
|
formula2bdd.hh \
|
||||||
|
|
@ -33,11 +34,9 @@ tgba_HEADERS = \
|
||||||
taatgba.hh \
|
taatgba.hh \
|
||||||
tgba.hh \
|
tgba.hh \
|
||||||
tgbagraph.hh \
|
tgbagraph.hh \
|
||||||
tgbakvcomplement.hh \
|
|
||||||
tgbamask.hh \
|
tgbamask.hh \
|
||||||
tgbaproxy.hh \
|
tgbaproxy.hh \
|
||||||
tgbaproduct.hh \
|
tgbaproduct.hh \
|
||||||
tgbasgba.hh \
|
|
||||||
tgbasafracomplement.hh
|
tgbasafracomplement.hh
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libtgba.la
|
noinst_LTLIBRARIES = libtgba.la
|
||||||
|
|
@ -48,9 +47,7 @@ libtgba_la_SOURCES = \
|
||||||
taatgba.cc \
|
taatgba.cc \
|
||||||
tgba.cc \
|
tgba.cc \
|
||||||
tgbagraph.cc \
|
tgbagraph.cc \
|
||||||
tgbakvcomplement.cc \
|
|
||||||
tgbaproduct.cc \
|
tgbaproduct.cc \
|
||||||
tgbamask.cc \
|
tgbamask.cc \
|
||||||
tgbaproxy.cc \
|
tgbaproxy.cc \
|
||||||
tgbasafracomplement.cc \
|
tgbasafracomplement.cc
|
||||||
tgbasgba.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;
|
class tgba_product;
|
||||||
typedef std::shared_ptr<const tgba_product> const_tgba_product_ptr;
|
typedef std::shared_ptr<const tgba_product> const_tgba_product_ptr;
|
||||||
typedef std::shared_ptr<tgba_product> 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
|
#endif // SPOT_TGBA_FWD_HH
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,7 @@ namespace spot
|
||||||
`--------*/
|
`--------*/
|
||||||
|
|
||||||
taa_tgba::taa_tgba(const bdd_dict_ptr& dict)
|
taa_tgba::taa_tgba(const bdd_dict_ptr& dict)
|
||||||
: dict_(dict),
|
: tgba(dict),
|
||||||
all_acceptance_conditions_(bddfalse),
|
|
||||||
all_acceptance_conditions_computed_(false),
|
|
||||||
neg_acceptance_conditions_(bddtrue),
|
|
||||||
init_(0), state_set_vec_()
|
init_(0), state_set_vec_()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -47,13 +44,13 @@ namespace spot
|
||||||
ss_vec::iterator j;
|
ss_vec::iterator j;
|
||||||
for (j = state_set_vec_.begin(); j != state_set_vec_.end(); ++j)
|
for (j = state_set_vec_.begin(); j != state_set_vec_.end(); ++j)
|
||||||
delete *j;
|
delete *j;
|
||||||
dict_->unregister_all_my_variables(this);
|
get_dict()->unregister_all_my_variables(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
taa_tgba::add_condition(transition* t, const ltl::formula* f)
|
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();
|
f->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,31 +66,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
const spot::set_state* s = down_cast<const spot::set_state*>(state);
|
const spot::set_state* s = down_cast<const spot::set_state*>(state);
|
||||||
assert(s);
|
assert(s);
|
||||||
return new taa_succ_iterator(s->get_state(), all_acceptance_conditions());
|
return new taa_succ_iterator(s->get_state(), acc_);
|
||||||
}
|
|
||||||
|
|
||||||
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_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
bdd
|
||||||
|
|
@ -172,14 +145,14 @@ namespace spot
|
||||||
`--------------*/
|
`--------------*/
|
||||||
|
|
||||||
taa_succ_iterator::taa_succ_iterator(const taa_tgba::state_set* s,
|
taa_succ_iterator::taa_succ_iterator(const taa_tgba::state_set* s,
|
||||||
bdd all_acc)
|
const acc_cond& acc)
|
||||||
: all_acceptance_conditions_(all_acc), seen_()
|
: seen_(), acc_(acc)
|
||||||
{
|
{
|
||||||
if (s->empty())
|
if (s->empty())
|
||||||
{
|
{
|
||||||
taa_tgba::transition* t = new taa_tgba::transition;
|
taa_tgba::transition* t = new taa_tgba::transition;
|
||||||
t->condition = bddtrue;
|
t->condition = bddtrue;
|
||||||
t->acceptance_conditions = bddfalse;
|
t->acceptance_conditions = 0U;
|
||||||
t->dst = new taa_tgba::state_set;
|
t->dst = new taa_tgba::state_set;
|
||||||
succ_.push_back(t);
|
succ_.push_back(t);
|
||||||
return;
|
return;
|
||||||
|
|
@ -202,7 +175,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
taa_tgba::transition* t = new taa_tgba::transition;
|
taa_tgba::transition* t = new taa_tgba::transition;
|
||||||
t->condition = bddtrue;
|
t->condition = bddtrue;
|
||||||
t->acceptance_conditions = bddfalse;
|
t->acceptance_conditions = 0U;
|
||||||
taa_tgba::state_set* ss = new taa_tgba::state_set;
|
taa_tgba::state_set* ss = new taa_tgba::state_set;
|
||||||
|
|
||||||
unsigned p;
|
unsigned p;
|
||||||
|
|
@ -330,12 +303,11 @@ namespace spot
|
||||||
return (*i_)->condition;
|
return (*i_)->condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
taa_succ_iterator::current_acceptance_conditions() const
|
taa_succ_iterator::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
assert(!done());
|
assert(!done());
|
||||||
return all_acceptance_conditions_ -
|
return acc_.comp((*i_)->acceptance_conditions);
|
||||||
((*i_)->acceptance_conditions & all_acceptance_conditions_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------.
|
/*----------------.
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "ltlast/formula.hh"
|
#include "ltlast/formula.hh"
|
||||||
#include "bdddict.hh"
|
#include "bdddict.hh"
|
||||||
#include "tgba.hh"
|
#include "tgba.hh"
|
||||||
|
#include "ltlvisit/tostring.hh"
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +46,7 @@ namespace spot
|
||||||
struct transition
|
struct transition
|
||||||
{
|
{
|
||||||
bdd condition;
|
bdd condition;
|
||||||
bdd acceptance_conditions;
|
acc_cond::mark_t acceptance_conditions;
|
||||||
const state_set* dst;
|
const state_set* dst;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -55,23 +56,19 @@ namespace spot
|
||||||
virtual ~taa_tgba();
|
virtual ~taa_tgba();
|
||||||
virtual spot::state* get_init_state() const;
|
virtual spot::state* get_init_state() const;
|
||||||
virtual tgba_succ_iterator* succ_iter(const spot::state* 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 std::string format_state(const spot::state* state) const = 0;
|
||||||
virtual bdd all_acceptance_conditions() const;
|
|
||||||
virtual bdd neg_acceptance_conditions() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bdd compute_support_conditions(const spot::state* state) const;
|
virtual bdd compute_support_conditions(const spot::state* state) const;
|
||||||
|
|
||||||
typedef std::vector<taa_tgba::state_set*> ss_vec;
|
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_;
|
taa_tgba::state_set* init_;
|
||||||
ss_vec state_set_vec_;
|
ss_vec state_set_vec_;
|
||||||
|
|
||||||
|
std::map<const ltl::formula*, acc_cond::mark_t,
|
||||||
|
ltl::formula_ptr_less_than> acc_map_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Disallow copy.
|
// Disallow copy.
|
||||||
taa_tgba(const taa_tgba& other) SPOT_DELETED;
|
taa_tgba(const taa_tgba& other) SPOT_DELETED;
|
||||||
|
|
@ -106,7 +103,7 @@ namespace spot
|
||||||
class SPOT_API taa_succ_iterator : public tgba_succ_iterator
|
class SPOT_API taa_succ_iterator : public tgba_succ_iterator
|
||||||
{
|
{
|
||||||
public:
|
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 ~taa_succ_iterator();
|
||||||
|
|
||||||
virtual bool first();
|
virtual bool first();
|
||||||
|
|
@ -115,7 +112,7 @@ namespace spot
|
||||||
|
|
||||||
virtual set_state* current_state() const;
|
virtual set_state* current_state() const;
|
||||||
virtual bdd current_condition() const;
|
virtual bdd current_condition() const;
|
||||||
virtual bdd current_acceptance_conditions() const;
|
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Those typedefs are used to generate all possible successors in
|
/// 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*>::const_iterator i_;
|
||||||
std::vector<taa_tgba::transition*> succ_;
|
std::vector<taa_tgba::transition*> succ_;
|
||||||
bdd all_acceptance_conditions_;
|
|
||||||
seen_map seen_;
|
seen_map seen_;
|
||||||
|
const acc_cond& acc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A taa_tgba instance with states labeled by a given type.
|
/// A taa_tgba instance with states labeled by a given type.
|
||||||
|
|
@ -153,6 +150,13 @@ namespace spot
|
||||||
public:
|
public:
|
||||||
taa_tgba_labelled(const bdd_dict_ptr& dict) : taa_tgba(dict) {};
|
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)
|
void set_init_state(const label& s)
|
||||||
{
|
{
|
||||||
std::vector<label> v(1);
|
std::vector<label> v(1);
|
||||||
|
|
@ -173,10 +177,11 @@ namespace spot
|
||||||
transition* t = new transition;
|
transition* t = new transition;
|
||||||
t->dst = dst;
|
t->dst = dst;
|
||||||
t->condition = bddtrue;
|
t->condition = bddtrue;
|
||||||
t->acceptance_conditions = bddfalse;
|
t->acceptance_conditions = 0U;
|
||||||
src->push_back(t);
|
src->push_back(t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
transition*
|
transition*
|
||||||
create_transition(const label& s, const label& d)
|
create_transition(const label& s, const label& d)
|
||||||
{
|
{
|
||||||
|
|
@ -187,29 +192,12 @@ namespace spot
|
||||||
|
|
||||||
void add_acceptance_condition(transition* t, const ltl::formula* f)
|
void add_acceptance_condition(transition* t, const ltl::formula* f)
|
||||||
{
|
{
|
||||||
if (dict_->acc_map.find(f) == dict_->acc_map.end())
|
auto p = acc_map_.emplace(f, 0);
|
||||||
{
|
if (p.second)
|
||||||
int v = dict_->register_acceptance_variable(f, this);
|
p.first->second = acc_.marks({acc_.add_set()});
|
||||||
bdd neg = bdd_nithvar(v);
|
else
|
||||||
neg_acceptance_conditions_ &= neg;
|
f->destroy();
|
||||||
|
t->acceptance_conditions |= p.first->second;
|
||||||
// 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());
|
|
||||||
f->destroy();
|
|
||||||
bdd v = bdd_ithvar(i->second);
|
|
||||||
t->acceptance_conditions |= v & bdd_exist(neg_acceptance_conditions_, v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Format the state as a string for printing.
|
/// \brief Format the state as a string for printing.
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
tgba::tgba()
|
tgba::tgba(const bdd_dict_ptr& d)
|
||||||
: iter_cache_(nullptr),
|
: iter_cache_(nullptr),
|
||||||
last_support_conditions_input_(0),
|
acc_(d),
|
||||||
num_acc_(-1)
|
last_support_conditions_input_(0)
|
||||||
{
|
{
|
||||||
props = 0U;
|
props = 0U;
|
||||||
}
|
}
|
||||||
|
|
@ -69,23 +69,6 @@ namespace spot
|
||||||
return "";
|
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
|
bool
|
||||||
tgba::is_empty() const
|
tgba::is_empty() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
#ifndef SPOT_TGBA_TGBA_HH
|
#ifndef SPOT_TGBA_TGBA_HH
|
||||||
# define SPOT_TGBA_TGBA_HH
|
# define SPOT_TGBA_TGBA_HH
|
||||||
|
|
||||||
#include "bdddict.hh"
|
|
||||||
#include "fwd.hh"
|
#include "fwd.hh"
|
||||||
|
#include "acc.hh"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "misc/casts.hh"
|
#include "misc/casts.hh"
|
||||||
|
|
@ -387,7 +387,7 @@ namespace spot
|
||||||
virtual bdd current_condition() const = 0;
|
virtual bdd current_condition() const = 0;
|
||||||
/// \brief Get the acceptance conditions on the transition leading
|
/// \brief Get the acceptance conditions on the transition leading
|
||||||
/// to this successor.
|
/// 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>
|
class SPOT_API tgba: public std::enable_shared_from_this<tgba>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
tgba();
|
tgba(const bdd_dict_ptr& d);
|
||||||
// Any iterator returned via release_iter.
|
// Any iterator returned via release_iter.
|
||||||
mutable tgba_succ_iterator* iter_cache_;
|
mutable tgba_succ_iterator* iter_cache_;
|
||||||
|
|
||||||
|
|
@ -572,7 +572,10 @@ namespace spot
|
||||||
/// formulae, and vice versa. This is useful when dealing with
|
/// formulae, and vice versa. This is useful when dealing with
|
||||||
/// several automata (which may use the same BDD variable for
|
/// several automata (which may use the same BDD variable for
|
||||||
/// different formula), or simply when printing.
|
/// 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.
|
/// \brief Format the state as a string for printing.
|
||||||
///
|
///
|
||||||
|
|
@ -615,40 +618,27 @@ namespace spot
|
||||||
virtual state* project_state(const state* s,
|
virtual state* project_state(const state* s,
|
||||||
const const_tgba_ptr& t) const;
|
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.
|
const acc_cond& acc() const
|
||||||
virtual unsigned int number_of_acceptance_conditions() const;
|
{
|
||||||
|
return acc_;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Return the conjuction of all negated acceptance
|
acc_cond& acc()
|
||||||
/// variables.
|
{
|
||||||
///
|
return acc_;
|
||||||
/// 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;
|
|
||||||
|
|
||||||
virtual bool is_empty() const;
|
virtual bool is_empty() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
acc_cond acc_;
|
||||||
|
|
||||||
/// Do the actual computation of tgba::support_conditions().
|
/// Do the actual computation of tgba::support_conditions().
|
||||||
virtual bdd compute_support_conditions(const state* state) const = 0;
|
virtual bdd compute_support_conditions(const state* state) const = 0;
|
||||||
mutable const state* last_support_conditions_input_;
|
mutable const state* last_support_conditions_input_;
|
||||||
private:
|
private:
|
||||||
mutable bdd last_support_conditions_output_;
|
mutable bdd last_support_conditions_output_;
|
||||||
mutable int num_acc_;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,41 +23,6 @@
|
||||||
namespace spot
|
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()
|
void tgba_digraph::merge_transitions()
|
||||||
{
|
{
|
||||||
for (auto& s: g_.states())
|
for (auto& s: g_.states())
|
||||||
|
|
@ -65,7 +30,7 @@ namespace spot
|
||||||
// Map a pair (dest state, acc) to the first transition seen
|
// Map a pair (dest state, acc) to the first transition seen
|
||||||
// with such characteristic.
|
// 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;
|
std::unordered_map<key_t, graph_t::transition, pair_hash> trmap;
|
||||||
|
|
||||||
auto t = g_.out_iteraser(s);
|
auto t = g_.out_iteraser(s);
|
||||||
|
|
@ -78,7 +43,7 @@ namespace spot
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_t k(t->dst, t->acc.id());
|
key_t k(t->dst, t->acc);
|
||||||
auto p = trmap.emplace(k, t.trans());
|
auto p = trmap.emplace(k, t.trans());
|
||||||
if (!p.second)
|
if (!p.second)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,14 @@ namespace spot
|
||||||
struct SPOT_API tgba_graph_trans_data
|
struct SPOT_API tgba_graph_trans_data
|
||||||
{
|
{
|
||||||
bdd cond;
|
bdd cond;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
|
|
||||||
explicit tgba_graph_trans_data()
|
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)
|
: cond(cond), acc(acc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +141,7 @@ namespace spot
|
||||||
return g_->trans_data(p_).cond;
|
return g_->trans_data(p_).cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bdd current_acceptance_conditions() const
|
virtual acc_cond::mark_t current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
assert(!done());
|
assert(!done());
|
||||||
return g_->trans_data(p_).acc;
|
return g_->trans_data(p_).acc;
|
||||||
|
|
@ -161,23 +161,18 @@ namespace spot
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
graph_t g_;
|
graph_t g_;
|
||||||
bdd_dict_ptr dict_;
|
|
||||||
bdd all_acceptance_conditions_;
|
|
||||||
bdd neg_acceptance_conditions_;
|
|
||||||
mutable unsigned init_number_;
|
mutable unsigned init_number_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tgba_digraph(const bdd_dict_ptr& dict)
|
tgba_digraph(const bdd_dict_ptr& dict)
|
||||||
: dict_(dict),
|
: tgba(dict),
|
||||||
all_acceptance_conditions_(bddfalse),
|
|
||||||
neg_acceptance_conditions_(bddtrue),
|
|
||||||
init_number_(0)
|
init_number_(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~tgba_digraph()
|
virtual ~tgba_digraph()
|
||||||
{
|
{
|
||||||
dict_->unregister_all_my_variables(this);
|
get_dict()->unregister_all_my_variables(this);
|
||||||
// Prevent this state from being destroyed by ~tgba(),
|
// Prevent this state from being destroyed by ~tgba(),
|
||||||
// as the state will be destroyed when g_ is destroyed.
|
// as the state will be destroyed when g_ is destroyed.
|
||||||
last_support_conditions_input_ = 0;
|
last_support_conditions_input_ = 0;
|
||||||
|
|
@ -212,11 +207,6 @@ namespace spot
|
||||||
return g_;
|
return g_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bdd_dict_ptr get_dict() const
|
|
||||||
{
|
|
||||||
return this->dict_;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned num_states() const
|
unsigned num_states() const
|
||||||
{
|
{
|
||||||
return g_.num_states();
|
return g_.num_states();
|
||||||
|
|
@ -314,8 +304,22 @@ namespace spot
|
||||||
return g_.trans_data(t);
|
return g_.trans_data(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_acceptance_conditions(bdd all);
|
void set_acceptance_conditions(unsigned num)
|
||||||
bdd set_single_acceptance_set();
|
{
|
||||||
|
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()
|
unsigned new_state()
|
||||||
{
|
{
|
||||||
|
|
@ -328,7 +332,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned new_transition(unsigned src, unsigned dst,
|
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);
|
return g_.new_transition(src, dst, cond, acc);
|
||||||
}
|
}
|
||||||
|
|
@ -337,7 +341,7 @@ namespace spot
|
||||||
bdd cond, bool acc = true)
|
bdd cond, bool acc = true)
|
||||||
{
|
{
|
||||||
if (acc)
|
if (acc)
|
||||||
return g_.new_transition(src, dst, cond, all_acceptance_conditions_);
|
return g_.new_transition(src, dst, cond, acc_.all_sets());
|
||||||
else
|
else
|
||||||
return g_.new_transition(src, dst, cond);
|
return g_.new_transition(src, dst, cond);
|
||||||
}
|
}
|
||||||
|
|
@ -364,22 +368,13 @@ namespace spot
|
||||||
/// \brief Copy the acceptance conditions of another tgba.
|
/// \brief Copy the acceptance conditions of another tgba.
|
||||||
void copy_acceptance_conditions_of(const const_tgba_ptr& a)
|
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)
|
void copy_ap_of(const const_tgba_ptr& a)
|
||||||
{
|
{
|
||||||
dict_->register_all_propositions_of(a, this);
|
get_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_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bdd compute_support_conditions(const state* s) const
|
virtual bdd compute_support_conditions(const state* s) const
|
||||||
|
|
@ -400,7 +395,7 @@ namespace spot
|
||||||
for (auto& t: g_.out(s))
|
for (auto& t: g_.out(s))
|
||||||
// Stop at the first transition, since the remaining should be
|
// Stop at the first transition, since the remaining should be
|
||||||
// labeled identically.
|
// labeled identically.
|
||||||
return t.acc == all_acceptance_conditions_;
|
return acc_.accepting(t.acc);
|
||||||
return false;
|
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;
|
const state* dest;
|
||||||
bdd cond;
|
bdd cond;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
};
|
};
|
||||||
typedef std::vector<transition> transitions;
|
typedef std::vector<transition> transitions;
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ namespace spot
|
||||||
return it_->cond;
|
return it_->cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd current_acceptance_conditions() const
|
acc_cond::mark_t current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
return it_->acc;
|
return it_->acc;
|
||||||
}
|
}
|
||||||
|
|
@ -128,19 +128,19 @@ namespace spot
|
||||||
for (auto it: original_->succ(local_state))
|
for (auto it: original_->succ(local_state))
|
||||||
{
|
{
|
||||||
const spot::state* s = it->current_state();
|
const spot::state* s = it->current_state();
|
||||||
bdd acc = it->current_acceptance_conditions();
|
auto acc = it->current_acceptance_conditions();
|
||||||
if (!wanted(s, acc))
|
if (!wanted(s, acc))
|
||||||
{
|
{
|
||||||
s->destroy();
|
s->destroy();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res->trans_.emplace_back(transition {s, it->current_condition(),
|
res->trans_.emplace_back
|
||||||
acc});
|
(transition {s, it->current_condition(), acc});
|
||||||
}
|
}
|
||||||
return res;
|
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:
|
protected:
|
||||||
const state* init_;
|
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);
|
state_set::const_iterator i = mask_.find(s);
|
||||||
return i != mask_.end();
|
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);
|
state_set::const_iterator i = mask_.find(s);
|
||||||
return i == mask_.end();
|
return i == mask_.end();
|
||||||
|
|
@ -186,19 +186,19 @@ namespace spot
|
||||||
|
|
||||||
class tgba_mask_acc_ignore: public tgba_mask
|
class tgba_mask_acc_ignore: public tgba_mask
|
||||||
{
|
{
|
||||||
const bdd& mask_;
|
unsigned mask_;
|
||||||
public:
|
public:
|
||||||
tgba_mask_acc_ignore(const const_tgba_ptr& masked,
|
tgba_mask_acc_ignore(const const_tgba_ptr& masked,
|
||||||
const bdd& mask,
|
unsigned mask,
|
||||||
const state* init)
|
const state* init)
|
||||||
: tgba_mask(masked, init),
|
: tgba_mask(masked, init),
|
||||||
mask_(mask)
|
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
|
const_tgba_ptr
|
||||||
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
||||||
const bdd to_ignore,
|
unsigned to_ignore,
|
||||||
const state* init)
|
const state* init)
|
||||||
{
|
{
|
||||||
return std::make_shared<tgba_mask_acc_ignore>(to_mask, to_ignore, 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
|
/// \ingroup tgba_on_the_fly_algorithms
|
||||||
/// \brief Mask a TGBA, rejecting some acceptance set of transitions.
|
/// \brief Mask a TGBA, rejecting some acceptance set of transitions.
|
||||||
///
|
///
|
||||||
/// This will ignore all transitions labeled by the acceptance ACC
|
/// This will ignore all transitions that have the TO_IGNORE
|
||||||
/// such that ACC & TO_IGNORE != bddfalse. The initial state can
|
/// acceptance mark. The initial state can optionally be reset to
|
||||||
/// optionally be reset to \a init.
|
/// \a init.
|
||||||
///
|
///
|
||||||
/// Note that the acceptance condition of the automaton (i.e. the
|
/// Note that the acceptance condition of the automaton (i.e. the
|
||||||
/// set of all acceptance set) is not changed, because so far this
|
/// set of all acceptance set) is not changed, because so far this
|
||||||
|
|
@ -62,7 +62,7 @@ namespace spot
|
||||||
/// all_acceptance_conditions().
|
/// all_acceptance_conditions().
|
||||||
SPOT_API const_tgba_ptr
|
SPOT_API const_tgba_ptr
|
||||||
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
||||||
const bdd to_ignore,
|
unsigned to_ignore,
|
||||||
const state* init = 0);
|
const state* init = 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,9 @@ namespace spot
|
||||||
public:
|
public:
|
||||||
tgba_succ_iterator_product_common(tgba_succ_iterator* left,
|
tgba_succ_iterator_product_common(tgba_succ_iterator* left,
|
||||||
tgba_succ_iterator* right,
|
tgba_succ_iterator* right,
|
||||||
|
const tgba_product* prod,
|
||||||
fixed_size_pool* pool)
|
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:
|
protected:
|
||||||
tgba_succ_iterator* left_;
|
tgba_succ_iterator* left_;
|
||||||
tgba_succ_iterator* right_;
|
tgba_succ_iterator* right_;
|
||||||
|
const tgba_product* prod_;
|
||||||
fixed_size_pool* pool_;
|
fixed_size_pool* pool_;
|
||||||
friend class spot::tgba_product;
|
friend class spot::tgba_product;
|
||||||
};
|
};
|
||||||
|
|
@ -150,13 +152,9 @@ namespace spot
|
||||||
public:
|
public:
|
||||||
tgba_succ_iterator_product(tgba_succ_iterator* left,
|
tgba_succ_iterator_product(tgba_succ_iterator* left,
|
||||||
tgba_succ_iterator* right,
|
tgba_succ_iterator* right,
|
||||||
bdd left_neg, bdd right_neg,
|
const tgba_product* prod,
|
||||||
bddPair* right_common_acc,
|
|
||||||
fixed_size_pool* pool)
|
fixed_size_pool* pool)
|
||||||
: tgba_succ_iterator_product_common(left, right, pool),
|
: tgba_succ_iterator_product_common(left, right, prod, pool)
|
||||||
left_neg_(left_neg),
|
|
||||||
right_neg_(right_neg),
|
|
||||||
right_common_acc_(right_common_acc)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,18 +201,17 @@ namespace spot
|
||||||
return current_cond_;
|
return current_cond_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd current_acceptance_conditions() const
|
acc_cond::mark_t current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
return ((left_->current_acceptance_conditions() & right_neg_)
|
return
|
||||||
| (bdd_replace(right_->current_acceptance_conditions(),
|
prod_->acc().join(prod_->left_acc(),
|
||||||
right_common_acc_) & left_neg_));
|
left_->current_acceptance_conditions(),
|
||||||
}
|
prod_->right_acc(),
|
||||||
|
right_->current_acceptance_conditions());
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bdd current_cond_;
|
bdd current_cond_;
|
||||||
bdd left_neg_;
|
|
||||||
bdd right_neg_;
|
|
||||||
bddPair* right_common_acc_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Iterate over the successors of a product computed on the fly.
|
/// Iterate over the successors of a product computed on the fly.
|
||||||
|
|
@ -225,8 +222,9 @@ namespace spot
|
||||||
public:
|
public:
|
||||||
tgba_succ_iterator_product_kripke(tgba_succ_iterator* left,
|
tgba_succ_iterator_product_kripke(tgba_succ_iterator* left,
|
||||||
tgba_succ_iterator* right,
|
tgba_succ_iterator* right,
|
||||||
|
const tgba_product* prod,
|
||||||
fixed_size_pool* pool)
|
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_;
|
return current_cond_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd current_acceptance_conditions() const
|
acc_cond::mark_t current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
return right_->current_acceptance_conditions();
|
return right_->current_acceptance_conditions();
|
||||||
}
|
}
|
||||||
|
|
@ -286,10 +284,10 @@ namespace spot
|
||||||
|
|
||||||
tgba_product::tgba_product(const const_tgba_ptr& left,
|
tgba_product::tgba_product(const const_tgba_ptr& left,
|
||||||
const const_tgba_ptr& right)
|
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))
|
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
|
// 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
|
// with (we don't have to fix the acceptance conditions, and
|
||||||
|
|
@ -308,55 +306,17 @@ namespace spot
|
||||||
left_kripke_ = false;
|
left_kripke_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dict_->register_all_variables_of(&left_, this);
|
auto d = get_dict();
|
||||||
dict_->register_all_variables_of(&right_, this);
|
d->register_all_propositions_of(&left_, this);
|
||||||
|
d->register_all_propositions_of(&right_, this);
|
||||||
|
|
||||||
if (left_kripke_)
|
assert(acc_.num_sets() == 0);
|
||||||
{
|
acc_.add_sets(left->acc().num_sets() + right->acc().num_sets());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tgba_product::~tgba_product()
|
tgba_product::~tgba_product()
|
||||||
{
|
{
|
||||||
if (!left_kripke_)
|
get_dict()->unregister_all_my_variables(this);
|
||||||
bdd_freepair(right_common_acc_);
|
|
||||||
dict_->unregister_all_my_variables(this);
|
|
||||||
// Prevent these states from being destroyed by ~tgba(): they
|
// Prevent these states from being destroyed by ~tgba(): they
|
||||||
// will be destroyed before when the pool is destructed.
|
// will be destroyed before when the pool is destructed.
|
||||||
if (last_support_conditions_input_)
|
if (last_support_conditions_input_)
|
||||||
|
|
@ -393,13 +353,9 @@ namespace spot
|
||||||
|
|
||||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
||||||
if (left_kripke_)
|
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
|
else
|
||||||
return new tgba_succ_iterator_product(li, ri,
|
return new tgba_succ_iterator_product(li, ri, this, p);
|
||||||
left_acc_complement_,
|
|
||||||
right_acc_complement_,
|
|
||||||
right_common_acc_,
|
|
||||||
p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
bdd
|
||||||
|
|
@ -412,10 +368,14 @@ namespace spot
|
||||||
return lsc & rsc;
|
return lsc & rsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd_dict_ptr
|
const acc_cond& tgba_product::left_acc() const
|
||||||
tgba_product::get_dict() const
|
|
||||||
{
|
{
|
||||||
return dict_;
|
return left_->acc();
|
||||||
|
}
|
||||||
|
|
||||||
|
const acc_cond& tgba_product::right_acc() const
|
||||||
|
{
|
||||||
|
return right_->acc();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
|
@ -441,18 +401,6 @@ namespace spot
|
||||||
return right_->project_state(s2->right(), t);
|
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
|
std::string
|
||||||
tgba_product::transition_annotation(const tgba_succ_iterator* t) const
|
tgba_product::transition_annotation(const tgba_succ_iterator* t) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,6 @@ namespace spot
|
||||||
virtual tgba_succ_iterator*
|
virtual tgba_succ_iterator*
|
||||||
succ_iter(const state* state) const;
|
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 format_state(const state* state) const;
|
||||||
|
|
||||||
virtual std::string
|
virtual std::string
|
||||||
|
|
@ -103,22 +101,16 @@ namespace spot
|
||||||
|
|
||||||
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
||||||
|
|
||||||
virtual bdd all_acceptance_conditions() const;
|
const acc_cond& left_acc() const;
|
||||||
virtual bdd neg_acceptance_conditions() const;
|
const acc_cond& right_acc() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bdd compute_support_conditions(const state* state) const;
|
virtual bdd compute_support_conditions(const state* state) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bdd_dict_ptr dict_;
|
|
||||||
const_tgba_ptr left_;
|
const_tgba_ptr left_;
|
||||||
const_tgba_ptr right_;
|
const_tgba_ptr right_;
|
||||||
bool left_kripke_;
|
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_;
|
fixed_size_pool pool_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,10 @@
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
tgba_proxy::tgba_proxy(const const_tgba_ptr& original)
|
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);
|
get_dict()->register_all_variables_of(original, this);
|
||||||
|
acc_.add_sets(original->acc().num_sets());
|
||||||
}
|
}
|
||||||
|
|
||||||
tgba_proxy::~tgba_proxy()
|
tgba_proxy::~tgba_proxy()
|
||||||
|
|
@ -48,12 +49,6 @@ namespace spot
|
||||||
return original_->succ_iter(state);
|
return original_->succ_iter(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd_dict_ptr
|
|
||||||
tgba_proxy::get_dict() const
|
|
||||||
{
|
|
||||||
return original_->get_dict();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
tgba_proxy::format_state(const state* state) const
|
tgba_proxy::format_state(const state* state) const
|
||||||
{
|
{
|
||||||
|
|
@ -72,18 +67,6 @@ namespace spot
|
||||||
return original_->project_state(s, t);
|
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
|
bdd
|
||||||
tgba_proxy::compute_support_conditions(const state* state) const
|
tgba_proxy::compute_support_conditions(const state* state) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,6 @@ namespace spot
|
||||||
virtual tgba_succ_iterator*
|
virtual tgba_succ_iterator*
|
||||||
succ_iter(const state* state) const;
|
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 format_state(const state* state) const;
|
||||||
|
|
||||||
virtual std::string
|
virtual std::string
|
||||||
|
|
@ -55,10 +53,6 @@ namespace spot
|
||||||
|
|
||||||
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
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:
|
protected:
|
||||||
virtual bdd compute_support_conditions(const state* state) const;
|
virtual bdd compute_support_conditions(const state* state) const;
|
||||||
const_tgba_ptr original_;
|
const_tgba_ptr original_;
|
||||||
|
|
|
||||||
|
|
@ -962,7 +962,7 @@ namespace spot
|
||||||
typedef std::multimap<bdd, state_complement*, bdd_less_than> succ_list_t;
|
typedef std::multimap<bdd, state_complement*, bdd_less_than> succ_list_t;
|
||||||
|
|
||||||
tgba_safra_complement_succ_iterator(const succ_list_t& list,
|
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)
|
: list_(list), the_acceptance_cond_(the_acceptance_cond)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -979,10 +979,10 @@ namespace spot
|
||||||
virtual bool done() const;
|
virtual bool done() const;
|
||||||
virtual state_complement* current_state() const;
|
virtual state_complement* current_state() const;
|
||||||
virtual bdd current_condition() const;
|
virtual bdd current_condition() const;
|
||||||
virtual bdd current_acceptance_conditions() const;
|
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||||
private:
|
private:
|
||||||
succ_list_t list_;
|
succ_list_t list_;
|
||||||
bdd the_acceptance_cond_;
|
acc_cond::mark_t the_acceptance_cond_;
|
||||||
succ_list_t::const_iterator it_;
|
succ_list_t::const_iterator it_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1020,7 +1020,7 @@ namespace spot
|
||||||
return it_->first;
|
return it_->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
acc_cond::mark_t
|
||||||
tgba_safra_complement_succ_iterator::current_acceptance_conditions() const
|
tgba_safra_complement_succ_iterator::current_acceptance_conditions() const
|
||||||
{
|
{
|
||||||
assert(!done());
|
assert(!done());
|
||||||
|
|
@ -1075,38 +1075,22 @@ namespace spot
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
||||||
tgba_safra_complement::tgba_safra_complement(const const_tgba_ptr& a)
|
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");
|
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
|
#if TRANSFORM_TO_TBA
|
||||||
the_acceptance_cond_ = bdd_ithvar(v);
|
the_acceptance_cond_ = acc_.mark(acc_.add_set());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TRANSFORM_TO_TGBA
|
#if TRANSFORM_TO_TGBA
|
||||||
unsigned nb_acc =
|
unsigned nb_acc =
|
||||||
static_cast<safra_tree_automaton*>(safra_)->get_nb_acceptance_pairs();
|
static_cast<safra_tree_automaton*>(safra_)->get_nb_acceptance_pairs();
|
||||||
all_acceptance_cond_ = bddfalse;
|
|
||||||
neg_acceptance_cond_ = bddtrue;
|
|
||||||
acceptance_cond_vec_.reserve(nb_acc);
|
acceptance_cond_vec_.reserve(nb_acc);
|
||||||
for (unsigned i = 0; i < nb_acc; ++i)
|
for (unsigned i = 0; i < nb_acc; ++i)
|
||||||
{
|
acceptance_cond_vec_.push_back(acc_.mark(acc_.add_set()));
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1171,7 +1155,7 @@ namespace spot
|
||||||
|
|
||||||
assert(tr != a->automaton.end());
|
assert(tr != a->automaton.end());
|
||||||
|
|
||||||
bdd condition = bddfalse;
|
acc_cond::mark_t condition = 0U;
|
||||||
tgba_safra_complement_succ_iterator::succ_list_t succ_list;
|
tgba_safra_complement_succ_iterator::succ_list_t succ_list;
|
||||||
int nb_acceptance_pairs = a->get_nb_acceptance_pairs();
|
int nb_acceptance_pairs = a->get_nb_acceptance_pairs();
|
||||||
bitvect* e = make_bitvect(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);
|
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
|
std::string
|
||||||
tgba_safra_complement::format_state(const state* state) const
|
tgba_safra_complement::format_state(const state* state) const
|
||||||
{
|
{
|
||||||
|
|
@ -1264,26 +1242,6 @@ namespace spot
|
||||||
return s->to_string();
|
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
|
bdd
|
||||||
tgba_safra_complement::compute_support_conditions(const state* state) const
|
tgba_safra_complement::compute_support_conditions(const state* state) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,7 @@ namespace spot
|
||||||
virtual state* get_init_state() const;
|
virtual state* get_init_state() const;
|
||||||
virtual tgba_succ_iterator* succ_iter(const state* 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 std::string format_state(const state* state) const;
|
||||||
virtual bdd all_acceptance_conditions() const;
|
|
||||||
virtual bdd neg_acceptance_conditions() const;
|
|
||||||
|
|
||||||
void* get_safra() const
|
void* get_safra() const
|
||||||
{
|
{
|
||||||
|
|
@ -73,13 +70,11 @@ namespace spot
|
||||||
const_tgba_ptr automaton_;
|
const_tgba_ptr automaton_;
|
||||||
void* safra_;
|
void* safra_;
|
||||||
#if TRANSFORM_TO_TBA
|
#if TRANSFORM_TO_TBA
|
||||||
bdd the_acceptance_cond_;
|
acc_cond::mark_t the_acceptance_cond_;
|
||||||
#endif
|
#endif
|
||||||
#if TRANSFORM_TO_TGBA
|
#if TRANSFORM_TO_TGBA
|
||||||
bdd all_acceptance_cond_;
|
|
||||||
bdd neg_acceptance_cond_;
|
|
||||||
// Map to i the i-th acceptance condition of the final automaton.
|
// 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
|
#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;
|
continue;
|
||||||
|
|
||||||
bdd cond = i->current_condition();
|
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 };
|
tgba_run::step s = { src, cond, acc };
|
||||||
|
|
||||||
if (match(s, dest))
|
if (match(s, dest))
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
unsigned n = aut->num_states();
|
unsigned n = aut->num_states();
|
||||||
unsigned sink = -1U;
|
unsigned sink = -1U;
|
||||||
bdd allacc = aut->all_acceptance_conditions();
|
acc_cond::mark_t allacc = aut->acc().all_sets();
|
||||||
if (allacc == bddfalse)
|
if (allacc == 0U)
|
||||||
{
|
{
|
||||||
// We cannot safely complete an automaton if it has no
|
// We cannot safely complete an automaton if it has no
|
||||||
// acceptance set as the added sink would become accepting.
|
// acceptance set as the added sink would become accepting.
|
||||||
|
|
@ -44,7 +44,7 @@ namespace spot
|
||||||
for (unsigned i = 0; i < n; ++i)
|
for (unsigned i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
bool selfloop = true;
|
bool selfloop = true;
|
||||||
bdd accsum = bddfalse;
|
acc_cond::mark_t accsum = 0U;
|
||||||
for (auto& t: aut->out(i))
|
for (auto& t: aut->out(i))
|
||||||
{
|
{
|
||||||
if (t.dst != i) // Not a self-loop
|
if (t.dst != i) // Not a self-loop
|
||||||
|
|
@ -66,7 +66,7 @@ namespace spot
|
||||||
for (unsigned i = 0; i < n; ++i)
|
for (unsigned i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
bdd missingcond = bddtrue;
|
bdd missingcond = bddtrue;
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
for (auto& t: aut->out(i))
|
for (auto& t: aut->out(i))
|
||||||
{
|
{
|
||||||
missingcond -= t.cond;
|
missingcond -= t.cond;
|
||||||
|
|
|
||||||
|
|
@ -225,35 +225,11 @@ namespace spot
|
||||||
dict->register_all_variables_of(right, res);
|
dict->register_all_variables_of(right, res);
|
||||||
dict->unregister_variable(bdd_var(v), res);
|
dict->unregister_variable(bdd_var(v), res);
|
||||||
|
|
||||||
// The left and right automata might have acceptance marker in
|
const acc_cond& la = left->acc();
|
||||||
// common.
|
const acc_cond& ra = right->acc();
|
||||||
// For the example, assume left has acceptance conditions A,B,C,D
|
res->set_acceptance_conditions(la.num_sets() + ra.num_sets());
|
||||||
// while right has acceptance condition C,D,E,F.
|
|
||||||
|
|
||||||
// Negative acceptance variables...
|
acc_cond::mark_t radd = ra.all_sets();
|
||||||
// !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;
|
|
||||||
|
|
||||||
pair_map seen;
|
pair_map seen;
|
||||||
pair_queue todo;
|
pair_queue todo;
|
||||||
|
|
@ -300,7 +276,7 @@ namespace spot
|
||||||
while (!ri || !ri->done())
|
while (!ri || !ri->done())
|
||||||
{
|
{
|
||||||
bdd cond = lc;
|
bdd cond = lc;
|
||||||
bdd ra = allacc;
|
acc_cond::mark_t racc = radd;
|
||||||
if (ri)
|
if (ri)
|
||||||
{
|
{
|
||||||
cond = lc & ri->current_condition();
|
cond = lc & ri->current_condition();
|
||||||
|
|
@ -311,7 +287,7 @@ namespace spot
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
d.second = ri->current_state();
|
d.second = ri->current_state();
|
||||||
ra = (ri->current_acceptance_conditions() & rma) | radd;
|
racc = ri->current_acceptance_conditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
int dest;
|
int dest;
|
||||||
|
|
@ -327,8 +303,10 @@ namespace spot
|
||||||
todo.push_back(d);
|
todo.push_back(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd la = (li->current_acceptance_conditions() & lma) | ladd;
|
acc_cond::mark_t a =
|
||||||
res->new_transition(src, dest, bdd_exist(cond, v), ra & la);
|
res->acc().join(la, li->current_acceptance_conditions(),
|
||||||
|
ra, racc);
|
||||||
|
res->new_transition(src, dest, bdd_exist(cond, v), a);
|
||||||
|
|
||||||
if (ri)
|
if (ri)
|
||||||
ri->next();
|
ri->next();
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
#include "tgbaalgos/scc.hh"
|
#include "tgbaalgos/scc.hh"
|
||||||
#include "tgba/bddprint.hh"
|
#include "tgba/bddprint.hh"
|
||||||
|
|
||||||
|
|
@ -72,7 +73,7 @@ namespace spot
|
||||||
class outgoing_acc
|
class outgoing_acc
|
||||||
{
|
{
|
||||||
const_tgba_ptr a_;
|
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,
|
typedef std::unordered_map<const state*, cache_entry,
|
||||||
state_ptr_hash, state_ptr_equal> cache_t;
|
state_ptr_hash, state_ptr_equal> cache_t;
|
||||||
cache_t cache_;
|
cache_t cache_;
|
||||||
|
|
@ -86,8 +87,8 @@ namespace spot
|
||||||
cache_t::const_iterator fill_cache(const state* s)
|
cache_t::const_iterator fill_cache(const state* s)
|
||||||
{
|
{
|
||||||
unsigned s1 = sm_ ? sm_->scc_of_state(s) : 0;
|
unsigned s1 = sm_ ? sm_->scc_of_state(s) : 0;
|
||||||
bdd common = a_->all_acceptance_conditions();
|
acc_cond::mark_t common = a_->acc().all_sets();
|
||||||
bdd union_ = bddfalse;
|
acc_cond::mark_t union_ = 0U;
|
||||||
for (auto it: a_->succ(s))
|
for (auto it: a_->succ(s))
|
||||||
{
|
{
|
||||||
// Ignore transitions that leave the SCC of s.
|
// Ignore transitions that leave the SCC of s.
|
||||||
|
|
@ -97,7 +98,7 @@ namespace spot
|
||||||
if (s2 != s1)
|
if (s2 != s1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bdd set = it->current_acceptance_conditions();
|
acc_cond::mark_t set = it->current_acceptance_conditions();
|
||||||
common &= set;
|
common &= set;
|
||||||
union_ |= set;
|
union_ |= set;
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +107,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection of all outgoing acceptance sets
|
// 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);
|
cache_t::const_iterator i = cache_.find(s);
|
||||||
if (i == cache_.end())
|
if (i == cache_.end())
|
||||||
|
|
@ -115,7 +116,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Union of all outgoing acceptance sets
|
// 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);
|
cache_t::const_iterator i = cache_.find(s);
|
||||||
if (i == cache_.end())
|
if (i == cache_.end())
|
||||||
|
|
@ -146,11 +147,10 @@ namespace spot
|
||||||
auto p = cache_.emplace(s, false);
|
auto p = cache_.emplace(s, false);
|
||||||
if (p.second)
|
if (p.second)
|
||||||
{
|
{
|
||||||
bdd all = a_->all_acceptance_conditions();
|
|
||||||
for (auto it: a_->succ(s))
|
for (auto it: a_->succ(s))
|
||||||
{
|
{
|
||||||
// Look only for transitions that are accepting.
|
// Look only for transitions that are accepting.
|
||||||
if (all != it->current_acceptance_conditions())
|
if (!a_->acc().accepting(it->current_acceptance_conditions()))
|
||||||
continue;
|
continue;
|
||||||
// Look only for self-loops.
|
// Look only for self-loops.
|
||||||
const state* dest = uniq_(it->current_state());
|
const state* dest = uniq_(it->current_state());
|
||||||
|
|
@ -168,37 +168,23 @@ namespace spot
|
||||||
// Order of accepting sets (for one SCC)
|
// Order of accepting sets (for one SCC)
|
||||||
class acc_order
|
class acc_order
|
||||||
{
|
{
|
||||||
std::vector<bdd> order_;
|
std::vector<unsigned> order_;
|
||||||
bdd found_;
|
acc_cond::mark_t found_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned
|
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;
|
// Update the order with any new set we discover
|
||||||
if (all != found_)
|
if (auto newsets = set - found_)
|
||||||
{
|
{
|
||||||
// Check for new conditions in acc
|
acc.fill_from(newsets, std::back_inserter(order_));
|
||||||
if ((acc & found_) != acc)
|
found_ |= newsets;
|
||||||
{
|
}
|
||||||
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 = temp;
|
|
||||||
unsigned next = slevel;
|
unsigned next = slevel;
|
||||||
while (next < order_.size() && bdd_implies(order_[next], acc))
|
while (next < order_.size() && set.has(order_[next]))
|
||||||
{
|
{
|
||||||
++next;
|
++next;
|
||||||
if (!skip_levels)
|
if (!skip_levels)
|
||||||
|
|
@ -208,44 +194,41 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print(int scc, const bdd_dict_ptr dict)
|
print(int scc)
|
||||||
{
|
{
|
||||||
std::vector<bdd>::iterator i;
|
std::vector<bdd>::iterator i;
|
||||||
std::cout << "Order_" << scc << ":\t";
|
std::cout << "Order_" << scc << ":\t";
|
||||||
for (i = order_.begin(); i != order_.end(); i++)
|
for (auto i: order_)
|
||||||
{
|
std::cout << i << ", ";
|
||||||
bdd_print_acc(std::cout, dict, *i);
|
std::cout << '\n';
|
||||||
std::cout << ", ";
|
|
||||||
}
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Accepting order for each SCC
|
// Accepting order for each SCC
|
||||||
class scc_orders
|
class scc_orders
|
||||||
{
|
{
|
||||||
bdd all_;
|
const acc_cond& acc_;
|
||||||
std::map<int, acc_order> orders_;
|
std::map<int, acc_order> orders_;
|
||||||
bool skip_levels_;
|
bool skip_levels_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
scc_orders(bdd all, bool skip_levels):
|
scc_orders(const acc_cond& acc, bool skip_levels):
|
||||||
all_(all), skip_levels_(skip_levels)
|
acc_(acc), skip_levels_(skip_levels)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
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
|
void
|
||||||
print(const bdd_dict_ptr dict)
|
print()
|
||||||
{
|
{
|
||||||
std::map<int, acc_order>::iterator i;
|
std::map<int, acc_order>::iterator i;
|
||||||
for (i = orders_.begin(); i != orders_.end(); 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
|
// be used as a level in degen_state to indicate the next expected
|
||||||
// acceptance set. Level order.size() is a special level used to
|
// acceptance set. Level order.size() is a special level used to
|
||||||
// denote accepting states.
|
// 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
|
// The order is arbitrary, but it turns out that using push_back
|
||||||
// instead of push_front often gives better results because
|
// instead of push_front often gives better results because
|
||||||
// acceptance sets at the beginning if the cycle are more often
|
// acceptance sets at the beginning if the cycle are more often
|
||||||
// used in the automaton. (This surprising fact is probably
|
// used in the automaton. (This surprising fact is probably
|
||||||
// related to the order in which we declare the BDD variables
|
// related to the order in which we declare the BDD variables
|
||||||
// during the translation.)
|
// during the translation.)
|
||||||
bdd all = a->all_acceptance_conditions();
|
unsigned n = a->acc().num_sets();
|
||||||
while (all != bddfalse)
|
for (unsigned i = n; i > 0; --i)
|
||||||
{
|
order.push_back(i - 1);
|
||||||
bdd next = bdd_satone(all);
|
|
||||||
all -= next;
|
|
||||||
order.push_back(next);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize scc_orders
|
// Initialize scc_orders
|
||||||
bdd allacc = a->all_acceptance_conditions();
|
scc_orders orders(a->acc(), skip_levels);
|
||||||
scc_orders orders(a->all_acceptance_conditions(), skip_levels);
|
|
||||||
|
|
||||||
// Make sure we always use the same pointer for identical states
|
// Make sure we always use the same pointer for identical states
|
||||||
// from the input automaton.
|
// from the input automaton.
|
||||||
|
|
@ -340,11 +320,12 @@ namespace spot
|
||||||
// start on the associated level.
|
// start on the associated level.
|
||||||
if (s.second == 0)
|
if (s.second == 0)
|
||||||
{
|
{
|
||||||
bdd acc = outgoing.common_acc(s.first);
|
auto set = outgoing.common_acc(s.first);
|
||||||
if (use_cust_acc_orders)
|
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
|
else
|
||||||
while (s.second < order.size() && bdd_implies(order[s.second], acc))
|
while (s.second < order.size()
|
||||||
|
&& set.has(order[s.second]))
|
||||||
{
|
{
|
||||||
++s.second;
|
++s.second;
|
||||||
if (!skip_levels)
|
if (!skip_levels)
|
||||||
|
|
@ -405,13 +386,13 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
// The old level is slevel. What should be the new one?
|
// The old level is slevel. What should be the new one?
|
||||||
bdd acc = i->current_acceptance_conditions();
|
auto acc = i->current_acceptance_conditions();
|
||||||
bdd otheracc = outgoing.common_acc(d.first);
|
auto otheracc = outgoing.common_acc(d.first);
|
||||||
|
|
||||||
if (want_sba && is_acc)
|
if (want_sba && is_acc)
|
||||||
{
|
{
|
||||||
// Ignore the last expected acceptance set (the value of
|
// 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
|
// transitions (of the current state) AND if it is not
|
||||||
// used by any outgoing transition of the destination
|
// used by any outgoing transition of the destination
|
||||||
// state.
|
// state.
|
||||||
|
|
@ -447,12 +428,12 @@ namespace spot
|
||||||
if (!order.empty())
|
if (!order.empty())
|
||||||
{
|
{
|
||||||
unsigned prev = order.size() - 1;
|
unsigned prev = order.size() - 1;
|
||||||
bdd common = outgoing.common_acc(s.first);
|
auto common = outgoing.common_acc(s.first);
|
||||||
if (bdd_implies(order[prev], common))
|
if (common.has(order[prev]))
|
||||||
{
|
{
|
||||||
bdd u = outgoing.union_acc(d.first);
|
auto u = outgoing.union_acc(d.first);
|
||||||
if (!bdd_implies(order[prev], u))
|
if (!u.has(order[prev]))
|
||||||
acc -= order[prev];
|
acc -= a->acc().mark(order[prev]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -523,7 +504,7 @@ namespace spot
|
||||||
// are not skipping levels.
|
// are not skipping levels.
|
||||||
if (skip_levels || !is_acc)
|
if (skip_levels || !is_acc)
|
||||||
while (next < order.size()
|
while (next < order.size()
|
||||||
&& bdd_implies(order[next], acc))
|
&& acc.has(order[next]))
|
||||||
{
|
{
|
||||||
++next;
|
++next;
|
||||||
if (!skip_levels)
|
if (!skip_levels)
|
||||||
|
|
@ -545,7 +526,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
d.second = 0; // Make it go to the first level.
|
d.second = 0; // Make it go to the first level.
|
||||||
// Skip levels as much as possible.
|
// Skip levels as much as possible.
|
||||||
if (acc != allacc && !skip_levels)
|
if (!a->acc().accepting(acc) && !skip_levels)
|
||||||
{
|
{
|
||||||
if (use_cust_acc_orders)
|
if (use_cust_acc_orders)
|
||||||
{
|
{
|
||||||
|
|
@ -554,7 +535,7 @@ namespace spot
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (d.second < order.size() &&
|
while (d.second < order.size() &&
|
||||||
bdd_implies(order[d.second], acc))
|
acc.has(order[d.second]))
|
||||||
++d.second;
|
++d.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,8 @@ namespace spot
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
si->first();
|
si->first();
|
||||||
accepting = ((!si->done())
|
auto a = si->current_acceptance_conditions();
|
||||||
&& (si->current_acceptance_conditions() ==
|
accepting = !si->done() && aut_->acc().accepting(a);
|
||||||
aut_->all_acceptance_conditions()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -96,10 +95,13 @@ namespace spot
|
||||||
{
|
{
|
||||||
std::string label =
|
std::string label =
|
||||||
bdd_format_formula(aut_->get_dict(),
|
bdd_format_formula(aut_->get_dict(),
|
||||||
si->current_condition())
|
si->current_condition());
|
||||||
+ "\n"
|
auto a = si->current_acceptance_conditions();
|
||||||
+ bdd_format_accset(aut_->get_dict(),
|
if (a)
|
||||||
si->current_acceptance_conditions());
|
{
|
||||||
|
label += "\n";
|
||||||
|
label += aut_->acc().format(a);
|
||||||
|
}
|
||||||
|
|
||||||
std::string s = aut_->transition_annotation(si);
|
std::string s = aut_->transition_annotation(si);
|
||||||
if (!s.empty())
|
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
|
// construction of contraints (4,5) : all loops in the product
|
||||||
// where no accepting run is detected in the ref. automaton,
|
// where no accepting run is detected in the ref. automaton,
|
||||||
|
|
@ -477,7 +477,7 @@ namespace spot
|
||||||
if (sm.scc_of(dp) != q1p_scc)
|
if (sm.scc_of(dp) != q1p_scc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tr.acc == all_acc)
|
if (ra.accepting(tr.acc))
|
||||||
continue;
|
continue;
|
||||||
for (unsigned q3 = 0; q3 < d.cand_size; ++q3)
|
for (unsigned q3 = 0; q3 < d.cand_size; ++q3)
|
||||||
{
|
{
|
||||||
|
|
@ -574,7 +574,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
// We only care about the looping case if
|
// We only care about the looping case if
|
||||||
// it is accepting in the reference.
|
// it is accepting in the reference.
|
||||||
if (tr.acc != all_acc)
|
if (!ra.accepting(tr.acc))
|
||||||
continue;
|
continue;
|
||||||
bdd all = tr.cond;
|
bdd all = tr.cond;
|
||||||
while (all != bddfalse)
|
while (all != bddfalse)
|
||||||
|
|
@ -636,7 +636,7 @@ namespace spot
|
||||||
auto autdict = aut->get_dict();
|
auto autdict = aut->get_dict();
|
||||||
auto a = make_tgba_digraph(autdict);
|
auto a = make_tgba_digraph(autdict);
|
||||||
a->copy_ap_of(aut);
|
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);
|
a->new_states(satdict.cand_size);
|
||||||
|
|
||||||
unsigned last_aut_trans = -1U;
|
unsigned last_aut_trans = -1U;
|
||||||
|
|
|
||||||
|
|
@ -28,18 +28,20 @@ namespace spot
|
||||||
// Clone the original automaton.
|
// Clone the original automaton.
|
||||||
tgba_digraph_ptr res = tgba_dupexp_dfs(aut);
|
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
|
// We will modify res in place, and the resulting
|
||||||
// automaton will only have one acceptance set.
|
// automaton will only have one acceptance set.
|
||||||
|
// This changes aut->acc();
|
||||||
res->set_single_acceptance_set();
|
res->set_single_acceptance_set();
|
||||||
|
|
||||||
unsigned num_acc = aut->number_of_acceptance_conditions();
|
unsigned num_sets = oldacc.num_sets();
|
||||||
unsigned n = res->num_states();
|
unsigned n = res->num_states();
|
||||||
// We will duplicate the automaton as many times as we have
|
// We will duplicate the automaton as many times as we have
|
||||||
// acceptance sets, and we need one extra sink state.
|
// 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;
|
unsigned sink = res->num_states() - 1;
|
||||||
// The sink state has an accepting self-loop.
|
// The sink state has an accepting self-loop.
|
||||||
res->new_acc_transition(sink, sink, bddtrue);
|
res->new_acc_transition(sink, sink, bddtrue);
|
||||||
|
|
@ -54,29 +56,26 @@ namespace spot
|
||||||
if (t.dst >= n) // Ignore transitions we added.
|
if (t.dst >= n) // Ignore transitions we added.
|
||||||
break;
|
break;
|
||||||
missingcond -= t.cond;
|
missingcond -= t.cond;
|
||||||
bdd curacc = t.acc;
|
acc_cond::mark_t curacc = t.acc;
|
||||||
// The original transition must not accept anymore.
|
// The original transition must not accept anymore.
|
||||||
t.acc = bddfalse;
|
t.acc = 0U;
|
||||||
|
|
||||||
// Transition that were fully accepting are never cloned.
|
// Transition that were fully accepting are never cloned.
|
||||||
if (curacc == oldaccs)
|
if (oldacc.accepting(curacc))
|
||||||
continue;
|
continue;
|
||||||
// Save t.cond and t.dst as the reference to t
|
// Save t.cond and t.dst as the reference to t
|
||||||
// is invalided by calls to new_transition().
|
// is invalided by calls to new_transition().
|
||||||
unsigned dst = t.dst;
|
unsigned dst = t.dst;
|
||||||
bdd cond = t.cond;
|
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',
|
// 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.
|
// belong to the acceptance set.
|
||||||
unsigned add = 0;
|
unsigned add = 0;
|
||||||
while (curacc != bddtrue)
|
for (unsigned set = 0; set < num_sets; ++set)
|
||||||
{
|
{
|
||||||
add += n;
|
add += n;
|
||||||
bdd h = bdd_high(curacc);
|
if (!oldacc.has(curacc, set))
|
||||||
if (h == bddfalse)
|
|
||||||
{
|
{
|
||||||
// Clone the transition
|
// Clone the transition
|
||||||
res->new_acc_transition(src + add, dst + add, cond);
|
res->new_acc_transition(src + add, dst + add, cond);
|
||||||
|
|
@ -93,26 +92,9 @@ namespace spot
|
||||||
// arc set would be better.
|
// arc set would be better.
|
||||||
if (dst <= src)
|
if (dst <= src)
|
||||||
res->new_transition(src, dst + add, cond);
|
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.
|
// Complete the original automaton.
|
||||||
if (missingcond != bddfalse)
|
if (missingcond != bddfalse)
|
||||||
|
|
@ -134,21 +116,18 @@ namespace spot
|
||||||
true, // inherently_weak
|
true, // inherently_weak
|
||||||
true); // deterministic
|
true); // deterministic
|
||||||
|
|
||||||
bdd oldaccs = aut->all_acceptance_conditions();
|
|
||||||
bdd oldnegs = aut->neg_acceptance_conditions();
|
|
||||||
|
|
||||||
scc_info si(res);
|
scc_info si(res);
|
||||||
|
|
||||||
// We will modify res in place, and the resulting
|
// We will modify res in place, and the resulting
|
||||||
// automaton will only have one acceptance set.
|
// 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();
|
res->prop_state_based_acc();
|
||||||
|
|
||||||
unsigned sink = res->num_states();
|
unsigned sink = res->num_states();
|
||||||
|
|
||||||
for (unsigned src = 0; src < sink; ++src)
|
for (unsigned src = 0; src < sink; ++src)
|
||||||
{
|
{
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
unsigned scc = si.scc_of(src);
|
unsigned scc = si.scc_of(src);
|
||||||
if (!si.is_accepting_scc(scc) && !si.is_trivial(scc))
|
if (!si.is_accepting_scc(scc) && !si.is_trivial(scc))
|
||||||
acc = all_acc;
|
acc = all_acc;
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ namespace spot
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static bdd_dict_ptr debug_dict = 0;
|
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
|
struct transition
|
||||||
{
|
{
|
||||||
|
|
@ -120,10 +122,10 @@ namespace spot
|
||||||
{
|
{
|
||||||
unsigned src;
|
unsigned src;
|
||||||
bdd cond;
|
bdd cond;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
unsigned dst;
|
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)
|
: src(src), cond(cond), acc(acc), dst(dst)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +144,7 @@ namespace spot
|
||||||
return true;
|
return true;
|
||||||
if (this->cond.id() > other.cond.id())
|
if (this->cond.id() > other.cond.id())
|
||||||
return false;
|
return false;
|
||||||
return this->acc.id() < other.acc.id();
|
return this->acc < other.acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const transition_acc& other) const
|
bool operator==(const transition_acc& other) const
|
||||||
|
|
@ -150,7 +152,7 @@ namespace spot
|
||||||
return (this->src == other.src
|
return (this->src == other.src
|
||||||
&& this->dst == other.dst
|
&& this->dst == other.dst
|
||||||
&& this->cond.id() == other.cond.id()
|
&& 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 src_ref;
|
||||||
unsigned dst_cand;
|
unsigned dst_cand;
|
||||||
unsigned dst_ref;
|
unsigned dst_ref;
|
||||||
bdd acc_cand;
|
acc_cond::mark_t acc_cand;
|
||||||
bdd acc_ref;
|
acc_cond::mark_t acc_ref;
|
||||||
|
|
||||||
path(unsigned src_cand, unsigned src_ref)
|
path(unsigned src_cand, unsigned src_ref)
|
||||||
: src_cand(src_cand), src_ref(src_ref),
|
: src_cand(src_cand), src_ref(src_ref),
|
||||||
dst_cand(src_cand), dst_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,
|
path(unsigned src_cand, unsigned src_ref,
|
||||||
unsigned dst_cand, unsigned dst_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),
|
: src_cand(src_cand), src_ref(src_ref),
|
||||||
dst_cand(dst_cand), dst_ref(dst_ref),
|
dst_cand(dst_cand), dst_ref(dst_ref),
|
||||||
acc_cand(acc_cand), acc_ref(acc_ref)
|
acc_cand(acc_cand), acc_ref(acc_ref)
|
||||||
|
|
@ -197,13 +199,13 @@ namespace spot
|
||||||
return true;
|
return true;
|
||||||
if (this->dst_ref > other.dst_ref)
|
if (this->dst_ref > other.dst_ref)
|
||||||
return false;
|
return false;
|
||||||
if (this->acc_ref.id() < other.acc_ref.id())
|
if (this->acc_ref < other.acc_ref)
|
||||||
return true;
|
return true;
|
||||||
if (this->acc_ref.id() > other.acc_ref.id())
|
if (this->acc_ref > other.acc_ref)
|
||||||
return false;
|
return false;
|
||||||
if (this->acc_cand.id() < other.acc_cand.id())
|
if (this->acc_cand < other.acc_cand)
|
||||||
return true;
|
return true;
|
||||||
if (this->acc_cand.id() > other.acc_cand.id())
|
if (this->acc_cand > other.acc_cand)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -224,7 +226,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
os << '<' << t.src << ','
|
os << '<' << t.src << ','
|
||||||
<< bdd_format_formula(debug_dict, t.cond) << ','
|
<< bdd_format_formula(debug_dict, t.cond) << ','
|
||||||
<< bdd_format_accset(debug_dict, t.acc)
|
<< debug_cand_acc->format(t.acc)
|
||||||
<< ',' << t.dst << '>';
|
<< ',' << t.dst << '>';
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
@ -236,15 +238,15 @@ namespace spot
|
||||||
<< p.src_ref << ','
|
<< p.src_ref << ','
|
||||||
<< p.dst_cand << ','
|
<< p.dst_cand << ','
|
||||||
<< p.dst_ref << ", "
|
<< p.dst_ref << ", "
|
||||||
<< bdd_format_accset(debug_dict, p.acc_cand) << ", "
|
<< debug_cand_acc->format(p.acc_cand) << ", "
|
||||||
<< bdd_format_accset(debug_dict, p.acc_ref) << '>';
|
<< debug_ref_acc->format(p.acc_ref) << '>';
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dict
|
struct dict
|
||||||
{
|
{
|
||||||
dict(const const_tgba_ptr& a)
|
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;
|
// int_map int_to_state;
|
||||||
unsigned cand_size;
|
unsigned cand_size;
|
||||||
unsigned int cand_nacc;
|
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<acc_cond::mark_t> all_cand_acc;
|
||||||
std::vector<bdd> all_ref_acc;
|
std::vector<acc_cond::mark_t> all_ref_acc;
|
||||||
|
|
||||||
bdd cand_all_acc;
|
|
||||||
bdd ref_all_acc;
|
|
||||||
|
|
||||||
std::vector<bool> is_weak_scc;
|
std::vector<bool> is_weak_scc;
|
||||||
|
|
||||||
|
acc_cond cacc;
|
||||||
|
|
||||||
~dict()
|
~dict()
|
||||||
{
|
{
|
||||||
aut->get_dict()->unregister_all_my_variables(this);
|
aut->get_dict()->unregister_all_my_variables(this);
|
||||||
|
|
@ -288,48 +289,27 @@ namespace spot
|
||||||
dict& d, bdd ap, bool state_based, scc_info& sm)
|
dict& d, bdd ap, bool state_based, scc_info& sm)
|
||||||
{
|
{
|
||||||
bdd_dict_ptr bd = aut->get_dict();
|
bdd_dict_ptr bd = aut->get_dict();
|
||||||
ltl::default_environment& env = ltl::default_environment::instance();
|
|
||||||
|
|
||||||
d.cand_acc.resize(d.cand_nacc);
|
d.cand_acc.resize(d.cand_nacc);
|
||||||
d.all_cand_acc.push_back(bddfalse);
|
d.cacc.add_sets(d.cand_nacc);
|
||||||
|
d.all_cand_acc.push_back(0U);
|
||||||
bdd allneg = bddtrue;
|
|
||||||
for (unsigned n = 0; n < d.cand_nacc; ++n)
|
for (unsigned n = 0; n < d.cand_nacc; ++n)
|
||||||
{
|
{
|
||||||
std::ostringstream s;
|
auto c = d.cacc.mark(n);
|
||||||
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];
|
|
||||||
d.cand_acc[n] = c;
|
d.cand_acc[n] = c;
|
||||||
|
|
||||||
size_t s = d.all_cand_acc.size();
|
size_t s = d.all_cand_acc.size();
|
||||||
for (size_t i = 0; i < s; ++i)
|
for (size_t i = 0; i < s; ++i)
|
||||||
d.all_cand_acc.push_back(d.all_cand_acc[i] | c);
|
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);
|
d.all_ref_acc.push_back(0U);
|
||||||
while (refall != bddtrue)
|
unsigned ref_nacc = aut->acc().num_sets();
|
||||||
|
for (unsigned n = 0; n < ref_nacc; ++n)
|
||||||
{
|
{
|
||||||
bdd v = bdd_ithvar(bdd_var(refall));
|
auto c = aut->acc().mark(n);
|
||||||
bdd c = bdd_exist(refnegall, v) & v;
|
|
||||||
|
|
||||||
size_t s = d.all_ref_acc.size();
|
size_t s = d.all_ref_acc.size();
|
||||||
for (size_t i = 0; i < s; ++i)
|
for (size_t i = 0; i < s; ++i)
|
||||||
d.all_ref_acc.push_back(d.all_ref_acc[i] | c);
|
d.all_ref_acc.push_back(d.all_ref_acc[i] | c);
|
||||||
|
|
||||||
refall = bdd_high(refall);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ref_size = aut->num_states();
|
unsigned ref_size = aut->num_states();
|
||||||
|
|
@ -485,9 +465,12 @@ namespace spot
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
debug_dict = ref->get_dict();
|
debug_dict = ref->get_dict();
|
||||||
|
debug_ref_acc = &ref->acc();
|
||||||
|
debug_cand_acc = &d.cacc;
|
||||||
dout << "ref_size: " << ref_size << '\n';
|
dout << "ref_size: " << ref_size << '\n';
|
||||||
dout << "cand_size: " << d.cand_size << '\n';
|
dout << "cand_size: " << d.cand_size << '\n';
|
||||||
#endif
|
#endif
|
||||||
|
auto& racc = ref->acc();
|
||||||
|
|
||||||
dout << "symmetry-breaking clauses\n";
|
dout << "symmetry-breaking clauses\n";
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
@ -586,8 +569,6 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd all_acc = ref->all_acceptance_conditions();
|
|
||||||
|
|
||||||
// construction of constraints (11,12,13)
|
// construction of constraints (11,12,13)
|
||||||
for (unsigned q1p = 0; q1p < ref_size; ++q1p)
|
for (unsigned q1p = 0; q1p < ref_size; ++q1p)
|
||||||
{
|
{
|
||||||
|
|
@ -630,7 +611,7 @@ namespace spot
|
||||||
for (unsigned q3 = 0; q3 < d.cand_size; ++q3)
|
for (unsigned q3 = 0; q3 < d.cand_size; ++q3)
|
||||||
{
|
{
|
||||||
bdd all = tr.cond;
|
bdd all = tr.cond;
|
||||||
bdd curacc = tr.acc;
|
acc_cond::mark_t curacc = tr.acc;
|
||||||
while (all != bddfalse)
|
while (all != bddfalse)
|
||||||
{
|
{
|
||||||
bdd l = bdd_satoneset(all, ap, bddfalse);
|
bdd l = bdd_satoneset(all, ap, bddfalse);
|
||||||
|
|
@ -643,23 +624,22 @@ namespace spot
|
||||||
{
|
{
|
||||||
if ((!is_acc) ||
|
if ((!is_acc) ||
|
||||||
(!is_weak &&
|
(!is_weak &&
|
||||||
(curacc |
|
!racc.accepting
|
||||||
d.all_ref_acc[fp]) != all_acc))
|
(curacc | d.all_ref_acc[fp])))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dout << "(11) " << p << " ∧ "
|
dout << "(11) " << p << " ∧ "
|
||||||
<< t << "δ → ¬(";
|
<< t << "δ → ¬(";
|
||||||
|
|
||||||
bdd all_ = d.all_cand_acc.back();
|
|
||||||
all_ -= d.all_cand_acc[f];
|
|
||||||
bool notfirst = false;
|
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_);
|
transition_acc
|
||||||
all_ -= one;
|
ta(q2, l,
|
||||||
|
d.cacc.mark(m), q1);
|
||||||
transition_acc ta(q2, l,
|
|
||||||
one, q1);
|
|
||||||
if (notfirst)
|
if (notfirst)
|
||||||
out << " ∧ ";
|
out << " ∧ ";
|
||||||
else
|
else
|
||||||
|
|
@ -671,15 +651,14 @@ namespace spot
|
||||||
out << -pid << ' ' << -ti;
|
out << -pid << ' ' << -ti;
|
||||||
|
|
||||||
// 11
|
// 11
|
||||||
bdd all_f = d.all_cand_acc.back();
|
acc_cond::mark_t all_f =
|
||||||
all_f -= d.all_cand_acc[f];
|
d.all_cand_acc.back() -
|
||||||
while (all_f != bddfalse)
|
d.all_cand_acc[f];
|
||||||
|
for (auto m: d.cacc.sets(all_f))
|
||||||
{
|
{
|
||||||
bdd one = bdd_satone(all_f);
|
transition_acc
|
||||||
all_f -= one;
|
ta(q2, l,
|
||||||
|
d.cacc.mark(m), q1);
|
||||||
transition_acc ta(q2, l,
|
|
||||||
one, q1);
|
|
||||||
int tai = d.transaccid[ta];
|
int tai = d.transaccid[ta];
|
||||||
assert(tai != 0);
|
assert(tai != 0);
|
||||||
out << ' ' << -tai;
|
out << ' ' << -tai;
|
||||||
|
|
@ -692,17 +671,15 @@ namespace spot
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
dout << "(12) " << p << " ∧ "
|
dout << "(12) " << p << " ∧ "
|
||||||
<< t << "δ → (";
|
<< t << "δ → (";
|
||||||
|
|
||||||
bdd all_ = d.all_cand_acc.back();
|
|
||||||
all_ -= d.all_cand_acc[f];
|
|
||||||
bool notfirst = false;
|
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_);
|
transition_acc
|
||||||
all_ -= one;
|
ta(q2, l,
|
||||||
|
d.cacc.mark(m), q1);
|
||||||
transition_acc ta(q2, l,
|
|
||||||
one, q1);
|
|
||||||
if (notfirst)
|
if (notfirst)
|
||||||
out << " ∧ ";
|
out << " ∧ ";
|
||||||
else
|
else
|
||||||
|
|
@ -712,15 +689,13 @@ namespace spot
|
||||||
out << ")\n";
|
out << ")\n";
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
// 12
|
// 12
|
||||||
bdd all_f = d.all_cand_acc.back();
|
acc_cond::mark_t all_f =
|
||||||
all_f -= d.all_cand_acc[f];
|
d.cacc.comp(d.all_cand_acc[f]);
|
||||||
while (all_f != bddfalse)
|
for (auto m: d.cacc.sets(all_f))
|
||||||
{
|
{
|
||||||
bdd one = bdd_satone(all_f);
|
transition_acc
|
||||||
all_f -= one;
|
ta(q2, l,
|
||||||
|
d.cacc.mark(m), q1);
|
||||||
transition_acc ta(q2, l,
|
|
||||||
one, q1);
|
|
||||||
int tai = d.transaccid[ta];
|
int tai = d.transaccid[ta];
|
||||||
assert(tai != 0);
|
assert(tai != 0);
|
||||||
|
|
||||||
|
|
@ -735,10 +710,9 @@ namespace spot
|
||||||
size_t sf = d.all_cand_acc.size();
|
size_t sf = d.all_cand_acc.size();
|
||||||
for (size_t f = 0; f < sf; ++f)
|
for (size_t f = 0; f < sf; ++f)
|
||||||
{
|
{
|
||||||
|
acc_cond::mark_t f2 =
|
||||||
bdd f2 = p.acc_cand |
|
p.acc_cand | d.all_cand_acc[f];
|
||||||
d.all_cand_acc[f];
|
acc_cond::mark_t f2p = 0U;
|
||||||
bdd f2p = bddfalse;
|
|
||||||
if (!is_weak)
|
if (!is_weak)
|
||||||
f2p = p.acc_ref | curacc;
|
f2p = p.acc_ref | curacc;
|
||||||
|
|
||||||
|
|
@ -751,47 +725,34 @@ namespace spot
|
||||||
dout << "(13) " << p << " ∧ "
|
dout << "(13) " << p << " ∧ "
|
||||||
<< t << "δ ";
|
<< t << "δ ";
|
||||||
|
|
||||||
bdd biga_ = d.all_cand_acc[f];
|
auto biga_ = d.all_cand_acc[f];
|
||||||
while (biga_ != bddfalse)
|
for (unsigned m = 0;
|
||||||
|
m < d.cand_nacc; ++m)
|
||||||
{
|
{
|
||||||
bdd a = bdd_satone(biga_);
|
transition_acc
|
||||||
biga_ -= a;
|
ta(q2, l,
|
||||||
|
d.cacc.mark(m), q3);
|
||||||
transition_acc ta(q2, l, a, q3);
|
int tai = d.transaccid[ta];
|
||||||
out << " ∧ " << ta << "FC";
|
const char* not_ = "¬";
|
||||||
}
|
if (d.cacc.has(biga_, m))
|
||||||
biga_ = d.all_cand_acc.back()
|
not_ = "";
|
||||||
- d.all_cand_acc[f];
|
out << tai << ' ';
|
||||||
while (biga_ != bddfalse)
|
out << " ∧ " << not_
|
||||||
{
|
<< ta << "FC";
|
||||||
bdd a = bdd_satone(biga_);
|
|
||||||
biga_ -= a;
|
|
||||||
|
|
||||||
transition_acc ta(q2, l, a, q3);
|
|
||||||
out << " ∧ ¬" << ta << "FC";
|
|
||||||
}
|
}
|
||||||
out << " → " << p2 << '\n';
|
out << " → " << p2 << '\n';
|
||||||
#endif
|
#endif
|
||||||
out << -pid << ' ' << -ti << ' ';
|
out << -pid << ' ' << -ti << ' ';
|
||||||
bdd biga = d.all_cand_acc[f];
|
auto biga = d.all_cand_acc[f];
|
||||||
while (biga != bddfalse)
|
for (unsigned m = 0;
|
||||||
|
m < d.cand_nacc; ++m)
|
||||||
{
|
{
|
||||||
bdd a = bdd_satone(biga);
|
transition_acc
|
||||||
biga -= a;
|
ta(q2, l,
|
||||||
|
d.cacc.mark(m), q3);
|
||||||
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);
|
|
||||||
int tai = d.transaccid[ta];
|
int tai = d.transaccid[ta];
|
||||||
|
if (d.cacc.has(biga, m))
|
||||||
|
tai = -tai;
|
||||||
out << tai << ' ';
|
out << tai << ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -818,7 +779,7 @@ namespace spot
|
||||||
auto autdict = aut->get_dict();
|
auto autdict = aut->get_dict();
|
||||||
auto a = make_tgba_digraph(autdict);
|
auto a = make_tgba_digraph(autdict);
|
||||||
a->copy_ap_of(aut);
|
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);
|
a->new_states(satdict.cand_size);
|
||||||
|
|
||||||
|
|
@ -835,7 +796,7 @@ namespace spot
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dout << "--- transition variables ---\n";
|
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;
|
std::set<src_cond> seen_trans;
|
||||||
for (int v: solution)
|
for (int v: solution)
|
||||||
{
|
{
|
||||||
|
|
@ -854,7 +815,7 @@ namespace spot
|
||||||
if (seen_trans.insert(src_cond(t->second.src,
|
if (seen_trans.insert(src_cond(t->second.src,
|
||||||
t->second.cond)).second)
|
t->second.cond)).second)
|
||||||
{
|
{
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
if (state_based)
|
if (state_based)
|
||||||
{
|
{
|
||||||
auto i = state_acc.find(t->second.src);
|
auto i = state_acc.find(t->second.src);
|
||||||
|
|
@ -887,11 +848,13 @@ namespace spot
|
||||||
ta->second.dst == last_sat_trans->dst)
|
ta->second.dst == last_sat_trans->dst)
|
||||||
{
|
{
|
||||||
assert(!state_based);
|
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)
|
else if (state_based)
|
||||||
{
|
{
|
||||||
state_acc[ta->second.src] |= ta->second.acc;
|
auto& v = state_acc[ta->second.src];
|
||||||
|
v |= ta->second.acc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,9 @@ namespace spot
|
||||||
const state*, int out,
|
const state*, int out,
|
||||||
const tgba_succ_iterator* si)
|
const tgba_succ_iterator* si)
|
||||||
{
|
{
|
||||||
out_->new_transition(in - 1, out - 1,
|
out_->new_transition
|
||||||
si->current_condition(),
|
(in - 1, out - 1, si->current_condition(),
|
||||||
si->current_acceptance_conditions());
|
si->current_acceptance_conditions());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ namespace spot
|
||||||
os << " | ";
|
os << " | ";
|
||||||
bdd_print_formula(os, d, i->label);
|
bdd_print_formula(os, d, i->label);
|
||||||
os << '\t';
|
os << '\t';
|
||||||
bdd_print_accset(os, d, i->acc);
|
os << a->acc().format(i->acc);
|
||||||
os << std::endl;
|
os << std::endl;
|
||||||
}
|
}
|
||||||
os << "Cycle:" << std::endl;
|
os << "Cycle:" << std::endl;
|
||||||
|
|
@ -100,7 +100,7 @@ namespace spot
|
||||||
os << " | ";
|
os << " | ";
|
||||||
bdd_print_formula(os, d, i->label);
|
bdd_print_formula(os, d, i->label);
|
||||||
os << '\t';
|
os << '\t';
|
||||||
bdd_print_accset(os, d, i->acc);
|
os << a->acc().format(i->acc);
|
||||||
os << '\n';
|
os << '\n';
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
|
|
@ -302,7 +302,7 @@ namespace spot
|
||||||
unsigned src;
|
unsigned src;
|
||||||
unsigned dst;
|
unsigned dst;
|
||||||
const tgba_run::steps* l;
|
const tgba_run::steps* l;
|
||||||
bdd seen_acc = bddfalse;
|
acc_cond::mark_t seen_acc = 0U;
|
||||||
|
|
||||||
typedef std::unordered_map<const state*, unsigned,
|
typedef std::unordered_map<const state*, unsigned,
|
||||||
state_ptr_hash, state_ptr_equal> state_map;
|
state_ptr_hash, state_ptr_equal> state_map;
|
||||||
|
|
@ -323,7 +323,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
// expected outgoing transition
|
// expected outgoing transition
|
||||||
bdd label = i->label;
|
bdd label = i->label;
|
||||||
bdd acc = i->acc;
|
acc_cond::mark_t acc = i->acc;
|
||||||
|
|
||||||
// compute the next expected state
|
// compute the next expected state
|
||||||
const state* next;
|
const state* next;
|
||||||
|
|
@ -379,7 +379,7 @@ namespace spot
|
||||||
|
|
||||||
s->destroy();
|
s->destroy();
|
||||||
|
|
||||||
assert(seen_acc == a->all_acceptance_conditions());
|
assert(a->acc().accepting(seen_acc));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ namespace spot
|
||||||
struct step {
|
struct step {
|
||||||
const state* s;
|
const state* s;
|
||||||
bdd label;
|
bdd label;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<step> steps;
|
typedef std::list<step> steps;
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ namespace spot
|
||||||
void
|
void
|
||||||
couvreur99_check_result::accepting_cycle()
|
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
|
// Compute an accepting cycle using successive BFS that are
|
||||||
// restarted from the point reached after we have discovered a
|
// restarted from the point reached after we have discovered a
|
||||||
// transition with a new acceptance conditions.
|
// transition with a new acceptance conditions.
|
||||||
|
|
@ -173,11 +173,11 @@ namespace spot
|
||||||
{
|
{
|
||||||
const couvreur99_check_status* ecs;
|
const couvreur99_check_status* ecs;
|
||||||
couvreur99_check_result* r;
|
couvreur99_check_result* r;
|
||||||
bdd& acc_to_traverse;
|
acc_cond::mark_t& acc_to_traverse;
|
||||||
int scc_root;
|
int scc_root;
|
||||||
|
|
||||||
scc_bfs(const couvreur99_check_status* ecs,
|
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),
|
: bfs_steps(ecs->aut), ecs(ecs), r(r),
|
||||||
acc_to_traverse(acc_to_traverse),
|
acc_to_traverse(acc_to_traverse),
|
||||||
scc_root(ecs->root.top().index)
|
scc_root(ecs->root.top().index)
|
||||||
|
|
@ -202,9 +202,10 @@ namespace spot
|
||||||
virtual bool
|
virtual bool
|
||||||
match(tgba_run::step& st, const state* s)
|
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
|
if (less_acc != acc_to_traverse
|
||||||
|| (acc_to_traverse == bddfalse
|
|| (acc_to_traverse == 0U
|
||||||
&& s == ecs->cycle_seed))
|
&& s == ecs->cycle_seed))
|
||||||
{
|
{
|
||||||
acc_to_traverse = less_acc;
|
acc_to_traverse = less_acc;
|
||||||
|
|
@ -218,7 +219,7 @@ namespace spot
|
||||||
substart = b.search(substart, run_->cycle);
|
substart = b.search(substart, run_->cycle);
|
||||||
assert(substart);
|
assert(substart);
|
||||||
}
|
}
|
||||||
while (acc_to_traverse != bddfalse || substart != ecs_->cycle_seed);
|
while (acc_to_traverse != 0U || substart != ecs_->cycle_seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ namespace spot
|
||||||
// * couvreur99_check::h, a hash of all visited nodes, with their order,
|
// * couvreur99_check::h, a hash of all visited nodes, with their order,
|
||||||
// (it is called "Hash" in Couvreur's paper)
|
// (it is called "Hash" in Couvreur's paper)
|
||||||
// * arc, a stack of acceptance conditions between each of these SCC,
|
// * 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
|
// * num, the number of visited nodes. Used to set the order of each
|
||||||
// visited node,
|
// visited node,
|
||||||
int num = 1;
|
int num = 1;
|
||||||
|
|
@ -152,7 +152,7 @@ namespace spot
|
||||||
state* init = ecs_->aut->get_init_state();
|
state* init = ecs_->aut->get_init_state();
|
||||||
ecs_->h[init] = 1;
|
ecs_->h[init] = 1;
|
||||||
ecs_->root.push(1);
|
ecs_->root.push(1);
|
||||||
arc.push(bddfalse);
|
arc.push(0U);
|
||||||
tgba_succ_iterator* iter = ecs_->aut->succ_iter(init);
|
tgba_succ_iterator* iter = ecs_->aut->succ_iter(init);
|
||||||
iter->first();
|
iter->first();
|
||||||
todo.emplace(init, iter);
|
todo.emplace(init, iter);
|
||||||
|
|
@ -207,7 +207,7 @@ namespace spot
|
||||||
// Fetch the values (destination state, acceptance conditions
|
// Fetch the values (destination state, acceptance conditions
|
||||||
// of the arc) we are interested in...
|
// of the arc) we are interested in...
|
||||||
const state* dest = succ->current_state();
|
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
|
// ... and point the iterator to the next successor, for
|
||||||
// the next iteration.
|
// the next iteration.
|
||||||
succ->next();
|
succ->next();
|
||||||
|
|
@ -265,8 +265,7 @@ namespace spot
|
||||||
ecs_->root.top().condition |= acc;
|
ecs_->root.top().condition |= acc;
|
||||||
ecs_->root.rem().splice(ecs_->root.rem().end(), rem);
|
ecs_->root.rem().splice(ecs_->root.rem().end(), rem);
|
||||||
|
|
||||||
if (ecs_->root.top().condition
|
if (ecs_->aut->acc().accepting(ecs_->root.top().condition))
|
||||||
== ecs_->aut->all_acceptance_conditions())
|
|
||||||
{
|
{
|
||||||
// We have found an accepting SCC.
|
// We have found an accepting SCC.
|
||||||
// Release all iterators in TODO.
|
// Release all iterators in TODO.
|
||||||
|
|
@ -521,7 +520,7 @@ namespace spot
|
||||||
// (called the "threshold").
|
// (called the "threshold").
|
||||||
int threshold = i->second;
|
int threshold = i->second;
|
||||||
std::list<const state*> rem;
|
std::list<const state*> rem;
|
||||||
bdd acc = succ.acc;
|
acc_cond::mark_t acc = succ.acc;
|
||||||
while (threshold < ecs_->root.top().index)
|
while (threshold < ecs_->root.top().index)
|
||||||
{
|
{
|
||||||
assert(!ecs_->root.empty());
|
assert(!ecs_->root.empty());
|
||||||
|
|
@ -543,8 +542,7 @@ namespace spot
|
||||||
ecs_->root.rem().splice(ecs_->root.rem().end(), rem);
|
ecs_->root.rem().splice(ecs_->root.rem().end(), rem);
|
||||||
|
|
||||||
// Have we found all acceptance conditions?
|
// Have we found all acceptance conditions?
|
||||||
if (ecs_->root.top().condition
|
if (ecs_->aut->acc().accepting(ecs_->root.top().condition))
|
||||||
== ecs_->aut->all_acceptance_conditions())
|
|
||||||
{
|
{
|
||||||
// Use this state to start the computation of an accepting
|
// Use this state to start the computation of an accepting
|
||||||
// cycle.
|
// cycle.
|
||||||
|
|
|
||||||
|
|
@ -195,9 +195,9 @@ namespace spot
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct successor {
|
struct successor {
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
const spot::state* s;
|
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:
|
// 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,
|
// * couvreur99_check::h, a hash of all visited nodes, with their order,
|
||||||
// (it is called "Hash" in Couvreur's paper)
|
// (it is called "Hash" in Couvreur's paper)
|
||||||
// * arc, a stack of acceptance conditions between each of these SCC,
|
// * 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
|
// * num, the number of visited nodes. Used to set the order of each
|
||||||
// visited node,
|
// visited node,
|
||||||
int num;
|
int num;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace spot
|
||||||
scc_stack::connected_component::connected_component(int i)
|
scc_stack::connected_component::connected_component(int i)
|
||||||
{
|
{
|
||||||
index = i;
|
index = i;
|
||||||
condition = bddfalse;
|
condition = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_stack::connected_component&
|
scc_stack::connected_component&
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ namespace spot
|
||||||
|
|
||||||
/// Index of the SCC.
|
/// Index of the SCC.
|
||||||
int index;
|
int index;
|
||||||
/// The bdd condition is the union of all acceptance conditions of
|
/// The union of all acceptance marks of transitions the
|
||||||
/// transitions which connect the states of the connected component.
|
/// connected component.
|
||||||
bdd condition;
|
acc_cond::mark_t condition;
|
||||||
|
|
||||||
std::list<const state*> rem;
|
std::list<const state*> rem;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,6 @@ namespace spot
|
||||||
|
|
||||||
struct gv04: public emptiness_check, public ec_statistics
|
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.
|
// Map of visited states.
|
||||||
typedef std::unordered_map<const state*, size_t,
|
typedef std::unordered_map<const state*, size_t,
|
||||||
state_ptr_hash, state_ptr_equal> hash_type;
|
state_ptr_hash, state_ptr_equal> hash_type;
|
||||||
|
|
@ -72,9 +68,9 @@ namespace spot
|
||||||
bool violation; // Whether an accepting run was found.
|
bool violation; // Whether an accepting run was found.
|
||||||
|
|
||||||
gv04(const const_tgba_ptr& a, option_map o)
|
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()
|
~gv04()
|
||||||
|
|
@ -125,7 +121,8 @@ namespace spot
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const state* s_prime = iter->current_state();
|
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();
|
inc_transitions();
|
||||||
|
|
||||||
trace << " Next successor: s_prime = "
|
trace << " Next successor: s_prime = "
|
||||||
|
|
@ -365,7 +362,7 @@ namespace spot
|
||||||
virtual bool
|
virtual bool
|
||||||
match(tgba_run::step& step, const state*)
|
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_start = data.stack[scc_root].s;
|
||||||
const state* bfs_end = bfs_start;
|
const state* bfs_end = bfs_start;
|
||||||
if (data.accepting != bddfalse)
|
if (a_->acc().num_sets() > 0)
|
||||||
{
|
{
|
||||||
first_bfs b1(this, scc_root);
|
first_bfs b1(this, scc_root);
|
||||||
bfs_start = b1.search(bfs_start, res->cycle);
|
bfs_start = b1.search(bfs_start, res->cycle);
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,6 @@ namespace spot
|
||||||
typedef std::vector<int> vap_t;
|
typedef std::vector<int> vap_t;
|
||||||
vap_t vap;
|
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.
|
// Map each state to a number.
|
||||||
typedef std::unordered_map<const state*, unsigned,
|
typedef std::unordered_map<const state*, unsigned,
|
||||||
state_ptr_hash, state_ptr_equal> state_map;
|
state_ptr_hash, state_ptr_equal> state_map;
|
||||||
|
|
@ -69,40 +65,27 @@ namespace spot
|
||||||
metadata(const const_tgba_ptr& aut)
|
metadata(const const_tgba_ptr& aut)
|
||||||
: state_acc(true), is_complete(true), is_deterministic(true)
|
: state_acc(true), is_complete(true), is_deterministic(true)
|
||||||
{
|
{
|
||||||
number_all_acc(aut);
|
|
||||||
number_all_states_and_fill_sup(aut);
|
number_all_states_and_fill_sup(aut);
|
||||||
number_all_ap();
|
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&
|
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.
|
// FIXME: We could use a cache for this.
|
||||||
if (b == bddfalse)
|
if (b == 0U)
|
||||||
return os;
|
return os;
|
||||||
os << " {";
|
os << " {";
|
||||||
bool notfirst = false;
|
bool notfirst = false;
|
||||||
while (b != bddfalse)
|
for (auto v: aut->acc().sets(b))
|
||||||
{
|
{
|
||||||
bdd one = bdd_satone(b);
|
|
||||||
b -= one;
|
|
||||||
if (notfirst)
|
if (notfirst)
|
||||||
os << ' ';
|
os << ' ';
|
||||||
else
|
else
|
||||||
notfirst = true;
|
notfirst = true;
|
||||||
os << acc[one];
|
os << v;
|
||||||
}
|
}
|
||||||
os << '}';
|
os << '}';
|
||||||
return os;
|
return os;
|
||||||
|
|
@ -124,7 +107,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
auto src = todo.front();
|
auto src = todo.front();
|
||||||
todo.pop_front();
|
todo.pop_front();
|
||||||
bdd prev = bddtrue;
|
acc_cond::mark_t prev = -1U;
|
||||||
bool st_acc = true;
|
bool st_acc = true;
|
||||||
bdd sum = bddfalse;
|
bdd sum = bddfalse;
|
||||||
bdd available = bddtrue;
|
bdd available = bddtrue;
|
||||||
|
|
@ -153,8 +136,8 @@ namespace spot
|
||||||
}
|
}
|
||||||
if (st_acc)
|
if (st_acc)
|
||||||
{
|
{
|
||||||
bdd acc = i->current_acceptance_conditions();
|
acc_cond::mark_t acc = i->current_acceptance_conditions();
|
||||||
if (prev != bddtrue && prev != acc)
|
if (prev != -1U && prev != acc)
|
||||||
st_acc = false;
|
st_acc = false;
|
||||||
else
|
else
|
||||||
prev = acc;
|
prev = acc;
|
||||||
|
|
@ -265,7 +248,7 @@ namespace spot
|
||||||
i != md.vap.end(); ++i)
|
i != md.vap.end(); ++i)
|
||||||
escape_str(os << " \"", to_string(d->bdd_map[*i].f)) << '"';
|
escape_str(os << " \"", to_string(d->bdd_map[*i].f)) << '"';
|
||||||
os << nl;
|
os << nl;
|
||||||
unsigned num_acc = md.acc.size();
|
unsigned num_acc = aut->acc().num_sets();
|
||||||
if (num_acc == 0)
|
if (num_acc == 0)
|
||||||
os << "acc-name: all";
|
os << "acc-name: all";
|
||||||
else if (num_acc == 1)
|
else if (num_acc == 1)
|
||||||
|
|
@ -309,7 +292,7 @@ namespace spot
|
||||||
|
|
||||||
os << "State: " << i;
|
os << "State: " << i;
|
||||||
if (this_acc == Hoaf_Acceptance_States && !j->done())
|
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;
|
os << nl;
|
||||||
|
|
||||||
for (; !j->done(); j->next())
|
for (; !j->done(); j->next())
|
||||||
|
|
@ -317,7 +300,7 @@ namespace spot
|
||||||
const state* dst = j->current_state();
|
const state* dst = j->current_state();
|
||||||
os << '[' << md.sup[j->current_condition()] << "] " << md.sm[dst];
|
os << '[' << md.sup[j->current_condition()] << "] " << md.sm[dst];
|
||||||
if (this_acc == Hoaf_Acceptance_Transitions)
|
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;
|
os << nl;
|
||||||
dst->destroy();
|
dst->destroy();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace spot
|
||||||
cycle_found(const state* start)
|
cycle_found(const state* start)
|
||||||
{
|
{
|
||||||
dfs_stack::const_reverse_iterator i = dfs_.rbegin();
|
dfs_stack::const_reverse_iterator i = dfs_.rbegin();
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
acc |= i->succ->current_acceptance_conditions();
|
acc |= i->succ->current_acceptance_conditions();
|
||||||
|
|
@ -51,7 +51,7 @@ namespace spot
|
||||||
// At least version 4.0 needs it.
|
// At least version 4.0 needs it.
|
||||||
assert(i != const_cast<const dfs_stack&>(dfs_).rend());
|
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
|
// We have found an non-accepting cycle, so the SCC is not
|
||||||
// weak.
|
// weak.
|
||||||
|
|
@ -83,9 +83,8 @@ namespace spot
|
||||||
// If no cycle is accepting, the SCC is weak.
|
// If no cycle is accepting, the SCC is weak.
|
||||||
if (!map.accepting(scc))
|
if (!map.accepting(scc))
|
||||||
return true;
|
return true;
|
||||||
// If all transitions use all acceptance conditions, the SCC is weak.
|
// If all transitions use the same acceptance set, the SCC is weak.
|
||||||
return (map.useful_acc_of(scc)
|
return map.useful_acc_of(scc).size() == 1;
|
||||||
== bdd_support(map.get_aut()->neg_acceptance_conditions()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -128,8 +127,8 @@ namespace spot
|
||||||
is_terminal_scc(scc_map& map, unsigned scc)
|
is_terminal_scc(scc_map& map, unsigned scc)
|
||||||
{
|
{
|
||||||
// If all transitions use all acceptance conditions, the SCC is weak.
|
// If all transitions use all acceptance conditions, the SCC is weak.
|
||||||
return ((map.useful_acc_of(scc) ==
|
return (map.accepting(scc)
|
||||||
bdd_support(map.get_aut()->neg_acceptance_conditions()))
|
&& map.useful_acc_of(scc).size() == 1
|
||||||
&& is_complete_scc(map, scc));
|
&& is_complete_scc(map, scc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,49 +35,12 @@ namespace spot
|
||||||
{
|
{
|
||||||
namespace
|
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
|
class lbtt_bfs : public tgba_reachable_iterator_breadth_first
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
lbtt_bfs(const const_tgba_ptr& a, std::ostream& os, bool sba_format)
|
lbtt_bfs(const const_tgba_ptr& a, std::ostream& os, bool sba_format)
|
||||||
: tgba_reachable_iterator_breadth_first(a),
|
: tgba_reachable_iterator_breadth_first(a),
|
||||||
os_(os),
|
os_(os),
|
||||||
all_acc_conds_(a->all_acceptance_conditions()),
|
|
||||||
acs_(all_acc_conds_),
|
|
||||||
sba_format_(sba_format),
|
sba_format_(sba_format),
|
||||||
sba_(nullptr)
|
sba_(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -104,7 +67,7 @@ namespace spot
|
||||||
// iterator.
|
// iterator.
|
||||||
tgba_succ_iterator* it = aut_->succ_iter(s);
|
tgba_succ_iterator* it = aut_->succ_iter(s);
|
||||||
bool accepting = it->first()
|
bool accepting = it->first()
|
||||||
&& it->current_acceptance_conditions() == all_acc_conds_;
|
&& aut_->acc().accepting(it->current_acceptance_conditions());
|
||||||
aut_->release_iter(it);
|
aut_->release_iter(it);
|
||||||
return accepting;
|
return accepting;
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +101,8 @@ namespace spot
|
||||||
body_ << out - 1 << ' ';
|
body_ << out - 1 << ' ';
|
||||||
if (!sba_format_)
|
if (!sba_format_)
|
||||||
{
|
{
|
||||||
acs_.split(body_, si->current_acceptance_conditions());
|
for (auto s: aut_->acc().sets(si->current_acceptance_conditions()))
|
||||||
|
body_ << s << ' ';
|
||||||
body_ << "-1 ";
|
body_ << "-1 ";
|
||||||
}
|
}
|
||||||
const ltl::formula* f = bdd_to_formula(si->current_condition(),
|
const ltl::formula* f = bdd_to_formula(si->current_condition(),
|
||||||
|
|
@ -155,7 +119,7 @@ namespace spot
|
||||||
if (sba_format_)
|
if (sba_format_)
|
||||||
os_ << '1';
|
os_ << '1';
|
||||||
else
|
else
|
||||||
os_ << aut_->number_of_acceptance_conditions() << 't';
|
os_ << aut_->acc().num_sets() << 't';
|
||||||
os_ << '\n' << body_.str() << "-1" << std::endl;
|
os_ << '\n' << body_.str() << "-1" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,7 +127,6 @@ namespace spot
|
||||||
std::ostream& os_;
|
std::ostream& os_;
|
||||||
std::ostringstream body_;
|
std::ostringstream body_;
|
||||||
bdd all_acc_conds_;
|
bdd all_acc_conds_;
|
||||||
acceptance_cond_splitter acs_;
|
|
||||||
bool sba_format_;
|
bool sba_format_;
|
||||||
const_tgba_digraph_ptr sba_;
|
const_tgba_digraph_ptr sba_;
|
||||||
};
|
};
|
||||||
|
|
@ -196,7 +159,7 @@ namespace spot
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Read the acceptance conditions.
|
// Read the acceptance conditions.
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int acc_n = 0;
|
int acc_n = 0;
|
||||||
|
|
@ -254,7 +217,7 @@ namespace spot
|
||||||
aut->set_init_state(src_state);
|
aut->set_init_state(src_state);
|
||||||
|
|
||||||
// Read the acceptance conditions.
|
// Read the acceptance conditions.
|
||||||
bdd acc = bddfalse;
|
acc_cond::mark_t acc = 0U;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int acc_n = 0;
|
int acc_n = 0;
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,9 @@ namespace spot
|
||||||
{
|
{
|
||||||
public:
|
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)
|
bool single_acc)
|
||||||
: dict(dict),
|
: dict(dict),
|
||||||
ls(ls),
|
ls(ls),
|
||||||
|
|
@ -150,7 +152,8 @@ namespace spot
|
||||||
next_set(bddtrue),
|
next_set(bddtrue),
|
||||||
transdfa(*this),
|
transdfa(*this),
|
||||||
exprop(exprop),
|
exprop(exprop),
|
||||||
single_acc(single_acc)
|
single_acc(single_acc),
|
||||||
|
acc(acc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,6 +187,9 @@ namespace spot
|
||||||
ratexp_to_dfa transdfa;
|
ratexp_to_dfa transdfa;
|
||||||
bool exprop;
|
bool exprop;
|
||||||
bool single_acc;
|
bool single_acc;
|
||||||
|
acc_cond& acc;
|
||||||
|
// Map BDD variables to acceptance marks.
|
||||||
|
std::map<int, unsigned> bm;
|
||||||
|
|
||||||
enum translate_flags
|
enum translate_flags
|
||||||
{
|
{
|
||||||
|
|
@ -231,6 +237,7 @@ namespace spot
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
register_proposition(const formula* f)
|
register_proposition(const formula* f)
|
||||||
{
|
{
|
||||||
|
|
@ -239,6 +246,30 @@ namespace spot
|
||||||
return num;
|
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
|
int
|
||||||
register_a_variable(const formula* f)
|
register_a_variable(const formula* f)
|
||||||
{
|
{
|
||||||
|
|
@ -247,6 +278,10 @@ namespace spot
|
||||||
int num = dict->register_acceptance_variable
|
int num = dict->register_acceptance_variable
|
||||||
(ltl::constant::true_instance(), this);
|
(ltl::constant::true_instance(), this);
|
||||||
a_set &= bdd_ithvar(num);
|
a_set &= bdd_ithvar(num);
|
||||||
|
|
||||||
|
auto p = bm.emplace(num, 0U);
|
||||||
|
if (p.second)
|
||||||
|
p.first->second = acc.add_set();
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
// A promise of 'x', noted P(x) is pretty much like the F(x)
|
// 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);
|
int num = dict->register_acceptance_variable(g, this);
|
||||||
a_set &= bdd_ithvar(num);
|
a_set &= bdd_ithvar(num);
|
||||||
g->destroy();
|
g->destroy();
|
||||||
|
|
||||||
|
auto p = bm.emplace(num, 0U);
|
||||||
|
if (p.second)
|
||||||
|
p.first->second = acc.add_set();
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -316,6 +356,11 @@ namespace spot
|
||||||
}
|
}
|
||||||
int num = dict->register_acceptance_variable(f, this);
|
int num = dict->register_acceptance_variable(f, this);
|
||||||
a_set &= bdd_ithvar(num);
|
a_set &= bdd_ithvar(num);
|
||||||
|
|
||||||
|
auto p = bm.emplace(num, 0U);
|
||||||
|
if (p.second)
|
||||||
|
p.first->second = acc.add_set();
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2105,7 +2150,10 @@ namespace spot
|
||||||
|
|
||||||
assert(dict == s->get_dict());
|
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
|
// Compute the set of all promises that can possibly occur
|
||||||
// inside the formula.
|
// inside the formula.
|
||||||
|
|
@ -2154,8 +2202,6 @@ namespace spot
|
||||||
bdd all_events = observable_events | unobservable_events;
|
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...
|
// This is in case the initial state is equivalent to true...
|
||||||
if (symb_merge)
|
if (symb_merge)
|
||||||
|
|
@ -2341,7 +2387,7 @@ namespace spot
|
||||||
formulae_to_translate.insert(truef);
|
formulae_to_translate.insert(truef);
|
||||||
namer->new_state(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.
|
// Register other transitions.
|
||||||
for (i = dests.begin(); i != dests.end(); ++i)
|
for (i = dests.begin(); i != dests.end(); ++i)
|
||||||
|
|
@ -2365,7 +2411,7 @@ namespace spot
|
||||||
if (!reachable && !seen)
|
if (!reachable && !seen)
|
||||||
namer->new_state(dest);
|
namer->new_state(dest);
|
||||||
reachable = true;
|
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)
|
if (reachable && !seen)
|
||||||
|
|
@ -2380,21 +2426,15 @@ namespace spot
|
||||||
delete namer;
|
delete namer;
|
||||||
|
|
||||||
dict->register_propositions(fc.used_vars(), a);
|
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();
|
unsigned ns = a->num_states();
|
||||||
for (unsigned s = 0; s < ns; ++s)
|
for (unsigned s = 0; s < ns; ++s)
|
||||||
for (auto& t: a->out(s))
|
for (auto& t: a->out(s))
|
||||||
t.acc = ac.reverse_complement(t.acc);
|
t.acc = a->acc().comp(t.acc);
|
||||||
|
|
||||||
|
|
||||||
if (!simplifier)
|
if (!simplifier)
|
||||||
// This should not be deleted before we have registered all propositions.
|
// This should not be deleted before we have registered all propositions.
|
||||||
delete s;
|
delete s;
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,9 @@ namespace spot
|
||||||
magic_search_(const const_tgba_ptr& a, size_t size,
|
magic_search_(const const_tgba_ptr& a, size_t size,
|
||||||
option_map o = option_map())
|
option_map o = option_map())
|
||||||
: emptiness_check(a, o),
|
: emptiness_check(a, o),
|
||||||
h(size),
|
h(size)
|
||||||
all_cond(a->all_acceptance_conditions())
|
|
||||||
{
|
{
|
||||||
assert(a->number_of_acceptance_conditions() <= 1);
|
assert(a->acc().num_sets() <= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~magic_search_()
|
virtual ~magic_search_()
|
||||||
|
|
@ -98,7 +97,7 @@ namespace spot
|
||||||
const state* s0 = a_->get_init_state();
|
const state* s0 = a_->get_init_state();
|
||||||
inc_states();
|
inc_states();
|
||||||
h.add_new_state(s0, BLUE);
|
h.add_new_state(s0, BLUE);
|
||||||
push(st_blue, s0, bddfalse, bddfalse);
|
push(st_blue, s0, bddfalse, 0U);
|
||||||
if (dfs_blue())
|
if (dfs_blue())
|
||||||
return std::make_shared<magic_search_result>(t, options());
|
return std::make_shared<magic_search_result>(t, options());
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +150,7 @@ namespace spot
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void push(stack_type& st, const state* s,
|
void push(stack_type& st, const state* s,
|
||||||
const bdd& label, const bdd& acc)
|
const bdd& label, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
inc_depth();
|
inc_depth();
|
||||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||||
|
|
@ -179,9 +178,6 @@ namespace spot
|
||||||
/// State targeted by the red dfs.
|
/// State targeted by the red dfs.
|
||||||
const state* target;
|
const state* target;
|
||||||
|
|
||||||
/// The unique acceptance condition of the automaton \a a.
|
|
||||||
bdd all_cond;
|
|
||||||
|
|
||||||
bool dfs_blue()
|
bool dfs_blue()
|
||||||
{
|
{
|
||||||
while (!st_blue.empty())
|
while (!st_blue.empty())
|
||||||
|
|
@ -194,7 +190,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
@ -208,7 +204,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
else
|
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 test 'c.get_color() != RED' is added to limit
|
||||||
// the number of runs reported by successive
|
// 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);
|
typename heap::color_ref c = h.get_color_ref(f_dest.s);
|
||||||
assert(!c.is_white());
|
assert(!c.is_white());
|
||||||
if (!st_blue.empty() &&
|
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 test 'c.get_color() != RED' is added to limit
|
||||||
// the number of runs reported by successive
|
// the number of runs reported by successive
|
||||||
|
|
@ -281,7 +277,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
struct stack_item
|
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) {};
|
: s(n), it(i), label(l), acc(a) {};
|
||||||
/// The visited state.
|
/// The visited state.
|
||||||
const state* s;
|
const state* s;
|
||||||
|
|
@ -57,7 +57,7 @@ namespace spot
|
||||||
bdd label;
|
bdd label;
|
||||||
/// The acceptance set of the transition traversed to reach \a s
|
/// The acceptance set of the transition traversed to reach \a s
|
||||||
/// (false for the first one).
|
/// (false for the first one).
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<stack_item> stack_type;
|
typedef std::list<stack_item> stack_type;
|
||||||
|
|
@ -112,7 +112,7 @@ namespace spot
|
||||||
|
|
||||||
assert(!stb.empty());
|
assert(!stb.empty());
|
||||||
|
|
||||||
bdd covered_acc = bddfalse;
|
acc_cond::mark_t covered_acc = 0U;
|
||||||
accepting_transitions_list acc_trans;
|
accepting_transitions_list acc_trans;
|
||||||
|
|
||||||
const state* start;
|
const state* start;
|
||||||
|
|
@ -120,7 +120,7 @@ namespace spot
|
||||||
start = stb.front().s->clone();
|
start = stb.front().s->clone();
|
||||||
if (!str.empty())
|
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
|
// take arbitrarily the last transition on the red stack
|
||||||
stack_type::const_iterator i, j;
|
stack_type::const_iterator i, j;
|
||||||
|
|
@ -164,7 +164,7 @@ namespace spot
|
||||||
assert(h_.has_been_visited(t.source));
|
assert(h_.has_been_visited(t.source));
|
||||||
assert(h_.has_been_visited(t.dest));
|
assert(h_.has_been_visited(t.dest));
|
||||||
acc_trans.push_back(t);
|
acc_trans.push_back(t);
|
||||||
covered_acc |= j->acc;
|
covered_acc |= j->acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = j; ++j;
|
i = j; ++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);
|
bool b = dfs(start, acc_trans, covered_acc);
|
||||||
assert(b);
|
assert(b);
|
||||||
|
|
@ -222,7 +222,7 @@ namespace spot
|
||||||
struct transition {
|
struct transition {
|
||||||
const state* source;
|
const state* source;
|
||||||
bdd label;
|
bdd label;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
const state* dest;
|
const state* dest;
|
||||||
};
|
};
|
||||||
typedef std::list<transition> accepting_transitions_list;
|
typedef std::list<transition> accepting_transitions_list;
|
||||||
|
|
@ -253,7 +253,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dfs(const state* target, accepting_transitions_list& acc_trans,
|
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));
|
assert(h_.has_been_visited(target));
|
||||||
stack_type st1;
|
stack_type st1;
|
||||||
|
|
@ -264,7 +264,7 @@ namespace spot
|
||||||
seen.insert(start);
|
seen.insert(start);
|
||||||
tgba_succ_iterator* i = a_->succ_iter(start);
|
tgba_succ_iterator* i = a_->succ_iter(start);
|
||||||
i->first();
|
i->first();
|
||||||
st1.emplace_front(start, i, bddfalse, bddfalse);
|
st1.emplace_front(start, i, bddfalse, 0U);
|
||||||
|
|
||||||
while (!st1.empty())
|
while (!st1.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -277,7 +277,7 @@ namespace spot
|
||||||
ndfsr_trace << " Visit the successor: "
|
ndfsr_trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
bdd label = f.it->current_condition();
|
||||||
bdd acc = f.it->current_acceptance_conditions();
|
auto acc = f.it->current_acceptance_conditions();
|
||||||
f.it->next();
|
f.it->next();
|
||||||
if (h_.has_been_visited(s_prime))
|
if (h_.has_been_visited(s_prime))
|
||||||
{
|
{
|
||||||
|
|
@ -308,7 +308,7 @@ namespace spot
|
||||||
assert(h_.has_been_visited(t.dest));
|
assert(h_.has_been_visited(t.dest));
|
||||||
acc_trans.push_back(t);
|
acc_trans.push_back(t);
|
||||||
covered_acc |= acc;
|
covered_acc |= acc;
|
||||||
if (covered_acc == a_->all_acceptance_conditions())
|
if (a_->acc().accepting(covered_acc))
|
||||||
{
|
{
|
||||||
clean(a_, st1, seen, dead);
|
clean(a_, st1, seen, dead);
|
||||||
s_prime->destroy();
|
s_prime->destroy();
|
||||||
|
|
@ -337,7 +337,7 @@ namespace spot
|
||||||
stack_item f_dest(f);
|
stack_item f_dest(f);
|
||||||
a_->release_iter(st1.front().it);
|
a_->release_iter(st1.front().it);
|
||||||
st1.pop_front();
|
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"
|
ndfsr_trace << " a propagation is needed, start a search"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
@ -349,8 +349,8 @@ namespace spot
|
||||||
assert(h_.has_been_visited(t.source));
|
assert(h_.has_been_visited(t.source));
|
||||||
assert(h_.has_been_visited(t.dest));
|
assert(h_.has_been_visited(t.dest));
|
||||||
acc_trans.push_back(t);
|
acc_trans.push_back(t);
|
||||||
covered_acc |= f_dest.acc;
|
covered_acc |= f_dest.acc;
|
||||||
if (covered_acc == a_->all_acceptance_conditions())
|
if (a_->acc().accepting(covered_acc))
|
||||||
{
|
{
|
||||||
clean(a_, st1, seen, dead);
|
clean(a_, st1, seen, dead);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -607,6 +607,7 @@ namespace spot
|
||||||
<< a_->format_state(begin) << std::endl;
|
<< a_->format_state(begin) << std::endl;
|
||||||
transition tmp;
|
transition tmp;
|
||||||
tmp.source = tmp.dest = 0; // Initialize to please GCC 4.0.1 (Darwin).
|
tmp.source = tmp.dest = 0; // Initialize to please GCC 4.0.1 (Darwin).
|
||||||
|
tmp.acc = 0U;
|
||||||
target.emplace(begin, tmp);
|
target.emplace(begin, tmp);
|
||||||
min_path<true> s(this, a_, target, h_);
|
min_path<true> s(this, a_, target, h_);
|
||||||
const state* res = s.search(current.dest->clone(), run->cycle);
|
const state* res = s.search(current.dest->clone(), run->cycle);
|
||||||
|
|
@ -621,6 +622,7 @@ namespace spot
|
||||||
m_source_trans target;
|
m_source_trans target;
|
||||||
transition tmp;
|
transition tmp;
|
||||||
tmp.source = tmp.dest = 0; // Initialize to please GCC 4.0.
|
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.
|
// Register all states from the cycle as target of the BFS.
|
||||||
for (tgba_run::steps::const_iterator i = run->cycle.begin();
|
for (tgba_run::steps::const_iterator i = run->cycle.begin();
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace spot
|
||||||
const ltl::formula* f, bool comments)
|
const ltl::formula* f, bool comments)
|
||||||
: tgba_reachable_iterator_breadth_first(a),
|
: tgba_reachable_iterator_breadth_first(a),
|
||||||
os_(os), f_(f), accept_all_(-1), fi_needed_(false),
|
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))
|
sba_(std::dynamic_pointer_cast<const tgba_digraph>(a))
|
||||||
{
|
{
|
||||||
assert(!sba_ || sba_->has_state_based_acc());
|
assert(!sba_ || sba_->has_state_based_acc());
|
||||||
|
|
@ -87,8 +87,8 @@ namespace spot
|
||||||
// is not terribly efficient since we have to create the
|
// is not terribly efficient since we have to create the
|
||||||
// iterator.
|
// iterator.
|
||||||
tgba_succ_iterator* it = aut_->succ_iter(s);
|
tgba_succ_iterator* it = aut_->succ_iter(s);
|
||||||
bool accepting =
|
bool accepting = it->first()
|
||||||
it->first() && it->current_acceptance_conditions() == all_acc_conds_;
|
&& aut_->acc().accepting(it->current_acceptance_conditions());
|
||||||
aut_->release_iter(it);
|
aut_->release_iter(it);
|
||||||
return accepting;
|
return accepting;
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +193,6 @@ namespace spot
|
||||||
bool fi_needed_;
|
bool fi_needed_;
|
||||||
state* init_;
|
state* init_;
|
||||||
bool comments_;
|
bool comments_;
|
||||||
bdd all_acc_conds_;
|
|
||||||
const_tgba_digraph_ptr sba_;
|
const_tgba_digraph_ptr sba_;
|
||||||
};
|
};
|
||||||
} // anonymous
|
} // anonymous
|
||||||
|
|
@ -202,7 +201,7 @@ namespace spot
|
||||||
never_claim_reachable(std::ostream& os, const const_tgba_ptr& g,
|
never_claim_reachable(std::ostream& os, const const_tgba_ptr& g,
|
||||||
const ltl::formula* f, bool comments)
|
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);
|
never_claim_bfs n(g, os, f, comments);
|
||||||
n.run();
|
n.run();
|
||||||
return os;
|
return os;
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ namespace spot
|
||||||
if (type_ == BA)
|
if (type_ == BA)
|
||||||
state_based_ = true;
|
state_based_ = true;
|
||||||
|
|
||||||
int original_acc = a->number_of_acceptance_conditions();
|
int original_acc = a->acc().num_sets();
|
||||||
|
|
||||||
// Remove useless SCCs.
|
// Remove useless SCCs.
|
||||||
if (type_ == Monitor)
|
if (type_ == Monitor)
|
||||||
|
|
@ -237,7 +237,7 @@ namespace spot
|
||||||
if (PREF_ == Deterministic
|
if (PREF_ == Deterministic
|
||||||
&& f
|
&& f
|
||||||
&& f->is_syntactic_recurrence()
|
&& f->is_syntactic_recurrence()
|
||||||
&& sim->number_of_acceptance_conditions() > 1)
|
&& sim->acc().num_sets() > 1)
|
||||||
tmpd = degeneralize_tba(sim);
|
tmpd = degeneralize_tba(sim);
|
||||||
|
|
||||||
auto in = tmpd ? tmpd : sim;
|
auto in = tmpd ? tmpd : sim;
|
||||||
|
|
@ -306,7 +306,7 @@ namespace spot
|
||||||
// because the input TBA might be smaller.
|
// because the input TBA might be smaller.
|
||||||
if (state_based_)
|
if (state_based_)
|
||||||
in = degeneralize(dba);
|
in = degeneralize(dba);
|
||||||
else if (dba->number_of_acceptance_conditions() != 1)
|
else if (dba->acc().num_sets() != 1)
|
||||||
in = degeneralize_tba(dba);
|
in = degeneralize_tba(dba);
|
||||||
else
|
else
|
||||||
in = dba;
|
in = dba;
|
||||||
|
|
@ -354,8 +354,7 @@ namespace spot
|
||||||
// Degeneralize the dba resulting from tba-determinization or
|
// Degeneralize the dba resulting from tba-determinization or
|
||||||
// sat-minimization (which is a TBA) if requested and needed.
|
// sat-minimization (which is a TBA) if requested and needed.
|
||||||
if (dba && !dba_is_wdba && type_ == BA
|
if (dba && !dba_is_wdba && type_ == BA
|
||||||
&& !(dba_is_minimal && state_based_
|
&& !(dba_is_minimal && state_based_ && dba->acc().num_sets() == 1))
|
||||||
&& dba->number_of_acceptance_conditions() == 1))
|
|
||||||
dba = degeneralize(dba);
|
dba = degeneralize(dba);
|
||||||
|
|
||||||
if (dba && sim)
|
if (dba && sim)
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ namespace spot
|
||||||
// print_set(std::cerr, *j) << '\n';
|
// print_set(std::cerr, *j) << '\n';
|
||||||
// }
|
// }
|
||||||
|
|
||||||
bdd acc = aut_->all_acceptance_conditions();
|
auto acc = aut_->acc().all_sets();
|
||||||
for (auto i: all_)
|
for (auto i: all_)
|
||||||
i->acc = acc;
|
i->acc = acc;
|
||||||
return threshold_ != 0 && cycles_left_ == 0;
|
return threshold_ != 0 && cycles_left_ == 0;
|
||||||
|
|
@ -316,7 +316,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
if (f == 0 && neg_aut == 0)
|
if (f == 0 && neg_aut == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (aut->number_of_acceptance_conditions() > 1)
|
if (aut->acc().num_sets() > 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto det = tba_determinize(aut, threshold_states, threshold_cycles);
|
auto det = tba_determinize(aut, threshold_states, threshold_cycles);
|
||||||
|
|
|
||||||
|
|
@ -35,20 +35,12 @@ namespace spot
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
std::string
|
|
||||||
acc(int n)
|
|
||||||
{
|
|
||||||
std::stringstream s;
|
|
||||||
s << n;
|
|
||||||
return "a" + s.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
random_labels(tgba_digraph_ptr aut,
|
random_labels(tgba_digraph_ptr aut,
|
||||||
unsigned src,
|
unsigned src,
|
||||||
unsigned dest,
|
unsigned dest,
|
||||||
int* props, int props_n, float t,
|
int* props, int props_n, float t,
|
||||||
const std::list<bdd>& accs, float a)
|
unsigned n_accs, float a)
|
||||||
{
|
{
|
||||||
int val = 0;
|
int val = 0;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
@ -70,21 +62,18 @@ namespace spot
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
p &= bdd_ibuildcube(val, size, props);
|
p &= bdd_ibuildcube(val, size, props);
|
||||||
|
|
||||||
bdd ac = bddfalse;
|
acc_cond::mark_t m = 0U;
|
||||||
for (std::list<bdd>::const_iterator i = accs.begin();
|
for (unsigned i = 0U; i < n_accs; ++i)
|
||||||
i != accs.end(); ++i)
|
|
||||||
if (drand() < a)
|
if (drand() < a)
|
||||||
ac |= *i;
|
m |= aut->acc().mark(i);
|
||||||
|
aut->new_transition(src, dest, p, m);
|
||||||
aut->new_transition(src, dest, p, ac);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tgba_digraph_ptr
|
tgba_digraph_ptr
|
||||||
random_graph(int n, float d,
|
random_graph(int n, float d,
|
||||||
const ltl::atomic_prop_set* ap, const bdd_dict_ptr& dict,
|
const ltl::atomic_prop_set* ap, const bdd_dict_ptr& dict,
|
||||||
int n_acc, float a, float t,
|
unsigned n_accs, float a, float t)
|
||||||
ltl::environment* env)
|
|
||||||
{
|
{
|
||||||
assert(n > 0);
|
assert(n > 0);
|
||||||
auto res = make_tgba_digraph(dict);
|
auto res = make_tgba_digraph(dict);
|
||||||
|
|
@ -96,20 +85,7 @@ namespace spot
|
||||||
for (auto i: *ap)
|
for (auto i: *ap)
|
||||||
props[pi++] = dict->register_proposition(i, res);
|
props[pi++] = dict->register_proposition(i, res);
|
||||||
|
|
||||||
std::list<bdd> accs;
|
res->set_acceptance_conditions(n_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));
|
|
||||||
|
|
||||||
// Using std::unordered_set instead of std::set for these sets is 3
|
// Using std::unordered_set instead of std::set for these sets is 3
|
||||||
// times slower (tested on a 50000 nodes example).
|
// times slower (tested on a 50000 nodes example).
|
||||||
|
|
@ -162,7 +138,7 @@ namespace spot
|
||||||
std::advance(i, index);
|
std::advance(i, index);
|
||||||
|
|
||||||
// Link it from src.
|
// 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);
|
nodes_to_process.insert(*i);
|
||||||
unreachable_nodes.erase(i);
|
unreachable_nodes.erase(i);
|
||||||
break;
|
break;
|
||||||
|
|
@ -178,7 +154,7 @@ namespace spot
|
||||||
state_randomizer[index] = state_randomizer[possibilities];
|
state_randomizer[index] = state_randomizer[possibilities];
|
||||||
state_randomizer[possibilities] = x;
|
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);
|
auto j = unreachable_nodes.find(x);
|
||||||
if (j != unreachable_nodes.end())
|
if (j != unreachable_nodes.end())
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ namespace spot
|
||||||
/// A density of 1 means all states will be connected to each other.
|
/// 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 ap The list of atomic property that should label the transition.
|
||||||
/// \param dict The bdd_dict to used for this automata.
|
/// \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
|
/// If this number is non null, then there is no guarantee
|
||||||
/// that the generated graph contains an accepting cycle (raise
|
/// that the generated graph contains an accepting cycle (raise
|
||||||
/// the value of \a a to improve the chances).
|
/// the value of \a a to improve the chances).
|
||||||
|
|
@ -49,7 +49,6 @@ namespace spot
|
||||||
/// to an acceptance set.
|
/// to an acceptance set.
|
||||||
/// \param t The probability (between 0.0 and 1.0) that an atomic proposition
|
/// \param t The probability (between 0.0 and 1.0) that an atomic proposition
|
||||||
/// is true.
|
/// 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
|
/// This algorithms is adapted from the one in Fig 6.2 page 48 of
|
||||||
/** \verbatim
|
/** \verbatim
|
||||||
|
|
@ -79,8 +78,7 @@ namespace spot
|
||||||
SPOT_API tgba_digraph_ptr
|
SPOT_API tgba_digraph_ptr
|
||||||
random_graph(int n, float d,
|
random_graph(int n, float d,
|
||||||
const ltl::atomic_prop_set* ap, const bdd_dict_ptr& dict,
|
const ltl::atomic_prop_set* ap, const bdd_dict_ptr& dict,
|
||||||
int n_acc = 0, float a = 0.1, float t = 0.5,
|
unsigned n_accs = 0, float a = 0.1, float t = 0.5);
|
||||||
ltl::environment* env = <l::default_environment::instance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SPOT_TGBAALGOS_RANDOMGRAPH_HH
|
#endif // SPOT_TGBAALGOS_RANDOMGRAPH_HH
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,8 @@ namespace spot
|
||||||
const state* segment_next; // The state immediately after the segment.
|
const state* segment_next; // The state immediately after the segment.
|
||||||
|
|
||||||
// Start from the end of the original cycle, and rewind until all
|
// Start from the end of the original cycle, and rewind until all
|
||||||
// acceptance conditions have been seen.
|
// acceptance sets have been seen.
|
||||||
bdd seen_acc = bddfalse;
|
acc_cond::mark_t seen_acc = 0U;
|
||||||
bdd all_acc = a->all_acceptance_conditions();
|
|
||||||
tgba_run::steps::const_iterator seg = org->cycle.end();
|
tgba_run::steps::const_iterator seg = org->cycle.end();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
@ -112,12 +111,12 @@ namespace spot
|
||||||
--seg;
|
--seg;
|
||||||
seen_acc |= seg->acc;
|
seen_acc |= seg->acc;
|
||||||
}
|
}
|
||||||
while (seen_acc != all_acc);
|
while (!a->acc().accepting(seen_acc));
|
||||||
segment_start = seg->s;
|
segment_start = seg->s;
|
||||||
|
|
||||||
// Now go forward and ends the segment as soon as we have seen all
|
// Now go forward and ends the segment as soon as we have seen all
|
||||||
// acceptance conditions, cloning it in our result along the way.
|
// acceptance sets, cloning it in our result along the way.
|
||||||
seen_acc = bddfalse;
|
seen_acc = 0U;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
assert(seg != org->cycle.end());
|
assert(seg != org->cycle.end());
|
||||||
|
|
@ -128,7 +127,7 @@ namespace spot
|
||||||
|
|
||||||
++seg;
|
++seg;
|
||||||
}
|
}
|
||||||
while (seen_acc != all_acc);
|
while (!a->acc().accepting(seen_acc));
|
||||||
segment_next = seg == org->cycle.end() ? org->cycle.front().s : seg->s;
|
segment_next = seg == org->cycle.end() ? org->cycle.front().s : seg->s;
|
||||||
|
|
||||||
// Close this cycle if needed, that is, compute a cycle going
|
// Close this cycle if needed, that is, compute a cycle going
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,7 @@ namespace spot
|
||||||
int serial = 1;
|
int serial = 1;
|
||||||
const tgba_run::steps* l;
|
const tgba_run::steps* l;
|
||||||
std::string in;
|
std::string in;
|
||||||
bdd all_acc = bddfalse;
|
acc_cond::mark_t all_acc = 0U;
|
||||||
bdd expected_all_acc = a->all_acceptance_conditions();
|
|
||||||
bool all_acc_seen = false;
|
bool all_acc_seen = false;
|
||||||
typedef std::unordered_map<const state*, std::set<int>,
|
typedef std::unordered_map<const state*, std::set<int>,
|
||||||
state_ptr_hash, state_ptr_equal> state_map;
|
state_ptr_hash, state_ptr_equal> state_map;
|
||||||
|
|
@ -116,7 +115,7 @@ namespace spot
|
||||||
|
|
||||||
// expected outgoing transition
|
// expected outgoing transition
|
||||||
bdd label = i->label;
|
bdd label = i->label;
|
||||||
bdd acc = i->acc;
|
acc_cond::mark_t acc = i->acc;
|
||||||
|
|
||||||
// compute the next expected state
|
// compute the next expected state
|
||||||
const state* next;
|
const state* next;
|
||||||
|
|
@ -170,7 +169,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
os << "ERROR: no transition with label="
|
os << "ERROR: no transition with label="
|
||||||
<< bdd_format_formula(a->get_dict(), 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
|
<< " leaving state " << serial
|
||||||
<< " for state " << a->format_state(next) << '\n'
|
<< " for state " << a->format_state(next) << '\n'
|
||||||
<< "The following transitions leave state " << serial
|
<< "The following transitions leave state " << serial
|
||||||
|
|
@ -185,9 +184,7 @@ namespace spot
|
||||||
<< bdd_format_formula(a->get_dict(),
|
<< bdd_format_formula(a->get_dict(),
|
||||||
j->current_condition())
|
j->current_condition())
|
||||||
<< " and acc="
|
<< " and acc="
|
||||||
<< (bdd_format_accset
|
<< a->acc().format(j->current_acceptance_conditions())
|
||||||
(a->get_dict(),
|
|
||||||
j->current_acceptance_conditions()))
|
|
||||||
<< " going to " << a->format_state(s2) << '\n';
|
<< " going to " << a->format_state(s2) << '\n';
|
||||||
s2->destroy();
|
s2->destroy();
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +200,7 @@ namespace spot
|
||||||
print_annotation(os, a, j);
|
print_annotation(os, a, j);
|
||||||
os << " with label="
|
os << " with label="
|
||||||
<< bdd_format_formula(a->get_dict(), 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;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -212,7 +209,7 @@ namespace spot
|
||||||
print_annotation(os, a, j);
|
print_annotation(os, a, j);
|
||||||
bdd_print_formula(os, a->get_dict(), label);
|
bdd_print_formula(os, a->get_dict(), label);
|
||||||
os << '\t';
|
os << '\t';
|
||||||
bdd_print_accset(os, a->get_dict(), acc);
|
a->acc().format(acc);
|
||||||
os << std::endl;
|
os << std::endl;
|
||||||
}
|
}
|
||||||
a->release_iter(j);
|
a->release_iter(j);
|
||||||
|
|
@ -226,24 +223,24 @@ namespace spot
|
||||||
if (l == &run->cycle && i != l->begin())
|
if (l == &run->cycle && i != l->begin())
|
||||||
{
|
{
|
||||||
all_acc |= acc;
|
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;
|
all_acc_seen = true;
|
||||||
if (debug)
|
if (debug)
|
||||||
os << "all acceptance conditions ("
|
os << "all acceptance conditions ("
|
||||||
<< bdd_format_accset(a->get_dict(), all_acc)
|
<< a->acc().format(all_acc)
|
||||||
<< ") have been seen\n";
|
<< ") have been seen\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->destroy();
|
s->destroy();
|
||||||
if (all_acc != expected_all_acc)
|
if (!a->acc().accepting(all_acc))
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
os << "ERROR: The cycle's acceptance conditions ("
|
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 ("
|
<< ") do not\nmatch those of the automaton ("
|
||||||
<< bdd_format_accset(a->get_dict(), expected_all_acc)
|
<< a->acc().format(a->acc().all_sets())
|
||||||
<< ")\n";
|
<< ")\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,6 @@ namespace spot
|
||||||
|
|
||||||
todo.push_back(seen(aut->get_init_state()));
|
todo.push_back(seen(aut->get_init_state()));
|
||||||
|
|
||||||
bdd all_acc = aut->all_acceptance_conditions();
|
|
||||||
|
|
||||||
bool all_accepting = true;
|
bool all_accepting = true;
|
||||||
while (all_accepting && !todo.empty())
|
while (all_accepting && !todo.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -86,8 +84,8 @@ namespace spot
|
||||||
|
|
||||||
for (auto it: aut->succ(s))
|
for (auto it: aut->succ(s))
|
||||||
{
|
{
|
||||||
bdd acc = it->current_acceptance_conditions();
|
auto acc = it->current_acceptance_conditions();
|
||||||
if (acc != all_acc)
|
if (!aut->acc().accepting(acc))
|
||||||
{
|
{
|
||||||
all_accepting = false;
|
all_accepting = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,9 @@ namespace spot
|
||||||
void
|
void
|
||||||
start()
|
start()
|
||||||
{
|
{
|
||||||
os_ << "acc =";
|
os_ << "acc = ";
|
||||||
print_acc(aut_->all_acceptance_conditions()) << ";\n";
|
aut_->acc().format_quoted(os_, aut_->acc().all_sets())
|
||||||
|
<< ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -61,7 +62,10 @@ namespace spot
|
||||||
os_ << "\", \"";
|
os_ << "\", \"";
|
||||||
escape_str(os_, bdd_format_formula(d, si->current_condition()));
|
escape_str(os_, bdd_format_formula(d, si->current_condition()));
|
||||||
os_ << "\",";
|
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();
|
dest->destroy();
|
||||||
}
|
}
|
||||||
while (si->next());
|
while (si->next());
|
||||||
|
|
@ -69,28 +73,6 @@ namespace spot
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream& os_;
|
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)
|
if (scc_map_[n].trivial)
|
||||||
return false;
|
return false;
|
||||||
return acc_set_of(n) == aut_->all_acceptance_conditions();
|
return aut_->acc().accepting(acc_set_of(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
const_tgba_ptr
|
const_tgba_ptr
|
||||||
|
|
@ -139,8 +139,6 @@ namespace spot
|
||||||
void
|
void
|
||||||
scc_map::build_map()
|
scc_map::build_map()
|
||||||
{
|
{
|
||||||
acceptance_convertor conv(aut_->neg_acceptance_conditions());
|
|
||||||
|
|
||||||
// Setup depth-first search from the initial state.
|
// Setup depth-first search from the initial state.
|
||||||
{
|
{
|
||||||
self_loops_ = 0;
|
self_loops_ = 0;
|
||||||
|
|
@ -148,7 +146,7 @@ namespace spot
|
||||||
num_ = -1;
|
num_ = -1;
|
||||||
h_.emplace(init, num_);
|
h_.emplace(init, num_);
|
||||||
root_.emplace_front(num_);
|
root_.emplace_front(num_);
|
||||||
arc_acc_.push(bddfalse);
|
arc_acc_.push(0U);
|
||||||
arc_cond_.push(bddfalse);
|
arc_cond_.push(bddfalse);
|
||||||
tgba_succ_iterator* iter = aut_->succ_iter(init);
|
tgba_succ_iterator* iter = aut_->succ_iter(init);
|
||||||
iter->first();
|
iter->first();
|
||||||
|
|
@ -209,7 +207,7 @@ namespace spot
|
||||||
const state* dest = succ->current_state();
|
const state* dest = succ->current_state();
|
||||||
if (!dest->compare(todo_.top().first))
|
if (!dest->compare(todo_.top().first))
|
||||||
++self_loops_;
|
++self_loops_;
|
||||||
bdd acc = succ->current_acceptance_conditions();
|
auto acc = succ->current_acceptance_conditions();
|
||||||
bdd cond = succ->current_condition();
|
bdd cond = succ->current_condition();
|
||||||
root_.front().supp &= bdd_support(cond);
|
root_.front().supp &= bdd_support(cond);
|
||||||
// ... and point the iterator to the next successor, for
|
// ... and point the iterator to the next successor, for
|
||||||
|
|
@ -268,17 +266,18 @@ namespace spot
|
||||||
cond_set conds;
|
cond_set conds;
|
||||||
conds.insert(cond);
|
conds.insert(cond);
|
||||||
bdd supp = bddtrue;
|
bdd supp = bddtrue;
|
||||||
bdd all = aut_->all_acceptance_conditions();
|
std::set<acc_cond::mark_t> used_acc = { acc };
|
||||||
bdd useful = conv.as_full_product(acc);
|
|
||||||
while (threshold > root_.front().index)
|
while (threshold > root_.front().index)
|
||||||
{
|
{
|
||||||
assert(!root_.empty());
|
assert(!root_.empty());
|
||||||
assert(!arc_acc_.empty());
|
assert(!arc_acc_.empty());
|
||||||
assert(arc_acc_.size() == arc_cond_.size());
|
assert(arc_acc_.size() == arc_cond_.size());
|
||||||
acc |= root_.front().acc;
|
acc |= root_.front().acc;
|
||||||
bdd lacc = arc_acc_.top();
|
auto lacc = arc_acc_.top();
|
||||||
acc |= lacc;
|
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);
|
states.splice(states.end(), root_.front().states);
|
||||||
succs.insert(root_.front().succ.begin(),
|
succs.insert(root_.front().succ.begin(),
|
||||||
root_.front().succ.end());
|
root_.front().succ.end());
|
||||||
|
|
@ -305,7 +304,8 @@ namespace spot
|
||||||
root_.front().supp &= supp;
|
root_.front().supp &= supp;
|
||||||
// This SCC is no longer trivial.
|
// This SCC is no longer trivial.
|
||||||
root_.front().trivial = false;
|
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
|
// 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);
|
assert(scc_map_.size() > n);
|
||||||
return scc_map_[n].acc;
|
return scc_map_[n].acc;
|
||||||
|
|
@ -367,7 +367,7 @@ namespace spot
|
||||||
return scc_map_.size();
|
return scc_map_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd
|
const std::set<acc_cond::mark_t>&
|
||||||
scc_map::useful_acc_of(unsigned n) const
|
scc_map::useful_acc_of(unsigned n) const
|
||||||
{
|
{
|
||||||
assert(scc_map_.size() > n);
|
assert(scc_map_.size() > n);
|
||||||
|
|
@ -449,12 +449,14 @@ namespace spot
|
||||||
res.dead_paths = d.dead_paths[init];
|
res.dead_paths = d.dead_paths[init];
|
||||||
|
|
||||||
res.useless_scc_map.reserve(res.scc_total);
|
res.useless_scc_map.reserve(res.scc_total);
|
||||||
res.useful_acc = bddfalse;
|
|
||||||
for (unsigned n = 0; n < res.scc_total; ++n)
|
for (unsigned n = 0; n < res.scc_total; ++n)
|
||||||
{
|
{
|
||||||
res.useless_scc_map[n] = !d.acc_paths[n];
|
res.useless_scc_map[n] = !d.acc_paths[n];
|
||||||
if (m.accepting(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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -495,8 +497,7 @@ namespace spot
|
||||||
if (n > 1)
|
if (n > 1)
|
||||||
ostr << 's';
|
ostr << 's';
|
||||||
ostr << ")\\naccs=";
|
ostr << ")\\naccs=";
|
||||||
escape_str(ostr, bdd_format_accset(m.get_aut()->get_dict(),
|
escape_str(ostr, m.get_aut()->acc().format(m.acc_set_of(state)));
|
||||||
m.acc_set_of(state)));
|
|
||||||
ostr << "\\nconds=[";
|
ostr << "\\nconds=[";
|
||||||
for (scc_map::cond_set::const_iterator i = cs.begin();
|
for (scc_map::cond_set::const_iterator i = cs.begin();
|
||||||
i != cs.end(); ++i)
|
i != cs.end(); ++i)
|
||||||
|
|
@ -514,8 +515,9 @@ namespace spot
|
||||||
escape_str(ostr, bdd_format_sat(m.get_aut()->get_dict(),
|
escape_str(ostr, bdd_format_sat(m.get_aut()->get_dict(),
|
||||||
m.aprec_set_of(state)));
|
m.aprec_set_of(state)));
|
||||||
ostr << "]\\n useful=[";
|
ostr << "]\\n useful=[";
|
||||||
escape_str(ostr, bdd_format_accset(m.get_aut()->get_dict(),
|
for (auto a: m.useful_acc_of(state))
|
||||||
m.useful_acc_of(state))) << ']';
|
m.get_aut()->acc().format(a);
|
||||||
|
ostr << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
out << " " << state << " [shape=box,"
|
out << " " << state << " [shape=box,"
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ namespace spot
|
||||||
/// The set of useful acceptance conditions (i.e. acceptance
|
/// The set of useful acceptance conditions (i.e. acceptance
|
||||||
/// conditions that are not always implied by other acceptance
|
/// conditions that are not always implied by other acceptance
|
||||||
/// conditions).
|
/// conditions).
|
||||||
bdd useful_acc;
|
std::set<acc_cond::mark_t> useful_acc;
|
||||||
|
|
||||||
std::ostream& dump(std::ostream& out) const;
|
std::ostream& dump(std::ostream& out) const;
|
||||||
};
|
};
|
||||||
|
|
@ -144,13 +144,13 @@ namespace spot
|
||||||
/// \brief Return the set of acceptance conditions occurring in an SCC.
|
/// \brief Return the set of acceptance conditions occurring in an SCC.
|
||||||
///
|
///
|
||||||
/// \pre This should only be called once build_map() has run.
|
/// \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.
|
/// \brief Return the set of useful acceptance conditions of SCC \a n.
|
||||||
///
|
///
|
||||||
/// Useless acceptances conditions are always implied by other acceptances
|
/// Useless acceptances conditions are always implied by other acceptances
|
||||||
/// conditions. This returns all the other acceptance conditions.
|
/// 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.
|
/// \brief Return the set of states of an SCC.
|
||||||
///
|
///
|
||||||
|
|
@ -183,14 +183,14 @@ namespace spot
|
||||||
struct scc
|
struct scc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
scc(int index) : index(index), acc(bddfalse),
|
scc(int index) : index(index), acc(0U),
|
||||||
supp(bddtrue), supp_rec(bddfalse),
|
supp(bddtrue), supp_rec(bddfalse),
|
||||||
trivial(true), useful_acc(bddfalse) {};
|
trivial(true) {};
|
||||||
/// Index of the SCC.
|
/// Index of the SCC.
|
||||||
int index;
|
int index;
|
||||||
/// The union of all acceptance conditions of transitions which
|
/// The union of all acceptance conditions of transitions which
|
||||||
/// connect the states of the connected component.
|
/// connect the states of the connected component.
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
/// States of the component.
|
/// States of the component.
|
||||||
std::list<const state*> states;
|
std::list<const state*> states;
|
||||||
/// Set of conditions used in the SCC.
|
/// Set of conditions used in the SCC.
|
||||||
|
|
@ -204,22 +204,13 @@ namespace spot
|
||||||
/// Trivial SCC have one state and no self-loops.
|
/// Trivial SCC have one state and no self-loops.
|
||||||
bool trivial;
|
bool trivial;
|
||||||
/// \brief Set of acceptance combinations used in the SCC.
|
/// \brief Set of acceptance combinations used in the SCC.
|
||||||
///
|
std::set<acc_cond::mark_t> useful_acc;
|
||||||
/// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const_tgba_ptr aut_; // Automata to decompose.
|
const_tgba_ptr aut_; // Automata to decompose.
|
||||||
typedef std::list<scc> stack_type;
|
typedef std::list<scc> stack_type;
|
||||||
stack_type root_; // Stack of SCC roots.
|
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.
|
// between each of these SCC.
|
||||||
std::stack<bdd> arc_cond_; // A stack of conditions
|
std::stack<bdd> arc_cond_; // A stack of conditions
|
||||||
// between each of these SCC.
|
// between each of these SCC.
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,7 @@ namespace spot
|
||||||
typedef std::map<int, unsigned> accremap_t;
|
typedef std::map<int, unsigned> accremap_t;
|
||||||
typedef std::vector<accremap_t> remap_table_t;
|
typedef std::vector<accremap_t> remap_table_t;
|
||||||
|
|
||||||
typedef std::tuple<bool, bdd, bdd> filtered_trans;
|
typedef std::tuple<bool, bdd, acc_cond::mark_t> filtered_trans;
|
||||||
typedef std::pair<bdd, bdd> acc_pair;
|
|
||||||
|
|
||||||
|
|
||||||
// SCC filters are objects with two methods:
|
// SCC filters are objects with two methods:
|
||||||
|
|
@ -53,13 +52,13 @@ namespace spot
|
||||||
return true;
|
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
|
// 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};
|
return filtered_trans{true, cond, acc};
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +100,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered_trans trans(unsigned src, unsigned dst,
|
filtered_trans trans(unsigned src, unsigned dst,
|
||||||
bdd cond, bdd acc)
|
bdd cond, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
bool keep;
|
bool keep;
|
||||||
std::tie(keep, cond, acc) =
|
std::tie(keep, cond, acc) =
|
||||||
|
|
@ -137,7 +136,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered_trans trans(unsigned src, unsigned dst,
|
filtered_trans trans(unsigned src, unsigned dst,
|
||||||
bdd cond, bdd acc)
|
bdd cond, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
bool keep;
|
bool keep;
|
||||||
std::tie(keep, cond, acc) =
|
std::tie(keep, cond, acc) =
|
||||||
|
|
@ -149,7 +148,7 @@ namespace spot
|
||||||
// If the transition is between two SCCs, or in a
|
// If the transition is between two SCCs, or in a
|
||||||
// non-accepting SCC. Remove the acceptance sets.
|
// non-accepting SCC. Remove the acceptance sets.
|
||||||
if (!this->si->is_accepting_scc(u) || u != this->si->scc_of(dst))
|
if (!this->si->is_accepting_scc(u) || u != this->si->scc_of(dst))
|
||||||
acc = bddfalse;
|
acc = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered_trans(keep, cond, acc);
|
return filtered_trans(keep, cond, acc);
|
||||||
|
|
@ -168,14 +167,14 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered_trans trans(unsigned src, unsigned dst,
|
filtered_trans trans(unsigned src, unsigned dst,
|
||||||
bdd cond, bdd acc)
|
bdd cond, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
bool keep;
|
bool keep;
|
||||||
std::tie(keep, cond, acc) =
|
std::tie(keep, cond, acc) =
|
||||||
this->next_filter::trans(src, dst, cond, acc);
|
this->next_filter::trans(src, dst, cond, acc);
|
||||||
|
|
||||||
if (!this->si->is_accepting_scc(this->si->scc_of(dst)))
|
if (!this->si->is_accepting_scc(this->si->scc_of(dst)))
|
||||||
acc = bddfalse;
|
acc = 0U;
|
||||||
return filtered_trans(keep, cond, acc);
|
return filtered_trans(keep, cond, acc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -184,10 +183,8 @@ namespace spot
|
||||||
template <class next_filter = id_filter>
|
template <class next_filter = id_filter>
|
||||||
struct acc_filter_simplify: next_filter
|
struct acc_filter_simplify: next_filter
|
||||||
{
|
{
|
||||||
std::vector<bdd> acc_;
|
// Acceptance sets to strip in each SCC.
|
||||||
typedef std::map<int, bdd> map_t;
|
std::vector<acc_cond::mark_t> strip_;
|
||||||
typedef std::vector<map_t> remap_t;
|
|
||||||
remap_t remap_;
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
acc_filter_simplify(scc_info* si, Args&&... 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();
|
unsigned scc_count = this->si->scc_count();
|
||||||
remap_table_t remap_table(scc_count);
|
auto& acc = this->si->get_aut()->acc();
|
||||||
std::vector<unsigned> max_table(scc_count);
|
assert(n == acc.num_sets());
|
||||||
std::vector<bdd> useful_table(scc_count);
|
(void) n;
|
||||||
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 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)
|
for (unsigned n = 0; n < scc_count; ++n)
|
||||||
{
|
{
|
||||||
if (!this->si->is_accepting_scc(n))
|
if (!this->si->is_accepting_scc(n))
|
||||||
continue;
|
continue;
|
||||||
bdd all = used_acc[n];
|
strip_[n] = acc.useless(used_acc[n].begin(), used_acc[n].end());
|
||||||
|
cnt[n] = acc.num_sets() - strip_[n].count();
|
||||||
//std::cerr << "SCC #" << n << "; used = " << all << std::endl;
|
if (cnt[n] > max)
|
||||||
|
max = cnt[n];
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
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
|
// Now that we know about the max number of acceptance
|
||||||
// conditions, add extra acceptance conditions to those SCC
|
// conditions, add extra acceptance conditions to those SCC
|
||||||
// that do not have enough.
|
// that do not have enough.
|
||||||
|
|
@ -314,118 +220,30 @@ namespace spot
|
||||||
{
|
{
|
||||||
if (!this->si->is_accepting_scc(n))
|
if (!this->si->is_accepting_scc(n))
|
||||||
continue;
|
continue;
|
||||||
//std::cerr << "SCC " << n << '\n';
|
if (cnt[n] < max)
|
||||||
bdd useful = useful_table[n];
|
strip_[n].remove_some(max - cnt[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);
|
|
||||||
}
|
|
||||||
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;
|
bool keep;
|
||||||
std::tie(keep, cond, acc) =
|
std::tie(keep, cond, acc) =
|
||||||
this->next_filter::trans(src, dst, cond, acc);
|
this->next_filter::trans(src, dst, cond, acc);
|
||||||
|
|
||||||
if (keep && acc != bddfalse)
|
if (keep && acc)
|
||||||
{
|
{
|
||||||
unsigned u = this->si->scc_of(dst);
|
unsigned u = this->si->scc_of(dst);
|
||||||
|
|
||||||
auto i = remap_[u].find(acc.id());
|
if (!this->si->is_accepting_scc(u))
|
||||||
if (i != remap_[u].end())
|
acc = 0U;
|
||||||
acc = i->second;
|
|
||||||
else
|
else
|
||||||
acc = bddfalse;
|
acc = this->si->get_aut()->acc().strip(acc, strip_[u]);
|
||||||
}
|
}
|
||||||
return filtered_trans{keep, cond, acc};
|
return filtered_trans{keep, cond, acc};
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -456,11 +274,8 @@ namespace spot
|
||||||
else
|
else
|
||||||
inout.push_back(-1U);
|
inout.push_back(-1U);
|
||||||
|
|
||||||
{
|
filtered->
|
||||||
bdd all = aut->all_acceptance_conditions();
|
set_acceptance_conditions(filter.accsets(aut->acc().num_sets()));
|
||||||
bdd neg = aut->neg_acceptance_conditions();
|
|
||||||
filtered->set_acceptance_conditions(filter.accsets(all, neg).first);
|
|
||||||
}
|
|
||||||
filtered->new_states(out_n);
|
filtered->new_states(out_n);
|
||||||
for (unsigned isrc = 0; isrc < in_n; ++isrc)
|
for (unsigned isrc = 0; isrc < in_n; ++isrc)
|
||||||
{
|
{
|
||||||
|
|
@ -474,7 +289,7 @@ namespace spot
|
||||||
continue;
|
continue;
|
||||||
bool want;
|
bool want;
|
||||||
bdd cond;
|
bdd cond;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
std::tie(want, cond, acc) =
|
std::tie(want, cond, acc) =
|
||||||
filter.trans(isrc, t.dst, t.cond, t.acc);
|
filter.trans(isrc, t.dst, t.cond, t.acc);
|
||||||
if (want)
|
if (want)
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,14 @@ namespace spot
|
||||||
struct scc
|
struct scc
|
||||||
{
|
{
|
||||||
public:
|
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)
|
index(index), in_cond(in_cond), in_acc(in_acc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int index; // Index of the SCC
|
int index; // Index of the SCC
|
||||||
bdd in_cond; // Condition on incoming transition
|
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;
|
scc_info::scc_node node;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,6 @@ namespace spot
|
||||||
{
|
{
|
||||||
unsigned n = aut->num_states();
|
unsigned n = aut->num_states();
|
||||||
sccof_.resize(n, -1U);
|
sccof_.resize(n, -1U);
|
||||||
bdd all_acc = aut->all_acceptance_conditions();
|
|
||||||
|
|
||||||
typedef std::list<scc> stack_type;
|
typedef std::list<scc> stack_type;
|
||||||
stack_type root_; // Stack of SCC roots.
|
stack_type root_; // Stack of SCC roots.
|
||||||
|
|
@ -81,7 +80,7 @@ namespace spot
|
||||||
unsigned init = aut->get_init_state_number();
|
unsigned init = aut->get_init_state_number();
|
||||||
num_ = -1;
|
num_ = -1;
|
||||||
h_[init] = num_;
|
h_[init] = num_;
|
||||||
root_.emplace_front(num_, bddfalse, bddfalse);
|
root_.emplace_front(num_, bddfalse, 0U);
|
||||||
todo_.emplace(init, aut->out(init).begin());
|
todo_.emplace(init, aut->out(init).begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,12 +116,12 @@ namespace spot
|
||||||
h_[s] = num + 1;
|
h_[s] = num + 1;
|
||||||
}
|
}
|
||||||
bdd cond = root_.front().in_cond;
|
bdd cond = root_.front().in_cond;
|
||||||
bdd acc = root_.front().node.acc;
|
auto acc = root_.front().node.acc;
|
||||||
bool triv = root_.front().node.trivial;
|
bool triv = root_.front().node.trivial;
|
||||||
node_.emplace_back(acc, triv);
|
node_.emplace_back(acc, triv);
|
||||||
std::swap(node_.back().succ, root_.front().node.succ);
|
std::swap(node_.back().succ, root_.front().node.succ);
|
||||||
std::swap(node_.back().states, root_.front().node.states);
|
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();
|
root_.pop_front();
|
||||||
// Record the transition between the SCC being popped
|
// Record the transition between the SCC being popped
|
||||||
// and the previous SCC.
|
// and the previous SCC.
|
||||||
|
|
@ -135,7 +134,7 @@ namespace spot
|
||||||
// We have a successor to look at.
|
// We have a successor to look at.
|
||||||
// Fetch the values we are interested in...
|
// Fetch the values we are interested in...
|
||||||
unsigned dest = succ->dst;
|
unsigned dest = succ->dst;
|
||||||
bdd acc = succ->acc;
|
auto acc = succ->acc;
|
||||||
bdd cond = succ->cond;
|
bdd cond = succ->cond;
|
||||||
++todo_.top().second;
|
++todo_.top().second;
|
||||||
|
|
||||||
|
|
@ -191,7 +190,8 @@ namespace spot
|
||||||
while (threshold > root_.front().index)
|
while (threshold > root_.front().index)
|
||||||
{
|
{
|
||||||
assert(!root_.empty());
|
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);
|
states.splice(states.end(), root_.front().node.states);
|
||||||
|
|
||||||
succs.insert(succs.end(),
|
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();
|
unsigned n = aut_->num_states();
|
||||||
std::vector<bdd> result(scc_count());
|
std::vector<std::set<acc_cond::mark_t>> result(scc_count());
|
||||||
acceptance_convertor conv(aut_->neg_acceptance_conditions());
|
|
||||||
|
|
||||||
for (unsigned src = 0; src < n; ++src)
|
for (unsigned src = 0; src < n; ++src)
|
||||||
{
|
{
|
||||||
unsigned src_scc = scc_of(src);
|
unsigned src_scc = scc_of(src);
|
||||||
if (src_scc == -1U || !is_accepting_scc(src_scc))
|
if (src_scc == -1U || !is_accepting_scc(src_scc))
|
||||||
continue;
|
continue;
|
||||||
|
auto& s = result[src_scc];
|
||||||
for (auto& t: aut_->out(src))
|
for (auto& t: aut_->out(src))
|
||||||
{
|
{
|
||||||
if (scc_of(t.dst) != src_scc)
|
if (scc_of(t.dst) != src_scc)
|
||||||
continue;
|
continue;
|
||||||
result[src_scc] |= conv.as_full_product(t.acc);
|
s.insert(t.acc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -255,9 +255,8 @@ namespace spot
|
||||||
unsigned n = scc_count();
|
unsigned n = scc_count();
|
||||||
std::vector<bool> result(scc_count());
|
std::vector<bool> result(scc_count());
|
||||||
auto acc = used_acc();
|
auto acc = used_acc();
|
||||||
bdd all = bdd_support(aut_->neg_acceptance_conditions());
|
|
||||||
for (unsigned s = 0; s < n; ++s)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,8 +275,6 @@ namespace spot
|
||||||
{
|
{
|
||||||
scc_info* m = sccinfo ? sccinfo : new scc_info(aut);
|
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";
|
out << "digraph G {\n i [label=\"\", style=invis, height=0]\n";
|
||||||
int start = m->scc_of(aut->get_init_state_number());
|
int start = m->scc_of(aut->get_init_state_number());
|
||||||
out << " i -> " << start << std::endl;
|
out << " i -> " << start << std::endl;
|
||||||
|
|
@ -293,7 +290,7 @@ namespace spot
|
||||||
q.pop();
|
q.pop();
|
||||||
|
|
||||||
out << " " << state << " [shape=box,"
|
out << " " << state << " [shape=box,"
|
||||||
<< (m->acc(state) == all_acc ? "style=bold," : "")
|
<< (aut->acc().accepting(m->acc(state)) ? "style=bold," : "")
|
||||||
<< "label=\"" << state;
|
<< "label=\"" << state;
|
||||||
{
|
{
|
||||||
size_t n = m->states_of(state).size();
|
size_t n = m->states_of(state).size();
|
||||||
|
|
|
||||||
|
|
@ -45,17 +45,17 @@ namespace spot
|
||||||
struct scc_node
|
struct scc_node
|
||||||
{
|
{
|
||||||
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)
|
acc(acc), trivial(trivial)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_succs succ;
|
scc_succs succ;
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
std::list<unsigned> states; // States of the component
|
std::list<unsigned> states; // States of the component
|
||||||
bool trivial:1;
|
bool trivial:1;
|
||||||
bool accepting:1;
|
bool accepting:1;
|
||||||
|
|
@ -114,7 +114,7 @@ namespace spot
|
||||||
return node(scc).trivial;
|
return node(scc).trivial;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd acc(unsigned scc) const
|
acc_cond::mark_t acc(unsigned scc) const
|
||||||
{
|
{
|
||||||
return node(scc).acc;
|
return node(scc).acc;
|
||||||
}
|
}
|
||||||
|
|
@ -134,18 +134,9 @@ namespace spot
|
||||||
return reachable_state(st) && node(scc_of(st)).useful;
|
return reachable_state(st) && node(scc_of(st)).useful;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Return the set of all used acceptance combinations, for
|
/// \brief Return the set of all used acceptance combinations, for
|
||||||
/// each accepting SCC.
|
/// each accepting SCC.
|
||||||
///
|
std::vector<std::set<acc_cond::mark_t>> used_acc() const;
|
||||||
/// 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<bool> weak_sccs() const;
|
std::vector<bool> weak_sccs() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,9 @@ namespace spot
|
||||||
se05_search(const const_tgba_ptr a, size_t size,
|
se05_search(const const_tgba_ptr a, size_t size,
|
||||||
option_map o = option_map())
|
option_map o = option_map())
|
||||||
: emptiness_check(a, o),
|
: emptiness_check(a, o),
|
||||||
h(size),
|
h(size)
|
||||||
all_cond(a->all_acceptance_conditions())
|
|
||||||
{
|
{
|
||||||
assert(a->number_of_acceptance_conditions() <= 1);
|
assert(a->acc().num_sets() <= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~se05_search()
|
virtual ~se05_search()
|
||||||
|
|
@ -98,7 +97,7 @@ namespace spot
|
||||||
const state* s0 = a_->get_init_state();
|
const state* s0 = a_->get_init_state();
|
||||||
inc_states();
|
inc_states();
|
||||||
h.add_new_state(s0, CYAN);
|
h.add_new_state(s0, CYAN);
|
||||||
push(st_blue, s0, bddfalse, bddfalse);
|
push(st_blue, s0, bddfalse, 0U);
|
||||||
if (dfs_blue())
|
if (dfs_blue())
|
||||||
return std::make_shared<se05_result>(t, options());
|
return std::make_shared<se05_result>(t, options());
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +150,7 @@ namespace spot
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void push(stack_type& st, const state* s,
|
void push(stack_type& st, const state* s,
|
||||||
const bdd& label, const bdd& acc)
|
const bdd& label, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
inc_depth();
|
inc_depth();
|
||||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||||
|
|
@ -176,9 +175,6 @@ namespace spot
|
||||||
/// by the last dfs visiting it.
|
/// by the last dfs visiting it.
|
||||||
heap h;
|
heap h;
|
||||||
|
|
||||||
/// The unique acceptance condition of the automaton \a a.
|
|
||||||
bdd all_cond;
|
|
||||||
|
|
||||||
bool dfs_blue()
|
bool dfs_blue()
|
||||||
{
|
{
|
||||||
while (!st_blue.empty())
|
while (!st_blue.empty())
|
||||||
|
|
@ -191,7 +187,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
@ -203,8 +199,9 @@ namespace spot
|
||||||
h.add_new_state(s_prime, CYAN);
|
h.add_new_state(s_prime, CYAN);
|
||||||
push(st_blue, s_prime, label, acc);
|
push(st_blue, s_prime, label, acc);
|
||||||
}
|
}
|
||||||
else if (c.get_color() == CYAN && (acc == all_cond ||
|
else if (c.get_color() == CYAN && (a_->acc().accepting(acc) ||
|
||||||
(f.s->compare(s_prime) != 0 && f.acc == all_cond)))
|
(f.s->compare(s_prime) != 0
|
||||||
|
&& a_->acc().accepting(f.acc))))
|
||||||
{
|
{
|
||||||
trace << " It is cyan and acceptance condition "
|
trace << " It is cyan and acceptance condition "
|
||||||
<< "is reached, report cycle" << std::endl;
|
<< "is reached, report cycle" << std::endl;
|
||||||
|
|
@ -212,7 +209,7 @@ namespace spot
|
||||||
push(st_red, s_prime, label, acc);
|
push(st_red, s_prime, label, acc);
|
||||||
return true;
|
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 test 'c.get_color() != RED' is added to limit
|
||||||
// the number of runs reported by successive
|
// 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);
|
typename heap::color_ref c = h.get_color_ref(f_dest.s);
|
||||||
assert(!c.is_white());
|
assert(!c.is_white());
|
||||||
if (!st_blue.empty() &&
|
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 test 'c.get_color() != RED' is added to limit
|
||||||
// the number of runs reported by successive
|
// the number of runs reported by successive
|
||||||
|
|
@ -281,7 +278,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,30 @@ namespace spot
|
||||||
protected:
|
protected:
|
||||||
// Shortcut used in update_po and go_to_next_it.
|
// Shortcut used in update_po and go_to_next_it.
|
||||||
typedef std::map<bdd, bdd, bdd_less_than> map_bdd_bdd;
|
typedef std::map<bdd, bdd, bdd_less_than> map_bdd_bdd;
|
||||||
|
int acc_vars;
|
||||||
public:
|
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,
|
direct_simulation(const const_tgba_ptr& t,
|
||||||
const map_constraint* map_cst = 0)
|
const map_constraint* map_cst = 0)
|
||||||
: a_(0),
|
: a_(0),
|
||||||
|
|
@ -234,9 +257,6 @@ namespace spot
|
||||||
old_a_ = a_;
|
old_a_ = a_;
|
||||||
|
|
||||||
|
|
||||||
acc_compl ac(a_->all_acceptance_conditions(),
|
|
||||||
a_->neg_acceptance_conditions());
|
|
||||||
|
|
||||||
// Replace all the acceptance conditions by their complements.
|
// Replace all the acceptance conditions by their complements.
|
||||||
// (In the case of Cosimulation, we also flip the transitions.)
|
// (In the case of Cosimulation, we also flip the transitions.)
|
||||||
{
|
{
|
||||||
|
|
@ -253,7 +273,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
for (auto& t: old_a_->out(s))
|
for (auto& t: old_a_->out(s))
|
||||||
{
|
{
|
||||||
bdd acc;
|
acc_cond::mark_t acc;
|
||||||
if (Sba && Cosimulation)
|
if (Sba && Cosimulation)
|
||||||
{
|
{
|
||||||
// If the acceptance is interpreted as
|
// If the acceptance is interpreted as
|
||||||
|
|
@ -262,16 +282,16 @@ namespace spot
|
||||||
// the destination state on its incoming arcs
|
// the destination state on its incoming arcs
|
||||||
// (which now become outgoing arcs after
|
// (which now become outgoing arcs after
|
||||||
// transposition).
|
// transposition).
|
||||||
acc = bddfalse;
|
acc = 0U;
|
||||||
for (auto& td: old_a_->out(t.dst))
|
for (auto& td: old_a_->out(t.dst))
|
||||||
{
|
{
|
||||||
acc = ac.complement(td.acc);
|
acc = old_a_->acc().comp(td.acc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
acc = ac.complement(t.acc);
|
acc = old_a_->acc().comp(t.acc);
|
||||||
}
|
}
|
||||||
if (Cosimulation)
|
if (Cosimulation)
|
||||||
a_->new_transition(t.dst, s, t.cond, acc);
|
a_->new_transition(t.dst, s, t.cond, acc);
|
||||||
|
|
@ -288,8 +308,13 @@ namespace spot
|
||||||
unsigned set_num = a_->get_dict()
|
unsigned set_num = a_->get_dict()
|
||||||
->register_anonymous_variables(size_a_ + 1, this);
|
->register_anonymous_variables(size_a_ + 1, this);
|
||||||
|
|
||||||
all_acceptance_conditions_ = a_->all_acceptance_conditions();
|
unsigned n_acc = a_->acc().num_sets();
|
||||||
all_proms_ = bdd_support(all_acceptance_conditions_);
|
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_initial = bdd_ithvar(set_num++);
|
||||||
bdd init = bdd_ithvar(set_num++);
|
bdd init = bdd_ithvar(set_num++);
|
||||||
|
|
@ -397,7 +422,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
acc = t.acc;
|
acc = mark_to_bdd(t.acc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// to_add is a conjunction of the acceptance condition,
|
// to_add is a conjunction of the acceptance condition,
|
||||||
|
|
@ -527,23 +552,14 @@ namespace spot
|
||||||
// Build the minimal resulting automaton.
|
// Build the minimal resulting automaton.
|
||||||
tgba_digraph_ptr build_result()
|
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());
|
tgba_digraph_ptr res = make_tgba_digraph(a_->get_dict());
|
||||||
res->copy_ap_of(a_);
|
res->copy_ap_of(a_);
|
||||||
res->set_acceptance_conditions(all_acceptance_conditions_);
|
res->copy_acceptance_conditions_of(a_);
|
||||||
if (Sba)
|
if (Sba)
|
||||||
res->prop_state_based_acc();
|
res->prop_state_based_acc();
|
||||||
|
|
||||||
bdd sup_all_acc = bdd_support(all_acceptance_conditions_);
|
|
||||||
// Non atomic propositions variables (= acc and class)
|
// 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>();
|
auto* gb = res->create_namer<int>();
|
||||||
|
|
||||||
|
|
@ -558,9 +574,9 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acceptance of states. Only used if Sba && Cosimulation.
|
// Acceptance of states. Only used if Sba && Cosimulation.
|
||||||
std::vector<bdd> accst;
|
std::vector<acc_cond::mark_t> accst;
|
||||||
if (Sba && Cosimulation)
|
if (Sba && Cosimulation)
|
||||||
accst.resize(res->num_states(), bddfalse);
|
accst.resize(res->num_states(), 0U);
|
||||||
|
|
||||||
stat.states = bdd_lstate_.size();
|
stat.states = bdd_lstate_.size();
|
||||||
stat.transitions = 0;
|
stat.transitions = 0;
|
||||||
|
|
@ -626,7 +642,8 @@ namespace spot
|
||||||
all_class_var_);
|
all_class_var_);
|
||||||
|
|
||||||
// Keep only ones who are acceptance condition.
|
// 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!
|
// Keep the other!
|
||||||
bdd cond = bdd_existcomp(cond_acc_dest,
|
bdd cond = bdd_existcomp(cond_acc_dest,
|
||||||
|
|
@ -635,7 +652,7 @@ namespace spot
|
||||||
// Because we have complemented all the acceptance
|
// Because we have complemented all the acceptance
|
||||||
// conditions on the input automaton, we must
|
// conditions on the input automaton, we must
|
||||||
// revert them to create a new transition.
|
// revert them to create a new transition.
|
||||||
acc = reverser.reverse_complement(acc);
|
acc = res->acc().comp(acc);
|
||||||
|
|
||||||
if (Cosimulation)
|
if (Cosimulation)
|
||||||
{
|
{
|
||||||
|
|
@ -647,7 +664,7 @@ namespace spot
|
||||||
// can't do this here, store this in a table
|
// can't do this here, store this in a table
|
||||||
// so we can fix it later.
|
// so we can fix it later.
|
||||||
accst[gb->get_state(src.id())] = acc;
|
accst[gb->get_state(src.id())] = acc;
|
||||||
acc = bddfalse;
|
acc = 0U;
|
||||||
}
|
}
|
||||||
gb->new_transition(dst.id(), src.id(), cond, acc);
|
gb->new_transition(dst.id(), src.id(), cond, acc);
|
||||||
}
|
}
|
||||||
|
|
@ -671,8 +688,8 @@ namespace spot
|
||||||
unsigned ns = res->num_states();
|
unsigned ns = res->num_states();
|
||||||
for (unsigned s = 0; s < ns; ++s)
|
for (unsigned s = 0; s < ns; ++s)
|
||||||
{
|
{
|
||||||
bdd acc = accst[s];
|
acc_cond::mark_t acc = accst[s];
|
||||||
if (acc == bddfalse)
|
if (acc == 0U)
|
||||||
continue;
|
continue;
|
||||||
for (auto& t: res->out(s))
|
for (auto& t: res->out(s))
|
||||||
t.acc = acc;
|
t.acc = acc;
|
||||||
|
|
@ -774,8 +791,6 @@ namespace spot
|
||||||
const map_constraint* map_cst_;
|
const map_constraint* map_cst_;
|
||||||
|
|
||||||
const_tgba_ptr original_;
|
const_tgba_ptr original_;
|
||||||
|
|
||||||
bdd all_acceptance_conditions_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// For now, we don't try to handle cosimulation.
|
// For now, we don't try to handle cosimulation.
|
||||||
|
|
@ -807,8 +822,7 @@ namespace spot
|
||||||
// simulation to run.
|
// simulation to run.
|
||||||
has_limit_ = false;
|
has_limit_ = false;
|
||||||
|
|
||||||
notap = (bdd_support(all_acceptance_conditions_)
|
notap = bdd_support(all_proms_) & all_class_var_ & on_cycle_;
|
||||||
& all_class_var_ & on_cycle_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function computes the don't care signature of the state
|
// 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))
|
if (scc != scc_info_->scc_of(t.dst))
|
||||||
acc = !on_cycle_;
|
acc = !on_cycle_;
|
||||||
else if (sccacc)
|
else if (sccacc)
|
||||||
acc = on_cycle_ & t.acc;
|
acc = on_cycle_ & mark_to_bdd(t.acc);
|
||||||
else
|
else
|
||||||
acc = on_cycle_ & all_proms_;
|
acc = on_cycle_ & all_proms_;
|
||||||
|
|
||||||
bdd to_add = acc & t.cond & relation_[cl];
|
bdd to_add = acc & t.cond & relation_[cl];
|
||||||
res |= to_add;
|
res |= to_add;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -864,9 +879,6 @@ namespace spot
|
||||||
bool could_imply_aux(bdd f1, bdd g1, bdd left_class,
|
bool could_imply_aux(bdd f1, bdd g1, bdd left_class,
|
||||||
bdd right, bdd right_class)
|
bdd right, bdd right_class)
|
||||||
{
|
{
|
||||||
(void) left_class;
|
|
||||||
(void) right_class;
|
|
||||||
|
|
||||||
bdd f2g2 = bdd_exist(right, on_cycle_);
|
bdd f2g2 = bdd_exist(right, on_cycle_);
|
||||||
bdd f2g2n = bdd_exist(f2g2, all_proms_);
|
bdd f2g2n = bdd_exist(f2g2, all_proms_);
|
||||||
|
|
||||||
|
|
@ -973,8 +985,7 @@ namespace spot
|
||||||
bdd b = bdd_exist(right, notap);
|
bdd b = bdd_exist(right, notap);
|
||||||
bdd add = bdd_exist(left & b, bdd_support(b));
|
bdd add = bdd_exist(left & b, bdd_support(b));
|
||||||
|
|
||||||
if (add != bddfalse
|
if (add != bddfalse && bdd_exist(add, all_proms_) == bddtrue)
|
||||||
&& bdd_exist(add, all_acceptance_conditions_) == bddtrue)
|
|
||||||
{
|
{
|
||||||
assert(src_right != dst_right);
|
assert(src_right != dst_right);
|
||||||
|
|
||||||
|
|
@ -988,8 +999,7 @@ namespace spot
|
||||||
bdd b = bdd_exist(left, notap);
|
bdd b = bdd_exist(left, notap);
|
||||||
bdd add = bdd_exist(right & b, bdd_support(b));
|
bdd add = bdd_exist(right & b, bdd_support(b));
|
||||||
|
|
||||||
if (add != bddfalse
|
if (add != bddfalse && bdd_exist(add, all_proms_) == bddtrue)
|
||||||
&& bdd_exist(add, all_acceptance_conditions_) == bddtrue)
|
|
||||||
{
|
{
|
||||||
assert(src_left != dst_left);
|
assert(src_left != dst_left);
|
||||||
|
|
||||||
|
|
@ -1003,8 +1013,7 @@ namespace spot
|
||||||
bdd b = bdd_exist(left, notap);
|
bdd b = bdd_exist(left, notap);
|
||||||
bdd add = bdd_exist(right & b, bdd_support(b));
|
bdd add = bdd_exist(right & b, bdd_support(b));
|
||||||
|
|
||||||
if (add != bddfalse
|
if (add != bddfalse && bdd_exist(add, all_proms_) == bddtrue)
|
||||||
&& bdd_exist(add, all_acceptance_conditions_) == bddtrue)
|
|
||||||
{
|
{
|
||||||
assert(src_left != dst_left && src_right != dst_right);
|
assert(src_left != dst_left && src_right != dst_right);
|
||||||
// FIXME: cas pas compris.
|
// FIXME: cas pas compris.
|
||||||
|
|
@ -1174,6 +1183,9 @@ namespace spot
|
||||||
}
|
}
|
||||||
while (diff != bddtrue);
|
while (diff != bddtrue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for (auto& i: class2state)
|
for (auto& i: class2state)
|
||||||
assert(previous_class_[i.second] == i.first);
|
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
|
SPOT_API tgba_digraph_ptr
|
||||||
dont_care_simulation(const const_tgba_ptr& t, int limit = -1);
|
dont_care_simulation(const const_tgba_ptr& t, int limit = -1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has('a'))
|
if (has('a'))
|
||||||
acc_ = aut->number_of_acceptance_conditions();
|
acc_ = aut->acc().num_sets();
|
||||||
|
|
||||||
if (has('c') || has('S'))
|
if (has('c') || has('S'))
|
||||||
scc_ = scc_info(aut).scc_count();
|
scc_ = scc_info(aut).scc_count();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace spot
|
||||||
unsigned n = a->num_states();
|
unsigned n = a->num_states();
|
||||||
for (unsigned s = 0; s < n; ++s)
|
for (unsigned s = 0; s < n; ++s)
|
||||||
for (auto& t: a->out(s))
|
for (auto& t: a->out(s))
|
||||||
t.acc = bddfalse;
|
t.acc = 0U;
|
||||||
a->set_acceptance_conditions(bddfalse);
|
a->set_acceptance_conditions(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,9 @@ namespace spot
|
||||||
/// \brief Initialize the search algorithm on the automaton \a a
|
/// \brief Initialize the search algorithm on the automaton \a a
|
||||||
tau03_search(const const_tgba_ptr a, size_t size, option_map o)
|
tau03_search(const const_tgba_ptr a, size_t size, option_map o)
|
||||||
: emptiness_check(a, o),
|
: emptiness_check(a, o),
|
||||||
h(size),
|
h(size)
|
||||||
all_cond(a->all_acceptance_conditions())
|
|
||||||
{
|
{
|
||||||
assert(a->number_of_acceptance_conditions() > 0);
|
assert(a->acc().num_sets() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~tau03_search()
|
virtual ~tau03_search()
|
||||||
|
|
@ -91,7 +90,7 @@ namespace spot
|
||||||
const state* s0 = a_->get_init_state();
|
const state* s0 = a_->get_init_state();
|
||||||
inc_states();
|
inc_states();
|
||||||
h.add_new_state(s0, BLUE);
|
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>
|
auto t = std::static_pointer_cast<tau03_search>
|
||||||
(this->emptiness_check::shared_from_this());
|
(this->emptiness_check::shared_from_this());
|
||||||
if (dfs_blue())
|
if (dfs_blue())
|
||||||
|
|
@ -124,7 +123,7 @@ namespace spot
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void push(stack_type& st, const state* s,
|
void push(stack_type& st, const state* s,
|
||||||
const bdd& label, const bdd& acc)
|
const bdd& label, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
inc_depth();
|
inc_depth();
|
||||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||||
|
|
@ -149,9 +148,6 @@ namespace spot
|
||||||
/// by the last dfs visiting it.
|
/// by the last dfs visiting it.
|
||||||
heap h;
|
heap h;
|
||||||
|
|
||||||
/// The unique acceptance condition of the automaton \a a.
|
|
||||||
bdd all_cond;
|
|
||||||
|
|
||||||
bool dfs_blue()
|
bool dfs_blue()
|
||||||
{
|
{
|
||||||
while (!st_blue.empty())
|
while (!st_blue.empty())
|
||||||
|
|
@ -164,7 +160,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
@ -199,10 +195,10 @@ namespace spot
|
||||||
<< a_->format_state(f.s) << " to "
|
<< a_->format_state(f.s) << " to "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = i->current_condition();
|
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);
|
typename heap::color_ref c_prime = h.get_color_ref(s_prime);
|
||||||
assert(!c_prime.is_white());
|
assert(!c_prime.is_white());
|
||||||
bdd acu = acc | c.get_acc();
|
auto acu = acc | c.get_acc();
|
||||||
if ((c_prime.get_acc() & acu) != acu)
|
if ((c_prime.get_acc() & acu) != acu)
|
||||||
{
|
{
|
||||||
trace << " a propagation is needed, go down"
|
trace << " a propagation is needed, go down"
|
||||||
|
|
@ -212,7 +208,7 @@ namespace spot
|
||||||
dfs_red(acu);
|
dfs_red(acu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c.get_acc() == all_cond)
|
if (a_->acc().accepting(c.get_acc()))
|
||||||
{
|
{
|
||||||
trace << "DFS_BLUE propagation is successful, report a"
|
trace << "DFS_BLUE propagation is successful, report a"
|
||||||
<< " cycle" << std::endl;
|
<< " cycle" << std::endl;
|
||||||
|
|
@ -230,7 +226,7 @@ namespace spot
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dfs_red(const bdd& acu)
|
void dfs_red(acc_cond::mark_t acu)
|
||||||
{
|
{
|
||||||
assert(!st_red.empty());
|
assert(!st_red.empty());
|
||||||
|
|
||||||
|
|
@ -244,7 +240,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
@ -254,7 +250,7 @@ namespace spot
|
||||||
trace << " It is white, pop it" << std::endl;
|
trace << " It is white, pop it" << std::endl;
|
||||||
s_prime->destroy();
|
s_prime->destroy();
|
||||||
}
|
}
|
||||||
else if ((c_prime.get_acc() & acu) != acu)
|
else if ((c_prime.get_acc() & acu) != acu)
|
||||||
{
|
{
|
||||||
trace << " It is blue and propagation "
|
trace << " It is blue and propagation "
|
||||||
<< "is needed, go down" << std::endl;
|
<< "is needed, go down" << std::endl;
|
||||||
|
|
@ -286,7 +282,7 @@ namespace spot
|
||||||
class color_ref
|
class color_ref
|
||||||
{
|
{
|
||||||
public:
|
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
|
color get_color() const
|
||||||
|
|
@ -298,15 +294,15 @@ namespace spot
|
||||||
assert(!is_white());
|
assert(!is_white());
|
||||||
*p = c;
|
*p = c;
|
||||||
}
|
}
|
||||||
const bdd& get_acc() const
|
acc_cond::mark_t get_acc() const
|
||||||
{
|
{
|
||||||
assert(!is_white());
|
assert(!is_white());
|
||||||
return *acc;
|
return *acc;
|
||||||
}
|
}
|
||||||
void cumulate_acc(const bdd& a)
|
void cumulate_acc(acc_cond::mark_t a)
|
||||||
{
|
{
|
||||||
assert(!is_white());
|
assert(!is_white());
|
||||||
*acc |= a;
|
*acc |= a;
|
||||||
}
|
}
|
||||||
bool is_white() const
|
bool is_white() const
|
||||||
{
|
{
|
||||||
|
|
@ -314,7 +310,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
color *p;
|
color *p;
|
||||||
bdd* acc;
|
acc_cond::mark_t* acc;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit_tau03_search_heap(size_t)
|
explicit_tau03_search_heap(size_t)
|
||||||
|
|
@ -349,7 +345,9 @@ namespace spot
|
||||||
void add_new_state(const state* s, color c)
|
void add_new_state(const state* s, color c)
|
||||||
{
|
{
|
||||||
assert(h.find(s) == h.end());
|
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
|
void pop_notify(const state*) const
|
||||||
|
|
@ -369,7 +367,8 @@ namespace spot
|
||||||
}
|
}
|
||||||
private:
|
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;
|
state_ptr_hash, state_ptr_equal> hash_type;
|
||||||
hash_type h;
|
hash_type h;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -67,24 +67,13 @@ namespace spot
|
||||||
/// \brief Initialize the search algorithm on the automaton \a a
|
/// \brief Initialize the search algorithm on the automaton \a a
|
||||||
tau03_opt_search(const const_tgba_ptr& a, size_t size, option_map o)
|
tau03_opt_search(const const_tgba_ptr& a, size_t size, option_map o)
|
||||||
: emptiness_check(a, o),
|
: emptiness_check(a, o),
|
||||||
current_weight(a->neg_acceptance_conditions()),
|
current_weight(a->acc()),
|
||||||
h(size),
|
h(size),
|
||||||
all_acc(a->all_acceptance_conditions()),
|
|
||||||
use_condition_stack(o.get("condstack")),
|
use_condition_stack(o.get("condstack")),
|
||||||
use_ordering(use_condition_stack && o.get("ordering")),
|
use_ordering(use_condition_stack && o.get("ordering")),
|
||||||
use_weights(o.get("weights", 1)),
|
use_weights(o.get("weights", 1)),
|
||||||
use_red_weights(use_weights && o.get("redweights", 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()
|
virtual ~tau03_opt_search()
|
||||||
|
|
@ -116,7 +105,7 @@ namespace spot
|
||||||
const state* s0 = a_->get_init_state();
|
const state* s0 = a_->get_init_state();
|
||||||
inc_states();
|
inc_states();
|
||||||
h.add_new_state(s0, CYAN, current_weight);
|
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>
|
auto t = std::static_pointer_cast<tau03_opt_search>
|
||||||
(this->emptiness_check::shared_from_this());
|
(this->emptiness_check::shared_from_this());
|
||||||
if (dfs_blue())
|
if (dfs_blue())
|
||||||
|
|
@ -149,7 +138,7 @@ namespace spot
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void push(stack_type& st, const state* s,
|
void push(stack_type& st, const state* s,
|
||||||
const bdd& label, const bdd& acc)
|
const bdd& label, acc_cond::mark_t acc)
|
||||||
{
|
{
|
||||||
inc_depth();
|
inc_depth();
|
||||||
tgba_succ_iterator* i = a_->succ_iter(s);
|
tgba_succ_iterator* i = a_->succ_iter(s);
|
||||||
|
|
@ -164,14 +153,16 @@ namespace spot
|
||||||
st.pop_front();
|
st.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
bdd project_acc(bdd acc) const
|
acc_cond::mark_t project_acc(acc_cond::mark_t acc) const
|
||||||
{
|
{
|
||||||
bdd result = bddfalse;
|
if (!use_ordering)
|
||||||
for (std::vector<bdd>::const_iterator i = cond.begin();
|
return acc;
|
||||||
i != cond.end() && (acc & *i) != bddfalse;
|
// FIXME: This should be improved.
|
||||||
++i)
|
std::vector<unsigned> res;
|
||||||
result |= *i;
|
unsigned max = a_->acc().num_sets();
|
||||||
return result;
|
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.
|
/// \brief weight of the state on top of the blue stack.
|
||||||
|
|
@ -187,9 +178,6 @@ namespace spot
|
||||||
/// by the last dfs visiting it.
|
/// by the last dfs visiting it.
|
||||||
heap h;
|
heap h;
|
||||||
|
|
||||||
/// The unique acceptance condition of the automaton \a a.
|
|
||||||
bdd all_acc;
|
|
||||||
|
|
||||||
/// Whether to use the "condition stack".
|
/// Whether to use the "condition stack".
|
||||||
bool use_condition_stack;
|
bool use_condition_stack;
|
||||||
/// Whether to use an ordering between the acceptance conditions.
|
/// Whether to use an ordering between the acceptance conditions.
|
||||||
|
|
@ -200,9 +188,6 @@ namespace spot
|
||||||
/// Whether to use weights in the red dfs.
|
/// Whether to use weights in the red dfs.
|
||||||
bool use_red_weights;
|
bool use_red_weights;
|
||||||
|
|
||||||
/// Ordering of the acceptance conditions.
|
|
||||||
std::vector<bdd> cond;
|
|
||||||
|
|
||||||
bool dfs_blue()
|
bool dfs_blue()
|
||||||
{
|
{
|
||||||
while (!st_blue.empty())
|
while (!st_blue.empty())
|
||||||
|
|
@ -215,7 +200,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
@ -224,7 +209,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
trace << " It is white, go down" << std::endl;
|
trace << " It is white, go down" << std::endl;
|
||||||
if (use_weights)
|
if (use_weights)
|
||||||
current_weight += acc;
|
current_weight.add(a_->acc(), acc);
|
||||||
inc_states();
|
inc_states();
|
||||||
h.add_new_state(s_prime, CYAN, current_weight);
|
h.add_new_state(s_prime, CYAN, current_weight);
|
||||||
push(st_blue, s_prime, label, acc);
|
push(st_blue, s_prime, label, acc);
|
||||||
|
|
@ -234,22 +219,21 @@ namespace spot
|
||||||
typename heap::color_ref c = h.get_color_ref(f.s);
|
typename heap::color_ref c = h.get_color_ref(f.s);
|
||||||
assert(!c.is_white());
|
assert(!c.is_white());
|
||||||
if (c_prime.get_color() == CYAN
|
if (c_prime.get_color() == CYAN
|
||||||
&& all_acc == ((current_weight - c_prime.get_weight())
|
&& a_->acc().accepting
|
||||||
| c.get_acc()
|
(current_weight.diff(a_->acc(), c_prime. get_weight())
|
||||||
| acc
|
| c.get_acc() | acc | c_prime.get_acc()))
|
||||||
| c_prime.get_acc()))
|
|
||||||
{
|
{
|
||||||
trace << " It is cyan and acceptance condition "
|
trace << " It is cyan and acceptance condition "
|
||||||
<< "is reached, report cycle" << std::endl;
|
<< "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);
|
push(st_red, s_prime, label, acc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trace << " It is cyan or blue and";
|
trace << " It is cyan or blue and";
|
||||||
bdd acu = acc | c.get_acc();
|
auto acu = acc | c.get_acc();
|
||||||
bdd acp = (use_ordering ? project_acc(acu) : acu);
|
auto acp = project_acc(acu);
|
||||||
if ((c_prime.get_acc() & acp) != acp)
|
if ((c_prime.get_acc() & acp) != acp)
|
||||||
{
|
{
|
||||||
trace << " a propagation is needed, "
|
trace << " a propagation is needed, "
|
||||||
|
|
@ -276,7 +260,7 @@ namespace spot
|
||||||
stack_item f_dest(f);
|
stack_item f_dest(f);
|
||||||
pop(st_blue);
|
pop(st_blue);
|
||||||
if (use_weights)
|
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);
|
typename heap::color_ref c_prime = h.get_color_ref(f_dest.s);
|
||||||
assert(!c_prime.is_white());
|
assert(!c_prime.is_white());
|
||||||
c_prime.set_color(BLUE);
|
c_prime.set_color(BLUE);
|
||||||
|
|
@ -285,8 +269,8 @@ namespace spot
|
||||||
typename heap::color_ref c =
|
typename heap::color_ref c =
|
||||||
h.get_color_ref(st_blue.front().s);
|
h.get_color_ref(st_blue.front().s);
|
||||||
assert(!c.is_white());
|
assert(!c.is_white());
|
||||||
bdd acu = f_dest.acc | c.get_acc();
|
auto acu = f_dest.acc | c.get_acc();
|
||||||
bdd acp = (use_ordering ? project_acc(acu) : acu);
|
auto acp = project_acc(acu);
|
||||||
if ((c_prime.get_acc() & acp) != acp)
|
if ((c_prime.get_acc() & acp) != acp)
|
||||||
{
|
{
|
||||||
trace << " The arc from "
|
trace << " The arc from "
|
||||||
|
|
@ -315,15 +299,15 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
dfs_red(bdd acu)
|
dfs_red(acc_cond::mark_t acu)
|
||||||
{
|
{
|
||||||
assert(!st_red.empty());
|
assert(!st_red.empty());
|
||||||
|
|
||||||
// These are useful only when USE_CONDITION_STACK is set.
|
// 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;
|
std::stack<cond_level> condition_stack;
|
||||||
unsigned depth = 1;
|
unsigned depth = 1;
|
||||||
condition_stack.emplace(bddfalse, 0);
|
condition_stack.emplace(0U, 0);
|
||||||
|
|
||||||
while (!st_red.empty())
|
while (!st_red.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -335,7 +319,7 @@ namespace spot
|
||||||
trace << " Visit the successor: "
|
trace << " Visit the successor: "
|
||||||
<< a_->format_state(s_prime) << std::endl;
|
<< a_->format_state(s_prime) << std::endl;
|
||||||
bdd label = f.it->current_condition();
|
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)
|
// Go down the edge (f.s, <label, acc>, s_prime)
|
||||||
f.it->next();
|
f.it->next();
|
||||||
inc_transitions();
|
inc_transitions();
|
||||||
|
|
@ -347,22 +331,23 @@ namespace spot
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (c_prime.get_color() == CYAN &&
|
else if (c_prime.get_color() == CYAN &&
|
||||||
(all_acc == ((use_red_weights ?
|
a_->acc().accepting
|
||||||
(current_weight - c_prime.get_weight())
|
(acc | acu | c_prime.get_acc() |
|
||||||
: bdd_false())
|
(use_red_weights ?
|
||||||
| c_prime.get_acc()
|
current_weight.diff(a_->acc(),
|
||||||
| acc
|
c_prime.
|
||||||
| acu)))
|
get_weight())
|
||||||
|
: acc_cond::mark_t(0U))))
|
||||||
{
|
{
|
||||||
trace << " It is cyan and acceptance condition "
|
trace << " It is cyan and acceptance condition "
|
||||||
<< "is reached, report cycle" << std::endl;
|
<< "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);
|
push(st_red, s_prime, label, acc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bdd acp;
|
acc_cond::mark_t acp;
|
||||||
if (use_ordering)
|
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)
|
else if (use_condition_stack)
|
||||||
acp = acu | acc;
|
acp = acu | acc;
|
||||||
else
|
else
|
||||||
|
|
@ -376,7 +361,7 @@ namespace spot
|
||||||
push(st_red, s_prime, label, acc);
|
push(st_red, s_prime, label, acc);
|
||||||
if (use_condition_stack)
|
if (use_condition_stack)
|
||||||
{
|
{
|
||||||
bdd old = acu;
|
auto old = acu;
|
||||||
acu |= acc;
|
acu |= acc;
|
||||||
condition_stack.emplace(acu - old, depth);
|
condition_stack.emplace(acu - old, depth);
|
||||||
}
|
}
|
||||||
|
|
@ -412,20 +397,22 @@ namespace spot
|
||||||
|
|
||||||
class explicit_tau03_opt_search_heap
|
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;
|
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;
|
state_ptr_hash, state_ptr_equal> hash_type;
|
||||||
public:
|
public:
|
||||||
class color_ref
|
class color_ref
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
color_ref(hash_type* h, hcyan_type* hc, const state* s,
|
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)
|
: 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)
|
: is_cyan(false), pc(c), acc(a)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -459,12 +446,12 @@ namespace spot
|
||||||
*pc=c;
|
*pc=c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const bdd& get_acc() const
|
acc_cond::mark_t get_acc() const
|
||||||
{
|
{
|
||||||
assert(!is_white());
|
assert(!is_white());
|
||||||
return *acc;
|
return *acc;
|
||||||
}
|
}
|
||||||
void cumulate_acc(const bdd& a)
|
void cumulate_acc(acc_cond::mark_t a)
|
||||||
{
|
{
|
||||||
assert(!is_white());
|
assert(!is_white());
|
||||||
*acc |= a;
|
*acc |= a;
|
||||||
|
|
@ -480,8 +467,8 @@ namespace spot
|
||||||
hcyan_type* phc; // point to the hash table hcyan
|
hcyan_type* phc; // point to the hash table hcyan
|
||||||
const state* ps; // point to the state in hcyan
|
const state* ps; // point to the state in hcyan
|
||||||
color *pc; // point to the color of a state stored in main hash table
|
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
|
acc_cond::mark_t* acc; // point to the acc set of a state stored
|
||||||
// or hcyan
|
// in main hash table or hcyan
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit_tau03_opt_search_heap(size_t)
|
explicit_tau03_opt_search_heap(size_t)
|
||||||
|
|
@ -540,7 +527,7 @@ namespace spot
|
||||||
(void)c;
|
(void)c;
|
||||||
hc.emplace(std::piecewise_construct,
|
hc.emplace(std::piecewise_construct,
|
||||||
std::forward_as_tuple(s),
|
std::forward_as_tuple(s),
|
||||||
std::forward_as_tuple(w, bddfalse));
|
std::forward_as_tuple(w, 0U));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_notify(const state*) const
|
void pop_notify(const state*) const
|
||||||
|
|
|
||||||
|
|
@ -26,96 +26,41 @@
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
weight::weight_vector* weight::pm = 0;
|
weight::weight(const acc_cond& acc):
|
||||||
|
m(acc.num_sets())
|
||||||
weight::weight(const bdd& neg_all_cond) : neg_all_acc(neg_all_cond)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
for (auto s: acc.sets(a))
|
||||||
if (varset[v] > 0)
|
++m[s];
|
||||||
{
|
|
||||||
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);
|
|
||||||
return *this;
|
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)
|
for (auto s: acc.sets(a))
|
||||||
if (varset[v] > 0)
|
if (m[s] > 0)
|
||||||
{
|
--m[s];
|
||||||
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);
|
|
||||||
return *this;
|
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();
|
unsigned max = acc.num_sets();
|
||||||
bdd res = bddfalse;
|
std::vector<unsigned> res;
|
||||||
|
for (unsigned n = 0; n < max; ++n)
|
||||||
while (itw1 != m.end() && itw2 != w.m.end())
|
if (m[n] > w.m[n])
|
||||||
{
|
res.push_back(n);
|
||||||
assert(itw1->first <= itw2->first);
|
return acc.marks(res.begin(), res.end());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const weight& w)
|
std::ostream& operator<<(std::ostream& os, const weight& w)
|
||||||
{
|
{
|
||||||
weight::weight_vector::const_iterator it;
|
unsigned s = w.m.size();
|
||||||
for (it = w.m.begin(); it != w.m.end(); ++it)
|
for (unsigned n = 0; n < s; ++n)
|
||||||
os << '(' << it->first << ',' << it->second << ')';
|
os << '(' << n << ',' << w.m[n] << ')';
|
||||||
return os;
|
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
|
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||||
// et Marie Curie.
|
// et Marie Curie.
|
||||||
//
|
//
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <bdd.h>
|
#include <bdd.h>
|
||||||
|
#include "tgba/acc.hh"
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -33,29 +34,23 @@ namespace spot
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Construct a empty vector (all counters set to zero).
|
/// Construct a empty vector (all counters set to zero).
|
||||||
///
|
weight(const acc_cond& acc);
|
||||||
/// \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);
|
|
||||||
/// Increment by one the counters of each acceptance condition in \a 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.
|
/// 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
|
/// Return the set of each acceptance condition such that its counter is
|
||||||
/// strictly greatest than the corresponding counter in w.
|
/// strictly greatest than the corresponding counter in w.
|
||||||
///
|
///
|
||||||
/// \pre For each acceptance condition, its counter is greatest or equal to
|
/// \pre For each acceptance condition, its counter is greatest or equal to
|
||||||
/// the corresponding counter in w.
|
/// the corresponding counter in w.
|
||||||
bdd operator-(const weight& w) const;
|
acc_cond::mark_t diff(const acc_cond& acc, const weight& w) const;
|
||||||
friend std::ostream& operator<<(std::ostream& os, const weight& w);
|
friend std::ostream& operator<<(std::ostream& os,
|
||||||
|
const weight& w);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<int, int> weight_vector;
|
typedef std::vector<int> weight_vector;
|
||||||
weight_vector m;
|
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;
|
int token;
|
||||||
std::string* str;
|
std::string* str;
|
||||||
const spot::ltl::formula* f;
|
const spot::ltl::formula* f;
|
||||||
bdd* acc;
|
spot::acc_cond::mark_t acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
%code
|
%code
|
||||||
|
|
@ -80,10 +80,9 @@ typedef std::pair<bool, spot::ltl::formula*> pair;
|
||||||
%token ACC_DEF
|
%token ACC_DEF
|
||||||
|
|
||||||
%destructor { delete $$; } <str>
|
%destructor { delete $$; } <str>
|
||||||
%destructor { delete $$; } <acc>
|
|
||||||
|
|
||||||
%printer { debug_stream() << *$$; } <str>
|
%printer { debug_stream() << *$$; } <str>
|
||||||
%printer { debug_stream() << *$$; } <acc>
|
%printer { debug_stream() << $$; } <acc>
|
||||||
|
|
||||||
%%
|
%%
|
||||||
tgba: acceptance_decl lines
|
tgba: acceptance_decl lines
|
||||||
|
|
@ -94,7 +93,8 @@ tgba: acceptance_decl lines
|
||||||
{ namer->new_state("0"); };
|
{ namer->new_state("0"); };
|
||||||
|
|
||||||
acceptance_decl: ACC_DEF acc_decl ';'
|
acceptance_decl: ACC_DEF acc_decl ';'
|
||||||
{ acc_map.commit(); }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* At least one line. */
|
/* At least one line. */
|
||||||
lines: line
|
lines: line
|
||||||
|
|
@ -137,11 +137,10 @@ line: strident ',' strident ',' condition ',' acc_list ';'
|
||||||
}
|
}
|
||||||
unsigned s = namer->new_state(*$1);
|
unsigned s = namer->new_state(*$1);
|
||||||
unsigned d = namer->new_state(*$3);
|
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 $1;
|
||||||
delete $3;
|
delete $3;
|
||||||
delete $5;
|
delete $5;
|
||||||
delete $7;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -166,7 +165,7 @@ condition:
|
||||||
|
|
||||||
acc_list:
|
acc_list:
|
||||||
{
|
{
|
||||||
$$ = new bdd(bddfalse);
|
$$ = 0U;
|
||||||
}
|
}
|
||||||
| acc_list strident
|
| acc_list strident
|
||||||
{
|
{
|
||||||
|
|
@ -180,7 +179,7 @@ acc_list:
|
||||||
// $2 will be destroyed on error recovery.
|
// $2 will be destroyed on error recovery.
|
||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
*$1 |= p.second;
|
$1 |= p.second;
|
||||||
}
|
}
|
||||||
delete $2;
|
delete $2;
|
||||||
$$ = $1;
|
$$ = $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