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
|
|
@ -26,6 +26,7 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
|||
tgbadir = $(pkgincludedir)/tgba
|
||||
|
||||
tgba_HEADERS = \
|
||||
acc.hh \
|
||||
bdddict.hh \
|
||||
bddprint.hh \
|
||||
formula2bdd.hh \
|
||||
|
|
@ -33,11 +34,9 @@ tgba_HEADERS = \
|
|||
taatgba.hh \
|
||||
tgba.hh \
|
||||
tgbagraph.hh \
|
||||
tgbakvcomplement.hh \
|
||||
tgbamask.hh \
|
||||
tgbaproxy.hh \
|
||||
tgbaproduct.hh \
|
||||
tgbasgba.hh \
|
||||
tgbasafracomplement.hh
|
||||
|
||||
noinst_LTLIBRARIES = libtgba.la
|
||||
|
|
@ -48,9 +47,7 @@ libtgba_la_SOURCES = \
|
|||
taatgba.cc \
|
||||
tgba.cc \
|
||||
tgbagraph.cc \
|
||||
tgbakvcomplement.cc \
|
||||
tgbaproduct.cc \
|
||||
tgbamask.cc \
|
||||
tgbaproxy.cc \
|
||||
tgbasafracomplement.cc \
|
||||
tgbasgba.cc
|
||||
tgbasafracomplement.cc
|
||||
|
|
|
|||
433
src/tgba/acc.hh
Normal file
433
src/tgba/acc.hh
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2014 Laboratoire de Recherche et Développement de
|
||||
// l'Epita.
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_TGBA_ACC_HH
|
||||
# define SPOT_TGBA_ACC_HH
|
||||
|
||||
# include <functional>
|
||||
# include <unordered_map>
|
||||
# include <sstream>
|
||||
# include "bdddict.hh"
|
||||
# include "ltlenv/defaultenv.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
class acc_cond
|
||||
{
|
||||
public:
|
||||
struct mark_t
|
||||
{
|
||||
typedef unsigned value_t;
|
||||
value_t id;
|
||||
|
||||
mark_t() = default;
|
||||
|
||||
mark_t(value_t id)
|
||||
: id(id)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(unsigned o) const
|
||||
{
|
||||
assert(o == 0U);
|
||||
return id == o;
|
||||
}
|
||||
|
||||
bool operator!=(unsigned o) const
|
||||
{
|
||||
assert(o == 0U);
|
||||
return id != o;
|
||||
}
|
||||
|
||||
bool operator==(mark_t o) const
|
||||
{
|
||||
return id == o.id;
|
||||
}
|
||||
|
||||
bool operator!=(mark_t o) const
|
||||
{
|
||||
return id != o.id;
|
||||
}
|
||||
|
||||
bool operator<(mark_t o) const
|
||||
{
|
||||
return id < o.id;
|
||||
}
|
||||
|
||||
bool operator<=(mark_t o) const
|
||||
{
|
||||
return id <= o.id;
|
||||
}
|
||||
|
||||
bool operator>(mark_t o) const
|
||||
{
|
||||
return id > o.id;
|
||||
}
|
||||
|
||||
bool operator>=(mark_t o) const
|
||||
{
|
||||
return id >= o.id;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return id != 0;
|
||||
}
|
||||
|
||||
|
||||
bool has(unsigned u) const
|
||||
{
|
||||
return id & (1U << u);
|
||||
}
|
||||
|
||||
mark_t& operator&=(mark_t r)
|
||||
{
|
||||
id &= r.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mark_t& operator|=(mark_t r)
|
||||
{
|
||||
id |= r.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mark_t& operator-=(mark_t r)
|
||||
{
|
||||
id &= ~r.id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mark_t operator&(mark_t r) const
|
||||
{
|
||||
return id & r.id;
|
||||
}
|
||||
|
||||
mark_t operator|(mark_t r) const
|
||||
{
|
||||
return id | r.id;
|
||||
}
|
||||
|
||||
mark_t operator-(mark_t r) const
|
||||
{
|
||||
return id & ~r.id;
|
||||
}
|
||||
|
||||
// Number of bits sets.
|
||||
unsigned count() const
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_popcount(id);
|
||||
#else
|
||||
unsigned c = 0U;
|
||||
auto v = id;
|
||||
while (v)
|
||||
{
|
||||
++c;
|
||||
v &= v - 1;
|
||||
}
|
||||
return c;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remove n bits that where set
|
||||
mark_t& remove_some(unsigned n)
|
||||
{
|
||||
while (n--)
|
||||
id &= id - 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, mark_t m)
|
||||
{
|
||||
auto a = m.id;
|
||||
os << '{';
|
||||
unsigned level = 0;
|
||||
const char* comma = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << comma << level;
|
||||
comma = ",";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
os << '}';
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
acc_cond(const bdd_dict_ptr& dict, unsigned n_sets = 0)
|
||||
: d_(dict), num_(0U), all_(0U)
|
||||
{
|
||||
add_sets(n_sets);
|
||||
}
|
||||
|
||||
acc_cond(const acc_cond& o)
|
||||
: num_(o.num_), all_(o.all_)
|
||||
{
|
||||
}
|
||||
|
||||
~acc_cond()
|
||||
{
|
||||
}
|
||||
|
||||
const bdd_dict_ptr& get_dict() const
|
||||
{
|
||||
return d_;
|
||||
}
|
||||
|
||||
unsigned add_sets(unsigned num)
|
||||
{
|
||||
if (num == 0)
|
||||
return -1U;
|
||||
unsigned j = num_;
|
||||
num_ += num;
|
||||
if (num_ > 8 * sizeof(mark_t::id))
|
||||
throw std::runtime_error("Too many acceptance sets used.");
|
||||
all_ = all_sets_();
|
||||
return j;
|
||||
}
|
||||
|
||||
unsigned add_set()
|
||||
{
|
||||
return add_sets(1);
|
||||
}
|
||||
|
||||
mark_t mark(unsigned u) const
|
||||
{
|
||||
return out(mark_(u));
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
mark_t marks(const iterator& begin, const iterator& end) const
|
||||
{
|
||||
mark_t::value_t res = 0U;
|
||||
for (iterator i = begin; i != end; ++i)
|
||||
res |= mark_(*i);
|
||||
return out(res);
|
||||
}
|
||||
|
||||
mark_t marks(std::initializer_list<unsigned> vals) const
|
||||
{
|
||||
return marks(vals.begin(), vals.end());
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
void fill_from(mark_t m, iterator here) const
|
||||
{
|
||||
auto a = in(m);
|
||||
unsigned level = 0;
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
*here++ = level;
|
||||
++level;
|
||||
a >>= 1;
|
||||
}
|
||||
assert(level <= num_sets());
|
||||
}
|
||||
|
||||
// FIXME: Return some iterable object without building a vector.
|
||||
std::vector<unsigned> sets(mark_t m) const
|
||||
{
|
||||
std::vector<unsigned> res;
|
||||
fill_from(m, std::back_inserter(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
// whether m contains u
|
||||
bool has(mark_t m, unsigned u) const
|
||||
{
|
||||
return m.has(u);
|
||||
}
|
||||
|
||||
mark_t cup(mark_t l, mark_t r) const
|
||||
{
|
||||
return l | r;
|
||||
}
|
||||
|
||||
mark_t cap(mark_t l, mark_t r) const
|
||||
{
|
||||
return l & r;
|
||||
}
|
||||
|
||||
mark_t set_minus(mark_t l, mark_t r) const
|
||||
{
|
||||
return l - r;
|
||||
}
|
||||
|
||||
mark_t join(const acc_cond& la, mark_t lm,
|
||||
const acc_cond& ra, mark_t rm) const
|
||||
{
|
||||
assert(la.num_sets() + ra.num_sets() == num_sets());
|
||||
return la.in(lm) | (ra.in(rm) << la.num_sets());
|
||||
}
|
||||
|
||||
mark_t comp(mark_t l) const
|
||||
{
|
||||
return out(all_ ^ in(l));
|
||||
}
|
||||
|
||||
mark_t all_sets() const
|
||||
{
|
||||
return out(all_);
|
||||
}
|
||||
|
||||
bool accepting(mark_t inf) const
|
||||
{
|
||||
return in(inf) == all_;
|
||||
}
|
||||
|
||||
std::ostream& format_quoted(std::ostream& os, mark_t m) const
|
||||
{
|
||||
auto a = in(m);
|
||||
if (a == 0U)
|
||||
return os;
|
||||
unsigned level = 0;
|
||||
const char* space = "";
|
||||
while (a)
|
||||
{
|
||||
if (a & 1)
|
||||
{
|
||||
os << space << '"' << level << '"';
|
||||
space = " ";
|
||||
}
|
||||
a >>= 1;
|
||||
++level;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& format(std::ostream& os, mark_t m) const
|
||||
{
|
||||
auto a = in(m);
|
||||
if (a == 0U)
|
||||
return os;
|
||||
return os << m;
|
||||
}
|
||||
|
||||
std::string format(mark_t m) const
|
||||
{
|
||||
std::ostringstream os;
|
||||
format(os, m);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
unsigned num_sets() const
|
||||
{
|
||||
return num_;
|
||||
}
|
||||
|
||||
template<class iterator>
|
||||
mark_t useless(iterator begin, iterator end) const
|
||||
{
|
||||
mark_t::value_t u = 0U; // The set of useless marks.
|
||||
for (unsigned x = 0; x < num_; ++x)
|
||||
{
|
||||
// Skip marks that are already known to be useless.
|
||||
if (u & (1 << x))
|
||||
continue;
|
||||
unsigned all = all_ ^ (u | (1 << x));
|
||||
for (iterator y = begin; y != end; ++y)
|
||||
{
|
||||
auto v = in(*y);
|
||||
if (v & (1 << x))
|
||||
{
|
||||
all &= v;
|
||||
if (!all)
|
||||
break;
|
||||
}
|
||||
}
|
||||
u |= all;
|
||||
}
|
||||
return out(u);
|
||||
}
|
||||
|
||||
mark_t strip(mark_t x, mark_t y) const
|
||||
{
|
||||
// strip every bit of x that is marked in y
|
||||
// strip(100101110100,
|
||||
// 001011001000)
|
||||
// == 10 1 11 100
|
||||
// == 10111100
|
||||
|
||||
auto xv = in(x); // 100101110100
|
||||
auto yv = in(y); // 001011001000
|
||||
|
||||
while (yv && xv)
|
||||
{
|
||||
// Mask for everything after the last 1 in y
|
||||
auto rm = (~yv) & (yv - 1); // 000000000111
|
||||
// Mask for everything before the last 1 in y
|
||||
auto lm = ~(yv ^ (yv - 1)); // 111111110000
|
||||
xv = ((xv & lm) >> 1) | (xv & rm);
|
||||
yv = (yv & lm) >> 1;
|
||||
}
|
||||
|
||||
return out(xv);
|
||||
}
|
||||
|
||||
protected:
|
||||
mark_t::value_t mark_(unsigned u) const
|
||||
{
|
||||
assert(u < num_sets());
|
||||
return 1U << u;
|
||||
}
|
||||
|
||||
mark_t::value_t all_sets_() const
|
||||
{
|
||||
if (num_ == 0)
|
||||
return 0;
|
||||
return -1U >> (8 * sizeof(mark_t::value_t) - num_);
|
||||
}
|
||||
|
||||
mark_t::value_t in(mark_t m) const
|
||||
{
|
||||
return m.id;
|
||||
}
|
||||
|
||||
mark_t out(mark_t::value_t r) const
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
bdd_dict_ptr d_;
|
||||
unsigned num_;
|
||||
mark_t::value_t all_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<spot::acc_cond::mark_t>
|
||||
{
|
||||
size_t operator()(spot::acc_cond::mark_t m) const
|
||||
{
|
||||
std::hash<decltype(m.id)> h;
|
||||
return h(m.id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SPOT_TGBA_ACC_HH
|
||||
|
|
@ -35,10 +35,6 @@ namespace spot
|
|||
class tgba_product;
|
||||
typedef std::shared_ptr<const tgba_product> const_tgba_product_ptr;
|
||||
typedef std::shared_ptr<tgba_product> tgba_product_ptr;
|
||||
|
||||
class tgba_sgba_proxy;
|
||||
typedef std::shared_ptr<const tgba_sgba_proxy> const_tgba_sgba_proxy_ptr;
|
||||
typedef std::shared_ptr<tgba_sgba_proxy> tgba_sgba_proxy_ptr;
|
||||
}
|
||||
|
||||
#endif // SPOT_TGBA_FWD_HH
|
||||
|
|
|
|||
|
|
@ -34,10 +34,7 @@ namespace spot
|
|||
`--------*/
|
||||
|
||||
taa_tgba::taa_tgba(const bdd_dict_ptr& dict)
|
||||
: dict_(dict),
|
||||
all_acceptance_conditions_(bddfalse),
|
||||
all_acceptance_conditions_computed_(false),
|
||||
neg_acceptance_conditions_(bddtrue),
|
||||
: tgba(dict),
|
||||
init_(0), state_set_vec_()
|
||||
{
|
||||
}
|
||||
|
|
@ -47,13 +44,13 @@ namespace spot
|
|||
ss_vec::iterator j;
|
||||
for (j = state_set_vec_.begin(); j != state_set_vec_.end(); ++j)
|
||||
delete *j;
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
void
|
||||
taa_tgba::add_condition(transition* t, const ltl::formula* f)
|
||||
{
|
||||
t->condition &= formula_to_bdd(f, dict_, this);
|
||||
t->condition &= formula_to_bdd(f, get_dict(), this);
|
||||
f->destroy();
|
||||
}
|
||||
|
||||
|
|
@ -69,31 +66,7 @@ namespace spot
|
|||
{
|
||||
const spot::set_state* s = down_cast<const spot::set_state*>(state);
|
||||
assert(s);
|
||||
return new taa_succ_iterator(s->get_state(), all_acceptance_conditions());
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
taa_tgba::get_dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
bdd
|
||||
taa_tgba::all_acceptance_conditions() const
|
||||
{
|
||||
if (!all_acceptance_conditions_computed_)
|
||||
{
|
||||
all_acceptance_conditions_ =
|
||||
compute_all_acceptance_conditions(neg_acceptance_conditions_);
|
||||
all_acceptance_conditions_computed_ = true;
|
||||
}
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
bdd
|
||||
taa_tgba::neg_acceptance_conditions() const
|
||||
{
|
||||
return neg_acceptance_conditions_;
|
||||
return new taa_succ_iterator(s->get_state(), acc_);
|
||||
}
|
||||
|
||||
bdd
|
||||
|
|
@ -172,14 +145,14 @@ namespace spot
|
|||
`--------------*/
|
||||
|
||||
taa_succ_iterator::taa_succ_iterator(const taa_tgba::state_set* s,
|
||||
bdd all_acc)
|
||||
: all_acceptance_conditions_(all_acc), seen_()
|
||||
const acc_cond& acc)
|
||||
: seen_(), acc_(acc)
|
||||
{
|
||||
if (s->empty())
|
||||
{
|
||||
taa_tgba::transition* t = new taa_tgba::transition;
|
||||
t->condition = bddtrue;
|
||||
t->acceptance_conditions = bddfalse;
|
||||
t->acceptance_conditions = 0U;
|
||||
t->dst = new taa_tgba::state_set;
|
||||
succ_.push_back(t);
|
||||
return;
|
||||
|
|
@ -202,7 +175,7 @@ namespace spot
|
|||
{
|
||||
taa_tgba::transition* t = new taa_tgba::transition;
|
||||
t->condition = bddtrue;
|
||||
t->acceptance_conditions = bddfalse;
|
||||
t->acceptance_conditions = 0U;
|
||||
taa_tgba::state_set* ss = new taa_tgba::state_set;
|
||||
|
||||
unsigned p;
|
||||
|
|
@ -330,12 +303,11 @@ namespace spot
|
|||
return (*i_)->condition;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
taa_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
return all_acceptance_conditions_ -
|
||||
((*i_)->acceptance_conditions & all_acceptance_conditions_);
|
||||
return acc_.comp((*i_)->acceptance_conditions);
|
||||
}
|
||||
|
||||
/*----------------.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "ltlast/formula.hh"
|
||||
#include "bdddict.hh"
|
||||
#include "tgba.hh"
|
||||
#include "ltlvisit/tostring.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -45,7 +46,7 @@ namespace spot
|
|||
struct transition
|
||||
{
|
||||
bdd condition;
|
||||
bdd acceptance_conditions;
|
||||
acc_cond::mark_t acceptance_conditions;
|
||||
const state_set* dst;
|
||||
};
|
||||
|
||||
|
|
@ -55,23 +56,19 @@ namespace spot
|
|||
virtual ~taa_tgba();
|
||||
virtual spot::state* get_init_state() const;
|
||||
virtual tgba_succ_iterator* succ_iter(const spot::state* state) const;
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
virtual std::string format_state(const spot::state* state) const = 0;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const spot::state* state) const;
|
||||
|
||||
typedef std::vector<taa_tgba::state_set*> ss_vec;
|
||||
|
||||
bdd_dict_ptr dict_;
|
||||
mutable bdd all_acceptance_conditions_;
|
||||
mutable bool all_acceptance_conditions_computed_;
|
||||
bdd neg_acceptance_conditions_;
|
||||
taa_tgba::state_set* init_;
|
||||
ss_vec state_set_vec_;
|
||||
|
||||
std::map<const ltl::formula*, acc_cond::mark_t,
|
||||
ltl::formula_ptr_less_than> acc_map_;
|
||||
|
||||
private:
|
||||
// Disallow copy.
|
||||
taa_tgba(const taa_tgba& other) SPOT_DELETED;
|
||||
|
|
@ -106,7 +103,7 @@ namespace spot
|
|||
class SPOT_API taa_succ_iterator : public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
taa_succ_iterator(const taa_tgba::state_set* s, bdd all_acc);
|
||||
taa_succ_iterator(const taa_tgba::state_set* s, const acc_cond& acc);
|
||||
virtual ~taa_succ_iterator();
|
||||
|
||||
virtual bool first();
|
||||
|
|
@ -115,7 +112,7 @@ namespace spot
|
|||
|
||||
virtual set_state* current_state() const;
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||
|
||||
private:
|
||||
/// Those typedefs are used to generate all possible successors in
|
||||
|
|
@ -141,8 +138,8 @@ namespace spot
|
|||
|
||||
std::vector<taa_tgba::transition*>::const_iterator i_;
|
||||
std::vector<taa_tgba::transition*> succ_;
|
||||
bdd all_acceptance_conditions_;
|
||||
seen_map seen_;
|
||||
const acc_cond& acc_;
|
||||
};
|
||||
|
||||
/// A taa_tgba instance with states labeled by a given type.
|
||||
|
|
@ -153,6 +150,13 @@ namespace spot
|
|||
public:
|
||||
taa_tgba_labelled(const bdd_dict_ptr& dict) : taa_tgba(dict) {};
|
||||
|
||||
~taa_tgba_labelled()
|
||||
{
|
||||
auto i = acc_map_.begin();
|
||||
while (i != acc_map_.end())
|
||||
(i++)->first->destroy();
|
||||
}
|
||||
|
||||
void set_init_state(const label& s)
|
||||
{
|
||||
std::vector<label> v(1);
|
||||
|
|
@ -173,10 +177,11 @@ namespace spot
|
|||
transition* t = new transition;
|
||||
t->dst = dst;
|
||||
t->condition = bddtrue;
|
||||
t->acceptance_conditions = bddfalse;
|
||||
t->acceptance_conditions = 0U;
|
||||
src->push_back(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
transition*
|
||||
create_transition(const label& s, const label& d)
|
||||
{
|
||||
|
|
@ -187,29 +192,12 @@ namespace spot
|
|||
|
||||
void add_acceptance_condition(transition* t, const ltl::formula* f)
|
||||
{
|
||||
if (dict_->acc_map.find(f) == dict_->acc_map.end())
|
||||
{
|
||||
int v = dict_->register_acceptance_variable(f, this);
|
||||
bdd neg = bdd_nithvar(v);
|
||||
neg_acceptance_conditions_ &= neg;
|
||||
|
||||
// Append neg to all acceptance conditions.
|
||||
typename ns_map::iterator i;
|
||||
for (i = name_state_map_.begin(); i != name_state_map_.end(); ++i)
|
||||
{
|
||||
taa_tgba::state::iterator i2;
|
||||
for (i2 = i->second->begin(); i2 != i->second->end(); ++i2)
|
||||
(*i2)->acceptance_conditions &= neg;
|
||||
}
|
||||
|
||||
all_acceptance_conditions_computed_ = false;
|
||||
}
|
||||
|
||||
bdd_dict::fv_map::iterator i = dict_->acc_map.find(f);
|
||||
assert(i != dict_->acc_map.end());
|
||||
f->destroy();
|
||||
bdd v = bdd_ithvar(i->second);
|
||||
t->acceptance_conditions |= v & bdd_exist(neg_acceptance_conditions_, v);
|
||||
auto p = acc_map_.emplace(f, 0);
|
||||
if (p.second)
|
||||
p.first->second = acc_.marks({acc_.add_set()});
|
||||
else
|
||||
f->destroy();
|
||||
t->acceptance_conditions |= p.first->second;
|
||||
}
|
||||
|
||||
/// \brief Format the state as a string for printing.
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
tgba::tgba()
|
||||
tgba::tgba(const bdd_dict_ptr& d)
|
||||
: iter_cache_(nullptr),
|
||||
last_support_conditions_input_(0),
|
||||
num_acc_(-1)
|
||||
acc_(d),
|
||||
last_support_conditions_input_(0)
|
||||
{
|
||||
props = 0U;
|
||||
}
|
||||
|
|
@ -69,23 +69,6 @@ namespace spot
|
|||
return "";
|
||||
}
|
||||
|
||||
unsigned int
|
||||
tgba::number_of_acceptance_conditions() const
|
||||
{
|
||||
if (num_acc_ < 0)
|
||||
{
|
||||
bdd all = all_acceptance_conditions();
|
||||
unsigned int n = 0;
|
||||
while (all != bddfalse)
|
||||
{
|
||||
++n;
|
||||
all -= bdd_satone(all);
|
||||
}
|
||||
num_acc_ = n;
|
||||
}
|
||||
return num_acc_;
|
||||
}
|
||||
|
||||
bool
|
||||
tgba::is_empty() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
#ifndef SPOT_TGBA_TGBA_HH
|
||||
# define SPOT_TGBA_TGBA_HH
|
||||
|
||||
#include "bdddict.hh"
|
||||
#include "fwd.hh"
|
||||
#include "acc.hh"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include "misc/casts.hh"
|
||||
|
|
@ -387,7 +387,7 @@ namespace spot
|
|||
virtual bdd current_condition() const = 0;
|
||||
/// \brief Get the acceptance conditions on the transition leading
|
||||
/// to this successor.
|
||||
virtual bdd current_acceptance_conditions() const = 0;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const = 0;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
|
@ -467,7 +467,7 @@ namespace spot
|
|||
class SPOT_API tgba: public std::enable_shared_from_this<tgba>
|
||||
{
|
||||
protected:
|
||||
tgba();
|
||||
tgba(const bdd_dict_ptr& d);
|
||||
// Any iterator returned via release_iter.
|
||||
mutable tgba_succ_iterator* iter_cache_;
|
||||
|
||||
|
|
@ -572,7 +572,10 @@ namespace spot
|
|||
/// formulae, and vice versa. This is useful when dealing with
|
||||
/// several automata (which may use the same BDD variable for
|
||||
/// different formula), or simply when printing.
|
||||
virtual bdd_dict_ptr get_dict() const = 0;
|
||||
bdd_dict_ptr get_dict() const
|
||||
{
|
||||
return acc_.get_dict();
|
||||
}
|
||||
|
||||
/// \brief Format the state as a string for printing.
|
||||
///
|
||||
|
|
@ -615,40 +618,27 @@ namespace spot
|
|||
virtual state* project_state(const state* s,
|
||||
const const_tgba_ptr& t) const;
|
||||
|
||||
/// \brief Return the set of all acceptance conditions used
|
||||
/// by this automaton.
|
||||
///
|
||||
/// The goal of the emptiness check is to ensure that
|
||||
/// a strongly connected component walks through each
|
||||
/// of these acceptiong conditions. I.e., the union
|
||||
/// of the acceptiong conditions of all transition in
|
||||
/// the SCC should be equal to the result of this function.
|
||||
virtual bdd all_acceptance_conditions() const = 0;
|
||||
|
||||
/// The number of acceptance conditions.
|
||||
virtual unsigned int number_of_acceptance_conditions() const;
|
||||
const acc_cond& acc() const
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
/// \brief Return the conjuction of all negated acceptance
|
||||
/// variables.
|
||||
///
|
||||
/// For instance if the automaton uses variables <tt>Acc[a]</tt>,
|
||||
/// <tt>Acc[b]</tt> and <tt>Acc[c]</tt> to describe acceptance sets,
|
||||
/// this function should return <tt>!Acc[a]\&!Acc[b]\&!Acc[c]</tt>.
|
||||
///
|
||||
/// This is useful when making products: each operand's condition
|
||||
/// set should be augmented with the neg_acceptance_conditions() of
|
||||
/// the other operand.
|
||||
virtual bdd neg_acceptance_conditions() const = 0;
|
||||
acc_cond& acc()
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
virtual bool is_empty() const;
|
||||
|
||||
protected:
|
||||
acc_cond acc_;
|
||||
|
||||
/// Do the actual computation of tgba::support_conditions().
|
||||
virtual bdd compute_support_conditions(const state* state) const = 0;
|
||||
mutable const state* last_support_conditions_input_;
|
||||
private:
|
||||
mutable bdd last_support_conditions_output_;
|
||||
mutable int num_acc_;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -23,41 +23,6 @@
|
|||
namespace spot
|
||||
{
|
||||
|
||||
void tgba_digraph::set_acceptance_conditions(bdd all)
|
||||
{
|
||||
if (all_acceptance_conditions_ != bddfalse)
|
||||
dict_->unregister_all_typed_variables(bdd_dict::acc, this);
|
||||
|
||||
bdd sup = bdd_support(all);
|
||||
dict_->register_acceptance_variables(sup, this);
|
||||
neg_acceptance_conditions_ = bddtrue;
|
||||
while (sup != bddtrue)
|
||||
{
|
||||
neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
|
||||
sup = bdd_high(sup);
|
||||
}
|
||||
all_acceptance_conditions_ =
|
||||
compute_all_acceptance_conditions(neg_acceptance_conditions_);
|
||||
|
||||
prop_single_acc_set(number_of_acceptance_conditions() == 1);
|
||||
}
|
||||
|
||||
bdd tgba_digraph::set_single_acceptance_set()
|
||||
{
|
||||
if (all_acceptance_conditions_ != bddfalse)
|
||||
dict_->unregister_all_typed_variables(bdd_dict::acc, this);
|
||||
|
||||
prop_single_acc_set();
|
||||
|
||||
int accvar =
|
||||
dict_->register_acceptance_variable(ltl::constant::true_instance(),
|
||||
this);
|
||||
bdd degen_acc = bdd_ithvar(accvar);
|
||||
all_acceptance_conditions_ = degen_acc;
|
||||
neg_acceptance_conditions_ = bdd_nithvar(accvar);
|
||||
return degen_acc;
|
||||
}
|
||||
|
||||
void tgba_digraph::merge_transitions()
|
||||
{
|
||||
for (auto& s: g_.states())
|
||||
|
|
@ -65,7 +30,7 @@ namespace spot
|
|||
// Map a pair (dest state, acc) to the first transition seen
|
||||
// with such characteristic.
|
||||
|
||||
typedef std::pair<graph_t::state, int> key_t;
|
||||
typedef std::pair<graph_t::state, acc_cond::mark_t> key_t;
|
||||
std::unordered_map<key_t, graph_t::transition, pair_hash> trmap;
|
||||
|
||||
auto t = g_.out_iteraser(s);
|
||||
|
|
@ -78,7 +43,7 @@ namespace spot
|
|||
continue;
|
||||
}
|
||||
|
||||
key_t k(t->dst, t->acc.id());
|
||||
key_t k(t->dst, t->acc);
|
||||
auto p = trmap.emplace(k, t.trans());
|
||||
if (!p.second)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,14 +76,14 @@ namespace spot
|
|||
struct SPOT_API tgba_graph_trans_data
|
||||
{
|
||||
bdd cond;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
|
||||
explicit tgba_graph_trans_data()
|
||||
: cond(bddfalse), acc(bddfalse)
|
||||
: cond(bddfalse), acc(0)
|
||||
{
|
||||
}
|
||||
|
||||
tgba_graph_trans_data(bdd cond, bdd acc = bddfalse)
|
||||
tgba_graph_trans_data(bdd cond, acc_cond::mark_t acc = 0U)
|
||||
: cond(cond), acc(acc)
|
||||
{
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ namespace spot
|
|||
return g_->trans_data(p_).cond;
|
||||
}
|
||||
|
||||
virtual bdd current_acceptance_conditions() const
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
return g_->trans_data(p_).acc;
|
||||
|
|
@ -161,23 +161,18 @@ namespace spot
|
|||
|
||||
protected:
|
||||
graph_t g_;
|
||||
bdd_dict_ptr dict_;
|
||||
bdd all_acceptance_conditions_;
|
||||
bdd neg_acceptance_conditions_;
|
||||
mutable unsigned init_number_;
|
||||
|
||||
public:
|
||||
tgba_digraph(const bdd_dict_ptr& dict)
|
||||
: dict_(dict),
|
||||
all_acceptance_conditions_(bddfalse),
|
||||
neg_acceptance_conditions_(bddtrue),
|
||||
: tgba(dict),
|
||||
init_number_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~tgba_digraph()
|
||||
{
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
// Prevent this state from being destroyed by ~tgba(),
|
||||
// as the state will be destroyed when g_ is destroyed.
|
||||
last_support_conditions_input_ = 0;
|
||||
|
|
@ -212,11 +207,6 @@ namespace spot
|
|||
return g_;
|
||||
}
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const
|
||||
{
|
||||
return this->dict_;
|
||||
}
|
||||
|
||||
unsigned num_states() const
|
||||
{
|
||||
return g_.num_states();
|
||||
|
|
@ -314,8 +304,22 @@ namespace spot
|
|||
return g_.trans_data(t);
|
||||
}
|
||||
|
||||
void set_acceptance_conditions(bdd all);
|
||||
bdd set_single_acceptance_set();
|
||||
void set_acceptance_conditions(unsigned num)
|
||||
{
|
||||
if (num < acc_.num_sets())
|
||||
{
|
||||
acc_.~acc_cond();
|
||||
new (&acc_) acc_cond(get_dict());
|
||||
}
|
||||
acc_.add_sets(num - acc_.num_sets());
|
||||
prop_single_acc_set(num == 1);
|
||||
}
|
||||
|
||||
acc_cond::mark_t set_single_acceptance_set()
|
||||
{
|
||||
set_acceptance_conditions(1);
|
||||
return acc_.mark(0);
|
||||
}
|
||||
|
||||
unsigned new_state()
|
||||
{
|
||||
|
|
@ -328,7 +332,7 @@ namespace spot
|
|||
}
|
||||
|
||||
unsigned new_transition(unsigned src, unsigned dst,
|
||||
bdd cond, bdd acc = bddfalse)
|
||||
bdd cond, acc_cond::mark_t acc = 0U)
|
||||
{
|
||||
return g_.new_transition(src, dst, cond, acc);
|
||||
}
|
||||
|
|
@ -337,7 +341,7 @@ namespace spot
|
|||
bdd cond, bool acc = true)
|
||||
{
|
||||
if (acc)
|
||||
return g_.new_transition(src, dst, cond, all_acceptance_conditions_);
|
||||
return g_.new_transition(src, dst, cond, acc_.all_sets());
|
||||
else
|
||||
return g_.new_transition(src, dst, cond);
|
||||
}
|
||||
|
|
@ -364,22 +368,13 @@ namespace spot
|
|||
/// \brief Copy the acceptance conditions of another tgba.
|
||||
void copy_acceptance_conditions_of(const const_tgba_ptr& a)
|
||||
{
|
||||
set_acceptance_conditions(a->neg_acceptance_conditions());
|
||||
assert(acc_.num_sets() == 0);
|
||||
acc_.add_sets(a->acc().num_sets());
|
||||
}
|
||||
|
||||
void copy_ap_of(const const_tgba_ptr& a)
|
||||
{
|
||||
dict_->register_all_propositions_of(a, this);
|
||||
}
|
||||
|
||||
virtual bdd all_acceptance_conditions() const
|
||||
{
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
virtual bdd neg_acceptance_conditions() const
|
||||
{
|
||||
return neg_acceptance_conditions_;
|
||||
get_dict()->register_all_propositions_of(a, this);
|
||||
}
|
||||
|
||||
virtual bdd compute_support_conditions(const state* s) const
|
||||
|
|
@ -400,7 +395,7 @@ namespace spot
|
|||
for (auto& t: g_.out(s))
|
||||
// Stop at the first transition, since the remaining should be
|
||||
// labeled identically.
|
||||
return t.acc == all_acceptance_conditions_;
|
||||
return acc_.accepting(t.acc);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,685 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2010, 2011, 2013, 2014 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include "bdd.h"
|
||||
#include "bddprint.hh"
|
||||
#include "tgba.hh"
|
||||
#include "tgbakvcomplement.hh"
|
||||
#include "misc/hash.hh"
|
||||
#include "tgbaalgos/bfssteps.hh"
|
||||
#include "misc/hashfunc.hh"
|
||||
#include "ltlast/formula.hh"
|
||||
#include "ltlast/constant.hh"
|
||||
#include "priv/countstates.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// rank
|
||||
|
||||
/// \brief A rank structure, one of the main structure of the algorithm.
|
||||
///
|
||||
/// A rank has a number (\a rank) that refers to the depth in the DAG of
|
||||
/// the current word. When the rank is odd, a \a condition is associated
|
||||
/// to this rank.
|
||||
struct rank_t
|
||||
{
|
||||
mutable unsigned rank;
|
||||
mutable bdd_ordered condition;
|
||||
|
||||
bool operator<(const rank_t& other) const
|
||||
{
|
||||
return rank < other.rank ||
|
||||
condition.order() < other.condition.order();
|
||||
}
|
||||
|
||||
unsigned get_rank() const
|
||||
{
|
||||
return rank;
|
||||
}
|
||||
|
||||
bdd_ordered get_condition() const
|
||||
{
|
||||
return condition;
|
||||
}
|
||||
|
||||
size_t hash() const
|
||||
{
|
||||
size_t hash = wang32_hash(rank);
|
||||
if (rank & 1)
|
||||
hash ^= wang32_hash(condition.order());
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string format(const bdd_dict_ptr& d) const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "{rank: " << rank;
|
||||
if (rank & 1)
|
||||
{
|
||||
ss << ", bdd: {" << condition.order() << ", "
|
||||
<< bdd_format_accset(d, condition.get_bdd())
|
||||
<< "} ";
|
||||
}
|
||||
ss << '}';
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
// typedefs.
|
||||
typedef std::unordered_map<shared_state, rank_t,
|
||||
state_shared_ptr_hash,
|
||||
state_shared_ptr_equal> state_rank_map;
|
||||
|
||||
////////////////////////////////////////
|
||||
// state_kv_complement
|
||||
|
||||
/// States used by spot::tgba_kv_complement.
|
||||
/// A state has a map of states associated to ranks, and a set
|
||||
/// of filtered states.
|
||||
/// \ingroup tgba_representation
|
||||
class state_kv_complement : public state
|
||||
{
|
||||
public:
|
||||
state_kv_complement();
|
||||
state_kv_complement(state_rank_map state_map,
|
||||
shared_state_set state_filter);
|
||||
virtual ~state_kv_complement() {}
|
||||
|
||||
virtual int compare(const state* other) const;
|
||||
virtual size_t hash() const;
|
||||
virtual state_kv_complement* clone() const;
|
||||
|
||||
void add(shared_state state, const rank_t& rank);
|
||||
const state_rank_map& get_state_map() const;
|
||||
const shared_state_set& get_filter_set() const;
|
||||
bool accepting() const;
|
||||
private:
|
||||
state_rank_map state_map_;
|
||||
shared_state_set state_filter_;
|
||||
};
|
||||
|
||||
state_kv_complement::state_kv_complement()
|
||||
{
|
||||
}
|
||||
|
||||
state_kv_complement::state_kv_complement(state_rank_map state_map,
|
||||
shared_state_set state_filter)
|
||||
: state_map_(state_map), state_filter_(state_filter)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
state_kv_complement::compare(const state* o) const
|
||||
{
|
||||
const state_kv_complement* other =
|
||||
down_cast<const state_kv_complement*>(o);
|
||||
|
||||
if (other == 0)
|
||||
return 1;
|
||||
|
||||
if (state_map_.size() < other->state_map_.size())
|
||||
return -1;
|
||||
else if (state_map_.size() > other->state_map_.size())
|
||||
return 1;
|
||||
|
||||
if (state_filter_.size() < other->state_filter_.size())
|
||||
return -1;
|
||||
else if (state_filter_.size() > other->state_filter_.size())
|
||||
return 1;
|
||||
|
||||
{
|
||||
state_rank_map::const_iterator i = state_map_.begin();
|
||||
state_rank_map::const_iterator j = other->state_map_.begin();
|
||||
while (i != state_map_.end() && j != other->state_map_.end())
|
||||
{
|
||||
int result = i->first->compare(j->first.get());
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (i->second < j->second)
|
||||
return -1;
|
||||
if (j->second < i->second)
|
||||
return 1;
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
shared_state_set::const_iterator i = state_filter_.begin();
|
||||
shared_state_set::const_iterator j = other->state_filter_.begin();
|
||||
while (i != state_filter_.end() && j != other->state_filter_.end())
|
||||
{
|
||||
int result = (*i)->compare(j->get());
|
||||
if (result != 0)
|
||||
return result;
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
state_kv_complement::hash() const
|
||||
{
|
||||
size_t hash = 0;
|
||||
|
||||
{
|
||||
state_rank_map::const_iterator i = state_map_.begin();
|
||||
while (i != state_map_.end())
|
||||
{
|
||||
hash ^= i->first->hash();
|
||||
hash ^= i->second.hash();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
shared_state_set::const_iterator i = state_filter_.begin();
|
||||
while (i != state_filter_.end())
|
||||
{
|
||||
hash ^= (*i)->hash();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
state_kv_complement*
|
||||
state_kv_complement::clone() const
|
||||
{
|
||||
return new state_kv_complement(*this);
|
||||
}
|
||||
|
||||
void
|
||||
state_kv_complement::add(shared_state state,
|
||||
const rank_t& rank)
|
||||
{
|
||||
state_map_[state] = rank;
|
||||
}
|
||||
|
||||
const state_rank_map&
|
||||
state_kv_complement::get_state_map() const
|
||||
{
|
||||
return state_map_;
|
||||
}
|
||||
|
||||
const shared_state_set&
|
||||
state_kv_complement::get_filter_set() const
|
||||
{
|
||||
return state_filter_;
|
||||
}
|
||||
|
||||
bool
|
||||
state_kv_complement::accepting() const
|
||||
{
|
||||
return state_filter_.empty();
|
||||
}
|
||||
|
||||
/// Successor iterators used by spot::tgba_kv_complement.
|
||||
/// \ingroup tgba_representation
|
||||
///
|
||||
/// Since the algorithm works on-the-fly, the key components of the
|
||||
/// algorithm are implemented in this class.
|
||||
///
|
||||
///
|
||||
class tgba_kv_complement_succ_iterator: public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
typedef std::list<bdd> bdd_list_t;
|
||||
|
||||
tgba_kv_complement_succ_iterator(const tgba_sgba_proxy* automaton,
|
||||
bdd the_acceptance_cond,
|
||||
const acc_list_t& acc_list,
|
||||
const state_kv_complement* origin);
|
||||
virtual ~tgba_kv_complement_succ_iterator() {};
|
||||
|
||||
virtual bool first();
|
||||
virtual bool next();
|
||||
virtual bool done() const;
|
||||
virtual state_kv_complement* current_state() const;
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
private:
|
||||
/// \brief Create the highest rank of \a origin_ as origin and
|
||||
/// \a condition as successor condition.
|
||||
void successor_highest_rank(bdd condition);
|
||||
void get_atomics(std::set<int>& list, bdd c);
|
||||
void get_conj_list();
|
||||
bool is_valid_rank() const;
|
||||
bool next_valid_rank();
|
||||
|
||||
const tgba_sgba_proxy* automaton_;
|
||||
bdd the_acceptance_cond_;
|
||||
const acc_list_t& acc_list_;
|
||||
const state_kv_complement* origin_;
|
||||
bdd_list_t condition_list_;
|
||||
bdd_list_t::const_iterator current_condition_;
|
||||
state_rank_map highest_current_ranks_;
|
||||
state_rank_map current_ranks_;
|
||||
shared_state_set highest_state_set_;
|
||||
};
|
||||
|
||||
tgba_kv_complement_succ_iterator::
|
||||
tgba_kv_complement_succ_iterator(const tgba_sgba_proxy* automaton,
|
||||
bdd the_acceptance_cond,
|
||||
const acc_list_t& acc_list,
|
||||
const state_kv_complement* origin)
|
||||
: automaton_(automaton), the_acceptance_cond_(the_acceptance_cond),
|
||||
acc_list_(acc_list), origin_(origin)
|
||||
{
|
||||
get_conj_list();
|
||||
}
|
||||
|
||||
/// Insert in \a list atomic properties of the formula \a c.
|
||||
void
|
||||
tgba_kv_complement_succ_iterator::get_atomics(std::set<int>& list, bdd c)
|
||||
{
|
||||
bdd current = bdd_satone(c);
|
||||
while (current != bddtrue && current != bddfalse)
|
||||
{
|
||||
list.insert(bdd_var(current));
|
||||
bdd high = bdd_high(current);
|
||||
if (high == bddfalse)
|
||||
current = bdd_low(current);
|
||||
else
|
||||
current = high;
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the conjunction of all the atomic properties from
|
||||
/// the successors of the current state.
|
||||
void
|
||||
tgba_kv_complement_succ_iterator::get_conj_list()
|
||||
{
|
||||
std::set<int> atomics;
|
||||
condition_list_.clear();
|
||||
state_rank_map sr_map = origin_->get_state_map();
|
||||
|
||||
// Retrieve all the atomics in acceptance conditions.
|
||||
for (state_rank_map::const_iterator i = sr_map.begin();
|
||||
i != sr_map.end();
|
||||
++i)
|
||||
{
|
||||
for (auto iterator: automaton_->succ(i->first.get()))
|
||||
{
|
||||
bdd c = iterator->current_condition();
|
||||
get_atomics(atomics, c);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the conjunction of all those atomic properties.
|
||||
unsigned atomics_size = atomics.size();
|
||||
|
||||
assert(atomics_size < 32);
|
||||
for (unsigned i = 1; i <= static_cast<unsigned>(1 << atomics_size); ++i)
|
||||
{
|
||||
bdd result = bddtrue;
|
||||
unsigned position = 1;
|
||||
for (std::set<int>::const_iterator a_it = atomics.begin();
|
||||
a_it != atomics.end();
|
||||
++a_it, position <<= 1)
|
||||
{
|
||||
bdd this_atomic;
|
||||
if (position & i)
|
||||
this_atomic = bdd_ithvar(*a_it);
|
||||
else
|
||||
this_atomic = bdd_nithvar(*a_it);
|
||||
result = bdd_apply(result, this_atomic, bddop_and);
|
||||
}
|
||||
condition_list_.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether \a current_ranks_ is a valid rank.
|
||||
/// For each odd rank, its condition associated must not
|
||||
/// be present in its tracked state.
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::is_valid_rank() const
|
||||
{
|
||||
for (state_rank_map::const_iterator i = current_ranks_.begin();
|
||||
i != current_ranks_.end();
|
||||
++i)
|
||||
{
|
||||
if (i->second.rank & 1)
|
||||
{
|
||||
if ((automaton_->state_acceptance_conditions(i->first.get()) &
|
||||
i->second.condition.get_bdd()) != bddfalse)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Decrease \a current_ranks_ and produces a valid rank.
|
||||
/// \a current_ranks_ is a map of states to a rank.
|
||||
/// A rank for a state is valid if it is inferior than the rank of its
|
||||
/// predecessor.
|
||||
/// When the rank is odd, its has an acceptance condition associated that
|
||||
/// must not be in its associated state.
|
||||
/// \return false if there is not valid rank as successor.
|
||||
bool tgba_kv_complement_succ_iterator::next_valid_rank()
|
||||
{
|
||||
state_rank_map::const_iterator i;
|
||||
do
|
||||
{
|
||||
for (i = current_ranks_.begin(); i != current_ranks_.end(); ++i)
|
||||
{
|
||||
if (i->second.rank != 0)
|
||||
{
|
||||
if (i->second.rank & 1)
|
||||
{
|
||||
if (i->second.condition.order() == 0)
|
||||
--i->second.rank;
|
||||
else
|
||||
i->second.condition =
|
||||
acc_list_[i->second.condition.order() - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
--i->second.rank;
|
||||
i->second.condition = acc_list_[acc_list_.size() - 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_ranks_[i->first] = highest_current_ranks_[i->first];
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((i != current_ranks_.end()) && !is_valid_rank());
|
||||
|
||||
return i != current_ranks_.end();
|
||||
}
|
||||
|
||||
/// \brief Create the highest rank of \a origin_ as origin and
|
||||
/// \a condition as successor condition.
|
||||
void
|
||||
tgba_kv_complement_succ_iterator::successor_highest_rank(bdd condition)
|
||||
{
|
||||
// Highest rank for bdd.
|
||||
state_rank_map sr_map = origin_->get_state_map();
|
||||
highest_current_ranks_.clear();
|
||||
|
||||
for (state_rank_map::const_iterator i = sr_map.begin();
|
||||
i != sr_map.end();
|
||||
++i)
|
||||
{
|
||||
for (auto iterator: automaton_->succ(i->first.get()))
|
||||
{
|
||||
bdd c = iterator->current_condition();
|
||||
if ((c & condition) != bddfalse)
|
||||
{
|
||||
shared_state s(iterator->current_state(), shared_state_deleter);
|
||||
if (highest_current_ranks_.find(s) != highest_current_ranks_.end())
|
||||
{
|
||||
if (i->second < highest_current_ranks_[s])
|
||||
highest_current_ranks_[s] = i->second;
|
||||
}
|
||||
else
|
||||
highest_current_ranks_[s] = i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Highest $O$ set of the algorithm.
|
||||
shared_state_set s_set = origin_->get_filter_set();
|
||||
highest_state_set_.clear();
|
||||
|
||||
for (shared_state_set::const_iterator i = s_set.begin();
|
||||
i != s_set.end();
|
||||
++i)
|
||||
{
|
||||
for (auto iterator: automaton_->succ(i->get()))
|
||||
{
|
||||
bdd c = iterator->current_condition();
|
||||
if ((c & condition) != bddfalse)
|
||||
{
|
||||
shared_state s(iterator->current_state(), shared_state_deleter);
|
||||
highest_state_set_.insert(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current_ranks_ = highest_current_ranks_;
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::first()
|
||||
{
|
||||
current_condition_ = condition_list_.begin();
|
||||
if (current_condition_ == condition_list_.end())
|
||||
return false;
|
||||
|
||||
successor_highest_rank(*current_condition_);
|
||||
|
||||
if (!is_valid_rank())
|
||||
next_valid_rank();
|
||||
return current_condition_ != condition_list_.end();
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::next()
|
||||
{
|
||||
if (current_condition_ == condition_list_.end())
|
||||
return false;
|
||||
|
||||
if (!next_valid_rank())
|
||||
{
|
||||
++current_condition_;
|
||||
if (!done())
|
||||
{
|
||||
successor_highest_rank(*current_condition_);
|
||||
if (!is_valid_rank())
|
||||
next_valid_rank();
|
||||
}
|
||||
}
|
||||
return current_condition_ != condition_list_.end();
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_kv_complement_succ_iterator::done() const
|
||||
{
|
||||
return current_condition_ == condition_list_.end();
|
||||
}
|
||||
|
||||
state_kv_complement*
|
||||
tgba_kv_complement_succ_iterator::current_state() const
|
||||
{
|
||||
if (done())
|
||||
return 0;
|
||||
|
||||
// If the filter set is empty, all the states of the map
|
||||
// that are associated to an even rank create the new filter set.
|
||||
shared_state_set filter;
|
||||
if (origin_->get_filter_set().empty())
|
||||
{
|
||||
for (state_rank_map::const_iterator i = current_ranks_.begin();
|
||||
i != current_ranks_.end();
|
||||
++i)
|
||||
if (!(i->second.rank & 1))
|
||||
filter.insert(i->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It the filter set is non-empty, we delete from this set states
|
||||
// that are now associated to an odd rank.
|
||||
for (shared_state_set::const_iterator i = highest_state_set_.begin();
|
||||
i != highest_state_set_.end();
|
||||
++i)
|
||||
{
|
||||
state_rank_map::const_iterator s(current_ranks_.find(*i));
|
||||
assert(s != current_ranks_.end());
|
||||
|
||||
if (!(s->second.get_rank() & 1))
|
||||
filter.insert(*i);
|
||||
}
|
||||
}
|
||||
|
||||
return new state_kv_complement(current_ranks_, filter);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement_succ_iterator::current_condition() const
|
||||
{
|
||||
if (done())
|
||||
return bddfalse;
|
||||
return *current_condition_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
if (done())
|
||||
return bddfalse;
|
||||
|
||||
// This algorithm doesn't generalized acceptance conditions.
|
||||
if (origin_->accepting())
|
||||
return the_acceptance_cond_;
|
||||
else
|
||||
return bddfalse;
|
||||
}
|
||||
|
||||
} // end namespace anonymous.
|
||||
|
||||
/// Retrieve all the atomic acceptance conditions of the automaton.
|
||||
/// They are inserted into \a acc_list_.
|
||||
void
|
||||
tgba_kv_complement::get_acc_list()
|
||||
{
|
||||
bdd c = automaton_->all_acceptance_conditions();
|
||||
bdd current = bdd_satone(c);
|
||||
unsigned i = 0;
|
||||
while (current != bddtrue && current != bddfalse)
|
||||
{
|
||||
acc_list_.push_back(bdd_ordered(bdd_var(current), i));
|
||||
++i;
|
||||
bdd high = bdd_high(current);
|
||||
if (high == bddfalse)
|
||||
current = bdd_low(current);
|
||||
else
|
||||
current = high;
|
||||
}
|
||||
}
|
||||
|
||||
tgba_kv_complement::tgba_kv_complement(const const_tgba_ptr& a)
|
||||
: automaton_(make_sgba(a))
|
||||
{
|
||||
get_dict()->register_all_variables_of(automaton_, this);
|
||||
int v = get_dict()
|
||||
->register_acceptance_variable(ltl::constant::true_instance(), this);
|
||||
the_acceptance_cond_ = bdd_ithvar(v);
|
||||
nb_states_ = count_states(automaton_);
|
||||
get_acc_list();
|
||||
}
|
||||
|
||||
tgba_kv_complement::~tgba_kv_complement()
|
||||
{
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
state*
|
||||
tgba_kv_complement::get_init_state() const
|
||||
{
|
||||
state_kv_complement* init = new state_kv_complement();
|
||||
rank_t r = {2 * nb_states_, bdd_ordered()};
|
||||
init->add(shared_state(automaton_->get_init_state(), shared_state_deleter),
|
||||
r);
|
||||
return init;
|
||||
}
|
||||
|
||||
tgba_succ_iterator*
|
||||
tgba_kv_complement::succ_iter(const state* state) const
|
||||
{
|
||||
const state_kv_complement* s =
|
||||
down_cast<const state_kv_complement*>(state);
|
||||
assert(s);
|
||||
|
||||
return new tgba_kv_complement_succ_iterator(automaton_.get(),
|
||||
the_acceptance_cond_,
|
||||
acc_list_, s);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_kv_complement::get_dict() const
|
||||
{
|
||||
return automaton_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_kv_complement::format_state(const state* state) const
|
||||
{
|
||||
const state_kv_complement* s =
|
||||
down_cast<const state_kv_complement*>(state);
|
||||
assert(s);
|
||||
std::ostringstream ss;
|
||||
ss << "{ set: {" << std::endl;
|
||||
|
||||
const state_rank_map& state_map = s->get_state_map();
|
||||
const shared_state_set& state_filter = s->get_filter_set();
|
||||
|
||||
for (state_rank_map::const_iterator i = state_map.begin();
|
||||
i != state_map.end();
|
||||
++i)
|
||||
{
|
||||
ss << " {" << automaton_->format_state(i->first.get())
|
||||
<< ", " << i->second.format(get_dict()) << "}\n";
|
||||
}
|
||||
ss << "} odd-less: {";
|
||||
|
||||
for (shared_state_set::const_iterator i = state_filter.begin();
|
||||
i != state_filter.end();
|
||||
++i)
|
||||
ss << " " << automaton_->format_state(i->get()) << '\n';
|
||||
ss << "} }";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement::all_acceptance_conditions() const
|
||||
{
|
||||
return the_acceptance_cond_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement::neg_acceptance_conditions() const
|
||||
{
|
||||
return !the_acceptance_cond_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_kv_complement::compute_support_conditions(const state* state) const
|
||||
{
|
||||
bdd result = bddfalse;
|
||||
for (auto i: succ(state))
|
||||
result |= i->current_condition();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // end namespace spot.
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2010, 2012, 2013, 2014 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_TGBA_TGBAKVCOMPLEMENT_HH
|
||||
#define SPOT_TGBA_TGBAKVCOMPLEMENT_HH
|
||||
|
||||
#include <vector>
|
||||
#include "bdd.h"
|
||||
#include "tgba.hh"
|
||||
#include "tgba/tgbasgba.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
class SPOT_API bdd_ordered
|
||||
{
|
||||
public:
|
||||
bdd_ordered()
|
||||
: bdd_(0), order_(0)
|
||||
{};
|
||||
|
||||
bdd_ordered(int bdd_, unsigned order_)
|
||||
: bdd_(bdd_), order_(order_)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned order() const
|
||||
{
|
||||
return order_;
|
||||
}
|
||||
|
||||
unsigned& order()
|
||||
{
|
||||
return order_;
|
||||
}
|
||||
|
||||
bdd get_bdd() const
|
||||
{
|
||||
return bdd_ithvar(bdd_);
|
||||
}
|
||||
private:
|
||||
int bdd_;
|
||||
unsigned order_;
|
||||
};
|
||||
|
||||
typedef std::vector<bdd_ordered> acc_list_t;
|
||||
|
||||
/// \ingroup tgba_on_the_fly_algorithms
|
||||
/// \brief Build a complemented automaton.
|
||||
///
|
||||
/// The construction comes from:
|
||||
/** \verbatim
|
||||
@Article{ kupferman.05.tcs,
|
||||
title = {From complementation to certification},
|
||||
author = {Kupferman, O. and Vardi, M.Y.},
|
||||
journal = {Theoretical Computer Science},
|
||||
volume = {345},
|
||||
number = {1},
|
||||
pages = {83--100},
|
||||
year = {2005},
|
||||
publisher = {Elsevier}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
/// The original automaton is used as a States-based Generalized
|
||||
/// Büchi Automaton.
|
||||
///
|
||||
/// The construction is done on-the-fly, by the
|
||||
/// \c tgba_kv_complement_succ_iterator class.
|
||||
/// \see tgba_kv_complement_succ_iterator
|
||||
class SPOT_API tgba_kv_complement : public tgba
|
||||
{
|
||||
public:
|
||||
tgba_kv_complement(const const_tgba_ptr& a);
|
||||
virtual ~tgba_kv_complement();
|
||||
|
||||
// tgba interface
|
||||
virtual state* get_init_state() const;
|
||||
virtual tgba_succ_iterator* succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
virtual std::string format_state(const state* state) const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
private:
|
||||
/// Retrieve all the atomic acceptance conditions of the automaton.
|
||||
/// They are inserted into \a acc_list_.
|
||||
void get_acc_list();
|
||||
private:
|
||||
const_tgba_sgba_proxy_ptr automaton_;
|
||||
bdd the_acceptance_cond_;
|
||||
unsigned nb_states_;
|
||||
acc_list_t acc_list_;
|
||||
}; // end class tgba_kv_complement.
|
||||
|
||||
typedef std::shared_ptr<tgba_kv_complement> tgba_kv_complement_ptr;
|
||||
typedef std::shared_ptr<const tgba_kv_complement>
|
||||
const_tgba_kv_complement_ptr;
|
||||
inline tgba_kv_complement_ptr
|
||||
make_kv_complement(const const_tgba_ptr& a)
|
||||
{
|
||||
return std::make_shared<tgba_kv_complement>(a);
|
||||
}
|
||||
} // end namespace spot.
|
||||
|
||||
|
||||
#endif // !SPOT_TGBA_TGBAKVCOMPLEMENT_HH
|
||||
|
|
@ -28,7 +28,7 @@ namespace spot
|
|||
{
|
||||
const state* dest;
|
||||
bdd cond;
|
||||
bdd acc;
|
||||
acc_cond::mark_t acc;
|
||||
};
|
||||
typedef std::vector<transition> transitions;
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ namespace spot
|
|||
return it_->cond;
|
||||
}
|
||||
|
||||
bdd current_acceptance_conditions() const
|
||||
acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
return it_->acc;
|
||||
}
|
||||
|
|
@ -128,19 +128,19 @@ namespace spot
|
|||
for (auto it: original_->succ(local_state))
|
||||
{
|
||||
const spot::state* s = it->current_state();
|
||||
bdd acc = it->current_acceptance_conditions();
|
||||
auto acc = it->current_acceptance_conditions();
|
||||
if (!wanted(s, acc))
|
||||
{
|
||||
s->destroy();
|
||||
continue;
|
||||
}
|
||||
res->trans_.emplace_back(transition {s, it->current_condition(),
|
||||
acc});
|
||||
res->trans_.emplace_back
|
||||
(transition {s, it->current_condition(), acc});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual bool wanted(const state* s, const bdd& acc) const = 0;
|
||||
virtual bool wanted(const state* s, acc_cond::mark_t acc) const = 0;
|
||||
|
||||
protected:
|
||||
const state* init_;
|
||||
|
|
@ -158,7 +158,7 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
bool wanted(const state* s, const bdd&) const
|
||||
bool wanted(const state* s, const acc_cond::mark_t) const
|
||||
{
|
||||
state_set::const_iterator i = mask_.find(s);
|
||||
return i != mask_.end();
|
||||
|
|
@ -177,7 +177,7 @@ namespace spot
|
|||
{
|
||||
}
|
||||
|
||||
bool wanted(const state* s, const bdd&) const
|
||||
bool wanted(const state* s, const acc_cond::mark_t) const
|
||||
{
|
||||
state_set::const_iterator i = mask_.find(s);
|
||||
return i == mask_.end();
|
||||
|
|
@ -186,19 +186,19 @@ namespace spot
|
|||
|
||||
class tgba_mask_acc_ignore: public tgba_mask
|
||||
{
|
||||
const bdd& mask_;
|
||||
unsigned mask_;
|
||||
public:
|
||||
tgba_mask_acc_ignore(const const_tgba_ptr& masked,
|
||||
const bdd& mask,
|
||||
unsigned mask,
|
||||
const state* init)
|
||||
: tgba_mask(masked, init),
|
||||
mask_(mask)
|
||||
{
|
||||
}
|
||||
|
||||
bool wanted(const state*, const bdd& acc) const
|
||||
bool wanted(const state*, const acc_cond::mark_t acc) const
|
||||
{
|
||||
return (acc & mask_) == bddfalse;
|
||||
return !acc.has(mask_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ namespace spot
|
|||
|
||||
const_tgba_ptr
|
||||
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
||||
const bdd to_ignore,
|
||||
unsigned to_ignore,
|
||||
const state* init)
|
||||
{
|
||||
return std::make_shared<tgba_mask_acc_ignore>(to_mask, to_ignore, init);
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ namespace spot
|
|||
/// \ingroup tgba_on_the_fly_algorithms
|
||||
/// \brief Mask a TGBA, rejecting some acceptance set of transitions.
|
||||
///
|
||||
/// This will ignore all transitions labeled by the acceptance ACC
|
||||
/// such that ACC & TO_IGNORE != bddfalse. The initial state can
|
||||
/// optionally be reset to \a init.
|
||||
/// This will ignore all transitions that have the TO_IGNORE
|
||||
/// acceptance mark. The initial state can optionally be reset to
|
||||
/// \a init.
|
||||
///
|
||||
/// Note that the acceptance condition of the automaton (i.e. the
|
||||
/// set of all acceptance set) is not changed, because so far this
|
||||
|
|
@ -62,7 +62,7 @@ namespace spot
|
|||
/// all_acceptance_conditions().
|
||||
SPOT_API const_tgba_ptr
|
||||
build_tgba_mask_acc_ignore(const const_tgba_ptr& to_mask,
|
||||
const bdd to_ignore,
|
||||
unsigned to_ignore,
|
||||
const state* init = 0);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,9 @@ namespace spot
|
|||
public:
|
||||
tgba_succ_iterator_product_common(tgba_succ_iterator* left,
|
||||
tgba_succ_iterator* right,
|
||||
const tgba_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: left_(left), right_(right), pool_(pool)
|
||||
: left_(left), right_(right), prod_(prod), pool_(pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +140,7 @@ namespace spot
|
|||
protected:
|
||||
tgba_succ_iterator* left_;
|
||||
tgba_succ_iterator* right_;
|
||||
const tgba_product* prod_;
|
||||
fixed_size_pool* pool_;
|
||||
friend class spot::tgba_product;
|
||||
};
|
||||
|
|
@ -150,13 +152,9 @@ namespace spot
|
|||
public:
|
||||
tgba_succ_iterator_product(tgba_succ_iterator* left,
|
||||
tgba_succ_iterator* right,
|
||||
bdd left_neg, bdd right_neg,
|
||||
bddPair* right_common_acc,
|
||||
const tgba_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: tgba_succ_iterator_product_common(left, right, pool),
|
||||
left_neg_(left_neg),
|
||||
right_neg_(right_neg),
|
||||
right_common_acc_(right_common_acc)
|
||||
: tgba_succ_iterator_product_common(left, right, prod, pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -203,18 +201,17 @@ namespace spot
|
|||
return current_cond_;
|
||||
}
|
||||
|
||||
bdd current_acceptance_conditions() const
|
||||
acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
return ((left_->current_acceptance_conditions() & right_neg_)
|
||||
| (bdd_replace(right_->current_acceptance_conditions(),
|
||||
right_common_acc_) & left_neg_));
|
||||
}
|
||||
return
|
||||
prod_->acc().join(prod_->left_acc(),
|
||||
left_->current_acceptance_conditions(),
|
||||
prod_->right_acc(),
|
||||
right_->current_acceptance_conditions());
|
||||
}
|
||||
|
||||
protected:
|
||||
bdd current_cond_;
|
||||
bdd left_neg_;
|
||||
bdd right_neg_;
|
||||
bddPair* right_common_acc_;
|
||||
};
|
||||
|
||||
/// Iterate over the successors of a product computed on the fly.
|
||||
|
|
@ -225,8 +222,9 @@ namespace spot
|
|||
public:
|
||||
tgba_succ_iterator_product_kripke(tgba_succ_iterator* left,
|
||||
tgba_succ_iterator* right,
|
||||
const tgba_product* prod,
|
||||
fixed_size_pool* pool)
|
||||
: tgba_succ_iterator_product_common(left, right, pool)
|
||||
: tgba_succ_iterator_product_common(left, right, prod, pool)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +268,7 @@ namespace spot
|
|||
return current_cond_;
|
||||
}
|
||||
|
||||
bdd current_acceptance_conditions() const
|
||||
acc_cond::mark_t current_acceptance_conditions() const
|
||||
{
|
||||
return right_->current_acceptance_conditions();
|
||||
}
|
||||
|
|
@ -286,10 +284,10 @@ namespace spot
|
|||
|
||||
tgba_product::tgba_product(const const_tgba_ptr& left,
|
||||
const const_tgba_ptr& right)
|
||||
: dict_(left->get_dict()), left_(left), right_(right),
|
||||
: tgba(left->get_dict()), left_(left), right_(right),
|
||||
pool_(sizeof(state_product))
|
||||
{
|
||||
assert(dict_ == right_->get_dict());
|
||||
assert(get_dict() == right_->get_dict());
|
||||
|
||||
// If one of the side is a Kripke structure, it is easier to deal
|
||||
// with (we don't have to fix the acceptance conditions, and
|
||||
|
|
@ -308,55 +306,17 @@ namespace spot
|
|||
left_kripke_ = false;
|
||||
}
|
||||
|
||||
dict_->register_all_variables_of(&left_, this);
|
||||
dict_->register_all_variables_of(&right_, this);
|
||||
auto d = get_dict();
|
||||
d->register_all_propositions_of(&left_, this);
|
||||
d->register_all_propositions_of(&right_, this);
|
||||
|
||||
if (left_kripke_)
|
||||
{
|
||||
all_acceptance_conditions_ = right_->all_acceptance_conditions();
|
||||
neg_acceptance_conditions_ = right_->neg_acceptance_conditions();
|
||||
return;
|
||||
}
|
||||
|
||||
bdd lna = left_->neg_acceptance_conditions();
|
||||
bdd rna = right_->neg_acceptance_conditions();
|
||||
|
||||
right_common_acc_ = bdd_newpair();
|
||||
|
||||
bdd tmp = lna;
|
||||
while (tmp != bddtrue)
|
||||
{
|
||||
assert(bdd_high(tmp) == bddfalse);
|
||||
int var = bdd_var(tmp);
|
||||
if (bdd_implies(rna, bdd_nithvar(var)))
|
||||
{
|
||||
int varclone = dict_->register_clone_acc(var, this);
|
||||
bdd_setpair(right_common_acc_, var, varclone);
|
||||
}
|
||||
tmp = bdd_low(tmp);
|
||||
}
|
||||
|
||||
bdd lac = left_->all_acceptance_conditions();
|
||||
bdd rac = right_->all_acceptance_conditions();
|
||||
|
||||
rna = bdd_replace(rna, right_common_acc_);
|
||||
rac = bdd_replace(rac, right_common_acc_);
|
||||
|
||||
left_acc_complement_ = lna;
|
||||
assert(bdd_exist(lna, rna) == lna);
|
||||
right_acc_complement_ = rna;
|
||||
assert(bdd_exist(rna, lna) == rna);
|
||||
|
||||
all_acceptance_conditions_ = ((lac & right_acc_complement_)
|
||||
| (rac & left_acc_complement_));
|
||||
neg_acceptance_conditions_ = lna & rna;
|
||||
assert(acc_.num_sets() == 0);
|
||||
acc_.add_sets(left->acc().num_sets() + right->acc().num_sets());
|
||||
}
|
||||
|
||||
tgba_product::~tgba_product()
|
||||
{
|
||||
if (!left_kripke_)
|
||||
bdd_freepair(right_common_acc_);
|
||||
dict_->unregister_all_my_variables(this);
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
// Prevent these states from being destroyed by ~tgba(): they
|
||||
// will be destroyed before when the pool is destructed.
|
||||
if (last_support_conditions_input_)
|
||||
|
|
@ -393,13 +353,9 @@ namespace spot
|
|||
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&pool_);
|
||||
if (left_kripke_)
|
||||
return new tgba_succ_iterator_product_kripke(li, ri, p);
|
||||
return new tgba_succ_iterator_product_kripke(li, ri, this, p);
|
||||
else
|
||||
return new tgba_succ_iterator_product(li, ri,
|
||||
left_acc_complement_,
|
||||
right_acc_complement_,
|
||||
right_common_acc_,
|
||||
p);
|
||||
return new tgba_succ_iterator_product(li, ri, this, p);
|
||||
}
|
||||
|
||||
bdd
|
||||
|
|
@ -412,10 +368,14 @@ namespace spot
|
|||
return lsc & rsc;
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_product::get_dict() const
|
||||
const acc_cond& tgba_product::left_acc() const
|
||||
{
|
||||
return dict_;
|
||||
return left_->acc();
|
||||
}
|
||||
|
||||
const acc_cond& tgba_product::right_acc() const
|
||||
{
|
||||
return right_->acc();
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
@ -441,18 +401,6 @@ namespace spot
|
|||
return right_->project_state(s2->right(), t);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_product::all_acceptance_conditions() const
|
||||
{
|
||||
return all_acceptance_conditions_;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_product::neg_acceptance_conditions() const
|
||||
{
|
||||
return neg_acceptance_conditions_;
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_product::transition_annotation(const tgba_succ_iterator* t) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ namespace spot
|
|||
virtual tgba_succ_iterator*
|
||||
succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
|
||||
virtual std::string format_state(const state* state) const;
|
||||
|
||||
virtual std::string
|
||||
|
|
@ -103,22 +101,16 @@ namespace spot
|
|||
|
||||
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
const acc_cond& left_acc() const;
|
||||
const acc_cond& right_acc() const;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
|
||||
protected:
|
||||
bdd_dict_ptr dict_;
|
||||
const_tgba_ptr left_;
|
||||
const_tgba_ptr right_;
|
||||
bool left_kripke_;
|
||||
bdd left_acc_complement_;
|
||||
bdd right_acc_complement_;
|
||||
bdd all_acceptance_conditions_;
|
||||
bdd neg_acceptance_conditions_;
|
||||
bddPair* right_common_acc_;
|
||||
fixed_size_pool pool_;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -22,9 +22,10 @@
|
|||
namespace spot
|
||||
{
|
||||
tgba_proxy::tgba_proxy(const const_tgba_ptr& original)
|
||||
: original_(original)
|
||||
: tgba(original->get_dict()), original_(original)
|
||||
{
|
||||
get_dict()->register_all_variables_of(original, this);
|
||||
acc_.add_sets(original->acc().num_sets());
|
||||
}
|
||||
|
||||
tgba_proxy::~tgba_proxy()
|
||||
|
|
@ -48,12 +49,6 @@ namespace spot
|
|||
return original_->succ_iter(state);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_proxy::get_dict() const
|
||||
{
|
||||
return original_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_proxy::format_state(const state* state) const
|
||||
{
|
||||
|
|
@ -72,18 +67,6 @@ namespace spot
|
|||
return original_->project_state(s, t);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_proxy::all_acceptance_conditions() const
|
||||
{
|
||||
return original_->all_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_proxy::neg_acceptance_conditions() const
|
||||
{
|
||||
return original_->neg_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_proxy::compute_support_conditions(const state* state) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@ namespace spot
|
|||
virtual tgba_succ_iterator*
|
||||
succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
|
||||
virtual std::string format_state(const state* state) const;
|
||||
|
||||
virtual std::string
|
||||
|
|
@ -55,10 +53,6 @@ namespace spot
|
|||
|
||||
virtual state* project_state(const state* s, const const_tgba_ptr& t) const;
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
const_tgba_ptr original_;
|
||||
|
|
|
|||
|
|
@ -962,7 +962,7 @@ namespace spot
|
|||
typedef std::multimap<bdd, state_complement*, bdd_less_than> succ_list_t;
|
||||
|
||||
tgba_safra_complement_succ_iterator(const succ_list_t& list,
|
||||
bdd the_acceptance_cond)
|
||||
acc_cond::mark_t the_acceptance_cond)
|
||||
: list_(list), the_acceptance_cond_(the_acceptance_cond)
|
||||
{
|
||||
}
|
||||
|
|
@ -979,10 +979,10 @@ namespace spot
|
|||
virtual bool done() const;
|
||||
virtual state_complement* current_state() const;
|
||||
virtual bdd current_condition() const;
|
||||
virtual bdd current_acceptance_conditions() const;
|
||||
virtual acc_cond::mark_t current_acceptance_conditions() const;
|
||||
private:
|
||||
succ_list_t list_;
|
||||
bdd the_acceptance_cond_;
|
||||
acc_cond::mark_t the_acceptance_cond_;
|
||||
succ_list_t::const_iterator it_;
|
||||
};
|
||||
|
||||
|
|
@ -1020,7 +1020,7 @@ namespace spot
|
|||
return it_->first;
|
||||
}
|
||||
|
||||
bdd
|
||||
acc_cond::mark_t
|
||||
tgba_safra_complement_succ_iterator::current_acceptance_conditions() const
|
||||
{
|
||||
assert(!done());
|
||||
|
|
@ -1075,38 +1075,22 @@ namespace spot
|
|||
//////////////////////////
|
||||
|
||||
tgba_safra_complement::tgba_safra_complement(const const_tgba_ptr& a)
|
||||
: automaton_(a), safra_(safra_determinisation::create_safra_automaton(a))
|
||||
: tgba(a->get_dict()), automaton_(a),
|
||||
safra_(safra_determinisation::create_safra_automaton(a))
|
||||
{
|
||||
assert(safra_ || !"safra construction fails");
|
||||
|
||||
// We will use one acceptance condition for this automata.
|
||||
// Let's call it Acc[True].
|
||||
int v = get_dict()
|
||||
->register_acceptance_variable(ltl::constant::true_instance(), safra_);
|
||||
|
||||
#if TRANSFORM_TO_TBA
|
||||
the_acceptance_cond_ = bdd_ithvar(v);
|
||||
the_acceptance_cond_ = acc_.mark(acc_.add_set());
|
||||
#endif
|
||||
|
||||
#if TRANSFORM_TO_TGBA
|
||||
unsigned nb_acc =
|
||||
static_cast<safra_tree_automaton*>(safra_)->get_nb_acceptance_pairs();
|
||||
all_acceptance_cond_ = bddfalse;
|
||||
neg_acceptance_cond_ = bddtrue;
|
||||
|
||||
acceptance_cond_vec_.reserve(nb_acc);
|
||||
for (unsigned i = 0; i < nb_acc; ++i)
|
||||
{
|
||||
int r = get_dict()->register_clone_acc(v, safra_);
|
||||
all_acceptance_cond_ &= bdd_nithvar(r);
|
||||
all_acceptance_cond_ |= bdd_ithvar(r) & neg_acceptance_cond_;
|
||||
neg_acceptance_cond_ &= bdd_nithvar(r);
|
||||
acceptance_cond_vec_.push_back(bdd_ithvar(r));
|
||||
}
|
||||
for (unsigned i = 0; i < nb_acc; ++i)
|
||||
{
|
||||
bdd c = acceptance_cond_vec_[i];
|
||||
acceptance_cond_vec_[i] = bdd_exist(neg_acceptance_cond_, c) & c;
|
||||
}
|
||||
acceptance_cond_vec_.push_back(acc_.mark(acc_.add_set()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1171,7 +1155,7 @@ namespace spot
|
|||
|
||||
assert(tr != a->automaton.end());
|
||||
|
||||
bdd condition = bddfalse;
|
||||
acc_cond::mark_t condition = 0U;
|
||||
tgba_safra_complement_succ_iterator::succ_list_t succ_list;
|
||||
int nb_acceptance_pairs = a->get_nb_acceptance_pairs();
|
||||
bitvect* e = make_bitvect(nb_acceptance_pairs);
|
||||
|
|
@ -1249,12 +1233,6 @@ namespace spot
|
|||
return new tgba_safra_complement_succ_iterator(succ_list, condition);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_safra_complement::get_dict() const
|
||||
{
|
||||
return automaton_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_safra_complement::format_state(const state* state) const
|
||||
{
|
||||
|
|
@ -1264,26 +1242,6 @@ namespace spot
|
|||
return s->to_string();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_safra_complement::all_acceptance_conditions() const
|
||||
{
|
||||
#if TRANSFORM_TO_TBA
|
||||
return the_acceptance_cond_;
|
||||
#else
|
||||
return all_acceptance_cond_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_safra_complement::neg_acceptance_conditions() const
|
||||
{
|
||||
#if TRANSFORM_TO_TBA
|
||||
return !the_acceptance_cond_;
|
||||
#else
|
||||
return neg_acceptance_cond_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_safra_complement::compute_support_conditions(const state* state) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,10 +57,7 @@ namespace spot
|
|||
virtual state* get_init_state() const;
|
||||
virtual tgba_succ_iterator* succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
virtual std::string format_state(const state* state) const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
void* get_safra() const
|
||||
{
|
||||
|
|
@ -73,13 +70,11 @@ namespace spot
|
|||
const_tgba_ptr automaton_;
|
||||
void* safra_;
|
||||
#if TRANSFORM_TO_TBA
|
||||
bdd the_acceptance_cond_;
|
||||
acc_cond::mark_t the_acceptance_cond_;
|
||||
#endif
|
||||
#if TRANSFORM_TO_TGBA
|
||||
bdd all_acceptance_cond_;
|
||||
bdd neg_acceptance_cond_;
|
||||
// Map to i the i-th acceptance condition of the final automaton.
|
||||
std::vector<bdd> acceptance_cond_vec_;
|
||||
std::vector<acc_cond::mark_t> acceptance_cond_vec_;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,262 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2011, 2012, 2014 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <cassert>
|
||||
#include "tgbasgba.hh"
|
||||
#include "bddprint.hh"
|
||||
#include "ltlast/constant.hh"
|
||||
#include "misc/hashfunc.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
namespace
|
||||
{
|
||||
/// \brief A state for spot::tgba_sgba_proxy.
|
||||
class state_sgba_proxy: public state
|
||||
{
|
||||
public:
|
||||
state_sgba_proxy(state* s, bdd acc)
|
||||
: s_(s), acc_(acc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
state_sgba_proxy(const state_sgba_proxy& o)
|
||||
: state(),
|
||||
s_(o.real_state()->clone()),
|
||||
acc_(o.acc_)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~state_sgba_proxy()
|
||||
{
|
||||
s_->destroy();
|
||||
}
|
||||
|
||||
state*
|
||||
real_state() const
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
bdd
|
||||
acceptance_cond() const
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
virtual int
|
||||
compare(const state* other) const
|
||||
{
|
||||
const state_sgba_proxy* o =
|
||||
down_cast<const state_sgba_proxy*>(other);
|
||||
assert(o);
|
||||
int res = s_->compare(o->real_state());
|
||||
if (res != 0)
|
||||
return res;
|
||||
return acc_.id() - o->acc_.id();
|
||||
}
|
||||
|
||||
virtual size_t
|
||||
hash() const
|
||||
{
|
||||
return wang32_hash(s_->hash()) ^ wang32_hash(acc_.id());
|
||||
}
|
||||
|
||||
virtual
|
||||
state_sgba_proxy* clone() const
|
||||
{
|
||||
return new state_sgba_proxy(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
state* s_;
|
||||
bdd acc_;
|
||||
};
|
||||
|
||||
/// \brief Iterate over the successors of tgba_sgba_proxy computed
|
||||
/// on the fly.
|
||||
class tgba_sgba_proxy_succ_iterator: public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
tgba_sgba_proxy_succ_iterator(tgba_succ_iterator* it)
|
||||
: it_(it), emulate_acc_cond_(false)
|
||||
{
|
||||
}
|
||||
|
||||
tgba_sgba_proxy_succ_iterator(tgba_succ_iterator* it, bdd acc)
|
||||
: it_(it), emulate_acc_cond_(true), acceptance_condition_(acc)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~tgba_sgba_proxy_succ_iterator()
|
||||
{
|
||||
delete it_;
|
||||
}
|
||||
|
||||
// iteration
|
||||
|
||||
bool
|
||||
first()
|
||||
{
|
||||
return it_->first();
|
||||
}
|
||||
|
||||
bool
|
||||
next()
|
||||
{
|
||||
return it_->next();
|
||||
}
|
||||
|
||||
bool
|
||||
done() const
|
||||
{
|
||||
return it_->done();
|
||||
}
|
||||
|
||||
// inspection
|
||||
|
||||
state_sgba_proxy*
|
||||
current_state() const
|
||||
{
|
||||
return new state_sgba_proxy(it_->current_state(),
|
||||
it_->current_acceptance_conditions());
|
||||
}
|
||||
|
||||
bdd
|
||||
current_condition() const
|
||||
{
|
||||
return it_->current_condition();
|
||||
}
|
||||
|
||||
bdd
|
||||
current_acceptance_conditions() const
|
||||
{
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return it_->current_acceptance_conditions();
|
||||
}
|
||||
|
||||
protected:
|
||||
tgba_succ_iterator* it_;
|
||||
// If the automaton has no acceptance condition,
|
||||
// every state is accepting.
|
||||
bool emulate_acc_cond_;
|
||||
bdd acceptance_condition_;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
tgba_sgba_proxy::tgba_sgba_proxy(const const_tgba_ptr& a,
|
||||
bool no_zero_acc)
|
||||
: a_(a), emulate_acc_cond_(false)
|
||||
{
|
||||
if (no_zero_acc && a_->number_of_acceptance_conditions() == 0)
|
||||
{
|
||||
emulate_acc_cond_ = true;
|
||||
int v = get_dict()
|
||||
->register_acceptance_variable(ltl::constant::true_instance(), this);
|
||||
acceptance_condition_ = bdd_ithvar(v);
|
||||
}
|
||||
|
||||
get_dict()->register_all_variables_of(a, this);
|
||||
}
|
||||
|
||||
tgba_sgba_proxy::~tgba_sgba_proxy()
|
||||
{
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
state*
|
||||
tgba_sgba_proxy::get_init_state() const
|
||||
{
|
||||
return new state_sgba_proxy(a_->get_init_state(), bddfalse);
|
||||
}
|
||||
|
||||
tgba_succ_iterator*
|
||||
tgba_sgba_proxy::succ_iter(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s = down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
tgba_succ_iterator* it = a_->succ_iter(s->real_state());
|
||||
return new tgba_sgba_proxy_succ_iterator(it);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgba_sgba_proxy::get_dict() const
|
||||
{
|
||||
return a_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_sgba_proxy::format_state(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s = down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
std::string a;
|
||||
if (!emulate_acc_cond_)
|
||||
a = bdd_format_accset(get_dict(), s->acceptance_cond());
|
||||
else
|
||||
a = bdd_format_accset(get_dict(), acceptance_condition_);
|
||||
if (a != "")
|
||||
a = " " + a;
|
||||
return a_->format_state(s->real_state()) + a;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::all_acceptance_conditions() const
|
||||
{
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return a_->all_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::neg_acceptance_conditions() const
|
||||
{
|
||||
if (emulate_acc_cond_)
|
||||
return bdd_nithvar(bdd_var(acceptance_condition_));
|
||||
return a_->neg_acceptance_conditions();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::state_acceptance_conditions(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s =
|
||||
down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return s->acceptance_cond();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_sgba_proxy::compute_support_conditions(const state* state) const
|
||||
{
|
||||
const state_sgba_proxy* s =
|
||||
down_cast<const state_sgba_proxy*>(state);
|
||||
assert(s);
|
||||
|
||||
if (emulate_acc_cond_)
|
||||
return acceptance_condition_;
|
||||
return a_->support_conditions(s->real_state());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2009, 2013, 2014 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SPOT_TGBA_TGBASGBA_HH
|
||||
# define SPOT_TGBA_TGBASGBA_HH
|
||||
|
||||
#include "tgba.hh"
|
||||
#include "misc/bddlt.hh"
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// \ingroup tgba_on_the_fly_algorithms
|
||||
/// \brief Change the labeling-mode of spot::tgba on the fly, producing a
|
||||
/// state-based generalized Büchi automaton.
|
||||
///
|
||||
/// This class acts as a proxy in front of a spot::tgba, that should
|
||||
/// label on states on-the-fly. The result is still a spot::tgba,
|
||||
/// but acceptances conditions are also on states.
|
||||
class SPOT_API tgba_sgba_proxy : public tgba
|
||||
{
|
||||
public:
|
||||
tgba_sgba_proxy(const const_tgba_ptr& a, bool no_zero_acc = true);
|
||||
|
||||
virtual ~tgba_sgba_proxy();
|
||||
|
||||
virtual state* get_init_state() const;
|
||||
|
||||
virtual tgba_succ_iterator* succ_iter(const state* state) const;
|
||||
|
||||
virtual bdd_dict_ptr get_dict() const;
|
||||
|
||||
virtual std::string format_state(const state* state) const;
|
||||
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
|
||||
/// \brief Retrieve the acceptance condition of a state.
|
||||
bdd state_acceptance_conditions(const state* state) const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const state* state) const;
|
||||
|
||||
private:
|
||||
const_tgba_ptr a_;
|
||||
// If the automaton has no acceptance condition,
|
||||
// every state is accepting.
|
||||
bool emulate_acc_cond_;
|
||||
bdd acceptance_condition_;
|
||||
// Disallow copy.
|
||||
tgba_sgba_proxy(const tgba_sgba_proxy&) SPOT_DELETED;
|
||||
tgba_sgba_proxy& operator=(const tgba_sgba_proxy&) SPOT_DELETED;
|
||||
};
|
||||
|
||||
inline tgba_sgba_proxy_ptr make_sgba(const const_tgba_ptr& a,
|
||||
bool no_zero_acc = true)
|
||||
{
|
||||
return std::make_shared<tgba_sgba_proxy>(a, no_zero_acc);
|
||||
}
|
||||
}
|
||||
#endif // SPOT_TGBA_TGBASGBA_HH
|
||||
Loading…
Add table
Add a link
Reference in a new issue