safra: get rid of boost::dynamic_bitset.

The bitvect implementation seems a tad faster, but most importantly
this removes the last dependency on Boost.

* src/tgba/tgbasafracomplement.cc: Replace boost::dynamic_bitset by
spot::bitvect.
This commit is contained in:
Alexandre Duret-Lutz 2013-12-18 18:33:57 +01:00
parent 9a097bb02e
commit 92ef3e1016

View file

@ -22,7 +22,8 @@
#include <deque> #include <deque>
#include <cassert> #include <cassert>
#include <sstream> #include <sstream>
#include <boost/dynamic_bitset.hpp> #include <algorithm>
#include "misc/bitvect.hh"
#include "bdd.h" #include "bdd.h"
#include "misc/hash.hh" #include "misc/hash.hh"
#include "misc/bddlt.hh" #include "misc/bddlt.hh"
@ -38,8 +39,6 @@
namespace spot namespace spot
{ {
typedef boost::dynamic_bitset<> bitset_t;
namespace namespace
{ {
// forward decl. // forward decl.
@ -121,8 +120,8 @@ namespace spot
safra_tree* mark(); safra_tree* mark();
// To get Rabin/Streett acceptance conditions. // To get Rabin/Streett acceptance conditions.
void getL(bitset_t& bitset) const; void getL(bitvect& bitset) const;
void getU(bitset_t& bitset) const; void getU(bitvect& bitset) const;
/// \brief Is this node the root of the tree? /// \brief Is this node the root of the tree?
bool is_root() const bool is_root() const
@ -522,11 +521,11 @@ namespace spot
/// filled with FALSE bits. /// filled with FALSE bits.
/// On return bitset[i] will be set if this state-tree is included in L_i. /// On return bitset[i] will be set if this state-tree is included in L_i.
void void
safra_tree::getL(bitset_t& bitset) const safra_tree::getL(bitvect& bitset) const
{ {
assert(bitset.size() > static_cast<unsigned>(name)); assert(bitset.size() > static_cast<unsigned>(name));
if (marked && !nodes.empty()) if (marked && !nodes.empty())
bitset[name] = true; bitset.set(name);
for (child_list::const_iterator i = children.begin(); for (child_list::const_iterator i = children.begin();
i != children.end(); i != children.end();
++i) ++i)
@ -540,11 +539,11 @@ namespace spot
/// filled with TRUE bits. /// filled with TRUE bits.
/// On return bitset[i] will be set if this state-tree is included in U_i. /// On return bitset[i] will be set if this state-tree is included in U_i.
void void
safra_tree::getU(bitset_t& bitset) const safra_tree::getU(bitvect& bitset) const
{ {
assert(bitset.size() > static_cast<unsigned>(name)); assert(bitset.size() > static_cast<unsigned>(name));
if (!nodes.empty()) if (!nodes.empty())
bitset[name] = false; bitset.clear(name);
for (child_list::const_iterator i = children.begin(); for (child_list::const_iterator i = children.begin();
i != children.end(); i != children.end();
++i) ++i)
@ -774,14 +773,16 @@ namespace spot
std::string conditions; std::string conditions;
if (this_node->is_root()) if (this_node->is_root())
{ {
bitset_t l(nb_accepting_conditions); bitvect* l = make_bitvect(nb_accepting_conditions);
bitset_t u(nb_accepting_conditions); bitvect* u = make_bitvect(nb_accepting_conditions);
u.flip(); u->set_all();
this_node->getL(l); this_node->getL(*l);
this_node->getU(u); this_node->getU(*u);
std::stringstream s; std::stringstream s;
s << "\\nL:" << l << ", U:" << u; s << "\\nL:" << *l << ", U:" << *u;
conditions = s.str(); conditions = s.str();
delete u;
delete l;
} }
std::cout << "node" << this_node << "[label=\""; std::cout << "node" << this_node << "[label=\"";
@ -869,9 +870,10 @@ namespace spot
class state_complement : public state class state_complement : public state
{ {
public: public:
state_complement(bitset_t U, bitset_t L, const safra_tree* tree, state_complement(bitvect* U, bitvect* L, const safra_tree* tree,
bool use_bitset = true); bool use_bitset = true);
state_complement(const state_complement& other); state_complement(const state_complement& other);
virtual ~state_complement();
/// \return the safra tree associated to this state. /// \return the safra tree associated to this state.
const safra_tree* get_safra() const const safra_tree* get_safra() const
@ -880,15 +882,15 @@ namespace spot
} }
/// \return in which sets U this state is included. /// \return in which sets U this state is included.
bitset_t get_U() const const bitvect& get_U() const
{ {
return U; return *U;
} }
/// \return in which sets L this state is included. /// \return in which sets L this state is included.
bitset_t get_L() const const bitvect& get_L() const
{ {
return L; return *L;
} }
/// \return whether this state track an infinite run. /// \return whether this state track an infinite run.
@ -901,20 +903,16 @@ namespace spot
virtual size_t hash() const; virtual size_t hash() const;
virtual state_complement* clone() const; virtual state_complement* clone() const;
virtual ~state_complement()
{
}
std::string to_string() const; std::string to_string() const;
const state* get_state() const; const state* get_state() const;
private: private:
bitset_t U; bitvect* U;
bitset_t L; bitvect* L;
const safra_tree* tree; const safra_tree* tree;
bool use_bitset; bool use_bitset;
}; };
state_complement::state_complement(bitset_t L, bitset_t U, state_complement::state_complement(bitvect* L, bitvect* U,
const safra_tree* tree, const safra_tree* tree,
bool use_bitset) bool use_bitset)
: state(), U(U), L(L), tree(tree), use_bitset(use_bitset) : state(), U(U), L(L), tree(tree), use_bitset(use_bitset)
@ -924,12 +922,18 @@ namespace spot
state_complement::state_complement(const state_complement& other) state_complement::state_complement(const state_complement& other)
: state() : state()
{ {
U = other.U; U = other.U->clone();
L = other.L; L = other.L->clone();
tree = other.tree; tree = other.tree;
use_bitset = other.use_bitset; use_bitset = other.use_bitset;
} }
state_complement::~state_complement()
{
delete U;
delete L;
}
int int
state_complement::compare(const state* other) const state_complement::compare(const state* other) const
{ {
@ -939,11 +943,11 @@ namespace spot
assert(s); assert(s);
#if TRANSFORM_TO_TBA #if TRANSFORM_TO_TBA
// When we transform to TBA instead of TGBA, states depend on the U set. // When we transform to TBA instead of TGBA, states depend on the U set.
if (U != s->U) if (*U != *s->U)
return (U < s->U) ? -1 : 1; return (*U < *s->U) ? -1 : 1;
#endif #endif
if (L != s->L) if (*L != *s->L)
return (L < s->L) ? -1 : 1; return (*L < *s->L) ? -1 : 1;
if (use_bitset != s->use_bitset) if (use_bitset != s->use_bitset)
return use_bitset - s->use_bitset; return use_bitset - s->use_bitset;
return tree->compare(s->tree); return tree->compare(s->tree);
@ -954,16 +958,10 @@ namespace spot
{ {
size_t hash = tree->hash(); size_t hash = tree->hash();
hash ^= wang32_hash(use_bitset); hash ^= wang32_hash(use_bitset);
hash ^= L->hash();
size_t size_bitset = L.size();
for (unsigned i = 0; i < size_bitset; ++i)
{
hash ^= wang32_hash(L[i]);
#if TRANSFORM_TO_TBA #if TRANSFORM_TO_TBA
hash ^= wang32_hash(U[i]); hash ^= U->hash();
#endif #endif
}
return hash; return hash;
} }
@ -986,9 +984,9 @@ namespace spot
ss << tree; ss << tree;
if (use_bitset) if (use_bitset)
{ {
ss << " - I:" << L; ss << " - I:" << *L;
#if TRANSFORM_TO_TBA #if TRANSFORM_TO_TBA
ss << " J:" << U; ss << " J:" << *U;
#endif #endif
} }
return ss.str(); return ss.str();
@ -1165,8 +1163,9 @@ namespace spot
tgba_safra_complement::get_init_state() const tgba_safra_complement::get_init_state() const
{ {
safra_tree_automaton* a = static_cast<safra_tree_automaton*>(safra_); safra_tree_automaton* a = static_cast<safra_tree_automaton*>(safra_);
bitset_t empty(a->get_nb_acceptance_pairs()); bitvect* empty = make_bitvect(a->get_nb_acceptance_pairs());
return new state_complement(empty, empty, a->get_initial_state(), false); return new state_complement(empty->clone(), empty,
a->get_initial_state(), false);
} }
@ -1223,36 +1222,41 @@ namespace spot
bdd condition = bddfalse; bdd condition = bddfalse;
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();
bitset_t e(nb_acceptance_pairs); bitvect* e = make_bitvect(nb_acceptance_pairs);
if (!s->get_use_bitset()) // if \delta'(q, a) if (!s->get_use_bitset()) // if \delta'(q, a)
{ {
for (trans_iter i = tr->second.begin(); i != tr->second.end(); ++i) for (trans_iter i = tr->second.begin(); i != tr->second.end(); ++i)
{ {
state_complement* s1 = new state_complement(e, e, i->second, false); state_complement* s1 = new state_complement(e->clone(), e->clone(),
state_complement* s2 = new state_complement(e, e, i->second, true); i->second, false);
state_complement* s2 = new state_complement(e->clone(), e->clone(),
i->second, true);
succ_list.insert(std::make_pair(i->first, s1)); succ_list.insert(std::make_pair(i->first, s1));
succ_list.insert(std::make_pair(i->first, s2)); succ_list.insert(std::make_pair(i->first, s2));
} }
} }
else else
{ {
bitset_t l(nb_acceptance_pairs); bitvect* l = make_bitvect(nb_acceptance_pairs);
bitset_t u(nb_acceptance_pairs); bitvect* u = make_bitvect(nb_acceptance_pairs);
u.flip(); u->set_all();
s->get_safra()->getL(l); // {i : q \in L_i} s->get_safra()->getL(*l); // {i : q \in L_i}
s->get_safra()->getU(u); // {j : q \in U_i} s->get_safra()->getU(*u); // {j : q \in U_i}
state_complement* st; state_complement* st;
#if TRANSFORM_TO_TBA #if TRANSFORM_TO_TBA
bitset_t newI = s->get_L() | l; // {I' = I \cup {i : q \in L_i}} bitvect* newI = s->get_L().clone();
bitset_t newJ = s->get_U() | u; // {J' = J \cup {j : q \in U_i}} *newI |= *l; // {I' = I \cup {i : q \in L_i}}
bitvect* newJ = s->get_U().clone();
*newJ |= *u; // {J' = J \cup {j : q \in U_i}}
if (newI.is_subset_of(newJ)) // \delta'((q, I, J), a) if I'\subseteq J' // \delta'((q, I, J), a) if I'\subseteq J'
if (newI->is_subset_of(*newJ))
{ {
for (trans_iter i = tr->second.begin(); i != tr->second.end(); ++i) for (trans_iter i = tr->second.begin(); i != tr->second.end(); ++i)
{ {
st = new state_complement(e, e, i->second, true); st = new state_complement(e->clone(), e->clone(), i->second, true);
succ_list.insert(std::make_pair(i->first, st)); succ_list.insert(std::make_pair(i->first, st));
} }
condition = the_acceptance_cond_; condition = the_acceptance_cond_;
@ -1265,22 +1269,30 @@ namespace spot
succ_list.insert(std::make_pair(i->first, st)); succ_list.insert(std::make_pair(i->first, st));
} }
} }
delete newI;
delete newJ;
#else #else
bitset_t S = s->get_L(); // {pending = S \cup {i : q \in L_i} \setminus {j : q \in U_j})}
bitset_t pending = (S | l) - u; // {pending = S \cup {i : q \in L_i} const bitvect& S = s->get_L();
// \setminus {j : q \in U_j})} bitvect* pending = S.clone();
*pending |= *l;
*pending -= *u;
for (trans_iter i = tr->second.begin(); i != tr->second.end(); ++i) for (trans_iter i = tr->second.begin(); i != tr->second.end(); ++i)
{ {
st = new state_complement(pending, e, i->second, true); st = new state_complement(pending->clone(), e->clone(),
i->second, true);
succ_list.insert(std::make_pair(i->first, st)); succ_list.insert(std::make_pair(i->first, st));
} }
delete pending;
for (unsigned i = 0; i < l.size(); ++i) for (unsigned i = 0; i < l->size(); ++i)
if (!S[i]) if (!S.get(i))
condition |= acceptance_cond_vec_[i]; condition |= acceptance_cond_vec_[i];
#endif #endif
delete u;
delete l;
} }
delete e;
return new tgba_safra_complement_succ_iterator(succ_list, condition); return new tgba_safra_complement_succ_iterator(succ_list, condition);
} }
assert(!"Safra automaton does not find this node"); assert(!"Safra automaton does not find this node");